如何在不改变原始纵横比的情况下组合两个不同大小的 UIImage?

Posted

技术标签:

【中文标题】如何在不改变原始纵横比的情况下组合两个不同大小的 UIImage?【英文标题】:How to combine two UIImages of difference size without altering their original aspect ratios? 【发布时间】:2014-01-26 17:05:11 【问题描述】:

我目前组合 UIImages 的方法来自这个answer on SO,以及this 关于调整 UIImage 大小与纵横比的流行问题。我目前的问题如下:

我有一个名为 pictureImage 的 UIImage 是用相机拍摄的,它的标准尺寸为 2448*3264。我还有一个名为self.annotateView 的UIImageView,它有一个320*568 的框架,用户可以在其中绘制和注释图片。当我在UIImageView 中展示pictureImage 时,我将图像展示设置为Aspect Fill,以便它占据整个iPhone 屏幕。当然这意味着pictureImage 的一部分在左右两边都被切断了(实际上两边都是304 像素),但这是故意的。

我的问题是,当我将 UIImages pictureImageannotateView.image 组合到 320*568 的新维度时,我的组合图像通过水平拉伸它改变了 annotateView.image 的原始方面。这很奇怪,因为新维度与 annotateView.image 的原始维度完全相同。

这是结果的样子 -

在组合 UIImages 之前

合并图片后

请注意,底层图片未拉伸。但是,annotateView.image 仅水平拉伸,而不是垂直拉伸。

这是我合并 UIImages 的代码。

//Note: self.firstTakenImage is set to 320*568

CGSize newSize = CGSizeMake(self.firstTakenImage.frame.size.width, self.firstTakenImage.frame.size.height);
UIGraphicsBeginImageContext(newSize);
[self.firstTakenImage.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
[self.drawView.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

【问题讨论】:

is firstTakenImage 是从 cam 中捕获的快照吗?最初有 2048*3264。 【参考方案1】:

在进行 drawInRect 时,您必须重做系统使用 AspectFill 为您所做的缩放和居中,以使其与原始过程相匹配。像这样的:

CGSize fullSize = self.pictureView.image.size;
CGSize newSize = self.outputView.frame.size;
CGFloat scale = newSize.height/fullSize.height;
CGFloat offset = (newSize.width - fullSize.width*scale)/2;
CGRect offsetRect = CGRectMake(offset, 0, newSize.width-offset*2, newSize.height);
NSLog(@"offset = %@",NSStringFromCGRect(offsetRect));

UIGraphicsBeginImageContext(newSize);
[self.pictureView.image drawInRect:offsetRect];
[self.annotateView.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *combImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

self.outputView.image = combImage;

【讨论】:

感谢您提出这个答案。不幸的是,代码的结果是pictureImage 现在按比例拉伸以匹配annotateView.image,而不是annotateView.image 的预期反面按比例缩小以匹配pictureImage。将稍微调整一下这段代码,看看我是否能想出一个解决方案。 嗯,有几个诊断问题:您是否为 outputView 设置了 view.contentMode?您确定 newSize 设置正确吗? 你是对的!我稍后在不同的控制器中对combImage 进行了一些额外的修改,因此拉伸了。谢谢 - 这个解决方案有效:)【参考方案2】: 支持纵向和横向两种类型的图像 在我的情况下可以合并绘图和其他子视图我正在添加标签来绘图
  

    CGSize fullSize = getImageForEdit.size;
    CGSize sizeInView = AVMakeRectWithAspectRatioInsideRect(imgViewFake.image.size, imgViewFake.bounds).size;
    CGFloat orgScale = orgScale = fullSize.width/sizeInView.width;
    CGSize newSize = CGSizeMake(orgScale * img.image.size.width, orgScale * img.image.size.height);
    if(newSize.width <= fullSize.width && newSize.height <= fullSize.height)
        newSize = fullSize;
    
    CGRect offsetRect;
    if (getImageForEdit.size.height > getImageForEdit.size.width)
        CGFloat scale = newSize.height/fullSize.height;
        CGFloat offset = (newSize.width - fullSize.width*scale)/2;
        offsetRect = CGRectMake(offset, 0, newSize.width-offset*2, newSize.height);
    
    else
        CGFloat scale = newSize.width/fullSize.width;
        CGFloat offset = (newSize.height - fullSize.height*scale)/2;
        offsetRect = CGRectMake(0, offset, newSize.width, newSize.height-offset*2);
    
    UIGraphicsBeginImageContextWithOptions(newSize, NO, getImageForEdit.scale);
    [getImageForEdit drawAtPoint:offsetRect.origin];
    //        [img.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    CGFloat oldScale = img.contentScaleFactor;
    img.contentScaleFactor = getImageForEdit.scale;
    [img drawViewHierarchyInRect:CGRectMake(0, 0, newSize.width, newSize.height) afterScreenUpdates:YES];
    img.contentScaleFactor = oldScale;
    UIImage *combImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    imageData = UIImageJPEGRepresentation(combImage, 1);

【讨论】:

对于图像质量,您可以替换 'UIGraphicsBeginImageContext(newSize);'与 UIGraphicsBeginImageContextWithOptions(newSize, NO, getImageForEdit.scale);【参考方案3】:

当您调用[self.drawView.image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; 时,您需要修改框架以解决您所描述的纵横比差异(因为您在两边都切掉了一些图像)。

即修改x位置和width绘制注解图。

修改是基于缩放到相同高度时 2 个矩形之间的差异。你说这是304,所以你可以最初将x设置为304,将width设置为newSize.width - 608进行测试。但真的应该计算差异......

【讨论】:

【参考方案4】:

麦克沃思在夫特答案3.x的强>

    let fullSize:CGSize = img.size
    let newSize:CGSize = fullSize
    let scale:CGFloat = newSize.height/fullSize.height
    let offset:CGFloat = (newSize.width - fullSize.width*scale)/2
    let offsetRect:CGRect = CGRect.init(x: offset, y: 0, width: newSize.width - offset*2, height: newSize.height)
    print(NSStringFromCGRect(offsetRect))     

    UIGraphicsBeginImageContext(newSize);
    self.pictureView.image.draw(in: offsetRect)
    self.annotateView.image.draw(in: CGRect.init(x: 0, y: 0, width: waterMarkImage.size.width, height: waterMarkImage.size.height))
    let combImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext();
    return combImage;

【讨论】:

什么样,如果我们需要合并图像与看法? :***.com/questions/44931810/… 跨度>

以上是关于如何在不改变原始纵横比的情况下组合两个不同大小的 UIImage?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python - 如何在不超过原始图像大小的情况下调整裁剪图像的大小以满足纵横比

Keras - 如何在不改变纵横比的情况下使用 ImageDataGenerator

如何在不破坏图像纵横比的情况下调整 QImage 或 QML 图像的大小以适应父容器

在不保持纵横比的情况下使用 mogrify 调整图像大小

在不丢失纵横比的情况下将图像放入特定大小的盒子中?

如何在调整窗口大小时锁定纵横比?