图像的压缩算法--尺寸压缩、格式压缩和品质压缩

简介: 图像的压缩算法--尺寸压缩、格式压缩和品质压缩

图像分辨率指图像中存储的信息量,是每英寸图像内有多少个像素点,分辨率的单位为PPI(Pixels Per Inch),通常叫做像素每英寸。图像分辨率一般被用于ps中,用来改变图像的清晰度。

一个影像可被定义是一个二维的函数 f(x,y),其中x和y是空间平面坐标,在任意一对坐标轴(x,y),f的大小称为这幅影像在该点的强度(instensity)或灰阶(gray level).也即,灰阶是指地物电磁波辐射强度表现在黑白影像上的色调深浅的等级,是划分地物波谱特征的尺度。

一张图片的图片大小主要取决于图片尺寸(点阵图如6000*4000就时指的图片尺寸),分辨率(每英寸图像内有多少个像素点),灰阶。图像压缩算法(学过图像处理的人知道,图片最简单的是位图,就时bitMap,对应的是原始无压缩的点阵图,而jpeg等图像算法能把相同的连续图像点按照对应图像压缩算法和分辨率对位图进行压缩保存,也可以还原位图。由于jpeg和png是有损压缩,压缩后和原图有失真)。所以图片压缩分三类:尺寸压缩最快成比例压缩(理论上可以压缩到接近无限小,你把他压缩到4个点了也没有什么物理意义了)、图像格式压缩(如:把bitMap转换为jpeg,PNG等图片格式)、图像品质压缩(UIImageJPEGRepresentation(image, compressionQuality)进行分辨率和压缩算法方面的压缩。注意:compressionQuality是图像质量参数和图像分辨率强相关不是简单压缩比,这种压缩有压缩下限。其中图像格式压缩和图像品质压缩可以同时进行,把png等非JPG格式的图片通过UIImageJPEGRepresentation函数及compressionQuality压缩参数进行压缩。由于图片的点阵图尺寸不会变,而连续相同的像素点也是固定,最多你把一个像素点灰阶从很大压缩到1,使用UIImageJPEGRepresentation压缩图像主要是图像格式方面的压缩,而修改它的compressionQuality主要是修改它的分辨率,所以通过UIImageJPEGRepresentation修改compressionQuality对图片压缩到一定程度,图像大小是无限趋近于不变化而不是无限接近0),也就是超大尺寸的图片经过非尺寸方面的压缩后可能很小,但是不会无限小通常有100k以上。

UIImageJPEGRepresentation(compressedImage, compressionQuality)其中的compressionQuality可以称为图片质量参数,它能决定压缩后的图片大小和分辨率。一般的图片,当compressionQuality为0.7时和原图片大小比较接近,但是这和图像的尺寸,色彩丰富度等各种图像指标有关,有的是compressionQuality为0.8,有的是compressionQuality为0.5时更接近压缩前的图片大小,这个没有固定的值,它取决为图片本身,不能用一张图片设置为0.5时解决原图片都认为compressionQuality为0.5接近原图片。以前我专门测试过compressionQuality的值对图片原来大小的比例。只要测试10兆超级大的尺寸图片,全黑图片,全白图片,色彩特别复杂的图片。有的文章一概而论的说法本来就是错误的。

注意把一般的jpg图片通过UIImagePNGRepresentation(compressedImage)转变为png格式的图片,大约会变大1.2倍左右(具体多少根据图片来决定,但是基本都变大是肯定的)。但是png支持透明背景图片,把png 格式透明背景的图片转变jpg格式的图片,图片背景会变成默认的黑色。

由于常见的jpeg和png都有损压缩,若非必要,尽量别来回压缩。图像压缩很费时间和内存的,特别是时间。

图像可以通过图像尺寸和图像大小(图像格式和分辨率方面的压缩)两方面的多次压缩。

下面是按照要求,把图像压缩到指定的大小或接近最小值的循环压缩图像的算法(注意这个很浪费时间,有大图像可能需要浪费你几秒很正长,大尺寸图像很可能压缩不到你设置的很小的值,但是能接近它的最小值。这种压缩的特点是图片大小压缩很快,并且不改变图片的尺寸):

static const long long shareImageMaxLength = 1024*1024;
-(UIImage *)getImageWithDada : (NSData *)data
{
    if(!data)
    {
        return nil;
    }
    UIImage *image = [UIImage imageWithData:data];
    if(data.length <= shareImageMaxLength)
    {
        NSLog(@"data.length:%lu", (unsigned long)data.length);
        return image;
    }
    else
    {
        CGFloat compressionQualityArr[1001] = {0};
        compressionQualityArr[0] = 0.0001;
        for(NSInteger i = 1; i <= 1000; i++)
        {
            compressionQualityArr[i] = i*0.001;
        }
        NSData *compressedData = [self findImageWithImage:image lowerBoundary:0 upperBoundary:1000 compressionQualityArr:compressionQualityArr];
        return [UIImage imageWithData:compressedData];
    }
}

-(NSData *)findImageWithImage : (UIImage *)image
                 lowerBoundary : (NSInteger)lowerBoundary
                 upperBoundary : (NSInteger)upperBoundary
         compressionQualityArr : (CGFloat *)compressionQualityArr

{
    NSInteger x = (lowerBoundary + upperBoundary) / 2;
    NSData *data = UIImageJPEGRepresentation(image, compressionQualityArr[x]);
    if(data.length <= shareImageMaxLength)
    {
        NSLog(@"data.length:%lu,compressionQualityArr[%ld]:%f", (unsigned long)data.length, (long)x, compressionQualityArr[x]);
        return data;
    }
    if ((data.length > shareImageMaxLength) && (x > 0))//说明在compressionQualityArr[lowerBoundary]-compressionQualityArr[x]范围参数之中
    {
        return [self findImageWithImage:image lowerBoundary:lowerBoundary upperBoundary:x compressionQualityArr:compressionQualityArr];
    }
    else
    {
        NSLog(@"data.length:%lu,compressionQualityArr[%ld]:%f", (unsigned long)data.length, (long)x, compressionQualityArr[x]);
        return data;
    }
}

下面是把宽或高大于指定尺寸的图片等比例压缩到指定宽高范围内的图片的算法。图像大小一般在苹果手机上影响下载的快慢等用户体验问题,但是图像尺寸太大,苹果电脑直接不支持。我们的app甚至出现过SDWebImage下载图片时崩溃,没有办法只有通过修改SDWebImage这个开源库,压缩图像的尺寸才避免了崩溃。前不久做多图片分享时,调用系统分享组件UIActivityViewController,结果直接分享的界面出不来。只要尺寸指定不超过iphone X,一个图片再怎么大也大不到哪里去,但是超大尺寸的图片搞个几百兆没有问题。下面图片宽高设置为不超过iphone X ps像素。由于我是通过NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]]直接得到的图像数据流,所以压缩函数的入参是(NSData *)data。

/**分享的图片最大宽度,单位:ps像素(不是物理像素)*/
static const long long maxShareImageWidth = 800;
/**分享的图片最大高度,单位:ps像素(不是物理像素)*/
static const long long maxShareImageHeight = 800;
-(UIImage *)compressImageWithDada : (NSData *)data
{
    UIImage *image = [UIImage imageWithData:data];
    if((image.size.height <= maxShareImageHeight) && (image.size.width <= maxShareImageWidth))
    {
        return image;
    }
    if((maxShareImageWidth == 0) || (maxShareImageHeight == 0))
    {
        //防止除数为0而crash,理论上不该出现maxIphoneScreenMaxSizeHeight为0
        return nil;
    }
//    float imageWidth = image.size.width;
//    float imageHeight = image.size.height;
    //800x800
    float width = maxShareImageWidth;
    float height = image.size.height/(image.size.width/width);
    
    if((image.size.width >= maxShareImageWidth) && (image.size.height >= maxShareImageHeight))
    {
        width = maxShareImageWidth;
        height = image.size.height/(image.size.width/width);
        if(height > maxShareImageHeight)
        {
            height = maxShareImageHeight;
            width = image.size.width/(image.size.height/height);
        }
    }
    else if(image.size.width >= maxShareImageWidth)
    {
        height = maxShareImageHeight;
        width = image.size.width/(image.size.height/height);
    }
//    else if(image.size.height >= maxIphoneScreenMaxSizeHeight)
//    {
//        width = maxIphoneScreenMaxSizeWidth;
//        height = image.size.height/(image.size.width/width);
//    }
    
    
//    float widthScale = imageWidth /width;
//    float heightScale = imageHeight /height;
    
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [image drawInRect:CGRectMake(0, 0, width , height)];
//    if (widthScale > heightScale) {
//        [image drawInRect:CGRectMake(0, 0, imageWidth /heightScale , height)];
//    }
//    else {
//        [image drawInRect:CGRectMake(0, 0, width , imageHeight /widthScale)];
//    }
    
    // 从当前context中创建一个改变大小后的图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    
    return newImage;
    
}

当然你不怕压缩太费时间你也可以把图像尺寸压缩和图像大小方面的压缩(我暂时也叫它图像分辨方面方面的压缩吧)。

下面是先用图像大小压缩,当压缩到最小还是太大就采用图像尺寸方面的压缩。这种压缩不能解决大尺寸图片苹果手机支持的问题。因为相对苹果支持的尺寸是大尺寸的图片经过图像大小方面的压缩可能已经达标了,但是图像尺寸其实没变仍旧超标。这个只是两种图像压缩都使用的例子。当然你可以设计成先图像尺寸递归压缩然后图像大小太大再使用图像大小压缩的方法,这种方法我就不写了,自己改造就可以了。

-(UIImage *)getImageWithDada : (NSData *)data
{
    if(!data)
    {
        return nil;
    }
    UIImage *image = [UIImage imageWithData:data];
    if(data.length <= shareImageMaxLength)
    {
        NSLog(@"data.length:%lu", (unsigned long)data.length);
        return image;
    }
    else
    {
        CGFloat compressionQualityArr[1001] = {0};
        compressionQualityArr[0] = 0.0001;
        for(NSInteger i = 1; i <= 1000; i++)
        {
            compressionQualityArr[i] = i*0.001;
        }
        NSData *compressedData = [self findImageWithImage:image lowerBoundary:0 upperBoundary:1000 compressionQualityArr:compressionQualityArr];
        if(data.length <= shareImageMaxLength)
        {
            return [UIImage imageWithData:compressedData];
        }
        else
        {
            return [self compressImageWithDada:compressedData];
        }
    }
}
目录
相关文章
|
19天前
|
存储 人工智能 自然语言处理
Delta-CoMe:清华联合OpenBMB等高校开源的新型增量压缩算法
Delta-CoMe是由清华大学NLP实验室联合OpenBMB开源社区、北京大学和上海财经大学提出的新型增量压缩算法。该算法通过结合低秩分解和低比特量化技术,显著减少了大型语言模型的存储和内存需求,同时保持了模型性能几乎无损。Delta-CoMe特别适用于处理数学、代码和多模态等复杂任务,并在推理速度上有所提升。
55 6
Delta-CoMe:清华联合OpenBMB等高校开源的新型增量压缩算法
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
阿里云人工智能平台 PAI 团队发表的图像编辑算法论文在 MM2024 上正式亮相发表。ACM MM(ACM国际多媒体会议)是国际多媒体领域的顶级会议,旨在为研究人员、工程师和行业专家提供一个交流平台,以展示在多媒体领域的最新研究成果、技术进展和应用案例。其主题涵盖了图像处理、视频分析、音频处理、社交媒体和多媒体系统等广泛领域。此次入选标志着阿里云人工智能平台 PAI 在图像编辑算法方面的研究获得了学术界的充分认可。
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
|
2月前
|
机器学习/深度学习 人工智能 算法
【MM2024】面向 StableDiffusion 的多目标图像编辑算法 VICTORIA
阿里云人工智能平台 PAI 团队与华南理工大学合作在国际多媒体顶级会议 ACM MM2024 上发表 VICTORIA 算法,这是一种面向 StableDiffusion 的多目标图像编辑算法。VICTORIA 通过文本依存关系来修正图像编辑过程中的交叉注意力图,从而确保关系对象的一致性,支持用户通过修改描述性提示一次性编辑多个目标。
|
1月前
|
存储 JSON 算法
TDengine 检测数据最佳压缩算法工具,助你一键找出最优压缩方案
在使用 TDengine 存储时序数据时,压缩数据以节省磁盘空间是至关重要的。TDengine 支持用户根据自身数据特性灵活指定压缩算法,从而实现更高效的存储。然而,如何选择最合适的压缩算法,才能最大限度地降低存储开销?为了解决这一问题,我们特别推出了一个实用工具,帮助用户快速判断并选择最适合其数据特征的压缩算法。
53 0
|
2月前
|
算法 数据安全/隐私保护
织物图像的配准和拼接算法的MATLAB仿真,对比SIFT,SURF以及KAZE
本项目展示了织物瑕疵检测中的图像拼接技术,使用SIFT、SURF和KAZE三种算法。通过MATLAB2022a实现图像匹配、配准和拼接,最终检测并分类织物瑕疵。SIFT算法在不同尺度和旋转下保持不变性;SURF算法提高速度并保持鲁棒性;KAZE算法使用非线性扩散滤波器构建尺度空间,提供更先进的特征描述。展示视频无水印,代码含注释及操作步骤。
|
3月前
|
算法 数据可视化 数据安全/隐私保护
基于LK光流提取算法的图像序列晃动程度计算matlab仿真
该算法基于Lucas-Kanade光流方法,用于计算图像序列的晃动程度。通过计算相邻帧间的光流场并定义晃动程度指标(如RMS),可量化图像晃动。此版本适用于Matlab 2022a,提供详细中文注释与操作视频。完整代码无水印。
|
5月前
|
机器学习/深度学习 编解码 监控
算法金 | 深度学习图像增强方法总结
**图像增强技术概括** 图像增强聚焦于提升视觉效果和细节,广泛应用于医学、遥感等领域。空间域增强包括直方图均衡化(增强对比度)、对比度拉伸、灰度变换、平滑滤波(均值、中值)和锐化滤波(拉普拉斯、高通)。频率域增强利用傅里叶变换、小波变换,通过高频和低频滤波增强图像特征。现代方法涉及超分辨率重建、深度学习去噪(如CNN、Autoencoder)、图像修复(如GAN)和GANs驱动的多种图像处理任务。
181 14
算法金 | 深度学习图像增强方法总结
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
|
5月前
|
算法
基于粒子群优化的图像融合算法matlab仿真
这是一个基于粒子群优化(PSO)的图像融合算法,旨在将彩色模糊图像与清晰灰度图像融合成彩色清晰图像。在MATLAB2022a中测试,算法通过PSO求解最优融合权值参数,经过多次迭代更新粒子速度和位置,以优化融合效果。核心代码展示了PSO的迭代过程及融合策略。最终,使用加权平均法融合图像,其中权重由PSO计算得出。该算法体现了PSO在图像融合领域的高效性和融合质量。
|
6月前
|
机器学习/深度学习 人工智能 算法
【CVPR2024】面向StableDiffusion的编辑算法FreePromptEditing,提升图像编辑效果
近日,阿里云人工智能平台PAI与华南理工大学贾奎教授团队合作在深度学习顶级会议 CVPR2024 上发表 FPE(Free-Prompt-Editing) 算法,这是一种面向StableDiffusion的图像编辑算法。在这篇论文中,StableDiffusion可用于实现图像编辑的本质被挖掘,解释证明了基于StableDiffusion编辑的算法本质,并基于此设计了新的图像编辑算法,大幅度提升了图像编辑的效率。
下一篇
DataWorks