按照纵横比缩放UIImage?

37

我正在使用这段代码来在iPhone上调整图像大小:

CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0);
UIGraphicsBeginImageContext(screenRect.size);
[value drawInRect:screenRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *tmpValue = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

只要图像的纵横比与新调整大小的图像相匹配,这个方法就可以很好地工作。我想修改它,使其保持正确的纵横比,只在图像不显示的任何地方放置黑色背景。因此,我仍然会得到一个320x480的图像,但是顶部和底部或侧面会有黑色。

是否有一种简单的方法类似于我正在做的事情?谢谢!


这是一篇保持宽高比的文章:https://dev59.com/VWsz5IYBdhLWcg3w0bOl - Leslie Godwin
2个回答

56

在设置屏幕矩形之后,可以执行以下操作来确定图像应该绘制在哪个矩形中:

float hfactor = value.bounds.size.width / screenRect.size.width;
float vfactor = value.bounds.size.height / screenRect.size.height;

float factor = fmax(hfactor, vfactor);

// Divide the size by the greater of the vertical or horizontal shrinkage factor
float newWidth = value.bounds.size.width / factor;
float newHeight = value.bounds.size.height / factor;

// Then figure out if you need to offset it to center vertically or horizontally
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;

CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);

如果您不想放大小于屏幕矩形的图像,请确保factor大于或等于1(例如,factor = fmax(factor, 1))。

要获得黑色背景,您可能只需将上下文颜色设置为黑色并在绘制图像之前调用fillRect。


"value" 是 Cory 用来存储源图像的变量。 - Frank Schmitt
@Frank Schmitt,我可以查询一下如何针对这种情况将上下文设置为黑色吗? - Zhen
编译器抛出“隐式声明函数'max'”的错误,尽管我记得包含了math.h库(我使用的是XCode 4.0)。将代码中的float factor = max( … 改为 float factor = MAX( …(全大写)解决了这个问题。顺便说一下,我需要重新调整UIImage(而不是UIImageView)的大小,是因为我在一个默认样式的UITableCell中设置了图像。这帮助我避免了实现自定义的UITableCell。非常感谢Frank提供的绝佳解决方案! - cleverbit
2
刚刚进行了编辑,使用了fmax函数,这个函数已经包含在苹果预编译头文件中。与MAX()的区别在于,它将所有内容都视为整数,而Core Graphics原生地使用CGFloat(双精度浮点数)来表示所有坐标值。因此,在Retina屏幕上,您的方法可能会偏移半个点 :) - Frank Schmitt
1
@iOS_Ramesh,“value”是您要调整大小的“UIImage”。 - Frank Schmitt
显示剩余2条评论

0

我知道这篇文章很老了,但还是感谢你的帖子——它让我不再尝试使用比例来绘制图像。如果有人需要,我在这里分享一个扩展类。它可以让你像这样调整图像大小:

      UIImage imgNew = img.Fit(40.0f, 40.0f);

我不需要适合的选项,但很容易扩展以支持填充。

using CoreGraphics;
using System;
using UIKit;

namespace SomeApp.iOS.Extensions
{
  public static class UIImageExtensions
  {
    public static CGSize Fit(this CGSize sizeImage,
      CGSize sizeTarget)
    {
      CGSize ret;
      float fw;
      float fh;
      float f;

      fw = (float) (sizeTarget.Width / sizeImage.Width);
      fh = (float) (sizeTarget.Height / sizeImage.Height);
      f = Math.Min(fw, fh);
      ret = new CGSize
      {
        Width = sizeImage.Width * f,
        Height = sizeImage.Height * f
      };
      return ret;
    }

    public static UIImage Fit(this UIImage image,
      float width,
      float height,
      bool opaque = false,
      float scale = 1.0f)
    {
      UIImage ret;

      ret = image.Fit(new CGSize(width, height),
        opaque,
        scale);
      return ret;
    }

    public static UIImage Fit(this UIImage image,
      CGSize sizeTarget,
      bool opaque = false,
      float scale = 1.0f)
    {
      CGSize sizeNewImage;
      CGSize size;
      UIImage ret;

      size = image.Size;
      sizeNewImage = size.Fit(sizeTarget);
      UIGraphics.BeginImageContextWithOptions(sizeNewImage,
        opaque,
        1.0f);
      using (CGContext context = UIGraphics.GetCurrentContext())
      {
        context.ScaleCTM(1, -1);
        context.TranslateCTM(0, -sizeNewImage.Height);
        context.DrawImage(new CGRect(CGPoint.Empty, sizeNewImage),
          image.CGImage);
        ret = UIGraphics.GetImageFromCurrentImageContext();
      }
      UIGraphics.EndImageContext();
      return ret;
    }
  }
}

根据上面的帖子,它为一张新图片创建了一个新的上下文,然后找出了图片的比例,最后将内容绘制到图片上。如果你还没有接触过Swift的Xcode开发,UIGraphics可能与我之前用过的其他系统有些不同,但也不算糟糕。其中一个问题是默认情况下位图是从底部向顶部绘制的。为了解决这个问题,可以采取以下方法:
        context.ScaleCTM(1, -1);
        context.TranslateCTM(0, -sizeNewImage.Height);

将绘图方向更改为常见的从左上到右下...但是您还需要移动原点,因此需要使用TranslateCTM。

希望这能为某人节省一些时间。

干杯


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接