调用imageWithData:UIImageJPEGRepresentation()多次只能第一次压缩图像

为了防止在我的应用程序滞后,我试图压缩大于1 MB的图像(主要是从iPhone的普通相机拍摄的图片。

UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; NSData *imageSize = UIImageJPEGRepresentation(image, 1); NSLog(@"original size %u", [imageSize length]); UIImage *image2 = [UIImage imageWithData:UIImageJPEGRepresentation(image, 0)]; NSData *newImageSize = UIImageJPEGRepresentation(image2, 1); NSLog(@"new size %u", [newImageSize length]); UIImage *image3 = [UIImage imageWithData:UIImageJPEGRepresentation(image2, 0)]; NSData *newImageSize2 = UIImageJPEGRepresentation(image3, 1); NSLog(@"new size %u", [newImageSize2 length]); picView = [[UIImageView alloc] initWithImage:image3] ; 

但是,我得到的NSLog输出的东西沿线

  original size 3649058 new size 1835251 new size 1834884 

第一次和第二次压缩之间的差异几乎可以忽略不计。 我的目标是让图像大小低于1 MB。 我忽略了一些东西/是否有其他方法来实现这一目标?

编辑:我想避免缩放图像的高度和宽度,如果可能的话。

一些想法:

  1. UIImageJPEGRepresentation函数不会返回“原始”图像。 例如,如果您使用1.0compressionQuality质量,则在技术上它不会返回“原始”图像,而是返回compressionQuality达到其最大值的图像的JPEG格式。 这实际上可以产生比原始资源更大的对象(至less如果原始图像是JPEG)。 您还将丢弃所有元数据(有关拍摄图像的位置,相机设置等信息)。

  2. 如果你想要原始资产,你应该使用PHImageManager

     NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL]; PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil]; PHAsset *asset = [result firstObject]; PHImageManager *manager = [PHImageManager defaultManager]; [manager requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { NSString *filename = [(NSURL *)info[@"PHImageFileURLKey"] lastPathComponent]; // do what you want with the `imageData` }]; 

    在8之前的iOS版本中,您必须使用ALAssetsLibrary类的ALAssetsLibrary

     NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL]; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library assetForURL:url resultBlock:^(ALAsset *asset) { ALAssetRepresentation *representation = [asset defaultRepresentation]; NSLog(@"size of original asset %llu", [representation size]); // I generally would write directly to a `NSOutputStream`, but if you want it in a // NSData, it would be something like: NSMutableData *data = [NSMutableData data]; // now loop, reading data into buffer and writing that to our data strea NSError *error; long long bufferOffset = 0ll; NSInteger bufferSize = 10000; long long bytesRemaining = [representation size]; uint8_t buffer[bufferSize]; NSUInteger bytesRead; while (bytesRemaining > 0) { bytesRead = [representation getBytes:buffer fromOffset:bufferOffset length:bufferSize error:&error]; if (bytesRead == 0) { NSLog(@"error reading asset representation: %@", error); return; } bytesRemaining -= bytesRead; bufferOffset += bytesRead; [data appendBytes:buffer length:bytesRead]; } // ok, successfully read original asset; // do whatever you want with it here } failureBlock:^(NSError *error) { NSLog(@"error=%@", error); }]; 

    请注意,这个assetForURLasynchronous运行。

  3. 如果你想要一个压缩的NSData ,你可以使用compressionQuality小于1.0 UIImageJPEGRepresentation 。 你的代码实际上是这样做的,它的compressionQuality0.0 ,应该提供最大的压缩率。 但是你不保存这个NSData ,而是用它来创build一个UIImage ,然后你得到一个compressionQuality1.0的新的UIImageJPEGRepresentation ,这样就失去了你最初实现的大部分压缩。

    考虑下面的代码:

     // a UIImage of the original asset (discarding meta data) UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; // this may well be larger than the original asset NSData *jpgDataHighestCompressionQuality = UIImageJPEGRepresentation(image, 1.0); [jpgDataHighestCompressionQuality writeToFile:[docsPath stringByAppendingPathComponent:@"imageDataFromJpeg.jpg"] atomically:YES]; NSLog(@"compressionQuality = 1.0; length = %u", [jpgDataHighestCompressionQuality length]); // this will be smaller, but with some loss of data NSData *jpgDataLowestCompressionQuality = UIImageJPEGRepresentation(image, 0.0); NSLog(@"compressionQuality = 0.0; length = %u", [jpgDataLowestCompressionQuality length]); UIImage *image2 = [UIImage imageWithData:jpgDataLowestCompressionQuality]; // ironically, this will be larger than jpgDataLowestCompressionQuality NSData *newImageSize = UIImageJPEGRepresentation(image2, 1.0); NSLog(@"new size %u", [newImageSize length]); 
  4. 除了前面提到的JPEG压缩质量外,还可以调整图像大小 。 你也可以用JPEG compressionQuality来结婚。

您不能一次又一次压缩图像。 如果是这样,一切都可以一次又一次压缩。 那么你觉得它有多小?

减小图像的一种方法是改变它的大小。 例如,将640X960更改为320X480。 但是你会失去质量。

我是第一个实现UIImageJPEGRepresentation(图像,0.75),然后改变大小。 也许图像的宽度和高度三分之二或一半。

Interesting Posts