调用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。 我忽略了一些东西/是否有其他方法来实现这一目标?
编辑:我想避免缩放图像的高度和宽度,如果可能的话。
一些想法:
-
UIImageJPEGRepresentation
函数不会返回“原始”图像。 例如,如果您使用1.0
的compressionQuality
质量,则在技术上它不会返回“原始”图像,而是返回compressionQuality
达到其最大值的图像的JPEG格式。 这实际上可以产生比原始资源更大的对象(至less如果原始图像是JPEG)。 您还将丢弃所有元数据(有关拍摄图像的位置,相机设置等信息)。 -
如果你想要原始资产,你应该使用
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); }];
请注意,这个
assetForURL
asynchronous运行。 -
如果你想要一个压缩的
NSData
,你可以使用compressionQuality
小于1.0
UIImageJPEGRepresentation
。 你的代码实际上是这样做的,它的compressionQuality
为0.0
,应该提供最大的压缩率。 但是你不保存这个NSData
,而是用它来创build一个UIImage
,然后你得到一个compressionQuality
为1.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]);
-
除了前面提到的JPEG压缩质量外,还可以调整图像大小 。 你也可以用JPEG
compressionQuality
来结婚。
您不能一次又一次压缩图像。 如果是这样,一切都可以一次又一次压缩。 那么你觉得它有多小?
减小图像的一种方法是改变它的大小。 例如,将640X960更改为320X480。 但是你会失去质量。
我是第一个实现UIImageJPEGRepresentation(图像,0.75),然后改变大小。 也许图像的宽度和高度三分之二或一半。