Comments (13)
应该是反复压缩内存没释放
from luban_ios.
只是处理了一张高清的大图。
from luban_ios.
@kukumaluCN 把图片发给我,我调试一下,看这个 250M 是怎么增加的
from luban_ios.
这张图在我们的内网测试环境,外网链接我没法提供,原图太大,图床不支持上传,可以邮件私发你。
这个是我写的测试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.
其实最消耗内存的是UIImageJPEGRepresentation(self.imageView.image, 1.0);
这个方法,取消之后,加载原始图片,基本没有那么高的瞬时内存尖峰。
from luban_ios.
@kukumaluCN [email protected] 另外我看了下,你测试的代码是为了较少峰值而牺牲了压缩质量,我个人认为这样压缩出来的大小并不是最理想的。
你测试的工程如果方便的话也发给我一下下。另外压缩这么大的图片,我还是第一次,也算是个机会看压缩超大图能不能造出来另外一种机制。
from luban_ios.
关注内存峰值是必须的,因为我们项目的特殊性,需要兼容比较老的设备,运存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.
我还发现,下面两个方式获取到的data的length,同一张图片,是有较大偏差的,有人说,第一个方法,系数要取0.7才可以。。。
NSData *data = UIImageJPEGRepresentation(self.imageView.image, 1.0);
NSData *data = [NSData dataWithContentsOfFile:retinaPath];
from luban_ios.
图片已经发送至您的邮箱,期待进一步交流。
from luban_ios.
@kukumaluCN 好的好的
from luban_ios.
另外给你们产品经理商量一下,为什么有这么大的图片?
from luban_ios.
对于一般场景为了避免使用 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;
from luban_ios.
//裁剪压缩,以1280为边界值动态裁剪 UIImage *compressImage = [image wx_compressLargeImage];
@kukumaluCN 您好,这里的微信压缩有开源的实现或者能提供一下代码吗?我想测试一下效果
from luban_ios.
Related Issues (13)
- 请更新到 1.0.6 版本
- 感觉新版压缩逻辑不对 HOT 1
- 算法问题 HOT 1
- 关于压缩比的问题 HOT 1
- 文件大小计算的不对 HOT 2
- 一个Swift版本如下 HOT 1
- 后台反应,压缩后图片模糊 HOT 6
- 核心代码注释
- 我之前说这个压缩有点问题,目前已找到 HOT 12
- 能提供一个方法,按照最大宽高来压缩吗? HOT 1
- 这个while好像没有意义 HOT 7
- 宽度被修改的问题找到了 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from luban_ios.