【问题标题】:CGContextDrawImage distorts proportionsCGContextDrawImage 扭曲比例
【发布时间】:2014-04-26 15:30:41
【问题描述】:

我有一个裁剪图像 (mainImage),允许用户在使用手指的基础上进行绘制。屏幕 A. 上的红色锯齿形显示手指绘制的部分。现在,使用下面的代码,新绘制的图像上下文(红色之字形)被推入与裁剪图像相同的边界,我最终得到一个扭曲的之字形(屏幕截图 B.)。您可以看到红色之字形是如何被推入裁剪后的 (mainImage) 的边界的。

我想要实现的是一个图像,它结合了 mainImage 和 drawImage 的两个上下文,而不会扭曲任何一张照片的比例。因此,只有与 mainImage 重叠的红色之字形部分将在新的上下文中绘制,如屏幕截图 C 所示。(我想要的结果的照片处理图像)。现在,commitDrawingWithOpacity: 方法的结果是屏幕截图 B。我想要屏幕截图 C 的结果。

我尝试了 CGContextClipToRect、CGContextClipToMask,还尝试为绘图图像创建一个新的矩形,但到目前为止还没有成功。我已经被这个问题困扰了将近一个月(自学),这是我在将我的应用程序提交给苹果之前需要做的最后一件事。因此,我们将不胜感激任何帮助。这是我正在使用的代码的链接https://github.com/dblapps/DAScratchPad

这是每个的大小:

drawImage.size = (width=320, height=568) // iPhone 5 屏幕尺寸

mainImage.size = (width=260, height=800) // 裁剪图像的大小

我的 imageView 设置为宽高比。

- (void) commitDrawingWithOpacity:(CGFloat)opacity {
    UIGraphicsBeginImageContext(mainImage.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextScaleCTM(ctx, 1.0f, -1.0f);
    CGContextTranslateCTM(ctx, 0.0f, -mainImage.size.height);

    CGRect rect = CGRectMake(0.0f, 0.0f, mainImage.size.width, mainImage.size.height);

    if (mainImage != nil) {
        CGContextDrawImage(ctx, rect, mainImage.CGImage);
    }

    CGContextSetAlpha(ctx, opacity);
    CGContextDrawImage(ctx, rect, drawImage.CGImage);
    mainImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.layer.contents = (id)mainImage.CGImage;
    drawLayer.contents = nil;
    drawImage = nil;
}

使用函数 AVMakeRectWithAspectRatioInsideRect 我已经能够为我的 mainImage 获得正确的大小比,但仍然没有让任何东西正常工作。

下面是我想要达到的结果的 Photoshop 截图。屏幕截图 B(上图)是我使用当前代码得到的结果。

【问题讨论】:

    标签: ios crop cgimage cgcontextdrawimage


    【解决方案1】:

    您正在使用mainImage 的比例绘制drawImage,因此它被扭曲了。您应该保持drawImage 的比例并正确定位它。这是您调整的潜在起点 - 很难从您的问题中准确说出您想要实现的目标:

    CGRect drawImageRect = (CGRect){
      .origin = {
        .x = -((drawImage.size.width - mainImage.size.width)   / 2),
        .y = -((drawImage.size.height - mainImage.size.height) / 2),
      },
      .size = drawImage.size,
    };
    

    这个矩形使用原始大小,然后调整图像绘制位置的原点

    【讨论】:

    • 谢谢!一直在尝试调整您提供的内容,但每次都会替换 drawImage 。我更新了我的问题并添加了我想要实现的新屏幕截图。当我使用您提供的代码时,我的 y 坐标为负数。我的 mainImage.size.height 为 800,而 drawImage.size.height 仅为 568,感觉这是我的问题的一部分,但不知道如何解决开始。
    • 我可能把减法弄错了。由于drawImage 的宽度大于mainImage,您应该期望它具有负值x。由于drawImage 的高度较小,它确实应该是正数。
    • 我明白了。但就目前而言,drawImage 高度为 568,mainImage 高度为 800 .. 但图像根本没有被高度裁剪。该方程将为 y 返回一个整数值,而实际上 y 应该为 0,因为图像仅针对宽度进行了裁剪。这有意义吗?
    • 如果图像是 800 高,那么屏幕的顶部还是底部?
    • 不,它在具有 aspectFit 比例的 imageView 中。对不起,应该说清楚。所以我相信我的问题是我无法获得 mainImage 的准确原点,因为裁剪前的 mainImage 默认尺寸是(600 x 800),它大于 drawImage 尺寸(又名屏幕尺寸),所以比例和原点从一开始就不对应
    【解决方案2】:

    对我来说,我需要利用这两个函数:AVMakeRectWithAspectRatioInsideRect 和 CGI​​mageCreateWithImageInRect 来获得所需的结果。我的问题是我的 mainImage 和 drawImage 之间的纵横比差异。所以 AVMakeRectWithAspectRatioInsideRect 给了我一个新的矩形,它具有正确的大小比和我的 mainImage 的原点。之后,我使用 CGImageCreateWithImageInRect 将 [drawImage CGImage] 放入新的矩形并 Presto!我的 drawImage 和 mainImage 创建了一个具有完全相同纵横比的新上下文。不再有图像失真或歪斜。工作代码发布在下面。

    - (void) commitDrawingWithOpacity:(CGFloat)opacity {
    
        CGRect drawRect = AVMakeRectWithAspectRatioInsideRect(mainImage.size, self.frame);
    
        UIGraphicsBeginImageContext(mainImage.size);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(ctx, 1.0f, -1.0f);
        CGContextTranslateCTM(ctx, 0.0f, -mainImage.size.height);
    
        CGRect rect = CGRectMake(0.0f, 0.0f, mainImage.size.width, mainImage.size.height);
    
        if (mainImage != nil) {
            CGContextDrawImage(ctx, rect, mainImage.CGImage);
        }
    
        CGImageRef imageRef = CGImageCreateWithImageInRect([drawImage CGImage], drawRect);
    
        CGContextSetAlpha(ctx, opacity);
        CGContextDrawImage(ctx, rect, imageRef);
    
        mainImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        self.layer.contents = (id)mainImage.CGImage;
        drawLayer.contents = nil;
        drawImage = nil;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 2014-10-21
      • 2018-07-22
      • 2011-04-20
      • 2010-10-15
      相关资源
      最近更新 更多