В настоящее время я впервые использую CoreGraphics API (в основном код C ++), и я пытаюсь получить эскиз (или «скриншот») из CGDisplayStream, который работает нормально, за исключением цветов.
Я создаю CGDisplayStream используя CGDisplayStreamCreate()
(документация) и использовать IOSurfaceRef
внутри блока обработчика (видеть это) создать CGImageRef.
Вот мой тестовый код:
CVPixelBufferRef p_buffer = NULL;
CFDictionaryRef attributes = CFDictionaryCreate(NULL, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CVReturn ret = CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, surface, attributes, &p_buffer);
CVPixelBufferLockBaseAddress(p_buffer, kCVPixelBufferLock_ReadOnly);
void* baseAddr = CVPixelBufferGetBaseAddress(p_buffer);
size_t width = CVPixelBufferGetWidth(p_buffer);
size_t height = CVPixelBufferGetHeight(p_buffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef cgContext = CGBitmapContextCreate(baseAddr, width, height, 8, CVPixelBufferGetBytesPerRow(p_buffer), colorSpace, kCGImageAlphaNoneSkipLast);
CGImageRef img = CGBitmapContextCreateImage(cgContext);
Вызов для создания CGDisplayStream выглядит следующим образом:
CGDisplayStreamCreate(CGMainDisplayID(), 1920, 1080, 'BGRA', NULL,
^(CGDisplayStreamFrameStatus status, uint64_t time, IOSurfaceRef surface, CGDisplayStreamUpdateRef metadata){ //above handler snipped is in here });
Я подозреваю, что либо pixelFormat (видеть это) или CGColorSpace производит мой странный вывод, но я не уверен. Я также не знаю, что я мог сделать сейчас, кроме как слепо угадывать некоторые случайные настройки.
Может быть, кто-нибудь может дать мне подсказку?
Вот мой вывод против «реального» скриншота.
Окончательно нашел решение Вот:
Я изменил линию
CGContextRef cgContext = CGBitmapContextCreate(baseAddr, width, height, 8, CVPixelBufferGetBytesPerRow(p_buffer), colorSpace, kCGImageAlphaNoneSkipLast);
в
CGContextRef cgContext = CGBitmapContextCreate(baseAddr, width, height, 8, CVPixelBufferGetBytesPerRow(p_buffer), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
и теперь работает нормально.
Мне до сих пор не очень понятно, почему это решение. Я предполагаю, что на данный момент требуется более глубокое знание форматов изображения и цвета.
Других решений пока нет …