2

我正在从 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];
4

2 回答 2

0

您的源 PNG 的 DPI 是多少?您正在通过假设原始图像size以像素为单位,但size为单位来创建第二张图像。

假设您有一个 450 x 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为原始点数的点数。

于 2012-05-28T06:42:48.230 回答
0

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

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

确保您正在做的另一件事,尽管它可能无济于事(见下文):

[[NSGraphicsContext currentContext] setShouldAntialias:YES];

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

于 2012-05-27T20:35:05.137 回答