SkBitmap *pskBitmap;
SkCanvas *pskCanvas;
BITMAPINFO *lpbmi;
HWND g_hWnd;
SkBitmap *bkBitmap;//背景图片
SkRect g_rtImg;// 图片最初按钮。
SkRect g_rtClip;//矩阵裁剪用 ,做图片旋转时,每次旋转时的裁剪会用到上一次的裁剪范围。
//g_rtClip是共用裁剪范围,多个不同的位置共用,每次旋转前初始化为要旋转图片的原始位置
//初始化背景图片,
void MyInitBkImage(char *filename)
{
SkFILEStream stream(filename);
SkImageDecoder * coder = SkImageDecoder::Factory(&stream);
if (coder)
{
bkBitmap = new SkBitmap();
coder->decode(&stream,bkBitmap,SkBitmap::kRGB_565_Config,SkImageDecoder::kDecodePixels_Mode);
}
}
//整体初始化
void MyInit()
{
pskBitmap = new SkBitmap();
pskBitmap->setConfig(SkBitmap::kRGB_565_Config,800,480);
pskBitmap->allocPixels();//分配位图所占空间
pskCanvas = new SkCanvas();
pskCanvas->setBitmapDevice(*pskBitmap);
lpbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(2) );
//printf("%d,%d\n",sizeof(BITMAPINFOHEADER),sizeof(BITMAPINFO));40,44
memset( lpbmi, 0, sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(2) );//必须同上方一直
lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);//位图信息头大小 40字节
lpbmi->bmiHeader.biWidth = 800;
lpbmi->bmiHeader.biHeight = -480;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = 16; //16位位图 565模式0xF800、0x07E0、0x001F
lpbmi->bmiHeader.biCompression = BI_BITFIELDS; //压缩参数 BI_RGB=0表示无压缩,
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiColors[0].rgbBlue = 0;
lpbmi->bmiColors[0].rgbGreen = 0xF8; //248?
lpbmi->bmiColors[0].rgbRed = 0;
lpbmi->bmiColors[0].rgbReserved = 0;
lpbmi->bmiColors[1].rgbBlue = 0xE0; //224
lpbmi->bmiColors[1].rgbGreen = 0x07; //7
lpbmi->bmiColors[1].rgbRed = 0;
lpbmi->bmiColors[1].rgbReserved = 0;
lpbmi->bmiColors[2].rgbBlue = 0x1F; //31
lpbmi->bmiColors[2].rgbGreen = 0;
lpbmi->bmiColors[2].rgbRed = 0;
lpbmi->bmiColors[2].rgbReserved = 0;
MyInitBkImage("\\USER\\skia\\bk.png");
g_rtImg.setLTRB(151,214,249,346); //初始化图片位置
//g_rtClip 在每次旋转前初始化
}
//画图片filename,rt为其范围,图片没有保存,每次临时加载
void DrawImage(char * filename,SkCanvas *canvas, SkRect rt, SkPaint *paint)
{
int ti = GetTickCount();
SkFILEStream stream(filename);
SkImageDecoder* coder = SkImageDecoder::Factory(&stream);
SkBitmap *bitmap;
if (coder)
{
//printf(" file %s code success\n",filename);
bitmap = new SkBitmap();
coder->decode(&stream, bitmap, SkBitmap::kRGB_565_Config,
SkImageDecoder::kDecodePixels_Mode);
}
else
{
printf(" file %s code fail\n",filename);
return;
}
//printf("24bit800*480png,code time =%d\n",GetTickCount()-ti);//367
ti = GetTickCount();
canvas->drawBitmap(*bitmap,rt.fLeft, rt.fTop);
//printf("24bit800*480png,draw time =%d\n",GetTickCount()-ti);//12
delete bitmap;
return;
}
//画背景
void DrawBKImage()
{
SkIRect rt;
rt.setXYWH(0,0,800,480);
int ti = GetTickCount();
pskCanvas->drawBitmap(*bkBitmap,rt.fLeft,rt.fTop);
printf("--------------time draw bk 24bit800*480=%d\n",GetTickCount()-ti);//11
}
//画图片filename,效果使其绕Y轴旋转rotateY角度,调用DrawImage()
void DrawRotateYImage(char * filename,int rotateY,SkRect rtImg)
{
SkRect rtClip = g_rtClip;//保留上次裁剪范围
pskCanvas->resetMatrix();
SkMatrix matrix;
Sk3DView sk3DView;
sk3DView.rotateY(rotateY); //绕Y轴旋转
sk3DView.getMatrix(&matrix);
matrix.preTranslate(-(rtImg.fLeft+rtImg.width()/2), 0);
matrix.postTranslate((rtImg.fLeft+rtImg.width()/2), 0);
matrix.mapRect(&g_rtClip,rtImg); //两个参数都是SkRect类型
//matrix.mapRect 作用:src经过matrix变化,形成dst
//图片的最初范围经过matrix变化(每次绕Y轴旋转角度不一样),得出新的裁剪范围
rtClip.join(g_rtClip); //计算最终裁剪范围
g_rtClip = rtClip ; //保存裁剪范围,供下次计算最终裁剪范围
//DrawBKImage();//此处画背景,不然会保留不同ratateY角度图片的痕迹 ,放在此处 画背景用时多 ,为4或者3,
pskCanvas->save();
pskCanvas->clipRect(rtClip);//矩阵裁剪
DrawBKImage();//此处画背景,不然会保留不同ratateY角度图片的痕迹 放在此处 画背景用时小 ,为0或者1,
//具体画的内容,与pskCanvas画布的裁剪有关系?
//pskCanvas->save(SkCanvas::kMatrix_SaveFlag); 可以去掉,之前已经有pskCanvas->save();
pskCanvas->concat(matrix);
DrawImage(filename,pskCanvas,rtImg,NULL);
//此处的位置参数须是图片原始位置,不能是裁剪范围,否则显示的位置偏离
//pskCanvas->restore(); 与save对应
pskCanvas->restore();
//pskCanvas->resetMatrix();
}
//触发图片旋转函数
void MyLButtonDown()
{
g_rtClip = g_rtImg; //初始裁剪范围为要画图片的正常范围。
for (int i =0;i<=10;i++)
{
DrawRotateYImage("\\user\\skia\\music-n.png",36*(i+0),g_rtImg);
HDC dc = GetDC(g_hWnd);
SetDIBitsToDevice(dc, 0, 0, 800, 480, 0, 0, 0, 800, pskBitmap->getPixels(), lpbmi, DIB_RGB_COLORS);
//将数据显示到屏幕上
ReleaseDC(g_hWnd,dc);
}
}
附图:
正常图效果
旋转45°效果
旋转180°效果
2011-11-18、11:01:59 补充
DrawRotateYImage()函数中:
//--------------------------------------------------------------------1
pskCanvas->save();
//--------------------------------------------------------------------2
pskCanvas->clipRect(rtClip);//矩阵裁剪
//--------------------------------------------------------------------3
DrawBKImage();//此处画背景,不然会保留不同ratateY角度图片的痕迹 放在此处 画背景用时小 ,为0或者1,
pskCanvas->concat(matrix);
//--------------------------------------------------------------------4
DrawImage(filename,pskCanvas,rtImg,NULL);
pskCanvas->restore();
//--------------------------------------------------------------------5
设置5个位置
将代码
SkRect rt = rtImg;
rt.fLeft +=150;
DrawImage(filename,pskCanvas,rt,NULL);
分别填到5个不同的位置。
总结:
在位置1,也就是pskCanvas->save之前,所有的画图是有效的。
在位置2,也就是cave之后,但是没有任何特殊的设置前,所有的画图是有效的。
在位置3,也就是clipRect之后,concat之前,所有的绘画,只在clipRect的矩形中有作用,其他范围绘画会被裁减
在位置4,也就是concat之后,restore之前,绘画的内容,会按照matrix旋转。如果经过matrix重置之后,如果还在之前clipRect的范围里,会显示。
此时是clipRect仍有效,但是是相对于经过matrix变化之后的图像
在位置5,也就是restore之后,所有绘画会正常显示。(复位到最近保存的设置,就是clipRect、concat等设置之前)
ezhong的博客园:http://www.cnblogs.com/ezhong/