【问题标题】:The simplest way to resize an UIImage?调整 UIImage 大小的最简单方法?
【发布时间】:2011-02-09 03:59:32
【问题描述】:

在我的 iPhone 应用程序中,我用相机拍照,然后我想将其调整为 290*390 像素。我正在使用这种方法来调整图像的大小:

UIImage *newImage = [image _imageScaledToSize:CGSizeMake(290, 390)
                         interpolationQuality:1];    

它工作得很好,但它是一个未记录的功能,所以我不能再在 iPhone OS4 上使用它。

那么...调整 UIImage 大小的最简单方法是什么?

【问题讨论】:

标签: ios uiimage resize


【解决方案1】:

最简单的方法是设置UIImageView 的框架并将contentMode 设置为调整大小选项之一。

如果您确实需要调整图像大小,也可以使用此实用方法:

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    //UIGraphicsBeginImageContext(newSize);
    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
    // Pass 1.0 to force exact pixel size.
    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

示例用法:

#import "MYUtil.h"
…
UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];

【讨论】:

  • 我不会在这里保留结果。 newImage 将被自动释放,它应该取决于调用它的方法来保留它。这种方法只是在乞求内存错误,因为init 不是方法名称的一部分。我希望像这样命名的方法返回一个自动释放的对象。
  • 有效点,已编辑。我只是提醒一下,我的代码使用它会在其他地方产生 malloc 错误而没有额外的保留,这显然是我的错:-)。
  • As of iOS 4.0,UIGraphics* 函数都是线程安全的。
  • @Paul Lynch:请记住,此更改破坏了原始帖子的使命:如何将图像调整为某个精确的 pixel 大小(而不是 point 大小)。
  • 对于那些因@NikolaiRuhe 指出的限制而苦苦挣扎的人,您可以通过在对UIGraphicsBeginImageContextWithOptions 的调用中传递 1.0 而不是 0.0 来将其强制为精确的像素大小
【解决方案2】:

iOS 10+ 的正确 Swift 3.0 解决方案:使用 ImageRenderer 和闭包语法:

func imageWith(newSize: CGSize) -> UIImage {
    let image = UIGraphicsImageRenderer(size: newSize).image { _ in
        draw(in: CGRect(origin: .zero, size: newSize))
    }
        
    return image.withRenderingMode(renderingMode)
}

这是 Objective-C 版本:

@implementation UIImage (ResizeCategory)
- (UIImage *)imageWithSize:(CGSize)newSize
{
    UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newSize];
    UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext*_Nonnull myContext) {
        [self drawInRect:(CGRect) {.origin = CGPointZero, .size = newSize}];
    }];
    return [image imageWithRenderingMode:self.renderingMode];
}
@end

【讨论】:

  • 非常优雅的解决方案,这应该是公认的答案!
  • 这比优雅好,没错。 Apple 的 api 文档建议新代码像此代码一样使用 UIGraphicsRenderer。谢谢
  • @appsunited 这个问题已经快 8 年了。而且这种方法只适用于 iOS10+ 如上所述。
  • 将新图像对象复制到剪贴板时,它会为我生成一个白色块。它实际上并没有调整图像视图的大小?
  • 这个函数返回一个0高0宽的图像,期望高度是9000高9000宽。
【解决方案3】:

这是Paul Lynch's answer 的 Swift 版本

func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

作为扩展:

