JPEG格式 介绍
JPEG格式
- jpeg是有损压缩格式, 将像素信息用jpeg保存成文件再读取出来,其中某些像素值会有少许变化。在保存时有个质量参数可在[0,100]之间选择,参数越大图片就越保真,但图片的体积也就越大。一般情况下选择70或80就足够了。
- jpeg没有透明信息。
- jpeg比较适合用来存储相机拍出来的照片,这类图像用jpeg压缩后的体积比较小。其使用的具体算法核心是离散余弦变换、Huffman编码、算术编码等技术,有兴趣的同学可以在网上找一大堆资料,本文就不详细介绍了。
接下来要介绍一个有关jpeg非常实用的技术——
jpeg格式支持不完全读取整张图片,即可以选择读取原图、1/2、1/4、1/8大小的图片
比如5000*5000的一张大图,可以只读取将其缩小成1/8后即625*625大小的图片。 这样比先完全读取5000*5000的图像,再用算法缩小成625*625大小不知快多少倍。
如果应用需求只需要一张小图时,这种读取方式就可以大显身手了。
在c代码中读取jpeg一般是使用libjpeg, 这个库提供了不完全读取图片的功能。
给ln::LBitmap添加有关jpeg的接口,如下ReadJpeg()第三个参数fraction可取值为1,2,4,8,分别对应1/1,1/2,1/4,1/8
JpegAPI
具体的实现在JpegDemo
用上面的函数进行jpeg的读取和保存的测试

```
ln::LBitmap bmp;
bmp.ReadBmp(L"one.bmp");
unsigned char *p = bmp.Pixel(0, 0);
printf("%d, %d, %d\n", p[0], p[1], p[2]);
bmp.WriteJpeg(L"one.jpg", 90);
```

读取one.bmp图片,然后保存成jpeg格式,one.jpg放大后显示如下

发现左上角的颜色发生了变化,并且也影响到周围的像素,就算将上面WriteJpeg()第二个参数换成100,也还是这种效果,这是Jpeg格式无法避免的问题
但如果读取一张风景照,再保存成Jpeg,就几乎看不出有什么差别了。
android平台下实现jpeg预读

BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
BitmapFactory.decodeFile(info.fullPath, opt); //这里仅仅只读取jpeg的大小
opt.inJustDecodeBounds = false;
if (opt.outWidth > opt.outHeight) {
opt.inSampleSize = opt.outWidth / phSize;//hpSize是允许的图片宽高的最大值
} else {
opt.inSampleSize = opt.outHeight / phSize;
}
Bitmap b = BitmapFactory.decodeFile(info.fullPath, opt);

