【问题标题】:How to easily resize/optimize an image size with iOS?如何使用 iOS 轻松调整/优化图像大小?
【发布时间】:2010-10-11 08:37:56
【问题描述】:

我的应用程序正在从网络下载一组图像文件,并将它们保存到本地 iPhone 磁盘。其中一些图像的尺寸相当大(例如,宽度大于 500 像素)。由于 iPhone 甚至没有足够大的显示屏来显示原始尺寸的图像,因此我计划将图像调整为更小的尺寸以节省空间/性能。

此外,其中一些图像是 JPEG,它们没有保存为通常的 60% 质量设置。

如何使用 iPhone SDK 调整图片大小,如何更改 JPEG 图像的质量设置?

【问题讨论】:

    标签: ios objective-c image cocoa-touch resize


    【解决方案1】:

    我们提供了一些建议作为对this question 的回答。我曾建议使用this post 中描述的技术,并附上相关代码:

    + (UIImage*)imageWithImage:(UIImage*)image 
                   scaledToSize:(CGSize)newSize;
    {
       UIGraphicsBeginImageContext( newSize );
       [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
       UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
       UIGraphicsEndImageContext();
    
       return newImage;
    }
    

    就图像的存储而言,iPhone 使用最快的图像格式是 PNG,因为它对该格式进行了优化。但是,如果您想将这些图像存储为 JPEG,您可以使用 UIImage 并执行以下操作:

    NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);
    

    这将创建一个 NSData 实例,其中包含 60% 质量设置的 JPEG 图像的原始字节。然后可以将该 NSData 实例的内容写入磁盘或缓存在内存中。

    【讨论】:

    • 先生...我写了相同的逻辑,但右侧会出现一条白色直线(肖像)请给我解决方案
    • 嗨,我们如何处理在调整大小时保持纵横比和剪辑绑定的问题?在我的情况下,当我调整具有不同比例的图像然后“newsize”时,我得到一个变形的调整大小的图像。谢谢!
    • 这在过去是有效的,但在 iOS5.0.1 及更高版本中,这会导致内存泄漏。还有其他方法可以做到这一点吗?
    • 推荐使用 [image drawInRect:rect blendMode:kCGBlendModeCopy alpha:1.0] 以提高性能(因此在绘制过程中绘制不必进行混合计算
    • 你应该使用 UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);其中 0.0 将使用主屏幕比例来支持视网膜及以上。 Apple 声明“您通常应该避免调用类似名称的 UIGraphicsBeginImageContext 函数(作为向后兼容的后备除外)”。
    【解决方案2】:

    调整图像大小的最简单、最直接的方法就是这样

    float actualHeight = image.size.height;
    float actualWidth = image.size.width;
    float imgRatio = actualWidth/actualHeight;
    float maxRatio = 320.0/480.0;
    
    if(imgRatio!=maxRatio){
        if(imgRatio < maxRatio){
            imgRatio = 480.0 / actualHeight;
            actualWidth = imgRatio * actualWidth;
            actualHeight = 480.0;
        }
        else{
            imgRatio = 320.0 / actualWidth;
            actualHeight = imgRatio * actualHeight;
            actualWidth = 320.0;
        }
    }
    CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
    UIGraphicsBeginImageContext(rect.size);
    [image drawInRect:rect];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    【讨论】:

    • 这很漂亮。我能够将发送到服务器的图像从大约 1Mb 缩减到 100k,同时仍然保持视网膜显示分辨率(尽管我将 320.0 和 480.0 值更改为 640.0 和 1136.0),并且在缩放后还进行了一些 JPEG 压缩: UIImageJPEGRepresentation(img, 0.7f);
    • 如果图像比例和最大比例相等怎么办?例如,如果 iamge 大小为 3200x4800 ?
    • 这在过去是有效的,但在 iOS5.0.1 及更高版本中,这会导致内存泄漏。还有其他方法可以做到这一点吗?
    【解决方案3】:

    上述方法适用于小图像,但是当您尝试调整非常大的图像时,您将很快耗尽内存并导致应用程序崩溃。一个更好的方法是使用CGImageSourceCreateThumbnailAtIndex 来调整图像大小,而无需先完全解码。

    如果你有想要调整大小的图片的路径,你可以使用这个:

    - (void)resizeImageAtPath:(NSString *)imagePath {
        // Create the image source (from path)
        CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);
    
        // To create image source from UIImage, use this
        // NSData* pngData =  UIImagePNGRepresentation(image);
        // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);
    
        // Create thumbnail options
        CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                (id) kCGImageSourceThumbnailMaxPixelSize : @(640)
        };
        // Generate the thumbnail
        CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
        CFRelease(src);
        // Write the thumbnail at path
        CGImageWriteToFile(thumbnail, imagePath);
    }
    

    更多详情here.

    【讨论】:

    • 谢谢,这个解决方案很有效),除了图片和pdf,你知道CGImageSource支持的其他文件格式吗?
    • 谢谢。我正在寻找 Android 解码器使用的 inSampleSize 的模拟。这是唯一提供一种以内存有效方式缩小图像的方法的答案。
    • 我直接使用存储中的文件获得了很好的结果,也可以使用内存中的图像,但速度不快(将大图像加载到 UIImage 然后缩放)。
    • 在共享扩展中不起作用。应用程序仍然因图像过大而崩溃。
    【解决方案4】:

    在不丢失纵横比的情况下缩放图像(即不拉伸图像)的最佳方法是使用此方法:

    //to scale images without changing aspect ratio
    + (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {
    
        float width = newSize.width;
        float height = newSize.height;
    
        UIGraphicsBeginImageContext(newSize);
        CGRect rect = CGRectMake(0, 0, width, height);
    
        float widthRatio = image.size.width / width;
        float heightRatio = image.size.height / height;
        float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;
    
        width = image.size.width / divisor;
        height = image.size.height / divisor;
    
        rect.size.width  = width;
        rect.size.height = height;
    
        //indent in case of width or height difference
        float offset = (width - height) / 2;
        if (offset > 0) {
            rect.origin.y = offset;
        }
        else {
            rect.origin.x = -offset;
        }
    
        [image drawInRect: rect];
    
        UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return smallImage;
    
    }
    

    将此方法添加到您的 Utility 类中,以便您可以在整个项目中使用它,并像这样访问它:

    xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];
    

    此方法在保持纵横比的同时进行缩放。 如果按比例缩小的图像的宽度大于高度(反之亦然),它还会为图像添加缩进。

    【讨论】:

      【解决方案5】:

      如果您可以控制服务器,我强烈建议您使用ImageMagik 调整图像服务器端的大小。在手机上下载大图像并调整它们的大小会浪费许多宝贵的资源——带宽、电池和内存。所有这些在手机上都是稀缺的。

      【讨论】:

      • FTFQ:“我的应用程序正在从网络下载一组图像文件,”
      • 这可能是一个相关的答案。问题表明图像是从网络下载的。如果 OP 可以与图像服务器端一起工作,他应该。如果他不能,回答会更有帮助。
      【解决方案6】:

      我为 Swift 中的图像缩放开发了一个终极解决方案。

      您可以使用它来调整图像的大小以填充、方面填充或方面适合指定的大小。

      您可以将图像对齐到中心或四个边缘和四个角中的任何一个。

      如果原始图像和目标大小的纵横比不相等,您还可以修剪额外的空间。

      enum UIImageAlignment {
          case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
      }
      
      enum UIImageScaleMode {
          case Fill,
          AspectFill,
          AspectFit(UIImageAlignment)
      }
      
      extension UIImage {
          func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
              let preWidthScale = width.map { $0 / size.width }
              let preHeightScale = height.map { $0 / size.height }
              var widthScale = preWidthScale ?? preHeightScale ?? 1
              var heightScale = preHeightScale ?? widthScale
              switch scaleMode {
              case .AspectFit(_):
                  let scale = min(widthScale, heightScale)
                  widthScale = scale
                  heightScale = scale
              case .AspectFill:
                  let scale = max(widthScale, heightScale)
                  widthScale = scale
                  heightScale = scale
              default:
                  break
              }
              let newWidth = size.width * widthScale
              let newHeight = size.height * heightScale
              let canvasWidth = trim ? newWidth : (width ?? newWidth)
              let canvasHeight = trim ? newHeight : (height ?? newHeight)
              UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)
      
              var originX: CGFloat = 0
              var originY: CGFloat = 0
              switch scaleMode {
              case .AspectFit(let alignment):
                  switch alignment {
                  case .Center:
                      originX = (canvasWidth - newWidth) / 2
                      originY = (canvasHeight - newHeight) / 2
                  case .Top:
                      originX = (canvasWidth - newWidth) / 2
                  case .Left:
                      originY = (canvasHeight - newHeight) / 2
                  case .Bottom:
                      originX = (canvasWidth - newWidth) / 2
                      originY = canvasHeight - newHeight
                  case .Right:
                      originX = canvasWidth - newWidth
                      originY = (canvasHeight - newHeight) / 2
                  case .TopLeft:
                      break
                  case .TopRight:
                      originX = canvasWidth - newWidth
                  case .BottomLeft:
                      originY = canvasHeight - newHeight
                  case .BottomRight:
                      originX = canvasWidth - newWidth
                      originY = canvasHeight - newHeight
                  }
              default:
                  break
              }
              self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
              let image = UIGraphicsGetImageFromCurrentImageContext()
              UIGraphicsEndImageContext()
              return image
          }
      }
      

      下面有应用此解决方案的示例。

      灰色矩形是目标站点图像将被调整大小。 浅蓝色矩形中的蓝色圆圈是图像(我使用了圆圈,因为它在不保留纵横比的情况下缩放时很容易看到)。 如果您通过trim: true,浅橙色标记将被修剪的区域。

      Aspect fit 缩放前后:

      aspect fit的另一个例子:

      Aspect fit 顶部对齐:

      方面填充

      填充

      我在示例中使用了放大,因为它更易于演示,但解决方案也适用于所讨论的缩小。

      对于 JPEG 压缩,你应该使用这个:

      let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
      if let data = UIImageJPEGRepresentation(image, compressionQuality) {
        // ...
      }
      

      您可以使用 Xcode 游乐场查看我的 gist

      【讨论】:

        【解决方案7】:

        对于 Swift 3,以下代码在保持纵横比的情况下缩放图像。您可以在Apple's documentation 中阅读有关 ImageContext 的更多信息:

        extension UIImage {
            class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
                let scale = newHeight / image.size.height
                let newWidth = image.size.width * scale
                UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
                image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return newImage!
            }
        }
        

        要使用它,请调用resizeImage()方法:

        UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)
        

        【讨论】:

          【解决方案8】:

          斯威夫特版

          func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {
          
              let scale = newWidth / image.size.width
              let newHeight = CGFloat(200.0)
              UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
              image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
          
              let newImage = UIGraphicsGetImageFromCurrentImageContext()
              UIGraphicsEndImageContext()
          
              return newImage
          }
          

          【讨论】:

            【解决方案9】:

            您可以使用此代码将图像缩放到所需的大小。

            + (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize
            {
                CGSize actSize = image.size;
                float scale = actSize.width/actSize.height;
            
                if (scale < 1) {
                    newSize.height = newSize.width/scale;
                } 
                else {
                    newSize.width = newSize.height*scale;
                }
            
                UIGraphicsBeginImageContext(newSize);
                [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
                UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
                UIGraphicsEndImageContext();
            
                return newImage;
            }
            

            【讨论】:

              【解决方案10】:

              在这里添加大量答案,但我已经寻求一种根据文件大小而不是尺寸调整大小的解决方案。

              这将减少图像的尺寸和质量,直到达到您的给定尺寸。

              func compressTo(toSizeInMB size: Double) -> UIImage? {
                  let bytes = size * 1024 * 1024
                  let sizeInBytes = Int(bytes)
                  var needCompress:Bool = true
                  var imgData:Data?
                  var compressingValue:CGFloat = 1.0
              
                  while (needCompress) {
              
                      if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) {
              
                          if data.count < sizeInBytes || compressingValue < 0.1 {
                              needCompress = false
                              imgData = data
                          } else {
                              compressingValue -= 0.1
                          }
                      }
                  }
              
                  if let data = imgData {
                      print("Finished with compression value of: \(compressingValue)")
                      return UIImage(data: data)
                  }
                  return nil
              }
              
              private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? {
                  let size = CGSize(width: self.size.width*factor, height: self.size.height*factor)
                  UIGraphicsBeginImageContext(size)
                  draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
                  if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
                      UIGraphicsEndImageContext()
                      return newImage;
                  }
                  return nil
              }
              

              感谢scaling by size answer

              【讨论】:

                【解决方案11】:

                根据本次会议iOS Memory Deep Dive,我们最好使用ImageIO 来缩小图像。

                使用UIImage 缩小图像的坏处。

                • 将原图解压到内存中
                • 内部坐标空间变换代价高昂

                使用ImageIO

                • ImageIO 可以在不污染内存的情况下读取图像大小和元数据信息。

                • ImageIO 可以仅以调整图像大小为代价来调整图像大小。

                关于内存中的图像

                • 内存使用与图像尺寸有关,与文件大小无关。
                • UIGraphicsBeginImageContextWithOptions 始终使用 SRGB 渲染格式,每个像素使用 4 个字节。
                • 一张图片有load -&gt; decode -&gt; render 3 个阶段。
                • UIImage 调整大小和调整大小的成本很高

                对于下图,如果使用UIGraphicsBeginImageContextWithOptions 我们只需要 590KB 来加载图像,而我们需要 2048 pixels x 1536 pixels x 4 bytes per pixel = 10MB 解码时

                而在 iOS 10 中引入的 UIGraphicsImageRenderer 将自动选择 iOS12 中的最佳图形格式。这意味着,如果您不需要 SRGB,则可以通过将 UIGraphicsBeginImageContextWithOptions 替换为 UIGraphicsImageRenderer 来节省 75% 的内存。

                这是我关于iOS images in memory的文章

                func resize(url: NSURL?, maxPixelSize: Int) -> CGImage? {
                    guard let url = url else {
                      return nil;
                    }
                  
                    let imgSource = CGImageSourceCreateWithURL(url, nil)
                    guard let imageSource = imgSource else {
                        return nil
                    }
                
                    var scaledImage: CGImage?
                    let options: [NSString: Any] = [
                            // The maximum width and height in pixels of a thumbnail.
                            kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
                            kCGImageSourceCreateThumbnailFromImageAlways: true,
                            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
                            kCGImageSourceCreateThumbnailWithTransform: true
                    ]
                    scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)
                
                    return scaledImage
                }
                
                
                
                DispatchQueue.global().async {
                  let image: CGImage? = resize(url: NSURL.init(string: "https://i.stack.imgur.com/rPcHQ.jpg"), maxPixelSize: 600)
                  DispatchQueue.main.async {
                    let imageView = UIImageView(frame: CGRect(x: 0, y: 0 ,width: 30, height: 30))
                    
                    if let cgimage = image {
                      imageView.image = UIImage(cgImage: cgimage);
                      
                    }
                  }
                }
                
                

                // Downsampling large images for display at smaller size
                func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
                    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
                    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
                    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
                    let downsampleOptions =
                        [kCGImageSourceCreateThumbnailFromImageAlways: true,
                        kCGImageSourceShouldCacheImmediately: true,
                        // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
                        kCGImageSourceCreateThumbnailWithTransform: true,
                        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
                    let downsampledImage =
                        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
                    return UIImage(cgImage: downsampledImage)
                }
                
                

                【讨论】:

                • 这种方法的主要问题是,如果图像源小于 MaxPixelSize,那么 SwiftUI 的图像将不得不调整大小,这会导致 LazyVGrid 中的抖动
                • 更新了示例。在后台线程而不是主线程中使用它如何,并且只用于大图像?
                【解决方案12】:

                Retina 显示器上可能出现的一个问题是图像的比例是由 ImageCapture 左右设置的。上面的调整大小功能不会改变这一点。在这些情况下,调整大小将无法正常工作。

                在下面的代码中,比例设置为 1(未缩放)并且返回的图像具有您期望的大小。这是在UIGraphicsBeginImageContextWithOptions 调用中完成的。

                -(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
                    UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
                    [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
                    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
                    UIGraphicsEndImageContext();
                    return newImage;
                }
                

                【讨论】:

                  【解决方案13】:

                  我最终使用 Brads 技术在 UIImage+Extensions 中创建了一个 scaleToFitWidth 方法,如果这对任何人都有用...

                  -(UIImage *)scaleToFitWidth:(CGFloat)width
                  {
                      CGFloat ratio = width / self.size.width;
                      CGFloat height = self.size.height * ratio;
                  
                      NSLog(@"W:%f H:%f",width,height);
                  
                      UIGraphicsBeginImageContext(CGSizeMake(width, height));
                      [self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
                      UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
                      UIGraphicsEndImageContext();
                  
                      return newImage;
                  }
                  

                  然后在任何你喜欢的地方

                  #import "UIImage+Extensions.h"

                  UIImage *newImage = [image scaleToFitWidth:100.0f];

                  另外值得注意的是,如果您想从 UIView 渲染图像,您可以将其进一步向下移动到 UIView+Extensions 类中

                  【讨论】:

                    【解决方案14】:

                    我只是想为 Cocoa Swift 程序员回答这个问题。此函数返回具有新大小的 NSImage。您可以像这样使用该功能。

                            let sizeChangedImage = changeImageSize(image, ratio: 2)
                    
                    
                    
                    
                    
                    
                     // changes image size
                    
                        func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage   {
                    
                        // getting the current image size
                        let w = image.size.width
                        let h = image.size.height
                    
                        // calculating new size
                        let w_new = w / ratio 
                        let h_new = h / ratio 
                    
                        // creating size constant
                        let newSize = CGSizeMake(w_new ,h_new)
                    
                        //creating rect
                        let rect  = NSMakeRect(0, 0, w_new, h_new)
                    
                        // creating a image context with new size
                        let newImage = NSImage.init(size:newSize)
                    
                    
                    
                        newImage.lockFocus()
                    
                            // drawing image with new size in context
                            image.drawInRect(rect)
                    
                        newImage.unlockFocus()
                    
                    
                        return newImage
                    
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      如果您的图片在文档目录中,请添加此 URL 扩展名:

                      extension URL {
                          func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? {
                              let imageData = try Data(contentsOf: self)
                              debugPrint("Image file size before compression: \(imageData.count) bytes")
                      
                              let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg")
                      
                              guard let actualImage = UIImage(data: imageData) else { return nil }
                              guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else {
                                  return nil
                              }
                              debugPrint("Image file size after compression: \(compressedImageData.count) bytes")
                      
                              do {
                                  try compressedImageData.write(to: compressedURL)
                                  return compressedURL
                              } catch {
                                  return nil
                              }
                          }
                      }
                      

                      用法:

                      guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else {
                          return
                      }
                      
                      //Here you will get URL of compressed image
                      guard let compressedImageURL = try localImageURL.compressedImageURL() else {
                          return
                      }
                      
                      debugPrint("compressedImageURL: \(compressedImageURL.absoluteString)")
                      

                      注意:- 将 更改为您的本地 jpg 图像路径。

                      【讨论】:

                        【解决方案16】:

                        如果有人还在寻找更好的选择

                        -(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {
                        
                        
                            UIImage *sourceImage = image;
                            UIImage *newImage = nil;
                        
                            CGSize imageSize = sourceImage.size;
                            CGFloat width = imageSize.width;
                            CGFloat height = imageSize.height;
                        
                            CGFloat targetWidth = targetSize.width;
                            CGFloat targetHeight = targetSize.height;
                        
                            CGFloat scaleFactor = 0.0;
                            CGFloat scaledWidth = targetWidth;
                            CGFloat scaledHeight = targetHeight;
                        
                            CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
                        
                            if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
                        
                                CGFloat widthFactor = targetWidth / width;
                                CGFloat heightFactor = targetHeight / height;
                        
                                if (widthFactor < heightFactor)
                                    scaleFactor = widthFactor;
                                else
                                    scaleFactor = heightFactor;
                        
                                scaledWidth  = width * scaleFactor;
                                scaledHeight = height * scaleFactor;
                        
                                // center the image
                        
                        
                                if (widthFactor < heightFactor) {
                                    thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
                                } else if (widthFactor > heightFactor) {
                                    thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
                                }
                            }
                        
                        
                            // this is actually the interesting part:
                        
                            UIGraphicsBeginImageContext(targetSize);
                        
                            CGRect thumbnailRect = CGRectZero;
                            thumbnailRect.origin = thumbnailPoint;
                            thumbnailRect.size.width  = scaledWidth;
                            thumbnailRect.size.height = scaledHeight;
                        
                            [sourceImage drawInRect:thumbnailRect];
                        
                            newImage = UIGraphicsGetImageFromCurrentImageContext();
                            UIGraphicsEndImageContext();
                        
                            if(newImage == nil) NSLog(@"could not scale image");
                        
                        
                            return newImage ;
                        
                        }
                        

                        【讨论】:

                          【解决方案17】:
                          - (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
                              CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
                              CGImageRef imageRef = image.CGImage;
                          
                              UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
                              CGContextRef context = UIGraphicsGetCurrentContext();
                          
                              CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
                              CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);
                          
                              CGContextConcatCTM(context, flipVertical);
                              CGContextDrawImage(context, newRect, imageRef);
                          
                              CGImageRef newImageRef = CGBitmapContextCreateImage(context);
                              UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
                          
                              CGImageRelease(newImageRef);
                              UIGraphicsEndImageContext();
                          
                              return newImage;
                          }
                          

                          【讨论】:

                          • 请在您的答案中至少提供一些代码解释。并使用答案编辑器格式化代码以使其可读。
                          【解决方案18】:

                          要调整图像大小,我使用此函数代替 DrawInRect 可以获得更好的(图形)结果:

                          - (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
                          {
                              float lScale = pWidth / pImage.size.width;
                              CGImageRef cgImage = pImage.CGImage;
                              UIImage   *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
                                                      orientation:UIImageOrientationRight];
                              return lResult;
                          }
                          

                          自动处理纵横比

                          【讨论】:

                            猜你喜欢
                            • 2015-05-27
                            • 2014-07-03
                            • 2022-01-11
                            • 1970-01-01
                            • 2023-03-27
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2023-03-23
                            相关资源
                            最近更新 更多