Mac OS OpenGL 屏幕抓取

Posted

技术标签:

【中文标题】Mac OS OpenGL 屏幕抓取【英文标题】:Mac OS OpenGL screen grab 【发布时间】:2015-06-01 12:53:46 【问题描述】:

我正在尝试通过 OpenGL 捕获 mac os 桌面,即 GL 桌面抓取。

CGContextRef bitmap;
CGImageRef image;
void * data;
long bytewidth;
GLint width, height;
long bytes;
CGColorSpaceRef cSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGLContextObj    glContextObj;
CGLPixelFormatObj pixelFormatObj ;
GLint            numPixelFormats ;

int attribs[] =

    kCGLPFAFullScreen,
    kCGLPFADisplayMask,
    NULL,
    kCGLPFAColorSize, 24,
    kCGLPFAAlphaSize, 0,
    kCGLPFADepthSize, 32,
    NULL
;

CGDirectDisplayID display;
if(display == kCGNullDirectDisplay)

    display = CGMainDisplayID();


attribs[2] = CGDisplayIDToOpenGLDisplayMask(display);

CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
if ( pixelFormatObj == NULL )    // No full screen context support

    attribs[10] = NULL;
    CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
    if (pixelFormatObj == NULL)
    
        return;
    

CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ;
CGLDestroyPixelFormat( pixelFormatObj ) ;
if ( glContextObj == NULL )

   return;


CGLSetCurrentContext( glContextObj ) ;
CGLSetFullScreen( glContextObj ) ;

glReadBuffer(GL_FRONT);

width = scrWidth;
height = srcHeight;

bytewidth = width * 4; // Assume 4 bytes/pixel for now
bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
bytes = bytewidth * height; // width * height

data = malloc(height * bytewidth);
if ( data == NULL )

    CGLSetCurrentContext( NULL );
    CGLClearDrawable( glContextObj ); // disassociate from full screen
    CGLDestroyContext( glContextObj ); // and destroy the context
    return;

bitmap = CGBitmapContextCreate(data, width, height, 8, bytewidth,
                               cSpace, kCGImageAlphaNoneSkipFirst /* XRGB */);
CFRelease(cSpace);

glFinish(); 
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

glReadPixels(0, 0, width, height,
             GL_RGB,
  #ifdef __BIG_ENDIAN__
             GL_UNSIGNED_BYTE, // for PPC
  #else
             GL_UNSIGNED_BYTE, // for Intel!
  #endif
             data);

swizzleBitmap(data, bytewidth, height);

image = CGBitmapContextCreateImage(bitmap);

CFRelease(bitmap);
free(data);

CGLSetCurrentContext( NULL );
CGLClearDrawable( glContextObj );
CGLDestroyContext( glContextObj );

但我得到的是黑色图像。 我正在使用 10.10.3 OS X Yosemite 。 这里有什么问题? 也许问题出在mac os版本?

我正在通过 glReadPixels 将像素数据写入文件,但没有结果,又是黑色图像。

【问题讨论】:

【参考方案1】:

OpenGL 不能可靠地用于屏幕捕获。执行 fullscreen-window-glReadPixels 的“OpenGL 屏幕捕获示例”依赖于底层图形系统的未定义行为。也就是说,窗口共享屏幕帧缓冲区,并且新创建的没有擦除画笔的窗口将“继承”创建它的屏幕内容。

在现代图形系统上,所有这些假设都失败了:

Windows 共享屏幕帧缓冲区 Windows 总是用一些清除画笔初始化 Windows 被合成到最终的桌面外观中

【讨论】:

感谢您提供此信息。即对于 Mac 屏幕抓取,我必须使用标准函数,如 CGDisplayCreateImageForRect、CGImageGetDataProvider ...? @GeorgGPU:是的,您必须为此使用标准系统函数。

以上是关于Mac OS OpenGL 屏幕抓取的主要内容,如果未能解决你的问题,请参考以下文章

Mac OS X安装OpenGL

在 Mac OS X 上使用现代 OpenGL [关闭]

在 Mac OS X 上使用 CGL 设置 OpenGL 上下文

在 Mac OS X 中编译使用 OpenGL 的 C 程序

运行使用 OpenGL 3.3 的 mac os x c++ 程序

无法使用 Xcode 和终端在 Mac OS 上使用 OpenGL 库编译 c++ 文件