8bit转16bit问题

dengsf 2007-01-16 05:27:51
很简单的问题,
只是想看如何能达到极速。

一个 256*240 8 bit的图像,
要转成 512*480 16 bit 图像,
大小刚好两倍。(原来1个像素对应转换后 2*2 的大小)
8 bit中的只是调色版数据,
需要查表得到实际的 16-bit RGB 值。
表的内容是固定的,
可以做一些预处理以方便处理,如同时转换多个像素等。

条件是固定的,
请问大家有什么加速的方法?
无论方法上,如表的预处理等,
还是语言使用,如用 MMX 指令等等。。
甚至很细微的操作也不妨提出。

欢迎讨论和指教!
...全文
1210 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
buggycode 2007-01-25
  • 打赏
  • 举报
回复
有意思,关注。

我赞成建一个大表256*256即128k的表。但是只初始化第一列。其他都设置成缺省值。查表时发现是缺省值就运算填入。
第一列是每个index的16bits值。后面的列将会放置当前行的第一例和其他行第一列的合成平均值。(可以考虑减半表格,减半可能导致查表变复杂 原来只要 (i<<8+j) )

这样只有2x+1,2y+1点不能直接查表获得,可以用四个点相加>>2或查表得到2个合成点>>1.

另外,认为可以在循环上下点功夫



gamedragon 2007-01-19
  • 打赏
  • 举报
回复
我说的64K是这样的,颜色i和颜色j混合插值,i的颜色是RiGiBi,j的颜色是RjBjGj,插出来的颜色是RkBkGk,总共有256种颜色,那么它们插值可能生成的颜色是256*256/2=32K(不好意思之前说错了),每个颜色2个字节,总表大小应该是64K。
不插值的话,就是256种颜色,每个颜色2个字节,表大小是512,这个就是调色板,肯定要云县准备好的。
zzwu 2007-01-19
  • 打赏
  • 举报
回复
我所考虑的那张表c[]长度只有256,用不到64k.
也只有长为256的表,才能从逻辑色直接对应到RGB色.

gamedragon 2007-01-19
  • 打赏
  • 举报
回复
确实如此,LS老兄跟我说的是一个意思,预先插值生成的表过大,不容易完全cache命中,所以不如直接用MMX指令来的有效。
zzwu 2007-01-19
  • 打赏
  • 举报
回复
插值得到的RGB值应为2的16次方=65536,考虑到对称性,可以只用32768个.
但我认为这种插值预先生成不很必要,因为,这不但大量占用空间,同时
估计其中的极大部分是没有用的.

zzwu 2007-01-18
  • 打赏
  • 举报
回复
这里的查表不是搜索,而是一种直接取数操作,例如
如果原来图像某点的逻辑色是k,则新图像中对应点的RGB颜色就是c[k],
其中c[]就是预先制作好的那张表,
因操作频繁,且表很小(512字节),此表很有可能一直驻留在cache中.
gamedragon 2007-01-18
  • 打赏
  • 举报
回复
查表这种内存操作在某些情况下加速并不明显,比较大的表甚至有可能降低速度,因为涉及到cache命中的问题,另外在寄存器中运算的速度要比内存操作快的多得多。
我之前帮忙优化算法,原来的算法是分配一小块内存,在其中进行计算(计算量不是太大),然后把新的数据copy进来,算法继续。其中涉及到大量memcpy操作。我把它改成直接在一整块大内存上进行操作,数据移动靠指针操作,原则上应该大幅提高速度。但实际效果只减少了一半时间,应该就是cache命中的关系。频繁操作的一块小内存是被完全映射到cache中的,cache的存取速度要比内存快得多。
zzwu 2007-01-18
  • 打赏
  • 举报
回复
还可以采用的加速技巧有:

* 将调色板中256种索引色,预先转成16bit的RGB色.
-- 这样对整个图像要进行pack的次数就由n*m次降为256次,很少了!

