ios 按大小压缩图像 - iPhone SDK

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9506871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:06:28  来源:igfitidea点击:

image compression by size - iPhone SDK

iphoneiosapiuiimagejpegrepresentation

提问by DonDyck

I would like to compress images (camera/photo library) and then send it to the server. I know I can compress by height and width, but I would like to compress the images by size to a fixed size (200 KB) only and keep the original height and width. The scale factor in JPEGRepresentation does not represent the size and only compression quality. How can I achieve this (compress to a fixed size) without using any third party library? Thanks for any help.

我想压缩图像(相机/照片库),然后将其发送到服务器。我知道我可以按高度和宽度压缩,但我只想按大小将图像压缩到固定大小(200 KB)并保持原始高度和宽度。JPEGRepresentation 中的比例因子不代表大小,只代表压缩质量。如何在不使用任何第三方库的情况下实现这一点(压缩到固定大小)?谢谢你的帮助。

回答by kgutteridge

Heres some example code that will attempt to compress an image for you so that it doesn't exceed either a max compression or maximum file size

下面是一些示例代码,它将尝试为您压缩图像,使其不超过最大压缩或最大文件大小

CGFloat compression = 0.9f;
CGFloat maxCompression = 0.1f;
int maxFileSize = 250*1024;

NSData *imageData = UIImageJPEGRepresentation(yourImage, compression);

while ([imageData length] > maxFileSize && compression > maxCompression)
{
    compression -= 0.1;
    imageData = UIImageJPEGRepresentation(yourImage, compression);
}

回答by nycynik

One way to do it, is to re-compress the file in a loop, until you find the desired size. You could first find height and width, and guess the compression factor (larger image more compression) then after you compress it, check the size, and split the difference again.

一种方法是在循环中重新压缩文件,直到找到所需的大小。您可以先找到高度和宽度,然后猜测压缩因子(图像越大压缩越多),然后在压缩后,检查大小,然后再次拆分差异。

I know this is not super efficient, but I do not believe there is a single call to achieve a image of a specific size.

我知道这不是非常有效,但我不相信有一个单一的调用来实现特定尺寸的图像。

回答by krunal

Here, JPEGRepresentation is quite memory consuming and if we use in Loop so it is extremely high memory consuming. So use below code & ImageSize won't be more then 200KB.

在这里,JPEGRepresentation 非常消耗内存,如果我们在 Loop 中使用,那么它的内存消耗非常高。所以使用下面的代码,ImageSize 不会超过 200KB。

UIImage* newImage = [self captureView:yourUIView];


- (UIImage*)captureView:(UIView *)view {  
CGRect rect = view.bounds;
UIGraphicsBeginImageContext(rect.size);  
CGContextRef context = UIGraphicsGetCurrentContext();  

[view.layer renderInContext:context];  
UIImage* img = [UIImage alloc]init];
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();  
NSLog(@"img=%@",img);
return img;
}

回答by Mindhavok

I took the answer of @kgutteridge and made a similar solution for Swift 3.0using recursive:

我接受了@kgutterridge 的回答,并使用递归为Swift 3.0做了一个类似的解决方案:

extension UIImage {
    static func compress(image: UIImage, maxFileSize: Int, compression: CGFloat = 1.0, maxCompression: CGFloat = 0.4) -> Data? {

        if let data = UIImageJPEGRepresentation(image, compression) {

            let bcf = ByteCountFormatter()
            bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only
            bcf.countStyle = .file
            let string = bcf.string(fromByteCount: Int64(data.count))
            print("Data size is: \(string)")

            if data.count > (maxFileSize * 1024 * 1024) && (compression > maxCompression) {
                let newCompression = compression - 0.1
                let compressedData = self.compress(image: image, maxFileSize: maxFileSize, compression: newCompression, maxCompression: maxCompression)
                return compressedData
            }

            return data
        }

        return nil
    }
}

回答by Winter

Swift 4:

斯威夫特 4:

extension UIImage {
    func compressTo(bytes: Int) -> UIImage {
        var compression: CGFloat = 0.9
        let maxCompression: CGFloat = 0.1
        let maxSize: Int = bytes * 1024

        var imageData = jpegData(compressionQuality: compression)!
        while imageData.count > maxSize && compression > maxCompression {
            compression -= 0.1
            imageData = jpegData(compressionQuality: compression)!
        }

        return UIImage(data: imageData)!
    }
}

回答by Banky Adebajo

After doing a few tests, I was able to find A relationship between image size and compression value. Since this relationship is linear for all values where the compression is less than 1, I created an algorithm to try to always compress images to a certain value.

经过几次测试,我能够找到 图像大小和压缩值之间的关系。由于这种关系对于压缩小于 1 的所有值都是线性的,因此我创建了一个算法来尝试始终将图像压缩到某个值。

//Use 0.99 because at 1, the relationship between the compression and the file size is not linear
NSData *image = UIImageJPEGRepresentation(currentImage, 0.99);
float maxFileSize = MAX_IMAGE_SIZE * 1024;

//If the image is bigger than the max file size, try to bring it down to the max file size
if ([image length] > maxFileSize) {
    image = UIImageJPEGRepresentation(currentImage, maxFileSize/[image length]);
}

回答by Superdev

- (UIImage *)resizeImageToSize:(CGSize)targetSize
{
    UIImage *sourceImage = captureImage;
    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;

        // make image center aligned
        if (widthFactor < heightFactor)
        {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        }
        else if (widthFactor > heightFactor)
        {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }

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