PNG到NSImage和背面导致接近透明度的锯齿

时间:2012-05-27 20:24:56

标签: cocoa opengl png nsimage

我正在调整Cocoa应用程序中的一些PNG文件。这些文件最终被另一个应用程序加载为OpenGL纹理,并且应用了一个写得不好的着色器,它在某一点上执行以下操作:

texColor = mix(constant,vec4(texColor.rgb/texColor.a,texColor.a),texColor.a);

除以alpha是一个坏主意,解决方案是确保该步骤中texColor的RGB组件永远不会超过1。然而!出于好奇的目的:

原始的PNG(在GIMP中创建)令人惊讶地工作正常,并且使用GIMP创建的调整大小的版本也可以正常工作。但是,使用下面的代码调整文件大小会导致纹理在任何透明像素附近出现锯齿,即使percent1.0也是如此。任何想法是什么,我无意中改变了这些突然导致着色器的错误出现的图像?

NSImage* originalImage = [[NSImage alloc] initWithData:[currentFile regularFileContents]];
NSSize newSize = NSMakeSize([originalImage size].width * percent, [originalImage size].height * percent);
NSImage* resizedImage = [[NSImage alloc] initWithSize:newSize];
[resizedImage lockFocus];
[originalImage drawInRect:NSMakeRect(0,0,newSize.width,newSize.height)
                 fromRect:NSMakeRect(0,0,[originalImage size].width, [originalImage size].height)
                operation:NSCompositeCopy fraction:1.0];
[resizedImage unlockFocus];

NSBitmapImageRep* bits = [[[NSBitmapImageRep alloc] initWithCGImage:[resizedImage CGImageForProposedRect:nil context:nil hints:nil]] autorelease];
NSData* data = [bits representationUsingType:NSPNGFileType properties:nil];
NSFileWrapper* newFile = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];

[newFile setPreferredFilename:currentFilename];
[folder removeFileWrapper:currentFile];
[folder addFileWrapper:newFile];

[originalImage release];
[resizedImage release];

2 个答案:

答案 0 :(得分:0)

在进行这些调整大小操作时,我通常将图像插值设置为高。这可能是你的问题。

[resizedImage lockFocus];
[NSGraphicsContext saveGraphicsState];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[originalImage drawInRect:...]
[NSGraphicsContext restoreGraphicsState];
[resizedImage unlockFocus];

确保你正在做的另一件事,虽然它可能没有帮助(见下文):

[[NSGraphicsContext currentContext] setShouldAntialias:YES];

这可能无法修复它,因为在不知道目标背景的情况下无法消除别名。但它仍然可能有所帮助。如果这是问题(你很快就不能对它进行反锯齿),你可能必须在你准备好绘制最终图像时合成这个大小调整。

答案 1 :(得分:0)

您的源PNG的DPI是多少?您假设原始图像的size以像素为单位,但size位于中,从而创建第二个图像。

假设您的图像为450像素×100像素,DPI为300.该图像以实际单位为1 1/2英寸x 1/3英寸。

现在,Cocoa中的分数名义上是1/72英寸。点的图像大小为108 x 24。

如果您随后根据该大小创建新图像,则没有指定DPI,因此假设每点一个像素。你正在创建一个小得多的图像,这意味着精细的特征必须更粗略地近似。

如果您选择原始图像的其中一个图像代表并使用其pixelsWidepixelsHigh值,您将获得更好的运气。但是,当您执行此操作时,新图像将具有与原始图像不同的真实世界大小。在我的例子中,原件是1 1/2 x 1/3英寸。新图像将具有相同的像素尺寸(450 x 100),但是在72 dpi时,它将是6.25 x 1.39英寸。要解决此问题,您需要将新位图代表的size设置为原点的size点。