* 在利用公式
R[2i+1,2k]=( (R[2*i,2k]+R[2*i+2,2k])/2 )
G[2i+1,2k]=( (G[2*i,2k]+G[2*i+2,2k])/2 )
B[2i+1,2k]=( (B[2*i,2k]+B[2*i+2,2k])/2 )
求RGB平均之前,预先检查被平均的两个像素是否相同,
如果相同,就直接利用其中一个像素,无需再作平均.
-- 考虑到256色图像相邻像素颜色相同的几率很大很大,
这一措施能收到的效益也会是非常可观的.


寻开心 2007-01-18
  • 打赏
  • 举报
回复
这个问题是比较特殊, zzwu已经说的很到位了
要想速度最快,当然是算法确定有用汇编语言来实现最快

从算法的角度上说, 1个象素扩大成为2*2的难度不大
即便考虑到插值, 只用加法和移位(替代/2操作)就可以了

考虑到实际的使用环境,16位bmp图是存在5551格式和565格式的问题还是比较麻烦的
gamedragon 2007-01-18
  • 打赏
  • 举报
回复
这个表实际上就是调色板,肯定是要预先准备好的了。
但是插值要查表的话,从索引直接得到插值后的颜色,就要准备64K*2=128K的数据,要完全cache命中不容易。
如果不插值的话,MOVD,PUNPCKLW,MOVDQ差不多也就这几条指令了吧,用MMX指令要注意地址对齐(记不清是8字节还是16字节对齐了)。
gamedragon 2007-01-17
  • 打赏
  • 举报
回复
只能想到用MMX加速,再就是保证cache命中,其他想不到什么了。
dengsf 2007-01-17
  • 打赏
  • 举报
回复
没人吗?
我知道问题确实很简单,
随便想一会就能写出很好的程序来。
只是想,
越是这类基本的东西,
越有可能有令人意想不到的秘技,
希望开阔视野而已。

确实没有的话当SF也可,
BZ不会删帖吧。
以后有其它深入的问题多指教即可。
zzwu 2007-01-17
  • 打赏
  • 举报
回复
当然,从8bit分量中取出5(或6)bit是需要的.
zzwu 2007-01-17
  • 打赏
  • 举报
回复
这里只有pack,没有用到unpack,因为调色板中的数据本身可以按byte取出的.
zzwu 2007-01-17
  • 打赏
  • 举报
回复
算法步骤如下:

1.先产生行列均为偶数的坐标(2i,2k)的象素,
 这些坐标的像素的颜色就是原来图像的像素的颜色,但需要从调色板里取出RGB值,
再按555或565格式组装成16位的字,作为新图像的RGB颜色值.
但取出后的R,G,B三个分量也要一数组保留起来,以便后面调用.

2.利用上述点的RGB值来产生具有偶数2k行奇数列坐标的像素的RGB:
R[2i+1,2k]=( (R[2*i,2k]+R[2*i+2,2k])/2 )
G[2i+1,2k]=( (G[2*i,2k]+G[2*i+2,2k])/2 )
B[2i+1,2k]=( (B[2*i,2k]+B[2*i+2,2k])/2 )
 以上插值就是左右相邻像素RGB的简单平均,显然可以不用乘法或除法,
这样算出的R,G,B值同样要装配成字后才能成为偶数行奇数列的颜色,
而且R,G,B三个分量值同样要保留起来供下面一步调用.

3.再用类似方法,由偶数行的RGB值来行程奇数行的RGB值。

为了提高速度,可以用ASM来实现,且尽量用一个程序完成,不要用子例程.
gamedragon 2007-01-17
  • 打赏
  • 举报
回复
要插值的话RGB三个分量要分别插值,对于16bit的图像涉及到unpack和pack,用MMX或SSE指令肯定会大幅提高运算速度。
zzwu 2007-01-17
  • 打赏
  • 举报
回复
可以设计一个专用的双线性插值来产生2*2的新图像,
插值实际只是相邻像素色彩的平均,
用到的乘2,除2以及RGB组装成16bit的字,均可以用左移右移及逻辑乘来实现。
所以,算法的工作量实际很小。
我想用不到MMX指令也可以很快!

4,446

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