2013-04-23 121 views
1

我實現了在Mac OS X中的C++項目下面的代碼,用於捕獲桌面屏幕圖像:Mac OS X的石英CGWindowListCreateImage打亂在1366×768分辨率

int ScreenCaptureRoutines::CaptureImage(int width, int height) 
{ 
    CGRect captureRect; 

    captureRect.origin.x = 0; 
    captureRect.origin.y = 0; 
    captureRect.size.width = width; 
    captureRect.size.height = height; 

    CGImageRef img = CGWindowListCreateImage(captureRect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageDefault); 

    if(img == NULL) 
    { 
     fprintf(stderr, "CGWindowListCreateImage failed\n!"); 
     return -1; 
    } 

    /* get pixels */ 
    CGDataProviderRef provider = CGImageGetDataProvider(img); 
    CFDataRef dataRef = CGDataProviderCopyData(provider); 
    uint8_t* pixels = (uint8_t*)CFDataGetBytePtr(dataRef); 

    BitmapUtility::SaveBitmapToFile(pixels, width, height, 32, "/Users/Main/test32.bmp"); 
} 

的代碼非常適用於分辨率,如1024x768,1280x1024,1280x960,1280x768等,但它完全爭奪1366x768圖像。

這是SaveBitmapFile方法用於保存像素:

void BitmapUtility::SaveBitmapToFile(u8* pBitmapBits, long lWidth, long lHeight, unsigned short wBitsPerPixel, char* lpszFileName) 
{ 
    BITMAPINFOHEADER bmpInfoHeader = {0}; 
    bmpInfoHeader.biSize = sizeBITMAPINFOHEADER; 
    bmpInfoHeader.biBitCount = wBitsPerPixel; 
    bmpInfoHeader.biClrImportant = 0; 
    bmpInfoHeader.biClrUsed = 0; 
    bmpInfoHeader.biCompression = BI_RGB; 
    bmpInfoHeader.biHeight = lHeight; 
    bmpInfoHeader.biWidth = lWidth; 
    bmpInfoHeader.biPlanes = 1; 
    bmpInfoHeader.biSizeImage = lWidth* lHeight * (wBitsPerPixel/8); 

    BITMAPFILEHEADER bfh = {0}; 
    bfh.bfType=0x4D42; 
    bfh.bfOffBits = sizeBITMAPINFOHEADER + sizeBITMAPFILEHEADER; 
    bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage; 

    //Creating bitmap file 
    int fileDescriptor = open(lpszFileName, O_CREAT | O_WRONLY); 
    if (fileDescriptor == -1) 
    { 
     //returning if error encountered when opening file 
     return; 
    } 

    ByteBufferOutputStream bufferInfoHeader; 

    bufferInfoHeader.write(&bmpInfoHeader.biSize, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biWidth, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biHeight, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biPlanes, 2); 
    bufferInfoHeader.write(&bmpInfoHeader.biBitCount, 2); 
    bufferInfoHeader.write(&bmpInfoHeader.biCompression, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biSizeImage, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biXPelsPerMeter, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biYPelsPerMeter, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biClrUsed, 4); 
    bufferInfoHeader.write(&bmpInfoHeader.biClrImportant, 4); 

    ByteBufferOutputStream bufferFileHeader; 

    bufferFileHeader.write(&bfh.bfType, 2); 
    bufferFileHeader.write(&bfh.bfSize, 4); 
    bufferFileHeader.write(&bfh.bfReserved1, 2); 
    bufferFileHeader.write(&bfh.bfReserved2, 2); 
    bufferFileHeader.write(&bfh.bfOffBits, 4); 

    //Writing bitmap to file 
    ssize_t bytesWritten = write(fileDescriptor, bufferFileHeader.get()->getData(), sizeBITMAPFILEHEADER); 
    bytesWritten = write(fileDescriptor, bufferInfoHeader.get()->getData(), sizeBITMAPINFOHEADER); 
    bytesWritten = write(fileDescriptor, pBitmapBits, bmpInfoHeader.biSizeImage); 

    //Closing bitmap file 
    close(fileDescriptor); 
} 

的SaveBitmapToFile方法只用於測試,在真實的生活場景,我居然通過捕獲的像素通過libavcodec的,以將幀轉換並保存爲FLV格式,但最終結果是相同的,圖像會被混淆。

有沒有人知道爲什麼代碼不適用於1366x768(或其他非標準的4:3或16:9分辨率)?

回答

3

首先,您應該嘗試渲染CGImageRef以便在捕獲後立即進行篩選,以確保數據有效。

看看捕獲的bmp文件。如果圖像看起來像僞隨機噪聲,那麼您的像素格式是錯誤的。你需要調用CGImageGetWidthCGImageGetHeight,並CGImageGetBitsPerPixel(和CGImage.h等功能),以確保像素格式是正確的。

如果你仍然可以製作出一些像素,但這些行沒有對齊,那麼你的字節跨度是錯誤的。 1024和1280是32,64和128的倍數。1366另一方面,2除數的最大功率是2.驅動程序通常使用64字節對齊的像素跨度,因爲這是常見的高速緩存行大小。步幅等於寬度+零填充。調用CGImageGetBytesPerRow從上一行的起始地址獲取字節偏移量,以獲得下一行的起始地址。

僞代碼編寫圖像步幅:

ptr = pixels 
bytesPerRow = CGImageGetBytesPerRow() 
bytesPerPixel = (CGImageGetBitsPerPixel() + 7)/8 

for row = 0 to height: 
    write(ptr, width*bytesPerPixel) 
    ptr += bytesPerRow 
+0

謝謝@ErdiChen,我認爲你的答案是正確的,我最終與在我的應用程序下面的代碼去:'寬度=寬度與0xFFFFFFF0;'。無論如何,你的答案似乎捕捉了問題的本質。 – 2013-07-01 14:37:29

+0

感謝Erdi您的精彩解釋。它解決了我的問題。 :) – 2013-07-06 07:01:11