Posts Tagged ‘clipboard’

Paste directly from clipboard into matlab image array

Sunday, October 12th, 2014

I find myself often wanting to experiment with images from papers I’m reading. To load the image into matlab properly I should extract it from the pdf, save it in a file and load the file via matlab. Often I skip the first step and just take a screengrab. But I still need to create a dummy file just to load it into matlab.

Here’s a mex function to load images directly from the clipboard. It even maintains all color channels (RGB, CMYK, RGBA, etc.)

Save this in a file paste.h:

#include <cstddef>
// Get image from clipboard as an RGB image
//
// Outputs:
//   IM  h*w*c list of rgb pixel color values as uint8, running over height,
//     then width, then rgb channels
//   h  height
//   w  width
//   c  channels
bool paste(unsigned char *& IM,size_t & h, size_t & w, size_t & c);

and in paste.mm:

#import "paste.h"
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>

bool paste(unsigned char *& IM,size_t & h, size_t & w, size_t & c)
{
  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
  NSDictionary *options = [NSDictionary dictionary];
  BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 
  if(!ok)
  {
    //printf("Error: clipboard doesn't seem to contain image...");
    return false;
  }
  NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
  NSImage *image = [objectsToPaste objectAtIndex:0];
  NSBitmapImageRep* bitmap = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
  // http://stackoverflow.com/a/19649616/148668
  w = [bitmap pixelsWide];
  h = [bitmap pixelsHigh];
  size_t rowBytes = [bitmap bytesPerRow];
  c = rowBytes/w;
  unsigned char* pixels = [bitmap bitmapData];
  IM = new unsigned char[w*h*c];
  for(size_t y = 0; y < h ; y++)
  {
    for(size_t x = 0; x < w; x++)
    {
      for(size_t d = 0;d<c;d++)
      {
        // For some reason colors are invertex
        IM[y+h*(x+d*w)] = pixels[y*rowBytes + x*c + d];
      }
    }
  }
  [image release];
  return true;
}

and in impaste.cpp

#ifdef MEX
#include <mex.h>
#include "paste.h"
#include <iostream>

void mexFunction(
  int nlhs, mxArray *plhs[], 
  int nrhs, const mxArray *prhs[])
{
  unsigned char * IM;
  size_t h,w,c;
  if(!paste(IM,h,w,c))
  {
    mexErrMsgTxt("Clipboard doesn't contain image.");
  }
  switch(nlhs)
  {
    default:
    {
      mexErrMsgTxt("Too many output parameters.");
    }
    case 1:
    {
      size_t dims[] = {h,w,c};
      plhs[0] = mxCreateNumericArray(3,dims,mxUINT8_CLASS,mxREAL);
      unsigned char * IMp = (unsigned char *)mxGetData(plhs[0]);
      std::copy(IM,IM+w*h*c,IMp);
      // Fall through
    }
    case 0: break;
  }
}

#endif

Then compile on Mac OS X using something like:

mex -v -largeArrayDims -DMEX CXX='/usr/bin/clang++' LD='/usr/bin/clang++' LDOPTIMFLAGS='-O ' LDFLAGS='\$LDFLAGS -framework Foundation -framework AppKit' -o impaste impaste.cpp paste.mm

Notice, I’m forcing the mex compiler to use clang and include the relevant frameworks.

Then you can call from matlab using something like:

IM = impaste();

or

imshow(impaste());

Render to Mac OS X clipboard from GLUT OpenGL app

Saturday, January 25th, 2014

Here’s a proof of concept application that renders the current viewport to the mac os x clipboard. Then you can paste into Preview.app or Photoshop etc. Save the following in render_to_clipboard.m:

#include <GLUT/GLUT.h>
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#include <stdlib.h>
#include <unistd.h>

void reshape(int width,int height)
{
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glViewport(0,0,width,height);
  gluPerspective(40, (double)width/height, 1, 10);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(0,0,3, 0,0,0, 0,1,0);
  glTranslatef(0, 0.0f, -1);
}

