1、逻辑坐标(单位长度 窗口) 和 设备坐标(像素长度 视口)
<1>逻辑坐标。逻辑坐标即是世界坐标系下的坐标。逻辑坐标与设备无关,客观世界中的场景可以由世界窗口或视口中进行描述,在窗口中进行描述时使用世界坐标系中的坐标单位也即逻辑坐标,在视口中进行描述使用的是设备坐标。
<2>设备坐标。图形输出时,Windows将GDI函数中指定的逻辑坐标映射为设备坐标。在屏幕显示的设备坐标系统中,单位以像素点为准,水平值从左到右增大(正方向向右),垂直值从上到下增大(正方向向下)。注意设备坐标系的原点永远不会移动,它们仅仅与物理设备有关。
另有链接讲了一些映射模式中设备坐标与逻辑坐标转换 http://blog.csdn.net/pcliuguangtao/article/details/5961458
2、几点细节区分
<1>设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的
<2>逻辑坐标和设备坐标即使在缺省模式(MM_TEXT)下其数值也未必一致,除了在以下两种情况下: 1. 窗口为非滚动窗口 2. 窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。
<3>在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻辑坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标,可以使用CDC 函数DptoLP()将设备坐标转化为逻辑坐标,同样可以用LptoDP()将逻辑坐标转化为设备坐标。
3、Bitblt用法
在VC中显示位图常用取BitBlt()方法,它是将一幅位图从一个设备场景复制到另一个。源和目标DC相互间必须兼容。假设我已经将要用的位图导入到工程资源中,所以我可以用: CBitmap cbmp; cbmp.LoadBitmap(IDB_BMP1);这样得到一个CBitmap对象。然后: BITMAP bitmap; cbmp.GetBitmap(&bitmap);这样得到一个BITMAP对象,之所以要得到此对象是因为从其中可以得到位图的大小数据。然后计算得到要在什么位置显示此位图(可以放在一个CRect rect;对象中)。然后显示此位图,这是最重要的一步: CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); hOldBitmap = dcMemory.SelectObject(&cbmp); pDC->BitBlt(rect.left, rect.top, bitmap.bmWidth, bitmap.bmHeight, &dcMemory, 0,0, SRCCOPY);其中pDC是一个CDC*,是将要在其中显示位图的设备环境。这样位图就已经显示出来了,但是还要释放资源: cbmp.DeleteObject(); dcMemory.SelectObject(hOldBitmap); dcMemory.DeleteDC();其中,要将临时设备环境选择入初始时位图,否则将不能正确释放!!
Bitblt作用将某一内存块的数据传送到另一内存块,前一内存块被称为"源",后一内存块被称为"目标"图象程序开发者使用Blit的函数在内存中将某页面上的一幅位图经过一定的变换转移到另一个页面上BitBlt光栅操作符dwRop参数是光栅操作代码(Rop),它是指源位图与目标位图以及图案刷的颜色值进行布尔运算的方式,以下列出了常用的光栅操作码及含义BLACKNESS 用黑色填充目标矩形区域.DSTINVERT 将目标矩形图象进行反相. MERGECOPY 将源矩形图象与指定的图案刷(Pattern)进行布尔"与"运算. MERGEPAINT 将源矩形图形经过反相后,与目标矩形图象进行布尔"或"运算.NOTSRCCOPY 将源矩形图象经过反相后,复制到目标矩形上.NOTSRCERASE 先将源矩形图象与目标矩形图象进行布尔"或"运算,然后再将得图象进行反相.PATCOPY 将指定的图案刷复制到目标矩形上.PATINVERT 将指定的图案刷与目标矩形图象进行布尔"异或"运算.PATPAINT 先将源矩形图象进行反相,与指定的图案刷进行布尔"或"运算,再与目标矩形图象进行布尔"或"运算SRCAND 将源矩形图象与目标矩形图象进行布尔"与"运算.SRCCOPY 将源矩形图象直接复制到目标矩形上.SRCERASE 将目标矩形图象进行反相,再与源矩形图象进行布尔"与"运算.SRCINVERT 将源矩形图象与目标矩形图象进行布尔"异或"运算.SRCPAINT 将源矩形图象与目标矩形图象进行布尔"或"运算.WHITENESS 用白色填充目标矩形区域.
4、可同理 StrenchBlt SetDIBitsToDevice StretchDIBits但注意三点点<1>使用StrenchXXX时,需要先设置CDC::SetStretchBltMode(MODE),其中MODE可取COLORONCOLOR或HALFTONE
<2>设备无关图xxxDIBitsxxx 函数参数包含BITMAPINFO,因为需要传入自定义调色板, 而设备相关图可直接使用BitBlt 或 StrenchBlt
<3>在StrenchXXX中,通过改变源与目标 宽、高正负号可使图片完成上下,左右等翻转
// 我传入的图片指针,指向内容从图片正确显示方向,由左至右,由上至下的顺序(见5<1>) void LiveView_CWJ(CWnd* pWnd, unsigned char * pImageBuffer, S_Show_Position* p, BITMAPINFO* bmpInfo, int nStretchMode) { CDC * pDC = pWnd->GetDC(); CDC MemDC; if(!MemDC.CreateCompatibleDC(pDC)) { pWnd->ReleaseDC(pDC); return; } CBitmap bmp; bmp.CreateCompatibleBitmap(pDC,bmpInfo->bmiHeader.biWidth,bmpInfo->bmiHeader.biHeight); CBitmap* pOldBmp = MemDC.SelectObject(&bmp); ::SetDIBitsToDevice(MemDC.GetSafeHdc(), 0,0,bmpInfo->bmiHeader.biWidth,bmpInfo->bmiHeader.biHeight, 0,0,//扫描方向由图像底部向上开始显示,我的理解是,设备无关图操作从数据"最后一行"往前开始显示,而设备相关图则从头到尾显示 //没做过测试哈^_^, 另外需要找时间再试试 改变映射模式时这几个API的显示效果 0,(bmpInfo->bmiHeader.biHeight),pImageBuffer,bmpInfo,DIB_RGB_COLORS);pDC->SetStretchBltMode(COLORONCOLOR);//COLORONCOLOR HALFTONEpDC->StretchBlt(p->x,p->y,p->S_Width,p->S_Height,&MemDC,0,bmpInfo->bmiHeader.biHeight,/*first*/bmpInfo->bmiHeader.biWidth,-bmpInfo->bmiHeader.biHeight,/*second */ //两者都为0时和此时对比,图像上下翻转SRCCOPY);MemDC.SelectObject(pOldBmp);MemDC.DeleteDC();bmp.DeleteObject();pWnd->ReleaseDC(pDC);}5、这张图像说明两个问题<1> 上面的解释中,我传入的图像指针,内存数据 按照 下图中小窗口中从左至右,自上而下的顺序排列
<2>Matlab读入二进制数据,展示时,按照先排“列”再排“行”,也就是说正确的显示方向应该讲Matlab读入的数据转置后显示,才是正确的方向
新闻热点
疑难解答