当前位置:  开发笔记 > IOS > 正文

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

如何解决《如何使用iOS轻松调整大小/优化图像大小?》经验,为你挑选了6个好方法。

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

此外,其中一些图像是JPEG,并且它们不会保存为通常的60%质量设置.

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



1> Brad Larson..:

提供了几个建议作为这个问题的答案.我已经建议使用相关代码在本文中描述的技术:

+ (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实例的内容写入磁盘或缓存在内存中.



2> lostInTransi..:

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

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


如果图像比率和最大比率相等,该怎么办?例如,如果iamge大小是3200x4800?

3> Pulkit Goyal..:

上述方法适用于小图像,但是当您尝试调整非常大的图像大小时,您将很快耗尽内存并使应用程序崩溃.更好的方法是使用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);
}

更多细节在这里.



4> codeburn..:

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

//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> Rog..:

如果您可以控制服务器,我强烈建议您使用ImageMagik调整图像服务器端的大小.下载大图像并在手机上调整大小是浪费了许多宝贵的资源 - 带宽,电池和内存.所有这些都在手机上很少见.


FTFQ:"我的应用程序正在从网络下载一组图像文件,"

6> mixel..:

我为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适合1(之前) Aspect适合1(之后)

方面拟合的另一个例子:

Aspect适合2(之前) Aspect适合2(之后)

Aspect适合顶部对齐:

Aspect适合3(之前) Aspect适合3(之后)

方面填充:

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

填充:

填充(之前) 填充(后)

我在我的示例中使用了upscaling,因为它更易于演示,但解决方案也适用于降尺度.

对于JPEG压缩,您应该使用:

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

你可以通过Xcode游乐场查看我的要点.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有