将NSImage绘制成不同大小的rect时,如何避免插值伪像?

时间:2012-07-12 21:03:34

标签: objective-c cocoa image-processing nsimage

我的最终目标是使用NSImage填充任意大小的矩形。我想:

  1. 填充整个矩形
  2. 保留图像的宽高比
  3. 在保持1)和2)
  4. 的同时尽可能多地显示图像
  5. 如果无法显示所有图像,请向中心裁剪。
  6. 这表明了我正在努力做的事情。顶部船的原始图像被绘制成下面各种尺寸的矩形。

    enter image description here

    好的,到目前为止一切顺利。我为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];
    

    除了一个问题外,效果很好。在某些尺寸下,图像看起来非常模糊:

    enter image description here

    我的第一个想法是我需要绘制整数像素,所以我在绘制之前使用了NSIntegralRect()。没有运气。

    正如我想的那样,我认为它可能是插值的结果。要从较大的图像绘制到较小的绘制矩形,NSImage必须进行插值。模糊的图像可能只是一个值不能很好地映射的情况,我们最终会得到一些无法避免的不良伪像。

    所以,问题是:我如何选择避免这些伪影的最佳矩形?我可以在绘图之前调整绘制矩形或裁剪矩形以避免这种情况,但我不知道如何或何时调整它们。

0 个答案:

没有答案