简体   繁体   English

如何使用 iOS 轻松调整/优化图像大小?

[英]How to easily resize/optimize an image size with iOS?

My application is downloading a set of image files from the.network, and saving them to the local iPhone disk.我的应用程序正在从 .network 下载一组图像文件,并将它们保存到本地 iPhone 磁盘。 Some of those images are pretty big in size (widths larger than 500 pixels, for instance).其中一些图像的尺寸非常大(例如,宽度大于 500 像素)。 Since the iPhone doesn't even have a big enough display to show the image in its original size, I'm planning on resizing the image to something a bit smaller to save on space/performance.由于 iPhone 甚至没有足够大的显示屏来显示原始尺寸的图像,我打算将图像的大小调整到更小的尺寸以节省空间/性能。

Also, some of those images are JPEGs and they are not saved as the usual 60% quality setting.此外,其中一些图像是 JPEG,它们不会保存为通常的 60% 质量设置。

How can I resize a picture with the iPhone SDK, and how can I change the quality setting of a JPEG image?如何使用 iPhone SDK 调整图片大小,以及如何更改 JPEG 图片的质量设置?

A couple of suggestions are provided as answers to this question .提供了一些建议作为此问题的答案。 I had suggested the technique described in this post , with the relevant code:我建议使用这篇文章中描述的技术以及相关代码:

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

   return newImage;
}

As far as storage of the image, the fastest image format to use with the iPhone is PNG, because it has optimizations for that format.就图像存储而言,iPhone 使用最快的图像格式是 PNG,因为它针对该格式进行了优化。 However, if you want to store these images as JPEGs, you can take your UIImage and do the following:但是,如果您想将这些图像存储为 JPEG,您可以使用 UIImage 并执行以下操作:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

This creates an NSData instance containing the raw bytes for a JPEG image at a 60% quality setting.这将创建一个 NSData 实例,其中包含质量设置为 60% 的 JPEG 图像的原始字节。 The contents of that NSData instance can then be written to disk or cached in memory.然后可以将该 NSData 实例的内容写入磁盘或缓存在 memory 中。

The easiest and most straightforward way to resize your images would be this调整图像大小的最简单和最直接的方法就是这个

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();

The above methods work well for small images, but when you try to resize a very large image, you will quickly run out of memory and crash the app.上述方法适用于小图像,但当您尝试调整非常大的图像大小时,您将很快用完 memory 并使应用程序崩溃。 A much better way is to use CGImageSourceCreateThumbnailAtIndex to resize the image without completely decoding it first.更好的方法是使用CGImageSourceCreateThumbnailAtIndex调整图像大小,而无需先完全解码。

If you have the path to the image you want to resize, you can use this:如果您有要调整大小的图像的路径,则可以使用:

- (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);
}

More details here .更多细节在这里

Best way to scale images without losing the aspect ratio (ie without stretching the imgage) is to use this method:在不丢失纵横比(即不拉伸图像)的情况下缩放图像的最佳方法是使用此方法:

//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;

}

Add this method to your Utility class so you can use it throughout your project, and access it like so:将此方法添加到您的实用程序 class 中,以便您可以在整个项目中使用它,并像这样访问它:

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

This method takes care of scaling while maintaining aspect ratio.此方法在保持纵横比的同时负责缩放。 It also adds indents to the image in case the scaled down image has more width than height (or vice versa).它还会在图像中添加缩进,以防缩小图像的宽度大于高度(反之亦然)。

If you have control over the server, I would strongly recommend resizing the images server side with ImageMagik .如果您可以控制服务器,我强烈建议您使用ImageMagik调整图像服务器端的大小。 Downloading large images and resizing them on the phone is a waste of many precious resources - bandwidth, battery and memory. All of which are scarce on phones.下载大图片并在手机上调整大小会浪费许多宝贵的资源——带宽、电池和 memory。所有这些在手机上都是稀缺的。

I developed an ultimate solution for image scaling in Swift.我在 Swift 中开发了图像缩放的最终解决方案。

You can use it to resize image to fill, aspect fill or aspect fit specified size.您可以使用它来调整图像的大小以填充、纵横比填充或纵横比适合指定大小。

You can align image to center or any of four edges and four corners.您可以将图像对齐到中心或四个边缘和四个角中的任何一个。

And also you can trim extra space which is added if aspect ratios of original image and target size are not equal.如果原始图像和目标尺寸的宽高比不相等,您还可以修剪额外的空间。

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
    }
}

There are examples of applying this solution below.下面是应用此解决方案的示例。

Gray rectangle is target site image will be resized to.灰色矩形是将调整大小的目标站点图像。 Blue circles in light blue rectangle is the image (I used circles because it's easy to see when it's scaled without preserving aspect).浅蓝色矩形中的蓝色圆圈是图像(我使用圆圈是因为在不保留纵横比的情况下缩放时很容易看到)。 Light orange color marks areas that will be trimmed if you pass trim: true .如果您通过trim: true ,浅橙色标记将被修剪的区域。

Aspect fit before and after scaling:缩放前后的纵横比拟合

纵横比 1(之前) 纵横比 1(之后)

Another example of aspect fit :方面适合的另一个例子:

纵横比 2(之前) 纵横比 2(之后)

Aspect fit with top alignment:与顶部 alignment 的纵横比:

纵横比 3(之前) Aspect fit 3(之后)

Aspect fill :方面填充

纵横比填充(之前) 纵横比填充(之后)

Fill :填写

填充(之前) 填充(之后)

