我的最终目标是使用NSImage填充任意大小的矩形。我想:
这表明了我正在努力做的事情。顶部船的原始图像被绘制成下面各种尺寸的矩形。
好的,到目前为止一切顺利。我为NSImage添加了一个类别来执行此操作。
@implementation NSImage (Fill)
/**
* Crops source to best fit the destination
*
* destRect is the rect in which we want to draw the image
* sourceRect is the rect of the image
*/
-(NSRect)scaleAspectFillRect:(NSRect)destRect fromRect:(NSRect)sourceRect
{
NSSize sourceSize = sourceRect.size;
NSSize destSize = destRect.size;
CGFloat sourceAspect = sourceSize.width / sourceSize.height;
CGFloat destAspect = destSize.width / destSize.height;
NSRect cropRect = NSZeroRect;
if (sourceAspect > destAspect) { // source is proportionally wider than dest
cropRect.size.height = sourceSize.height;
cropRect.size.width = cropRect.size.height * destAspect;
cropRect.origin.x = (sourceSize.width - cropRect.size.width) / 2;
} else { // dest is proportionally wider than source (or they are equal)
cropRect.size.width = sourceSize.width;
cropRect.size.height = cropRect.size.width / destAspect;
cropRect.origin.y = (sourceSize.height - cropRect.size.height) / 2;
}
return cropRect;
}
- (void)drawScaledAspectFilledInRect:(NSRect)rect
{
NSRect imageRect = NSMakeRect(0, 0, [self size].width, [self size].height);
NSRect sourceRect = [self scaleAspectFillRect:rect fromRect:imageRect];
[[NSGraphicsContext currentContext]
setImageInterpolation:NSImageInterpolationHigh];
[self drawInRect:rect
fromRect:sourceRect
operation:NSCompositeSourceOver
fraction:1.0 respectFlipped:YES hints:nil];
}
@end
当我想将图像绘制成某个矩形时,我称之为:
[myImage drawScaledAspectFilledInRect:onScreenRect];
除了一个问题外,效果很好。在某些尺寸下,图像看起来非常模糊:
我的第一个想法是我需要绘制整数像素,所以我在绘制之前使用了NSIntegralRect()。没有运气。
正如我想的那样,我认为它可能是插值的结果。要从较大的图像绘制到较小的绘制矩形,NSImage必须进行插值。模糊的图像可能只是一个值不能很好地映射的情况,我们最终会得到一些无法避免的不良伪像。
所以,问题是:我如何选择避免这些伪影的最佳矩形?我可以在绘图之前调整绘制矩形或裁剪矩形以避免这种情况,但我不知道如何或何时调整它们。