摘要:将像素数据从 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];
}
对于文件写入,我使用 ImageKitIKSaveOptions
附件面板设置输出文件类型和相关选项,然后使用以下代码进行写入:
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。
(来源:walkytalky.net)
(来源:walkytalky.net)
复制到剪贴板在 的当前实现中没有出现这个红色条纹image
,但在原始实现中出现了,它生成了imageRep
usingNSCalibratedRGBColorSpace
而不是NSDeviceRGBColorSpace
. 所以我猜我从 OpenGL 获得的像素中的颜色表示存在一些问题,无法正确通过后续转换,但我不知道该怎么做。
那么,谁能告诉我(i)是什么原因造成的,以及(ii)我怎样才能让它消失?我不太关心所有格式,但我真的希望至少 PDF 可以工作。