Резюме: экспорт данных пикселей из NSOpenGLView в некоторые форматы файлов дает неправильные цвета
Я разрабатываю приложение для визуализации некоторых экспериментальных данных. Одна из его функций - визуализация данных в подклассе NSOpenGLView
и разрешение экспортировать полученное изображение в файл или скопировать в буфер обмена.
Представление экспортирует данные в виде NSImage
, сгенерированного следующим образом:
- (NSImage*) image
{
NSBitmapImageRep* imageRep;
NSImage* image;
NSSize viewSize = [self bounds].size;
int width = viewSize.width;
int height = viewSize.height;
[self lockFocus];
[self drawRect:[self bounds]];
[self unlockFocus];
imageRep=[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:width*4
bitsPerPixel:32] autorelease];
[[self openGLContext] makeCurrentContext];
glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,[imageRep bitmapData]);
image=[[[NSImage alloc] initWithSize:NSMakeSize(width,height)] autorelease];
[image addRepresentation:imageRep];
[image setFlipped:YES]; // this is deprecated in 10.6
[image lockFocusOnRepresentation:imageRep]; // this will flip the rep
[image unlockFocus];
return image;
}
Копирование использует это изображение очень просто, например так:
- (IBAction) copy:(id) sender
{
NSImage* img = [self image];
NSPasteboard* pb = [NSPasteboard generalPasteboard];
[pb clearContents];
NSArray* copied = [NSArray arrayWithObject:img];
[pb writeObjects:copied];
}
Для записи в файл я использую вспомогательную панель ImageKit IKSaveOptions
, чтобы установить тип выходного файла и связанные параметры, а затем используйте следующий код для написания:
NSImage* glImage = [glView image];
NSRect rect = [glView bounds];
rect.origin.x = rect.origin.y = 0;
img = [glImage CGImageForProposedRect:&rect
context:[NSGraphicsContext currentContext]
hints:nil];
if (img)
{
NSURL* url = [NSURL fileURLWithPath: path];
CGImageDestinationRef dest = CGImageDestinationCreateWithURL((CFURLRef)url,
(CFStringRef)newUTType,
1,
NULL);
if (dest)
{
CGImageDestinationAddImage(dest,
img,
(CFDictionaryRef)[imgSaveOptions imageProperties]);
CGImageDestinationFinalize(dest);
CFRelease(dest);
}
}
(Я тут немного обрезал посторонний код, но, насколько я вижу, ничего, что могло бы повлиять на результат. newUTType
исходит от панели IKSaveOptions
.)
Это прекрасно работает, когда файл экспортируется в формате GIF, JPEG, PNG, PSD или TIFF, но экспорт в PDF, BMP, TGA, ICNS и JPEG-2000 приводит к появлению артефактов красного цвета на части изображения. Ниже приведены примеры изображений: первое экспортировано в формате JPG, второе - в формате PDF.
Изображение экспортировано в формате JPEG с правильными цветами http://walkytalky.net/extern/ionx-jpg.jpg
Изображение экспортировано в формате PDF с красной полосой на пипетке http://walkytalky.net/extern/ionx-pdf.jpg
Копировать в буфер обмена не показывает эту красную полосу с текущей реализацией image
, но сделал с оригинальной реализацией, которая сгенерировала imageRep
с использованием NSCalibratedRGBColorSpace
вместо NSDeviceRGBColorSpace
, Так что я предполагаю, что есть некоторая проблема с представлением цвета в пикселях, которое я получаю от OpenGL, который не проходит через последующие преобразования должным образом, но я не знаю, что с этим делать.
Итак, кто-нибудь может сказать мне: (i) что вызвало это, и (ii) как я могу заставить его уйти? Меня не волнует всех форматов, но я бы действительно хотел, чтобы хотя бы PDF работал.