bool buffer_to_clipboard(
  const GLubyte * pixels, 
  const int w, 
  const int h, 
  const int components)
{
  const int length = w*h*components;
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  // http://stackoverflow.com/a/3416891/148668
  size_t bufferLength = w * h * components;
  CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, bufferLength, NULL);
  size_t bitsPerComponent = 8;
  size_t bitsPerPixel = bitsPerComponent * components;
  size_t bytesPerRow = components * w;
  CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
  CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
  CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

  CGImageRef iref = CGImageCreate(
    w, 
    h, 
    bitsPerComponent, 
    bitsPerPixel, 
    bytesPerRow, 
    colorSpaceRef, 
    bitmapInfo, 
    provider,   // data provider
    NULL,       // decode
    YES,        // should interpolate
    renderingIntent);

  NSImage * temp_image = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(w, h)];

  // Painfully flip image across x-axis
  NSSize newSize = NSMakeSize(w,h);
  NSImage *image = [[NSImage alloc] initWithSize:newSize];
  [image lockFocus];
  NSAffineTransform *flip = [NSAffineTransform transform];
  [flip translateXBy: 0 yBy: h];
  [flip scaleXBy:1 yBy:-1];
  [flip concat];
  NSRect r1 = NSMakeRect(0, 0, w,h);
  [[temp_image bestRepresentationForRect:r1 context:nil hints:nil] drawInRect: r1];
  [image unlockFocus];

  BOOL copied = false;
  if (image != nil)
  {
    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
    [pasteboard clearContents];
    NSArray *copiedObjects = [NSArray arrayWithObject:image];
    copied = [pasteboard writeObjects:copiedObjects];
    [pasteboard release];
  }
  [image release];
  [pool release];
  return true;
}

bool render_to_clipboard()
{
  GLenum format = GL_RGBA;
  int components = 4;
  int VP[4];
  glGetIntegerv(GL_VIEWPORT,VP);
  // OpenGL by default tries to read data in multiples of 4, if our data is
  // only RGB or BGR and the width is not divible by 4 then we need to alert
  // opengl
  if((VP[2] % 4) != 0 && 
   (format == GL_RGB || 
    format == GL_BGR))
  {
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
  }
  GLubyte *pixels;
  pixels = (unsigned char *) malloc (VP[2]* VP[3]* components);
  glReadPixels( VP[0], VP[1], VP[2], VP[3], format, GL_UNSIGNED_BYTE, pixels);
  return buffer_to_clipboard(pixels, VP[2], VP[3], components);
}

void display()
{
  glClearColor(1,0,0,1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glutWireTeapot(1.0);
  glutSwapBuffers();
  render_to_clipboard();
}

void exitCB()
{
  exit(0);
}

int main(int argc, char * argv[])
{
  glutInit(&argc,argv);
  glutInitDisplayString( "rgba depth double samples>=8 ");
  glutInitWindowSize(401,301);
  glutCreateWindow("test");
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  // Render once and quit
  glutIdleFunc(exitCB);
  glutMainLoop();
  return 0;
}

Then you can compile with

cc -o render_to_clipboard render_to_clipboard.m -framework GLUT -framework OpenGL -lobjc -framework Foundation -framework AppKit

And run with:

./render_to_clipboard

This will flash a GLUT window, render once and quit. You can then paste your frame, which should be:

render teaport to mac os x clipboard

Copy image file to clipboard

Saturday, January 25th, 2014

Here’s a small objective-c program to take an image file and copy it to the clipboard on Mac OS X. Dump this in a file called impbcopy.m:

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>
BOOL copy_to_clipboard(NSString *path)
{
  // http://stackoverflow.com/questions/2681630/how-to-read-png-image-to-nsimage
  NSImage * image;
  if([path isEqualToString:@"-"])
  {
    // http://caiustheory.com/read-standard-input-using-objective-c 
    NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];
    image = [[NSImage alloc] initWithData:[input readDataToEndOfFile]];
  }else
  { 
    image =  [[NSImage alloc] initWithContentsOfFile:path];
  }
  // http://stackoverflow.com/a/18124824/148668
  BOOL copied = false;
  if (image != nil)
  {
    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
    [pasteboard clearContents];
    NSArray *copiedObjects = [NSArray arrayWithObject:image];
    copied = [pasteboard writeObjects:copiedObjects];
    [pasteboard release];
  }
  [image release];
  return copied;
}

