Giter VIP home page Giter VIP logo

Comments (13)

lovelyelfpop avatar lovelyelfpop commented on August 30, 2024

应该是反复压缩内存没释放

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

只是处理了一张高清的大图。

from luban_ios.

GuoZhiQiang avatar GuoZhiQiang commented on August 30, 2024

@kukumaluCN 把图片发给我,我调试一下,看这个 250M 是怎么增加的

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

这张图在我们的内网测试环境,外网链接我没法提供,原图太大,图床不支持上传,可以邮件私发你。

这个是我写的测试demo,原图加载时,转data估算的大小:

这个是用您的方法压缩后测算的大小,以及对应的内存峰值。可以看到,原始图片读入内存瞬时峰值在230M左右,压缩峰值瞬时能到248M!我的测试机是7P。

我参考了微信的压缩机制,改用了自己的一套压缩算法,效果如下,相对优化了很多,但是还是有压缩瞬间的内存峰值:

测试的核心代码如下:

//鲁班压缩:
if (self.flag) {
    self.flag = NO;
    UIImage *image = [UIImage imageNamed:@"ada9dcab6fe0452488539bd31782a272.JPG"];
    //鲁班压缩
    NSData *data = [UIImage lubanCompressImage:image];
    UIImage *finalCompressImage = [UIImage imageWithData:data];
    self.imageView.image = finalCompressImage;
    
    CGFloat le = data.length/1024.0/1024.0;
    self.label.text = [NSString stringWithFormat:@"压缩后:%.0fx%.0f - %fMB", self.imageView.image.size.width, self.imageView.image.size.height, le];
}
else {
    self.flag = YES;
    self.imageView.image = [UIImage imageNamed:@"ada9dcab6fe0452488539bd31782a272.JPG"];
    
    NSData *data = UIImageJPEGRepresentation(self.imageView.image, 1.0);
    CGFloat le = data.length/1024.0/1024.0;
    self.label.text = [NSString stringWithFormat:@"原图:%.0fx%.0f - %fMB", self.imageView.image.size.width, self.imageView.image.size.height, le];
}
//微信压缩:
if (self.flag) {
    self.flag = NO;
    UIImage *image = [UIImage imageNamed:@"ada9dcab6fe0452488539bd31782a272.JPG"];
    //裁剪压缩,以1280为边界值动态裁剪
    UIImage *compressImage = [image wx_compressLargeImage];
    //二次压缩图像,防止裁剪后依旧为高清图
    NSData *data = UIImageJPEGRepresentation(compressImage, 0.5);
    UIImage *finalCompressImage = [UIImage imageWithData:data];
    self.imageView.image = finalCompressImage;
    
    CGFloat le = data.length/1024.0/1024.0;
    self.label.text = [NSString stringWithFormat:@"压缩后:%.0fx%.0f - %fMB", self.imageView.image.size.width, self.imageView.image.size.height, le];
}
else {
    self.flag = YES;
    self.imageView.image = [UIImage imageNamed:@"ada9dcab6fe0452488539bd31782a272.JPG"];
    
    NSData *data = UIImageJPEGRepresentation(self.imageView.image, 1.0);
    CGFloat le = data.length/1024.0/1024.0;
    self.label.text = [NSString stringWithFormat:@"原图:%.0fx%.0f - %fMB", self.imageView.image.size.width, self.imageView.image.size.height, le];
}

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

其实最消耗内存的是UIImageJPEGRepresentation(self.imageView.image, 1.0);这个方法,取消之后,加载原始图片,基本没有那么高的瞬时内存尖峰。

from luban_ios.

GuoZhiQiang avatar GuoZhiQiang commented on August 30, 2024

@kukumaluCN [email protected] 另外我看了下,你测试的代码是为了较少峰值而牺牲了压缩质量,我个人认为这样压缩出来的大小并不是最理想的。

你测试的工程如果方便的话也发给我一下下。另外压缩这么大的图片,我还是第一次,也算是个机会看压缩超大图能不能造出来另外一种机制。

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

关注内存峰值是必须的,因为我们项目的特殊性,需要兼容比较老的设备,运存512M那种,我们测试发现,瞬时内存峰值超过200M,就会造成crash,所以没办法,必须优化内存占用和内存峰值。
关于压缩质量,其实我做过对比,上面的那些图看不清楚,其实微信的压缩算法很优秀,压缩过后的大小能控制在400k左右,但是清晰度高很多,您压缩后的图片大小会小很多,但是清晰度不太够。
下面是对比,图片放大了5X的局部展示:

这个是微信的压缩算法,微信以1280为边界值做裁剪压缩处理,压缩系数0.5:

