为了防止我的应用程序滞后,我正在尝试压缩大于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。我是否忽视了某些事情/有没有其他方法来实现这一目标?
编辑:如果可能的话,我想避免缩放图像的高度和宽度。
答案 0 :(得分:16)
有几点想法:
UIImageJPEGRepresentation
功能不会返回“原始”图像。例如,如果您使用compressionQuality
1.0
,从技术上讲,它不返回“原始”图像,而是返回图像的JPEG再现,其中compressionQuality
为最大值。这实际上可以产生比原始资产更大的对象(至少如果原始图像是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版本中,您必须使用assetForURL
类的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
以异步方式运行。
如果您想要NSData
进行压缩,则可以UIImageJPEGRepresentation
使用compressionQuality
小于1.0
。您的代码实际上使用compressionQuality
0.0
执行此操作,该代码应提供最大压缩。但是你不保存NSData
,而是用它来创建UIImage
,然后你得到UIImageJPEGRepresentation
compressionQuality
1.0
的新// 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]);
,因此失去了你最初实现的大部分压缩。
请考虑以下代码:
compressionQuality
除了前面提到的JPEG压缩质量之外,您还可以resize the image。您也可以将其与JPEG {{1}}结合使用。
答案 1 :(得分:1)
您无法反复压缩图像。如果是这样,一切都可以一次又一次地压缩。那么你认为它会有多小?
使图像变小的一种方法是改变图像的大小。例如,将640X960更改为320X480。但是你会失去品质。
答案 2 :(得分:-1)
我是第一个实现UIImageJPEGRepresentation(图像,0.75),然后改变大小。也许是图像的宽度和高度的三分之二或一半。