int main(int argc, char * const argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  if(argc<2)
  {
    printf("Usage:\n\n"
      "Copy file to clipboard:\n    ./impbcopy path/to/file\n\n"
      "Copy stdin to clipboard:\n    cat /path/to/file | ./impbcopy -");
    return EXIT_FAILURE;
  }
  NSString *path= [NSString stringWithUTF8String:argv[1]];
  BOOL success = copy_to_clipboard(path);
  [pool release];
  return (success?EXIT_SUCCESS:EXIT_FAILURE);
}

Then compile with:

gcc -Wall -g -O3 -ObjC -framework Foundation -framework AppKit -o impbcopy impbcopy.m

And run with something like:

./impbcopy path/to/file.png

or from stdin use:

cat path/to/file.jpg | ./impbcopy -

Update: For completeness, here’s a small program to paste the clipboard image to a file:

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>

@interface NSImage(saveAsPNGWithName)
- (void) saveAsPNGWithName:(NSString*) fileName;
@end

@implementation NSImage(saveAsPNGWithName)

- (void) saveAsPNGWithName:(NSString*) fileName
{
    // Cache the reduced image
    NSData *imageData = [self TIFFRepresentation];
    NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
    NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
    imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps];
    [imageData writeToFile:fileName atomically:NO];        
}

@end

BOOL paste_from_clipboard(NSString *path)
{
  // http://stackoverflow.com/a/18124824/148668
  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
  NSDictionary *options = [NSDictionary dictionary];
  BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 
  if(ok)
  {
    NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
    NSImage *image = [objectsToPaste objectAtIndex:0];
    // http://stackoverflow.com/a/3213017/148668
    [image release];
  }else
  {
    printf("Error: Clipboard doesn't seem to contain an image.\n");
  }
  return ok;
}

int main(int argc, char * const argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  if(argc<2)
  {
    printf("Usage:\n\n"
      "Paste clipboard to file:\n    ./impbcopy path/to/file\n\n");
    return EXIT_FAILURE;
  }
  NSString *path= [NSString stringWithUTF8String:argv[1]];
  BOOL success = paste_from_clipboard(path);
  [pool release];
  return (success?EXIT_SUCCESS:EXIT_FAILURE);
}

Compile with:

clang -Wall -g -O3 -ObjC -framework Foundation -framework AppKit -o impbpaste impbpaste.m

and run:

./impbpaste foo.png

Update: could also try the command line program pngpaste which has more features.

Patch for AntTweakBar to support pasting from clipboard on Mac OS X

Tuesday, January 3rd, 2012

I recently noticed I could use pbpaste and a system call to integrate the clipboard’s contents into my C++ programs. I use AntTweakBar all the time for quick prototyping UI and though it has a default internal clipboard, I found it frustrating that it doesn’t hook into my mac’s global clipboard. To make this happen I just modified TwBar.cpp in two places EditInPlaceSetClipboard and EditInPlaceGetClipboard, surrounding each edit with #elif defined ANT_OSX. Now I can copy from my AntTweakBar and paste into some other app or copy from some other app and paste into an AntTweakBar string field.

Here’s what to place in EditInPlaceSetClipboard

// PATCH BEGIN Alec Jacobson, 2012
// PATCH BEGIN Alec Jacobson, 2012
#elif defined ANT_OSX
    stringstream cmd;
    cmd << "echo \"" << _String << "\" | pbcopy";
    FILE* pipe = popen(cmd.str().c_str(), "r");
    if (!pipe)
    {
        return false;
    }
// PATCH END

And here’s what to place in EditInPlaceGetClipboard

// PATCH BEGIN Alec Jacobson, 2012
// PATCH BEGIN Alec Jacobson, 2012                                                                        
#elif defined ANT_OSX
    FILE* pipe = popen("pbpaste", "r");                                                                   
    if (!pipe)
    {   
        return false;
    }                                                                                                     
    char buffer[128];
    string result = "";                                                                                   
    while(!feof(pipe))
    {   
        if(fgets(buffer, 128, pipe) != NULL)                                                              
        {
            result += buffer;                                                                             
        }                                                                                                 
    }   
    pclose(pipe);
    *_OutString = result.c_str();                                                                         
// PATCH END

To ensure your binaries run with this patched version you might consider compiling AntTweakBar as a static library.

