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: