• Skia第一个摘出来的例子,图片绕Y轴转


    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/

  • 相关阅读:
    FastJSON使用笔记
    使用mysql-connector-java出现的错误
    Maven的学习
    前端部分-CSS基础介绍
    前端知识之HTML内容
    python--使用pymyslq操作数据库
    python---反射详解
    python----re正则模块详解
    python---str和repr
    python---random模块详解
  • 原文地址:https://www.cnblogs.com/ezhong/p/2252780.html
Copyright © 2020-2023  润新知