深入探究:TIFF格式的影像如何转jpg (保持色彩不变)

最终代码链接附在最后,但我想先详细介绍一下TIFF(或者tif)转jpg,转换的问题和难点在哪里?

1. tif可以有8位,24位,32位甚至更高,又分为有符号,无符号等,对于学遥感和GIS的来说,接触到的tif影像往往是高像素深度的,tif影像中的灰度值可以是几千几万。但jpg,一般是8位,rgb都是0到255取值,所以tif到jpg,意味着色彩的压缩。

2. tif可以是多波段的,例如高分一号影像就有红绿蓝近红外四个波段,而jpg只有RGB三个颜色通道,tif转jpg意味着波段信息的丢失

一些人会觉得使用工具将tif直接转成jpg是件容易的事情,我们来看一下效果:

原始影像在ArcGIS中打开是左边的样子,中间则是用的ArcGIS工具箱中的工具转的(工具叫做:栅格转其他格式,注意转之前可能需要改变像素深度,降低到8位,不然那个工具会提示转换失败)。可以看到,直接转格式的效果并不好,图像变灰了。

我当时认为是arcgis在直接转jpg的时候,压缩了导致了,所以我决定自己写代码转,思路如下:使用gdal C# 版的读取每个像元值,找到最大和最小值,然后新建bitmap,将最大值变为255,最小值变为0,中间则是线性拉伸的,函数关系式应该是这样的:

得到的jpg是上边右边那幅图,说明自己写代码线性拉伸得到的jpg也会色彩失真。

重点来了:

仔细理解一下,其实,这些图片都包含了相同或相似的灰度信息和色彩信息,我们看到的颜色不同和色彩失真的情况,只是图像显示的方式不一样罢了。我们的电脑屏幕支持rgb,为什么我们转出来的jpg和在电脑上用arcgis打开看到的不一样,如果你只用转少量的格式,完全可以截图。但要实现批量和自动化,则需要写代码了。

以arcgis为例,打开属性的符号系统:

这下,应该明白了,arcgis在显示影像的时候,实际上不是单纯的将影像线性拉伸到0-255范围,而是采用了一定的方法,包括百分比截断,直方图均衡化,最值等等方式。

以百分比截断为例,就是设置两个百分比阈值,比如图中最小值0.5,最大值0.5,意思是说,在直方图中(如下图),前0.5%范围内的像元值变成0,后0.5%范围内的像元值变成255,中间的像元值则还是线性拉伸。

比如红色波段的直方图中,最小是89,最大是507,假如有10000个像元,那么,前10000x0.5%=50个像元拉伸为0,后50拉伸为255。这里的前50和后50指的是直方图中的个数,比如89的有10个,90的有20个,91的有25个,那么,所有像元值为89,90,91的像素,在jpg中相应的位置都赋值为0。网上也有一些关于百分比截断的说明,我看都不详细,有的还有错误。

最后,附上我自己写代码实现的tif转jpg的成果,拉伸方式采用的是百分比截断,还是C#结合GDAL读取影像,然后使用bitmap绘制保存。

但有个问题就是图像的宽度和高度发生了变化,不知道是什么原因,正在探究...

我把代码也上传了,点下面的链接下载。

C#将tif影像转成jpg方法(显示保持颜色不变,类似于直接在arcgis中截图)

 

更新:

后来发现这样转换的效果不是太理想,比直接在ArcGIS中截图效果差太多了,实际上可以使用arcpy,调用ExportToJPEG方法将影响导出成jpg图片,其实际就类似于ArcGIS中导出地图,ExportToJPEG经常用于使用arcpy批量制图,用在这里也是可以的,ExportToJPEG方法可以参考官方帮助文档:http://desktop.arcgis.com/zh-cn/arcmap/10.3/analyze/arcpy-mapping/exporttojpeg.htm

 

猜你喜欢

转载自blog.csdn.net/tuoyakan9097/article/details/81261675
今日推荐