Accessing clipboard (copy paste) from C++ program on Mac OS X

Monday, January 2nd, 2012

I’ve been using pbcopy and pbpaste to control the clipboard via the command on mac for a while now. It’s not to hard to utilized these in a c++ program, integrating my little apps with the clipboard without having to go through Cocoa or objective c or any libraries. Here’s a little demo:


#include <string>
#include <iostream>
#include <sstream>
#include <stdio.h>

// http://stackoverflow.com/questions/478898
std::string exec(const char* cmd)
{
  FILE* pipe = popen(cmd, "r");
  if (!pipe) return "ERROR";
  char buffer[128];
  std::string result = "";
  while(!feof(pipe))
  {
    if(fgets(buffer, 128, pipe) != NULL)
    {
      result += buffer;
    }
  }
  pclose(pipe);
  return result;
}

std::string paste()
{
  return exec("pbpaste");
}

std::string copy(const char * new_clipboard)
{
  std::stringstream cmd;
  cmd << "echo \"" << new_clipboard << "\" | pbcopy";
  return exec(cmd.str().c_str());
}

int main(int argc, char * argv[])
{
  using namespace std;
  cout<<"old clipboard: "<<paste()<<endl;
  copy("Bomb!");
  cout<<"new clipboard: "<<paste()<<endl;
  return 0;
}

Vi(m) tip #9: Copy, Cut and Paste into Mac OS X clipboard

Wednesday, June 30th, 2010

I can get a lot done in vim without ever having to use the mouse or really exit “vim world”. But the one thing that I keep falling back on is copy and pasting from and to other applications. Here’s a way to do these
operations without resorting to the mouse or foreign keystrokes. Issue these in command mode:

Cut line under cursor


:.!pbcopy

Copy line under cursor


:.!pbcopy|pbpaste

Paste as line beneath cursor


:r !pbpaste

You can also use this if you’ve made a selection in Visual Mode:

Cut current selection

(warning: this grabs the whole lines of any lines within selection)


:'<,'>!pbcopy

Copy current selection

(warning: this grabs the whole lines of any lines within selection)


:'<,'>!pbcopy|pbpaste

Note: It seems for that one you should just select the first letter of each line. Not the entire block, then it just cuts…

Update: It’s much simpler:


"*yy

Yanks the current line to the clipboard. Similarly,


"*dd

cuts the current line and


"*p

pastes the clipboard below the current line.

Synergy server and client settings and commands

Saturday, November 21st, 2009

After the recommendation of a linux friend, I have begun using synergy to share my mouse and keyboard between the new macbook pro on my desk and the old powerbook two shelves up (I do have to physically switch the DVI cable to see the right computer on my monitor though … DVI switches still cost too much).

On the server (the computer which actually owns the mouse and keyboard), named
Enfermera:

Here is my synergy.conf file saved in ~/.synergy.conf


section: screens
  Enfermera.local:
  AJX.local:
end
section: links
  Enfermera.local:
    right = AJX.local
  AJX.local:
    left = Enfermera.local
end

Then on this computer (server) I run the command


synergys -f --config ~/.synergy.conf 

On the client (the computer not physically or emotionally connected to the mouse and keyboard), named AJX:
I run the command to start listening for mouse and keyboard coming from Enfermera:


synergyc -f Enfermera.local

Note: Another awesome feature of synergy is that your linked computers will share clipboards allowing you to copy from one computer and paste into the other.

Note: I was able to install this on Mac OS X 10.4 and Mac OS X 10.5 (both using sudo port install synergy), the two operating systems had no problems talking to each other through synergy.

Escape code for html <pre> or <code> tag into clipboard

Thursday, August 13th, 2009

Here’s a speed up for posting code in a <pre> or <code> tag in an html page or blog. The script escapes all less than and greater than symbols (< with &lt; and > with &gt;) in a given file then puts the results in the clipboard to facilitate pasting into a text area or text editor. Save this in a file called escape-copy.sh:


#!/bin/bash
cat "$1" | sed s/\</\\\<\;/g | sed s/\>/\\\>\;/g | pbcopy

Posting the above code was super easy now, I just ran ./escape-copy.sh escape-copy.sh and pasted it in a <pre> tag.