public extension UIImage {
    func copy(newSize: CGSize, retina: Bool = true) -> UIImage? {
        // In next line, pass 0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
        // Pass 1 to force exact pixel size.
        UIGraphicsBeginImageContextWithOptions(
            /* size: */ newSize,
            /* opaque: */ false,
            /* scale: */ retina ? 0 : 1
        )
        defer { UIGraphicsEndImageContext() }

        self.draw(in: CGRect(origin: .zero, size: newSize))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

【讨论】:

  • 刚刚注意到,在 iOS 中,您的 newSize 将根据设备增加 2 倍、3 倍
  • UIGraphicsBeginImageContextWithOptions(newSize, false, image.scale);适用于所有设备
  • 请注意,这不会调整底层 CGImage 的大小(至少在 iOS 12.1 中)。根据问题可以,但是如果您要写出图像,则必须使用 cgImage,并且您将获得原始图像。
  • 仅针对 scaleToFill 进行缩放
【解决方案4】:

更紧凑的 Swift 4 和 iOS 10+ 版本:

extension UIImage {
    func resized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

用法:

let resizedImage = image.resized(to: CGSize(width: 50, height: 50))

【讨论】:

    【解决方案5】:

    Trevor Howard 有一些 UIImage categories 可以很好地处理调整大小。如果不出意外,您可以使用代码作为示例。

    注意:从 iOS 5.1 开始,此答案可能无效。请参阅下面的评论。

    【讨论】:

    • 我也需要调整一些图像的大小,我首先尝试了 Trevor 对 UIImage 的添加,但在 PNG 上遇到了一些奇怪的错误(关于 alpha 通道的问题)。不过,这个问题的公认答案效果很好。
    • 这不再有效(至少对于 iOS5.1
    • @Jann,看看帖子下面的提交。
    • @Jann 如果您遵循 cmets 中建议的修复,请使用“Matt 说:2011 年 11 月 22 日下午 5:39”,因为他释放了 colorspaceref(与 horseshoe7 的类似解决方案不同)。
    • @sanmai 使用这些调整大小方法中的任何一种都会使图像失去清晰度。有什么办法可以达到锐度
    【解决方案6】:

    我也看到了这一点(我在UIButtons 上使用正常和选定状态,因为按钮不适合resize)。归功于原作者。

    首先创建一个名为UIImageResizing.hUIImageResizing.m的空.h和.m文件

    // Put this in UIImageResizing.h
    @interface UIImage (Resize)
    - (UIImage*)scaleToSize:(CGSize)size;
    @end
    
    // Put this in UIImageResizing.m
    @implementation UIImage (Resize)
    
    - (UIImage*)scaleToSize:(CGSize)size {
    UIGraphicsBeginImageContext(size);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0, size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
    
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return scaledImage;
    }
    
    @end
    

    将该 .h 文件包含在您要使用该函数的任何 .m 文件中,然后像这样调用它:

    UIImage* image = [UIImage imageNamed:@"largeImage.png"];
    UIImage* smallImage = [image scaleToSize:CGSizeMake(100.0f,100.0f)];
    

    【讨论】:

    • 这不会复制图像方向。
    【解决方案7】:

    用于 Stretch Fill、Aspect Fill 和 Aspect Fit 的快速解决方案

    extension UIImage {
        enum ContentMode {
            case contentFill
            case contentAspectFill
            case contentAspectFit
        }
        
        func resize(withSize size: CGSize, contentMode: ContentMode = .contentAspectFill) -> UIImage? {
            let aspectWidth = size.width / self.size.width
            let aspectHeight = size.height / self.size.height
            
            switch contentMode {
            case .contentFill:
                return resize(withSize: size)
            case .contentAspectFit:
                let aspectRatio = min(aspectWidth, aspectHeight)
                return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
            case .contentAspectFill:
                let aspectRatio = max(aspectWidth, aspectHeight)
                return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
            }
        }
        
        private func resize(withSize size: CGSize) -> UIImage? {
            UIGraphicsBeginImageContextWithOptions(size, false, self.scale)
            defer { UIGraphicsEndImageContext() }
            draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
    

    要使用,您可以执行以下操作:

    let image = UIImage(named: "image.png")!
    let newImage = image.resize(withSize: CGSize(width: 200, height: 150), contentMode: .contentAspectFill)
    

    感谢 abdullahselek 的原始解决方案。

    【讨论】:

      【解决方案8】:

      对 Paul 代码的这项改进将在配备 Retina 显示屏的 iPhone 上为您提供清晰的高分辨率图像。否则缩小时会很模糊。

      + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
      if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
          if ([[UIScreen mainScreen] scale] == 2.0) {
              UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);
          } else {
              UIGraphicsBeginImageContext(newSize);
          }
      } else {
          UIGraphicsBeginImageContext(newSize);
      }
      [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
      UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
      UIGraphicsEndImageContext();
      return newImage;
      }
      

      【讨论】:

      • 仅供参考,您所做的更改是不必要的,因为在 UIGraphicsBeginImageContextWithOptions 中为比例提供 0.0 值将自动使用主屏幕的比例(从 iOS 3.2 开始)。
      【解决方案9】:

      这是一个简单的方法:

          UIImage * image = [UIImage imageNamed:@"image"];
          CGSize sacleSize = CGSizeMake(10, 10);
          UIGraphicsBeginImageContextWithOptions(sacleSize, NO, 0.0);
          [image drawInRect:CGRectMake(0, 0, sacleSize.width, sacleSize.height)];
          UIImage * resizedImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      

      resizedImage 是一张新图片。

      【讨论】:

        【解决方案10】:

        这里是上面 iWasRobbed 写的类别的修改。它保持原始图像的纵横比而不是扭曲它。

        - (UIImage*)scaleToSizeKeepAspect:(CGSize)size {
            UIGraphicsBeginImageContext(size);
        
            CGFloat ws = size.width/self.size.width;
            CGFloat hs = size.height/self.size.height;
        
            if (ws > hs) {
                ws = hs/ws;
                hs = 1.0;
            } else {
                hs = ws/hs;
                ws = 1.0;
            }
        
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextTranslateCTM(context, 0.0, size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
        
            CGContextDrawImage(context, CGRectMake(size.width/2-(size.width*ws)/2,
                size.height/2-(size.height*hs)/2, size.width*ws,
                size.height*hs), self.CGImage);
        
            UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
        
            UIGraphicsEndImageContext();
        
            return scaledImage;
        }
        

        【讨论】:

          【解决方案11】:

          如果你只是想要一个更小的图像并且不关心确切的大小:

          + (UIImage *)imageWithImage:(UIImage *)image scaledToScale:(CGFloat)scale
          {
              UIGraphicsBeginImageContextWithOptions(self.size, YES, scale);
              CGContextRef context = UIGraphicsGetCurrentContext();
              CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
              [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
              UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
              UIGraphicsEndImageContext();
              return newImage;
          }
          

          将比例设置为 0.25f 将为您提供来自 8MP 相机的 816 x 612 图像。

          这里是a category UIImage+Scale,供需要的人使用。

          【讨论】:

            【解决方案12】:

            为什么这么复杂?我认为使用系统 API 可以达到同样的效果:

            UIImage *largeImage;
            CGFloat ratio = 0.4; // you want to get a new image that is 40% the size of large image.
            UIImage *newImage = [UIImage imageWithCGImage:largeImage.CGImage
                                                    scale:1/ratio
                                              orientation:largeImage.imageOrientation];
            // notice the second argument, it is 1/ratio, not ratio.
            

            唯一的问题是您应该将目标比率的倒数作为第二个参数传递,因为根据文档,第二个参数指定原始图像与新缩放图像的比率。

            【讨论】:

            • 因为比例(%)和像素(w/h)不是一回事。
            • 比例应该是 largeImage.scale/ratio 而不是 1/ratio。
            • 你拯救了我的一天。
            【解决方案13】:

            这是一个与 Swift 3Swift 4 兼容的 UIImage 扩展,可将图像缩放到具有宽高比的给定尺寸

            extension UIImage {
            
                func scaledImage(withSize size: CGSize) -> UIImage {
                    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
                    defer { UIGraphicsEndImageContext() }
                    draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
                    return UIGraphicsGetImageFromCurrentImageContext()!
                }
            
                func scaleImageToFitSize(size: CGSize) -> UIImage {
                    let aspect = self.size.width / self.size.height
                    if size.width / aspect <= size.height {
                        return scaledImage(withSize: CGSize(width: size.width, height: size.width / aspect))
                    } else {
                        return scaledImage(withSize: CGSize(width: size.height * aspect, height: size.height))
                    }
                }
            
            }
            

            示例用法

            let image = UIImage(named: "apple")
            let scaledImage = image.scaleImageToFitSize(size: CGSize(width: 45.0, height: 45.0))
            

            【讨论】:

            • 我建议将函数命名为 scaledImage(with size:)scaledWithSize(_:)。同样UIGraphicsGetImageFromCurrentImageContext 不能真正返回nil,因此! 也可以。您还可以将矩形创建简化为CGRect(origin: .zero, size: size)
            【解决方案14】:

            对于 Swift 5:

            extension UIImage {
              func resized(to newSize: CGSize) -> UIImage? {
                UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
                defer { UIGraphicsEndImageContext() }
            
                draw(in: CGRect(origin: .zero, size: newSize))
                return UIGraphicsGetImageFromCurrentImageContext()
              }
            }
            

            【讨论】:

              【解决方案15】:

              我在 Apple 自己的示例中找到了一个 UIImage 类别,该类别具有相同的作用。这是链接:https://developer.apple.com/library/ios/samplecode/sc2273/Listings/AirDropSample_UIImage_Resize_m.html

              您只需要更改呼叫:

              UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);
              

              imageWithImage:scaledToSize:inRect: 中:

              UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0);
              

              为了考虑图片中的alpha通道。

              【讨论】:

                【解决方案16】:
                 func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage 
                {
                        let scale = newWidth / image.size.width
                        let newHeight = image.size.height * scale
                        UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
                        image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
                        let newImage = UIGraphicsGetImageFromCurrentImageContext()
                        UIGraphicsEndImageContext()
                        return newImage
                }
                

                【讨论】:

                • 在您的代码中添加一些描述性文本是个好主意。
                【解决方案17】:

                对于我的 Xamarian 同胞,这里是 @Paul Lynch 答案的 Xamarin.iOS C# 版本。

                private UIImage ResizeImage(UIImage image, CGSize newSize) 
                {
                    UIGraphics.BeginImageContextWithOptions(newSize, false, 0.0f);
                    image.Draw(new CGRect(0, 0, newSize.Width, newSize.Height));
                    UIImage newImage = UIGraphics.GetImageFromCurrentImageContext();
                    UIGraphics.EndImageContext();
                    return newImage;
                }
                

                【讨论】:

                  【解决方案18】:

                  如果您想制作 UIImage 的缩略图(按比例调整大小或可能涉及一些裁剪),请查看UIImage+Resize 类别,该类别允许您使用简洁、类似 ImageMagick 的语法:

                  UIImage* squareImage       = [image resizedImageByMagick: @"320x320#"];
                  

                  【讨论】:

                    【解决方案19】:

                    [cf Chris] 将 调整为 所需的大小:

                    UIImage *after = [UIImage imageWithCGImage:before.CGImage
                                                         scale:CGImageGetHeight(before.CGImage)/DESIREDHEIGHT
                                                   orientation:UIImageOrientationUp];
                    

                    或者,等效地,替换CGImageGetWidth(...)/DESIREDWIDTH

                    【讨论】:

                    • 请注意,图像数据本身并没有调整大小,而是应用了比例因子,这意味着图像在内存中的大小相同。
                    【解决方案20】:

                    Rogerio Chaves 快速扩展回答

                    func scaledTo(size: CGSize) -> UIImage{
                        UIGraphicsBeginImageContextWithOptions(size, false, 0.0);
                        self.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
                        let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
                        UIGraphicsEndImageContext()
                        return newImage
                    }
                    

                    还有奖金

                    func scaledTo(height: CGFloat) -> UIImage{
                        let width = height*self.size.width/self.size.height
                        return scaledTo(size: CGSize(width: width, height: height))
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      带有故障保护选项的 Swift 3.0(在出现错误时返回原始图像):

                      func resize(image: UIImage, toSize size: CGSize) -> UIImage{
                          UIGraphicsBeginImageContextWithOptions(size,false,1.0)
                          image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
                          if let resizedImage = UIGraphicsGetImageFromCurrentImageContext() {
                              UIGraphicsEndImageContext()
                              return resizedImage
                          }
                          UIGraphicsEndImageContext()
                          return image
                      }
                      

                      【讨论】:

                        【解决方案22】:

                        (兼容 Swift 4)iOS 10+ 和 iOS UIGraphicsImageRenderer,否则使用UIGraphicsGetImageFromCurrentImageContext

                        /// Resizes an image
                        ///
                        /// - Parameter newSize: New size
                        /// - Returns: Resized image
                        func scaled(to newSize: CGSize) -> UIImage {
                            let rect = CGRect(origin: .zero, size: newSize)
                        
                            if #available(iOS 10, *) {
                                let renderer = UIGraphicsImageRenderer(size: newSize)
                                return renderer.image { _ in
                                    self.draw(in: rect)
                                }
                            } else {
                                UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
                                self.draw(in: rect)
                                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                                UIGraphicsEndImageContext()
                                return newImage!
                            }
                        }
                        

                        【讨论】:

                          【解决方案23】:

                          不拉伸图像的有效方法 Swift 4

                          // Method to resize image
                          func resize(image: UIImage, toScaleSize:CGSize) -> UIImage {
                                          UIGraphicsBeginImageContextWithOptions(toScaleSize, true, image.scale)
                                                  image.draw(in: CGRect(x: 0, y: 0, width: toScaleSize.width, height: toScaleSize.height))
                                                  let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
                                                  UIGraphicsEndImageContext()
                                                  return scaledImage!
                                          }
                          

                          //调用方法

                              let resizedImage = self.resize(image: UIImage(named: "YourImageName")!, toScaleSize: CGSize(width: 290, height: 390))
                          

                          【讨论】:

                            【解决方案24】:

                            @Paul Lynch 的回答很棒,但它会改变图像比例。 如果您不想更改图像比例,但仍希望新图像适合新尺寸,请尝试此操作。

                            + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
                            
                            // calculate a new size which ratio is same to original image
                            CGFloat ratioW = image.size.width / newSize.width;
                            CGFloat ratioH = image.size.height / newSize.height;
                            
                            CGFloat ratio = image.size.width / image.size.height;
                            
                            CGSize showSize = CGSizeZero;
                            if (ratioW > 1 && ratioH > 1) { 
                            
                                if (ratioW > ratioH) { 
                                    showSize.width = newSize.width;
                                    showSize.height = showSize.width / ratio;
                                } else {
                                    showSize.height = newSize.height;
                                    showSize.width = showSize.height * ratio;
                                }
                            
                            } else if (ratioW > 1) {
                            
                                showSize.width = showSize.width;
                                showSize.height = showSize.width / ratio;
                            
                            } else if (ratioH > 1) {
                            
                                showSize.height = showSize.height;
                                showSize.width = showSize.height * ratio;
                            
                            }
                            
                            //UIGraphicsBeginImageContext(newSize);
                            // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
                            // Pass 1.0 to force exact pixel size.
                            UIGraphicsBeginImageContextWithOptions(showSize, NO, 0.0);
                            [image drawInRect:CGRectMake(0, 0, showSize.width, showSize.height)];
                            UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
                            UIGraphicsEndImageContext();
                            return newImage;}
                            

                            【讨论】:

                              【解决方案25】:

                              使用这个扩展

                              extension UIImage {
                                  public func resize(size:CGSize, completionHandler:(resizedImage:UIImage, data:NSData?)->()) {
                                      dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { () -> Void in
                                          let newSize:CGSize = size
                                          let rect = CGRectMake(0, 0, newSize.width, newSize.height)
                                          UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
                                          self.drawInRect(rect)
                                          let newImage = UIGraphicsGetImageFromCurrentImageContext()
                                          UIGraphicsEndImageContext()
                                          let imageData = UIImageJPEGRepresentation(newImage, 0.5)
                                          dispatch_async(dispatch_get_main_queue(), { () -> Void in
                                              completionHandler(resizedImage: newImage, data:imageData)
                                          })
                                      })
                                  }
                              }
                              

                              【讨论】:

                                【解决方案26】:

                                另一种调整 UIImage 大小的方法:

                                // Resize to height = 100 points.
                                let originalImage = UIImage(named: "MyOriginalImage")!
                                let resizingFactor = 100 / originalImage.size.height
                                let newImage = UIImage(cgImage: originalImage.cgImage!, scale: originalImage.scale / resizingFactor, orientation: .up)
                                

                                【讨论】:

                                  【解决方案27】:

                                  Swift 2.0:

                                  let image = UIImage(named: "imageName")
                                  let newSize = CGSize(width: 10, height: 10)
                                  
                                  UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
                                  image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
                                  let imageResized = UIGraphicsGetImageFromCurrentImageContext()
                                  UIGraphicsEndImageContext()
                                  

                                  【讨论】:

                                    【解决方案28】:

                                    这是我有点冗长的 Swift 代码

                                    func scaleImage(image:UIImage,  toSize:CGSize) -> UIImage {
                                        UIGraphicsBeginImageContextWithOptions(toSize, false, 0.0);
                                    
                                        let aspectRatioAwareSize = self.aspectRatioAwareSize(image.size, boxSize: toSize, useLetterBox: false)
                                    
                                    
                                        let leftMargin = (toSize.width - aspectRatioAwareSize.width) * 0.5
                                        let topMargin = (toSize.height - aspectRatioAwareSize.height) * 0.5
                                    
                                    
                                        image.drawInRect(CGRectMake(leftMargin, topMargin, aspectRatioAwareSize.width , aspectRatioAwareSize.height))
                                        let retVal = UIGraphicsGetImageFromCurrentImageContext()
                                        UIGraphicsEndImageContext()
                                        return retVal
                                    }
                                    
                                    func aspectRatioAwareSize(imageSize: CGSize, boxSize: CGSize, useLetterBox: Bool) -> CGSize {
                                        // aspect ratio aware size
                                        // http://stackoverflow.com/a/6565988/8047
                                        let imageWidth = imageSize.width
                                        let imageHeight = imageSize.height
                                        let containerWidth = boxSize.width
                                        let containerHeight = boxSize.height
                                    
                                        let imageAspectRatio = imageWidth/imageHeight
                                        let containerAspectRatio = containerWidth/containerHeight
                                    
                                        let retVal : CGSize
                                        // use the else at your own risk: it seems to work, but I don't know 
                                        // the math
                                        if (useLetterBox) {
                                            retVal = containerAspectRatio > imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
                                        } else {
                                            retVal = containerAspectRatio < imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
                                        }
                                    
                                        return retVal
                                    }
                                    

                                    【讨论】:

                                    • 这节省了我的时间。谢谢!
                                    • 有用,但在 segue 和回来活动后表现得很奇怪,请看这里:stackoverflow.com/questions/30978685/…
                                    • 请注意:您可能希望在aspectRatioAwareSize 函数中添加一个前置条件 (guard),这样当 imageSize 或 boxSize 的输入参数时它不会抛出除以零异常是CGSize.zero
                                    • @pkluz 这是一个很好的建议,但我认为你在整个函数中都需要它们,因为每个变量都是另一行的除数......我将把它保留为是为了清楚。对于 github 的生产或库,您可能想要加强这一点......不仅仅是警卫,我担心该函数使用的短变量名称不会说太多。我可能会先解决这个问题,然后为其他事情添加保护,然后添加单元测试。
                                    【解决方案29】:

                                    Swift 4 答案:

                                    func scaleDown(image: UIImage, withSize: CGSize) -> UIImage {
                                        let scale = UIScreen.main.scale
                                        UIGraphicsBeginImageContextWithOptions(withSize, false, scale)
                                        image.draw(in: CGRect(x: 0, y: 0, width: withSize.width, height: withSize.height))
                                        let newImage = UIGraphicsGetImageFromCurrentImageContext()
                                        UIGraphicsEndImageContext()
                                        return newImage!
                                    }
                                    

                                    【讨论】:

                                    • 无需设置真实比例:The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
                                    【解决方案30】:

                                    我发现很难找到可以在 Swift 3 项目中直接使用的答案。其他答案的主要问题是他们不尊重图像的 alpha 通道。这是我在项目中使用的技术。

                                    extension UIImage {
                                    
                                        func scaledToFit(toSize newSize: CGSize) -> UIImage {
                                            if (size.width < newSize.width && size.height < newSize.height) {
                                                return copy() as! UIImage
                                            }
                                    
                                            let widthScale = newSize.width / size.width
                                            let heightScale = newSize.height / size.height
                                    
                                            let scaleFactor = widthScale < heightScale ? widthScale : heightScale
                                            let scaledSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)
                                    
                                            return self.scaled(toSize: scaledSize, in: CGRect(x: 0.0, y: 0.0, width: scaledSize.width, height: scaledSize.height))
                                        }
                                    
                                        func scaled(toSize newSize: CGSize, in rect: CGRect) -> UIImage {
                                            if UIScreen.main.scale == 2.0 {
                                                UIGraphicsBeginImageContextWithOptions(newSize, !hasAlphaChannel, 2.0)
                                            }
                                            else {
                                                UIGraphicsBeginImageContext(newSize)
                                            }
                                    
                                            draw(in: rect)
                                            let newImage = UIGraphicsGetImageFromCurrentImageContext()
                                            UIGraphicsEndImageContext()
                                    
                                            return newImage ?? UIImage()
                                        }
                                    
                                        var hasAlphaChannel: Bool {
                                            guard let alpha = cgImage?.alphaInfo else {
                                                return false
                                            }
                                            return alpha == CGImageAlphaInfo.first ||
                                                alpha == CGImageAlphaInfo.last ||
                                                alpha == CGImageAlphaInfo.premultipliedFirst ||
                                                alpha == CGImageAlphaInfo.premultipliedLast
                                        }
                                    }
                                    

                                    使用示例:

                                    override func viewDidLoad() {
                                        super.viewDidLoad()
                                    
                                        let size = CGSize(width: 14.0, height: 14.0)
                                        if let image = UIImage(named: "barbell")?.scaledToFit(toSize: size) {
                                            let imageView = UIImageView(image: image)
                                            imageView.center = CGPoint(x: 100, y: 100)
                                            view.addSubview(imageView)
                                        }
                                    }
                                    

                                    此代码是对 Apple's extension 的重写,增加了对带和不带 alpha 通道的图像的支持。

                                    作为进一步阅读,我建议检查this article 以了解不同的图像大小调整技术。当前的方法提供了不错的性能,它操作高级 API 并且易于理解。我建议坚持使用它,除非您发现调整图像大小是性能的瓶颈。

                                    【讨论】:

                                      猜你喜欢
                                      • 2013-03-04
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2012-02-04
                                      • 1970-01-01
                                      • 2015-11-20
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多