Захватите экран Mac OS, используя формат GL_RGB - PullRequest
4 голосов
/ 25 января 2010

Я использую код glgrab, чтобы попытаться получить полноэкранный скриншот экрана Mac. Однако я хочу, чтобы данные растрового изображения были в формате GL_RGB. То есть каждый пиксель должен быть в формате:

0x00RRGGBB

Исходный код указывал формат GL_BGRA. Однако изменение этого значения на GL_RGB дает мне совершенно пустой результат. Общий исходный код, который я использую:

CGImageRef grabViaOpenGL(CGDirectDisplayID display, CGRect srcRect)
{
    CGContextRef bitmap;
    CGImageRef image;
    void * data;
    long bytewidth;
    GLint width, height;
    long bytes;
    CGColorSpaceRef cSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);

    CGLContextObj    glContextObj;
    CGLPixelFormatObj pixelFormatObj ;
    GLint            numPixelFormats ;
    //CGLPixelFormatAttribute
    int attribs[] =
    {
//      kCGLPFAClosestPolicy,
        kCGLPFAFullScreen,
        kCGLPFADisplayMask,
        NULL,    /* Display mask bit goes here */
        kCGLPFAColorSize, 24,
        kCGLPFAAlphaSize, 0,
        kCGLPFADepthSize, 32,
        kCGLPFASupersample,
        NULL
    } ;


    if ( display == kCGNullDirectDisplay )
        display = CGMainDisplayID();
    attribs[2] = CGDisplayIDToOpenGLDisplayMask(display);


    /* Build a full-screen GL context */
    CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
    if ( pixelFormatObj == NULL )    // No full screen context support
    {
        // GL didn't find any suitable pixel formats. Try again without the supersample bit:
        attribs[10] = NULL;
        CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
        if (pixelFormatObj == NULL)
        {
            qDebug("Unable to find an openGL pixel format that meets constraints");
            return NULL;
        }
    }
    CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ;
    CGLDestroyPixelFormat( pixelFormatObj ) ;
    if ( glContextObj == NULL )
    {
        qDebug("Unable to create OpenGL context");
        return NULL;
    }


    CGLSetCurrentContext( glContextObj ) ;
    CGLSetFullScreen( glContextObj ) ;


    glReadBuffer(GL_FRONT);


    width = srcRect.size.width;
    height = srcRect.size.height;


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

    /* Build bitmap context */
    data = malloc(height * bytewidth);
    if ( data == NULL )
    {
        CGLSetCurrentContext( NULL );
        CGLClearDrawable( glContextObj ); // disassociate from full screen
        CGLDestroyContext( glContextObj ); // and destroy the context
        qDebug("OpenGL drawable clear failed");
        return NULL;
    }
    bitmap = CGBitmapContextCreate(data, width, height, 8, bytewidth,
                                   cSpace, kCGImageAlphaNoneSkipFirst /* XRGB */);
    CFRelease(cSpace);


    /* Read framebuffer into our bitmap */
    glFinish(); /* Finish all OpenGL commands */
    glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

    /*
     * Fetch the data in XRGB format, matching the bitmap context.
     */
    glReadPixels((GLint)srcRect.origin.x, (GLint)srcRect.origin.y, width, height,
                 GL_RGB,
#ifdef __BIG_ENDIAN__
                 GL_UNSIGNED_INT_8_8_8_8_REV, // for PPC
#else
                 GL_UNSIGNED_INT_8_8_8_8, // for Intel! http://lists.apple.com/archives/quartz-dev/2006/May/msg00100.html
#endif
                 data);
    /*
     * glReadPixels generates a quadrant I raster, with origin in the lower left
     * This isn't a problem for signal processing routines such as compressors,
     * as they can simply use a negative 'advance' to move between scanlines.
     * CGImageRef and CGBitmapContext assume a quadrant III raster, though, so we need to
     * invert it. Pixel reformatting can also be done here.
     */
    swizzleBitmap(data, bytewidth, height);


    /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */
    image = CGBitmapContextCreateImage(bitmap);

    /* Get rid of bitmap */
    CFRelease(bitmap);
    free(data);


    /* Get rid of GL context */
    CGLSetCurrentContext( NULL );
    CGLClearDrawable( glContextObj ); // disassociate from full screen
    CGLDestroyContext( glContextObj ); // and destroy the context

    /* Returned image has a reference count of 1 */
    return image;
}

Я совершенно новичок в OpenGL, поэтому я был бы признателен за некоторые указатели в правильном направлении. Ура!

Обновление:

После некоторых экспериментов мне удалось сузить проблему. Моя проблема в том, что, хотя я не хочу альфа-компонент, я хочу, чтобы каждый пиксель был упакован в 4-байтовые границы. Теперь, когда я указываю форматы GL_RGB или GL_BGR для вызова glReadPixels, я получаю данные растрового изображения, упакованные в 3-байтовые блоки. Когда я указываю GL_RGBA или GL_BGRA, я получаю четыре байтовых блока, но всегда с последним компонентом альфа-канала.

Затем я попытался изменить значение, переданное на

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

однако, без изменений AlphaNoneSkipFirst или AlphaNoneSkipLast альфа-канал помещается в начало байтового блока пикселей.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 29 января 2010

Я не парень Mac, но если вы можете получить данные RGBA и хотите XRGB, разве вы не можете просто сдвинуть бит на пиксель на восемь бит?

foreach( unsigned int* RGBA_pixel, pixbuf )
{
    (*RGBA_pixel) = (*RGBA_pixel) >> 8;
}
1 голос
/ 25 января 2010

Попробуйте с GL_UNSIGNED_BYTE вместо GL_UNSIGNED_INT_8_8_8_8_REV / GL_UNSIGNED_INT_8_8_8_8.

Хотя кажется, что вы хотите вместо GL_RGBA - тогда он должен работать либо с 8_8_8_8_REV, либо с 8_8_8_8.

0 голосов
/ 02 февраля 2010

Когда я использую GL_BGRA, данные возвращаются предварительно обработанными, что подтверждается, потому что цвета выглядят правильно, когда я отображаю результат в окне.

Свяжитесь со мной, если вы хотите проект, который я создал. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...