分类:
2008-11-14 11:59:40
色彩深度 color depth 在图像中,它是由很多个点来组成的,那么存储每个像素点所用的位数就叫做像素深度。对一个图片,这个值是可以有所不同的,从而会使得图片的数据有多和少的区别。 一幅彩色图像的每个像素用 R,G,B 三个分量表示,若每个分量用8位,那么一个像素共用3X8=24位表示,就说像素的深度为24 bit,每个像素可以是2的24次方=16 777 216种颜色中的一种。表示一个像素的位数越多,它能表达的颜色数目就越多。 在用二进制数表示彩色图像的像素时,除 R,G,B 分量用固定位数表示外,往往还增加1位或几位作为属性(Attribute)位。例如,RGB 5∶5∶5表示一个像素时,用2个字节共16位表示,其中 R,G,B 各占5位,剩下一位作为属性位。在这种情况下,像素深度为16位,而图像深度为15 位。 在用32位表示一个像素时,若 R,G,B 分别用8位表示,剩下的8位常称为 alpha 通道(alpha channel)位,或称为覆盖(overlay)位、中断位、属性位。它的用法可用一个预乘 α 通道(premultiplied alpha)的例子说明。假如一个像素(A,R,G,B)的四个分量都用归一化的数值表示,(A,R,G,B)为(1,1,0,0)时显示红色。当像素为 (0.5,1,0,0)时,预乘的结果就变成(0.5,0.5,0,0),这表示原来该像素显示的红色的强度为1,而现在显示的红色的强度降了一半。 这个 alpha 值,在这里就用来表示该像素如何产生特技效果。 总体来说,图像的宽高、分辨率越高,就是组成一幅图的像素越多,则图像文件越大;像素深度越深,就是表达单个像素的颜色和亮度的位数越多,图像文件就越大。 |
第四个参数stateSurf,是故事的主角,一层一层跟进去,找到了他的原型
“typedef void* MMP_SURFACE;”
所以他是一个空指针,这种用法在我们的程序里面用得很多,应该是灵活的原因吧!
进入程序
|
可以看到程序先对 imageWidth 做了一个数据对齐的处理,得到 imageDelta,接着将此值乘以高度,得到 displaySize,并且对此值再做一次对齐处理!得到了所需的 stream 的大小,然后根据 baseScanPtr 的大小,M2D_CreateSurface,再把这个 surface 的头指针赋给newDisplay ,然后后面再用 *display = (MMP_M2D_SURFACE)newDisplay;,将此首地址传出去给我们前面说的 &stateSurf 。
PS:数据对齐是为了加快数据访问的一种技术,但是这里看起来好像并不是这个目的,是否跟图片的显示有关系呢?有待验证。
至此,我们已经在 SDRAM 里面开辟了一块区域,为图片的显示做好了准备。接着,就要把真实的图片data 放到里面去,这时候有两个方式:
#ifdef SMTK_RESOURCE_DYNAMIC_LOADING
smtkFileMgrResourceIsExist(FileName);
result = smtkGuiMgrCreateJpgToSurface((MMP_WCHAR*) FileName,
Surface,
FileWIDTH,
FileHEIGHT,
SMTK_GUI_FIT);
#else
result = smtkJpegMgrSimpleDecode( (MMP_UINT8*)BitmapJpg,
sizeofBitmapJpg,
Surface,
BITMAP_WIDTH,
BITMAP_HEIGHT);
#endif
第一种方法:smtkGuiMgrCreateJpgToSurface
此方法依赖于 filesystem,它可以直接傳進filename, 不必自己處理load file的動作,是比较方便的。使用这种方法,在文件头的地方都有类似:
#ifdef SMTK_RESOURCE_DYNAMIC_LOADING
static const PAL_TCHAR* FileName = RESOURCE_TDEFAULT PAL_T("FileName.jpg");
这样的定义。其中
#define RESOURCE_TDEFAULT NOR_VOLUME L"smediadata/"
这样就找到了这个图片在 filesystem中的路径了。
切进去函数 smtkGuiMgrCreateJpgToSurface,可以看到程序先调用 smtkJpegMgrStartDecode 对 jpeg 做解码,然后紧解着调用 smtkJpegMgrGetDecodeStatus 查询解码的情况,如果已经解完,则退出;否则一直在那边 polling decodeStatus。这个地方有两个问题需要注意:
1、 进入 smtkJpegMgrStartDecode,可以看到里面有 PalSetEvent(smtkJpegMgr.eventMgrToThread); 这样一行。这儿函数,产生了一个线程事件后,就退出了,继续跑后面的程序。这样来看,jepg 的解码,是一个独立的进程,所以,smtkJpegMgrStartDecode 执行完成,并不意味着解码结束!这也是后面用一个 while 可以polling decodeStatus 的原因。
2、 在用while polling decodeStatus 的时候,里面除了用smtkJpegMgrGetDecodeStatus 来得到解码的状态,还调用了 PalSleep(10); 这一句非常重要!因为我们的系统是一个多线程的系统,所以这样做后,可以使得这个 while,不会始终占用着 CPU 的资源,而使其他线程可以跑起来。例如在 slidershow +music 的时候,这样做,可以让后面的music 继续播,而不会因为 CPU 资源被占而停掉。至于要 sleep 多久,可以只能慢慢调节,取一个好一些的效果,不过一般用 10 比较多。
回头再看 smtkJpegMgrStartDecode,它其实只是将当前准备解码的图片的信息,传给了 smtkJpegShareData 这个结构体,然后就调用 PalSetEvent 将 jpeg 的decode 线程跑起来。再往后,就是很复杂的操作系统的东西了,信号量、消息队列等等都跑了出去。这些比较复杂,让操作系统去处理就好了。
第二种方法:smtkJpegMgrSimpleDecode通常是用來decode 非file型態的jpeg,如果 nor 的空间够,我们也可以都用这个方式,去将图片串成一个 array,然后直接对其操作。