这个是微信的压缩算法,微信以1280为边界值做裁剪压缩处理,压缩系数0.1:

这个是您提供的压缩机制:

微信的压缩算法我参考了这个:iOS 图片压缩----微信图片处理策略,并做了算法优化,原理是一致的,关于压缩系数,取了0.5,这个产出和文中说的一致,和微信朋友圈的相当。
不过,这套算法依旧使用了UIImageJPEGRepresentation这个函数,这个是导致内存峰值的罪魁祸首,目前还没找到更好的方法,有人说微信还使用了ImageIO,算法如下,但是经过测算,内存占用不降反升。。。我也很想找到一个压缩大图的比较好的方案,很希望和您探讨。

+ (UIImage *)jxt_scaledImageWithData:(NSData *)data toSize:(CGSize)size
{
    if (!data) {
        return nil;
    }
    UIImage *thumbnail = nil;
    CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
    if (sourceRef) {
        CGFloat maxPixelSize = MAX(size.width, size.height);
        NSDictionary *options = @{
                                  (__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
                                  (__bridge id)kCGImageSourceCreateThumbnailWithTransform:(__bridge id)kCFBooleanTrue,
                                  (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]
                                  };
        CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
        if (imageRef) {
            thumbnail = [UIImage imageWithCGImage:imageRef];
            CGImageRelease(imageRef);
        }
        CFRelease(sourceRef);
    }
    return thumbnail;
}

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

我还发现,下面两个方式获取到的data的length,同一张图片,是有较大偏差的,有人说,第一个方法,系数要取0.7才可以。。。

NSData *data = UIImageJPEGRepresentation(self.imageView.image, 1.0);
NSData *data = [NSData dataWithContentsOfFile:retinaPath];

from luban_ios.

kukumaluCN avatar kukumaluCN commented on August 30, 2024

图片已经发送至您的邮箱,期待进一步交流。

from luban_ios.

GuoZhiQiang avatar GuoZhiQiang commented on August 30, 2024

@kukumaluCN 好的好的👌。微信压缩的那个我之前看过也实现过,但 压缩后的大小我还是接受不了,清晰是很清晰,不适合多图上传的场景。于是实现了luban。在实际场景中,10张图片,用微信那个压缩后5M左右,luban压缩完1M左右,清晰度也还可以,当然了如果要更清晰的可以下载原图。

from luban_ios.

GuoZhiQiang avatar GuoZhiQiang commented on August 30, 2024

另外给你们产品经理商量一下,为什么有这么大的图片?

from luban_ios.

GuoZhiQiang avatar GuoZhiQiang commented on August 30, 2024

对于一般场景为了避免使用 UIImageJPEGRepresentation 造成的内存暴涨 可以使用下面的方法进行压缩处理:

//imageURL 图片的本地存储地址; size 图片大小; scale 压缩比 0.0~1.0
- (UIImage* _Nullable)downsampleImageURL:(NSURL *)imageURL sampleSize:(CGSize)size scale:(CGFloat)scale
{
    CFDictionaryRef sourceOpt = (__bridge CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache: @NO};
    CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageURL, sourceOpt);
    if (!source) {
        NSLog(@"imageSource is Null!");
        return nil;
    }
    int maxDimension = MAX(size.width, size.height) * scale;
    CFDictionaryRef downsampleOpt = (__bridge CFDictionaryRef)@{
        (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES,
        (NSString *)kCGImageSourceShouldCacheImmediately : @YES ,
        (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES,
        (NSString *)kCGImageSourceThumbnailMaxPixelSize : @(maxDimension)};
    CGImageRef downsampleImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOpt);
    CFRelease(source);
    
    return [UIImage imageWithCGImage:downsampleImage];
}

在本例中使用 可以这样子:

    NSString *filePaht = [[NSBundle mainBundle] pathForResource:@"IMG_1998" ofType:@"JPG"];
    UIImage *imgData   = [UIImage imageWithContentsOfFile:filePaht];
    NSURL *urlPath = [NSURL fileURLWithPath:filePaht];
    self.imgCompressed    = [self downsampleImageURL:urlPath sampleSize:imgData.size scale:0.3];
    self.img_brower.image = _imgCompressed;

@kukumaluCN @lovelyelfpop

from luban_ios.

zhaozzq avatar zhaozzq commented on August 30, 2024
   //裁剪压缩,以1280为边界值动态裁剪
   UIImage *compressImage = [image wx_compressLargeImage];

@kukumaluCN 您好,这里的微信压缩有开源的实现或者能提供一下代码吗?我想测试一下效果

from luban_ios.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.