gpt4 book ai didi

ios - 调用 imageWithData :UIImageJPEGRepresentation() multiple times only compresses image the first time

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:50:16 27 4
gpt4 key购买 nike

为了防止我的应用程序滞后,我尝试压缩大于 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 处于最大值。这实际上可以产生比原始 Assets 更大的对象(至少如果原始图像是 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`
    }];

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

    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 异步运行。

  3. 如果您想要压缩的NSData,您可以使用UIImageJPEGRepresentationcompressionQuality小于1.0。您的代码实际上使用 0.0compressionQuality 执行此操作,这应该提供最大压缩。但是你不保存那个 NSData,而是用它来创建一个 UIImage 然后你得到一个新的 UIImageJPEGRepresentation 和一个 1.0 的 compressionQuality,因此失去了您最初实现的大部分压缩。

    考虑以下代码:

    // 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 压缩质量外,您还可以 resize the image .您也可以将其与 JPEG compressionQuality 相结合。

关于ios - 调用 imageWithData :UIImageJPEGRepresentation() multiple times only compresses image the first time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17005456/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com