1.BMP图片文件格式
参见博客BMP文件格式详解,这篇博客写的非常详细,不想看的话可以看下面的简单介绍,简介大多引用自这里。
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:bmp文件头(bmp file header);位图信息头(bitmap information);调色板(color palette);位图数据(bitmap data)。下面是8位BMP图像和24位BMP图像的简介,如果觉得不详细的话就去看上面的博客。
BMP文件头:
BMP信息头:
8位BMP文件格式: BMP文件头(14Byte),位图信息头(40字节),调色板(256*4字节。是这么来的:8位一共可以表示256种颜色,每种颜色4字节(R,G,B,Alpha)),位图数据(每行(图片的宽×每个像素的Byte)必须是4的倍数,不足会用0填充)。下面以一张图片的数据简单说明一下。
下面这张图片是256×256的,大小是65.05KB:
下面是这张图的部分数据及对应的信息,其中数据部分的数据值对应的就是调色板的数据,如47,在调色板(B,G,R,Alpha)中就是(47, 47, 47, 0),大于一字节的数据是用小端形式存储的(不懂小端模式的话可以参见这篇博客):
24位BMP图片格式: BMP文件头(14Byte),位图信息头(40字节),位图数据(每行(图片的宽×每个像素的Byte)必须是4的倍数,不足会用0填充)。下面以一张图片的数据简单说明一下。
下面这张图片是256×256的,文件大小是192.05KB
下面是这张图的部分数据及对应的信息,其中文件头和信息头和8位BMP是一样的,不过没有调色板,直接用24位表示一种颜色(如图中的39,16,52表示R(52)G(16)B(39))。大于一字节的数据也是用小端形式存储的。
2.拉格朗日差值简介
问题提法(来自XTU数值分析课程的PPT):
通俗一点说也就是通过几个已知的样本点来求估计一个位置的点的函数值。
一般求法(来自百度):
3.运用拉格朗日差值对BMP图片进行处理
原理(来自XTU数值分析课程的PPT):
以上图中的6×6缩小到3×3为列子,解释一下此算法的过程:
- 求出缩小图片列对应原图列中的位置(g(i)),想象一下缩放的过程就能明白为什么这样算。
- 求出每个g(i)附近的n个点(n越大,精度越高)。
- 把每个g(i)附近的n个点(对应原图中的点,如2.5附近的三个点是2,3,4这三个点的函数值就是原图中的颜色值(RGB),这n个点也可能有小于0或者大于原图宽度的点,如果有的话就做对称处理,具体参见第6步)当成样本点,利用拉格朗日差值算法算出g(i)的函数值,注意算出来的值要转换成整数。
- 以8位图中2.5附近的三个点2,3,4为列子计算(假设2 ,3,4点的数据值分别是22,100,33):
- 如果是8位图片的话,算出来的值代表的就是该点RGB(8位图中的RGB和数据值是一样的,Alpha为0,有兴趣可以调下Alpha看看有什么效果)。如果是24位图片的话就当成3个8位图片处理,依次对R、G、B进行处理。
- 如果算出来的n个值中有小于0或者大于原图宽度的值,就对其进行对称处理,具体方法如下:假如插值需要3个样本,它们是(-1,f(-1)),(0,f(0)),(1,f(1)),那么其中的(-1,f(-1))要做对称处理。处理后三个样本为(-1,f(1)),(0,f(0)),(1,f(1)),即f(-1)变成f(1),不过算的时候还是用-1算,只是函数值变了。
- 对图片中的每一行都进行行处理。
- 经过7步的处理后,我们把6×6缩成了6×3,还要进行行处理来缩成3×3。
- 注意每行数据必须是4的倍数,不足的要进行0填充。
- 处理后图的第k行,从离它最近的原图行取样进行插值。对于处理后图的第k行,原图中离它最近的行是round(k*(H0-1)/(H-1)),H0是原图高度,H是处理后图像的高度。原图共8行,第0行~第7行,即H0=8(即原图高度为8)。缩放后图像的行数为4行,第0行~第3行,即H=4。计算缩放图像的第1行,应从原图的第round(1*(8-1)/(4-1))=round(2.333…)=2行取样。计算缩放图像的第2行,应从原图的第round(2*(8-1)/(4-1))=round(4.666…)=5行取样。计算缩放图像的第3行,应从原图的round(3*(8-1)/(4-1))=round(7)=7行取样。
- 放大缩小原理一样。
代码实现(Java版本)
可以下载我写的戳这里,不过写的很菜QAQ。