将BitmapFactory.Options的inJustDecodeBounds 设置为true后,就只会读取Jpeg的大小,而不会去解析像素数据。然后再设置inSampleSize后,就可以根据这个值来读取适当大小的图片,研究Android的源码后可以发现底层也是调用的libjpeg库来实现。
ios,mac
本人还没有在iOS/mac中发现如何预读jpeg的官方API。Apple对图形、图像、多媒体领域提供了丰富接口,如果这个功能真没实现就太令我惊讶了! 不过ObjectC完全兼容C,可以调用libjpeg库来实现这个功能。
.NET下仅读取jpeg的大小
下面是用c#仅仅读取jpeg宽高(没有解析像素数据), 直接用C#读取1/2,1/4,1/8还不知道如何实现
FileStream stream = new FileStream(path, FileMode.Open);
Image img = Image.FromStream(stream, false, false); //关键是将第三个参数设置为false
Console.WriteLine("size: {0},{1}", img.Width, img.Height);
jpeg批量转化工具
用相机拍出来的原始jpeg图片是高保真质量, 所占文件体积非常大,本人写了一个批量转化的工具,可以将jpeg的质量都转化成80, 图像的宽高不变, 这时人眼几乎看不出有什么差别, 但其体积只有原来的1/3. 如果有大量的照片需要保存时, 节约的空间就很客观了。实现原理很简单, 就是读取jpeg文件, 然后再保存.
用c#实现的,代码量非常少,在此贴出全部源码
Exif信息
另外jpeg文件一般有一个附属的exif信息,这个信息中有图像大小,拍摄时间,拍摄的相关参数,照片方向,图像缩略图等信息。
用相机拍出来的jpeg都会有这个信息。如果照片方向不是正立的话,在读取到像素取后,还得按exif所指明的方向将图像旋转下。mspaint程序就没有做这个处理,有些图片用picasa查看和用mspaint查看方向就不一样。当然为了简单起见,上面的LBitmap中也自动忽略了exif信息及其图像拍摄时的方向。
如果不用读取1/2,1/4,1/8的方法,也可以从exif中来读取缩略图,但这个缩略图一般很小。
说到exif,不得不说一款用perl实现的命令行工具:exiftool。几乎所有的多媒体文件(图像、音乐、视频)都可以用这个工具来查看其有关信息,当然如果不是jpeg文件就是指广义上的"exif"。在git中有已经编译好可执行文件exiftool.exe。使用方法是将这个文件放到系统路径下,然后在想查看的文件路径下执行 exiftool filename
在实现BatchJpeg工具时如果仅仅用上面实现的LBitmap来读取,保存, 将会失去exif信息, 而相片的拍摄时间等信息又很重要, 所以还得用另一个库exiv2来读取写入exif。如果用c#, 用上面的代码exif信息会自动保留下来。默默地向c#致敬。
intelJpeg库
如果在win32环境下对jpeg IO速度有很高的要求,可以使用interlJpeg库,不开源,但提供有*.h,*.lib文件。这个库可以大大提高jpg读取、保存速度。
当时分别用c#和c实现了jpeg批量转化工具, 在处理大量图片时发现c#用时居然只有c的一半。太奇怪了,按理说,c的速度比c#应该快才对啊, 而实事是c慢了这么多。 最后发现问题就在libjpeg上,用了intetJpeg后速度就和c#差不多了(猜想.NET内部也是用intelJpeg来处理jpeg)。
JPEG格式 介绍的更多相关文章
- 图像JPEG格式介绍
1 JPG格式介绍 JPEG (Joint PhotographicExperts GROUP)是由国际标准组织和国际电话电报咨询委员会为静态图像所建立的第一个国际数字图像压缩标准,也是至今一直在使用 ...
- 图像bayer格式介绍以及bayer插值原理CFA
1 图像bayer格式介绍 bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像. 对于彩色图像,需要采集多种最基本的颜色, ...
- Matlab JPEG详细介绍
作为一个基本的图像压缩方式,JPEG 已经得到了广泛的运用,但 JPEG 相关的基本原理,却经常被忽视,或解释得很不确切.这里我们详细讨论一下 JPEG 的编码原理,并结合实例来给出一个更加感性的认识 ...
- 图像bayer格式介绍【转】
本文转载自:http://www.cnblogs.com/whw19818/p/6223143.html 1 图像bayer格式介绍 bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发 ...
- 让阿里云的Centos,PHP组件 ImageMagick支持png和jpeg格式
我们在Centos安装ImageMagick教程中讲述了如何安装ImageMagick,安装完毕之后发现程序并不支持png和jpeg格式的图片,但是这两种图片又是我们平时所常见的,所以我们还要进一步地 ...
- Mysql Binlog 三种格式介绍及分析
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
- ecshop图片上传JPEG格式失败问题
在根目录下找到includes文件目录,在其目录中找到cls_image.php打开并找到: $allow_file_types = '|GIF|JPG|JEPG|PNG|BMP|SWF|'; 此处J ...
- 嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示
在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们 ...
- 超图不支持JPEG格式的WMTS服务
就目前面而言,超图不支持JPEG格式的WMTS服务,只支持PNG格式的. <本篇完>
随机推荐
- RPC性能优化
优化 1:元数据共享 hessian 序列化会将两种信息写到输出流: 元数据:即类全名,字段名 值数据:即各个字段对应值(如果字段是复杂类型,则会递归传递该复杂类型 的元数据和内部字段的值数据) 在 ...
- php--常见算法1
<?php //递归输出123321 function digui($num){ echo $num; if($num<3){ digui($num+1); } echo $num; } ...
- python部署到服务器(2) 一一 nginx+uwsgi+Django
参考菜鸟教程,https://blog.csdn.net/qq_42314550/article/details/81805328, 和 https://www.cnblogs.com/chenice ...
- cubase 的 CC控制器使用
- 【input】标签去除默认样式
input{-webkit-appearance: none; -moz-appearance: none; -o-appearance: none; appearance: none;}
- 【vuex】mutation和action的区别
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } ...
- vue的store状态管理模式
var store = { debug: true, state: { message: 'Hello!' }, setMessageAction (newValue) { //所有 store 中 ...
- java.sql.SQLException: Unknown column 'user0_.user_name' in 'field list' 报错问题
报错信息: java.sql.SQLException: Unknown column 'user0_.user_name' in 'field list'Query is: select user0 ...
- 04 vue-cli 脚手架、webpack-simple模板项目生成、组件使用
alice https://www.cnblogs.com/alice-bj/p/9317504.html https://www.cnblogs.com/alice-bj/p/9318069.htm ...
- 【JZOJ5603】【NOI2018模拟3.27】Xjz
题目描述 给定字符串 S 和 T. 串A和串B匹配的定义改为:存在一个字符的映射,使得A应用这个映射之后等于B,且这个映射必须为一个排列. A=121, B=313,当映射为{1->3, 2-& ...