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/
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ezhong的博客签名-------------------------------------
以上内容来自ezhong的博客园,作者:ezhong
ezhong的博客园: http://www.cnblogs.com/ezhong
感谢您的阅读。感谢您的分享。