1: about bitmap
位图的操作维系在CFbsBitmap,它可以表示一个被font和bitmap server所管理的位图。 它提供位图的生成,加载和存储。相关的还有一个TBitmapUtil类,这个类提供给用户很多函数来操作位图的bits(!),呵呵,是不是很实用啊。
位图一般根据其大小被存储在两个不同的堆中,大尺寸位图(这里有个限度值,为4KB)的存储位置和小尺寸位图是不同的,存储大尺寸位图的堆可以自动进行碎片整理以优化其空间:)
每个位图都有寸有两个尺度单位,一个是twips大小,这是所见即所得的真实世界大小尺寸,还有一个是象素尺寸。
如果要要更直接的操作位图,可以使用CFbsBitmap::DataAddress(), 它可以获得位图加载到内存中的地址,以次来操作位图bit,恐怕是最快的方法了,不过很烦,呵呵,注意了,这里如对RGB进行操作,要注意到色彩的差别, 一般概念上的是0xXXXXXX,用6位来表示RGB值,这成为24-bit色彩,但3650/7650的是4094色,即12bit色彩 (4KColor),因此操作时,我们要在两者之间转换,我们可以使用TRgb::Color4K进行转换,注意了,其参数是TInt值,不要 写*Address样式,否则在模拟器上能通过,手机上就会报告Kern-Exec 3错误了,很头疼:)
那怎么弄呢?我靠,居然不说!!
2: CCamera的两个size
这两天在解决一个在NOKIA 6680/1上的一个bug,在这个手机上,我们的程序启动camera的时候,会闪屏,很严重的那种,而且屏幕上finder的图片和其他的手机,比如7610等不一样,7610上是一个宽屏的,而他上面是一个全屏的,今天trace的时候发现API有问题,不知道是NOKIA的那个猪写的。先在SDK描述:
StartViewFinderBitmapsL()
virtual void StartViewFinderBitmapsL(TSize &aSize)=0;
Description
Starts transfer of view finder data.
Bitmaps are returned by MCameraObserver::ViewFinderFrameReady().
Parameters
TSize &aSize On return, the size used.
Leave codes
KErrNotReady if PowerOn() has not been called, or has not yet completed.
他说会在这个API中返回size的,所以在MCameraObserver::ViewFinderFrameReady().中就用到了这个size来表示bitmap的大小,在很多手机也是对的,但是很不信在6680/1上就是不对,即aSize的数值和从MCameraObserver::ViewFinderFrameReady()的参数aFrame(CFbsBitmap的一个引用)里面取得的大小不一样,这样用drawrect一画就遭了,高比宽大,很不好啊~~, 如果我们就是用bitmap的size的话,在二版的机器上是没有问题的,但是在三版的机子上有个紧接着的问题,就是当你在capture一个图之后要做preview的时候,由于要显示整个图,但是现在的screen的大小比图实际的大小要小很多,如果不做压缩的话就只能看到图的很小一部分,所以我还需要做个判断,当图的大小比screen的尺寸大的时候还要做压缩,nokia的程序能够自适应,可以参考一下。
有个参考的实现如下:
TSize finderSize = Size(); // screen size
TSize frameSize = iPreviewSize; // picture size, return by ccamera interface
TInt w1 = iPreviewImage->SizeInPixels().iWidth; // bitmpa size
TInt h1 = iPreviewImage->SizeInPixels().iHeight;
TInt w2 = finderSize.iWidth;
TInt h2 = finderSize.iHeight;
TInt w3;
TInt h3;
if (w2 < w1)
{
w3 = w2;
h3 = (TInt)((double)(h1) * (double)((double)w2 / (double)w1));
w1 = w3;
h1 = h3;
}
if (h2 < h1)
{
h3 = h2;
w3 = (TInt)((double)(w1) * (double)((double)h2 / (double)h1));
w1 = w3;
h1 = h3;
}
frameSize.SetSize(w1, h1);
TPoint finderPosition(0, 0);
finderPosition.iX += ((finderSize.iWidth - frameSize.iWidth)/2);
finderPosition.iY += ((finderSize.iHeight - frameSize.iHeight)/2);
User::ResetInactivityTime();
gc.Clear(aRect);
TRect drawRect( finderPosition, frameSize );
gc.DrawBitmap( drawRect, iPreviewImage );