I used upscaling in my examples because it's simpler to demonstrate but solution also works for downscaling as in question.我在示例中使用了放大,因为它更易于演示,但解决方案也适用于所讨论的缩小。

For JPEG compression you should use this:对于 JPEG 压缩,你应该使用这个:

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

You can check out my gist with Xcode playground.你可以通过 Xcode 游乐场查看我的要点

For Swift 3, the below code scales the image keeping the aspect ratio.对于 Swift 3,下面的代码缩放图像以保持宽高比。 You can read more about the ImageContext in Apple's documentation :您可以在Apple 的文档中阅读有关 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!
    }
}

To use it, call resizeImage() method:要使用它,请调用resizeImage()方法:

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

Swift Version Swift版

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
}

you can use this code to scale image in required size.您可以使用此代码按所需大小缩放图像。

+ (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;
}

Adding to the slew of answers here, but I have gone for a solution which resizes by file size, rather than dimensions.添加到这里的大量答案,但我已经找到了一个根据文件大小而不是尺寸调整大小的解决方案。

This will both reduce the dimensions and quality of the image until it reaches your given size.这将同时降低图像的尺寸和质量,直到达到您给定的尺寸。

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
}

Credit for scaling by size answer按大小缩放的信用答案

According to this session, iOS Memory Deep Dive , we had better use ImageIO to downscale images.根据这个 session, iOS Memory Deep Dive ,我们最好使用ImageIO来缩小图像。

The bad of using UIImage downscale images.使用UIImage缩小图像的坏处。

  • Will decompress original image into memory将原图解压成memory
  • Internal coordinate space transforms are expensive内部坐标空间变换是昂贵的

Use ImageIO使用ImageIO

  • ImageIO can read image sizes and metadata information without dirtying memory. ImageIO 可以读取图像大小和元数据信息而不会弄脏 memory。

  • ImageIO can resize images at cost of resized image only. ImageIO 可以仅以调整图像大小为代价来调整图像大小。

About Image in memory关于memory中的图片

  • Memory use is related to the dimensions of the images, not the file size. Memory 使用与图像尺寸有关,与文件大小无关。
  • UIGraphicsBeginImageContextWithOptions always uses SRGB rendering-format, which use 4 bytes per pixel. UIGraphicsBeginImageContextWithOptions始终使用SRGB渲染格式,每个像素使用 4 个字节。
  • A image have load -> decode -> render 3 phases.图像有load -> decode -> render 3 个阶段。
  • UIImage is expensive for sizing and to resizing UIImage调整大小和调整大小都很昂贵

For the following image, if you use UIGraphicsBeginImageContextWithOptions we only need 590KB to load a image, while we need 2048 pixels x 1536 pixels x 4 bytes per pixel = 10MB when decoding对于下图,如果使用UIGraphicsBeginImageContextWithOptions我们只需要 590KB 来加载图像,而解码时我们需要2048 pixels x 1536 pixels x 4 bytes per pixel = 10MB 在此处输入图像描述

while UIGraphicsImageRenderer , introduced in iOS 10, will automatically pick the best graphic format in iOS12.而 iOS 10 中引入的UIGraphicsImageRenderer会在 iOS12 中自动选择最佳图形格式。 It means, you may save 75% of memory by replacing UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer if you don't need SRGB.这意味着,如果不需要 SRGB,可以通过将UIGraphicsBeginImageContextWithOptions替换为UIGraphicsImageRenderer来节省 memory 的 75%。

This is my article about iOS images in memory这是我关于memory中iOS张图片的文章

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);
      
    }
  }
}

or要么

// 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)
}

A problem that might occur on retina displays is that the scale of the image is set by ImageCapture or so.视网膜显示器上可能出现的一个问题是图像的比例是由 ImageCapture 等设置的。 The resize functions above will not change that.上面的调整大小函数不会改变这一点。 In these cases the resize will work not properly.在这些情况下,调整大小将无法正常工作。

In the code below, the scale is set to 1 (not scaled) and the returned image has the size that you would expect.在下面的代码中,比例设置为 1(未缩放)并且返回的图像具有您期望的大小。 This is done in the UIGraphicsBeginImageContextWithOptions call.这是在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;
}

I ended up using Brads technique to create a scaleToFitWidth method in UIImage+Extensions if that's useful to anyone...我最终使用 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;
}

then wherever you like然后无论你喜欢

#import "UIImage+Extensions.h"

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

Also worth noting you could move this further down into a UIView+Extensions class if you want to render images from a UIView同样值得注意的是,如果你想从 UIView 渲染图像,你可以将它进一步向下移动到UIView+Extensions class

I just wanted to answer that question for Cocoa Swift programmers.我只是想为 Cocoa Swift 程序员回答这个问题。 This function returns NSImage with new size.这个 function 返回具有新大小的 NSImage。 You can use that function like this.您可以像这样使用 function。

        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

}

If you image is in document directory, Add this URL extension:如果您的图像在文档目录中,请添加此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
        }
    }
}

Usage:用法:

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)")

Note:- Change < LocalImagePath.jpg > with your local jpg image path.注意:- 将 < LocalImagePath.jpg > 更改为您本地的 jpg 图像路径。

If anyone still looking for better option如果有人仍在寻找更好的选择

-(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 ;

}
- (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;
}

To resize an image I have better (graphical) results by using this function in stead of DrawInRect:要调整图像大小,我可以通过使用此 function 代替 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;
}

Aspect ratio is taken care for automatically纵横比自动调整

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM