图像分辨率指图像中存储的信息量,是每英寸图像内有多少个像素点,分辨率的单位为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 *)imagelowerBoundary : (NSInteger)lowerBoundaryupperBoundary : (NSInteger)upperBoundarycompressionQualityArr : (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为0return nil;}
//    float imageWidth = image.size.width;
//    float imageHeight = image.size.height;//800x800float 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// 并把它设置成为当前正在使用的contextUIGraphicsBeginImageContext(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];}}
}

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

  1. linux 常用压缩格式,Linux下常用压缩格式的压缩与解压方法

    Linux下常用压缩格式的压缩与解压方法 --------------------------------------------- .tar 打包:tar cvf *.tar *.*(原文件或目录) ...

  2. pydicom读取头文件_pydicom读取压缩格式的DICOM图像报错的解决方案

    本文由Markdown语法编辑器编辑完成. 前言: 已知用pydicom读取一类Dicom图像时会报错,报错信息大致如下: OSError: cannot identify image file &l ...

  3. unity 纹理压缩格式‘_[2018.1]Unity贴图压缩格式设置

    一.移动平台GPU 参考文档: 各种移动GPU压缩纹理的使用方法 - LuMing - 博客园​www.cnblogs.com 1.Imagination Technologies的PowerVR S ...

  4. 【Android 安装包优化】7z 文件压缩格式 ( 7z 格式简介 | 7z 命令使用说明 )

    文章目录 一.7z 文件压缩格式简介 二.7z 命令使用说明 1.压缩命令 2.解压命令 三.7z 命令示例 1.配置 7z 命令环境变量 2.压缩 3.解压缩 四.参考资料 一.7z 文件压缩格式简 ...

  5. android视频压分辨率压缩,视频的文件格式、压缩格式、码率、分辨率

    首先,明确几个基本概念:视频的文件格式.压缩格式.码率.分辨率, 视频的文件格式有:mkv,mp4,flv,wmv,rmvb等: 视频的压缩格式有:h.263,h.264,mpeg-2,rmvb等: ...

  6. 漫谈压缩格式:zip、tar、bz2、tar.gz...

    [Linux]漫谈压缩格式:zip.tar.bz2.tar.gz... 前言 为什么要有压缩文件 什么是压缩文件 常见压缩格式介绍 Linux常用压缩命令 tar命令 实例 对于.zip 小结 前言 ...

  7. Hive常见的压缩格式

    压缩格式 Hive支持的压缩格式有bzip2.gzip.deflate.snappy.lzo等.Hive依赖Hadoop的压缩方法,所以Hadoop版本越高支持的压缩方法越多,可以在$HADOOP_H ...

  8. 关于Hive中的存储格式及压缩格式详解

    最近面试,遇到了关于Hive的数据存储格式的问题,回答不尽人意,抽时间总结多看看关于Hive存储格式和压缩格式的内容. Hive底层数据是以HDFS文件的形式存储在Hadoop中的,选择一个合适的文件 ...

  9. unity-贴图压缩格式

    title: unity-贴图压缩格式 categories: Unity3d tags: [unity, ios, astc] date: 2017-12-21 20:09:12 comments: ...

最新文章

  1. [elixir! #0037] Agent 小传
  2. xgboost模型在centos系统下的可视化
  3. android6.0源码分析之Camera API2.0简介
  4. 编程实战一通讯录程序
  5. 【数据结构与算法】之深入解析“课程表”的求解思路与算法示例
  6. Java继承多态经典案例分享
  7. 偷学Office 2007之易用性改造
  8. java数组代表unicode值么,02-Java的数组
  9. Swift3.0P1 语法指南——枚举
  10. MySQL优化(二)
  11. 打印等腰三角形javascript
  12. 用CAJViewer识别图片文字
  13. Windows错误系统配置提权之系统服务权限配置错误 (二)
  14. 请定义一个方法用于判断一个字符串是否是对称的字符串,并在主方法中测试方法。例如:“abcba“、“上海自来水来自海上“均为对称字符串。
  15. 利用百度云存储制作外链mp3音乐地址
  16. 服务器RAID常见级别与JBOD概述
  17. 项目成功关键要素和项目成功关键要素
  18. golang:深入理解Go时间处理(time.Time)
  19. 基于Simulink宽带单基地雷达系统仿真(附源码)
  20. OpenVSLAM+图像拼接

热门文章

  1. C语言中常见的转义字符总结
  2. 第四章——软件测试流程和规范
  3. 数据仓库系列(3):数据的价值如何体现
  4. 埃森哲《2022 中国企业数字化转型指数》: 中国企业数字化进程五年间稳步推进,17% 企业成领军者
  5. 2022年我应该怎么学习SAP?上篇
  6. cocos creator 绘制闪电特效
  7. mixly for linux64,Mixly编程for Linux
  8. 双连通分量的题目列表(一)
  9. elasticsearch 怎么删除过期的数据
  10. Spring框架学习笔记---完结