??xml version="1.0" encoding="utf-8" standalone="yes"?>中文精品久久久久人妻,国产精品伊人久久伊人电影,国产精品日韩深夜福利久久http://www.shnenglu.com/swo2006/category/3203.htmlzh-cnMon, 19 May 2008 18:41:46 GMTMon, 19 May 2008 18:41:46 GMT60C++囑Ş领域新闻与资?/title><link>http://www.shnenglu.com/swo2006/articles/15119.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Mon, 13 Nov 2006 01:23:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/15119.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/15119.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/15119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/15119.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/15119.html</trackback:ping><description><![CDATA[http://www.kaidianle.com/article/list22277.html<img src ="http://www.shnenglu.com/swo2006/aggbug/15119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-11-13 09:23 <a href="http://www.shnenglu.com/swo2006/articles/15119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BMP位图文gl构及^滑羃?/title><link>http://www.shnenglu.com/swo2006/articles/14750.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Mon, 06 Nov 2006 14:25:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/14750.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/14750.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/14750.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/14750.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/14750.html</trackback:ping><description><![CDATA[ <span id="vnrxdrx" class="unnamed3"> <p> <font face="宋体" size="2">用普通方法显CBMP位图Q占内存大,速度慢,在图形羃时Q失真严?在低颜色位数的设备上昄高颜色位数的囑Ş囑Ş时失真大。本文采用视频函数显CBMP位图Q可以消除以上的~点?/font> </p> <p> <font face="宋体" size="2">一、BMP文gl构</font> </p> <p> <font face="宋体" size="2">BMP文gl成<br />BMP文g由文件头、位图信息头、颜色信息和囑Ş数据四部分组成?<br />BMP文g?br />BMP文g头数据结构含有BMP文g的类型、文件大和位图起始位置{信息?<br />其结构定义如?<br />typedef struct tagBITMAPFILEHEADER<br />{<br />WORDbfType; // 位图文g的类型,必须为BM<br />DWORD bfSize; // 位图文g的大,以字节ؓ单位 <br />WORDbfReserved1; // 位图文g保留字,必须?<br />WORDbfReserved2; // 位图文g保留字,必须?<br />DWORD bfOffBits; // 位图数据的v始位|,以相对于位图<br />// 文g头的偏移量表C,以字节ؓ单位<br />} BITMAPFILEHEADER;</font> </p> <p> <br /> <font face="宋体" size="2">3. 位图信息?/font> </p> <p> <br /> <font face="宋体" size="2">BMP位图信息头数据用于说明位囄寸{信息?br />typedef struct tagBITMAPINFOHEADER{<br />DWORD biSize; // 本结构所占用字节?br />LONGbiWidth; // 位图的宽度,以像素ؓ单位<br />LONGbiHeight; // 位图的高度,以像素ؓ单位<br />WORD biPlanes; // 目标讑֤的别,必须?<br />WORD biBitCount// 每个像素所需的位敎ͼ必须?(双色),<br />// 4(16?Q?(256??4(真彩?之一<br />DWORD biCompression; // 位图压羃cdQ必L 0(不压~?,<br />// 1(BI_RLE8压羃cd)?(BI_RLE4压羃cd)之一<br />DWORD biSizeImage; // 位图的大,以字节ؓ单位<br />LONGbiXPelsPerMeter; // 位图水^分L率,每米像素?br />LONGbiYPelsPerMeter; // 位图垂直分L率,每米像素?br />DWORD biClrUsed;// 位图实际使用的颜色表中的颜色?br />DWORD biClrImportant;// 位图昄q程中重要的颜色?br />} BITMAPINFOHEADER;</font> </p> <p> <br /> <font face="宋体" size="2">4. 颜色?/font> </p> <p> <font face="宋体" size="2">  颜色表用于说明位图中的颜Ԍ它有若干个表,每一个表Ҏ一个RGBQUADcd的结构,定义一U颜艌ӀRGBQUADl构的定义如?<br />typedef struct tagRGBQUAD {<br />BYTErgbBlue;// 蓝色的亮?D围ؓ0-255)<br />BYTErgbGreen; // l色的亮?D围ؓ0-255)<br />BYTErgbRed; // U色的亮?D围ؓ0-255)<br />BYTErgbReserved;// 保留Q必Mؓ0<br />} RGBQUAD;<br />颜色表中RGBQUADl构数据的个数有biBitCount来确?<br />当biBitCount=1,4,8Ӟ分别?,16,256个表?<br />当biBitCount=24Ӟ没有颜色表项?br />位图信息头和颜色表组成位图信息,BITMAPINFOl构定义如下:<br />typedef struct tagBITMAPINFO {<br />BITMAPINFOHEADER bmiHeader; // 位图信息?br />RGBQUAD bmiColors[1]; // 颜色?br />} BITMAPINFO;</font> </p> <p> <br /> <font face="宋体" size="2">5. 位图数据<br />  位图数据记录了位囄每一个像素|记录序是在扫描行内是从左到?扫描行之间是从下C。位囄一个像素值所占的字节?<br />当biBitCount=1Ӟ8个像素占1个字?<br />当biBitCount=4Ӟ2个像素占1个字?<br />当biBitCount=8Ӟ1个像素占1个字?<br />当biBitCount=24?1个像素占3个字?<br />Windows规定一个扫描行所占的字节数必L<br />4的倍数(即以long为单?,不的以0填充Q?br />一个扫描行所占的字节数计方?<br />DataSizePerLine= (biWidth* biBitCount+31)/8; <br />// 一个扫描行所占的字节?br />DataSizePerLine= DataSizePerLine/4*4; // 字节数必L4的倍数<br />位图数据的大?不压~情况下):<br />DataSize= DataSizePerLine* biHeight;</font> </p> <p> <br /> <font face="宋体" size="2">二、BMP位图一般显C方?/font> </p> <p> <font face="宋体" size="2">1. 甌内存I间用于存放位图文g<br />  GlobalAlloc(GHNDQFileLength);</font> </p> <p> <font face="宋体" size="2">2. 位图文gd所甌内存I间?br />   LoadFileToMemory( mpBitsSrcQmFileName);</font> </p> <p> <font face="宋体" size="2">3. 在OnPaint{函C用创建显C用位图<br />  用CreateDIBitmap()创徏昄用位图,用CreateCompatibleDC()创徏兼容DC,<br />  用SelectBitmap()选择昄位图?/font> </p> <p> <font face="宋体" size="2">4. 用BitBlt或StretchBlt{函数显CZ?/font> </p> <p> <font face="宋体" size="2">5. 用DeleteObject()删除所创徏的位?/font> </p> <p> <font face="宋体" size="2">  以上Ҏ的缺Ҏ: 1)昄速度? 2) 内存占用? 3) 位图在羃显C时囑Şq?(可通过安装字体qx软g来解?; 4) 在低颜色位数的设备上(?56昄模式)昄高颜色位数的囑Ş(如真彩色)囑Şq严重?/font> </p> <p> <font face="宋体" size="2">三、BMP位图~放昄<br />   用DrawDib视频函数来显CZ图,内存占用,速度快,而且q可以对囑Şq行淡化(Dithering)处理。E化处理是一U图形算法,可以用来在一个支持比囑փ所用颜色要的讑֤上显C彩色图像。BMP位图昄Ҏ如下:</font> </p> <p> <font face="宋体" size="2">1. 打开视频函数DrawDibOpen()Q一般放在在构造函C</font> </p> <p> <font face="宋体" size="2">2. 甌内存I间用于存放位图文g<br />  GlobalAlloc(GHNDQFileLength);</font> </p> <p> <font face="宋体" size="2">3. 位图文gd所甌内存I间?--- <br />  LoadFileToMemory( mpBitsSrcQmFileName);</font> </p> <p> <font face="宋体" size="2">4. 在OnPaint{函C用DrawDibRealize()QDrawDibDraw()昄位图</font> </p> <p> <font face="宋体" size="2">5. 关闭视频函数DrawDibClose(),一般放在在析构函数?/font> </p> <p> <font face="宋体" size="2">  以上Ҏ的优Ҏ: 1)昄速度? 2) 内存占用? 3) ~放昄时图形失真小,4) 在低颜色位数的设备上昄高颜色位数的囑Ş囑Ş时失真小; 5) 通过直接处理位图数据Q可以制作简单动甅R?/font> </p> <p> <font face="宋体" size="2">四、CViewBimapcȝE要?/font> </p> <p> <font face="宋体" size="2">1. 在CViewBimapcMd视频函数{成?/font> </p> <p> <font face="宋体" size="2">HDRAWDIB m_hDrawDib; // 视频函数<br />HANDLEmhBitsSrc; // 位图文g句柄(内存)<br />LPSTR mpBitsSrc; // 位图文g地址(内存)<br />BITMAPINFOHEADER *mpBitmapInfo; // 位图信息?/font> </p> <p> <font face="宋体" size="2">2. 在CViewBimapcL造函Cd打开视频函数<br />  m_hDrawDib= DrawDibOpen();</font> </p> <p> <font face="宋体" size="2">3. 在CViewBimapcL构函Cd关闭视频函数</font> </p> <p> <font face="宋体" size="2">if( m_hDrawDib != NULL)<br />{<br />DrawDibClose( m_hDrawDib);<br />m_hDrawDib = NULL;<br />}</font> </p> <p> <font face="宋体" size="2">4. 在CViewBimapcd形显C函数OnPaint中添加GraphicDraw()<br />voidCViewBitmap::OnPaint()<br />{<br />CPaintDC dc(this); // device context for painting<br />GraphicDraw( );<br />}</font> </p> <p> <font face="宋体" size="2">voidCViewBitmap::GraphicDraw( void )<br />{<br />CClientDC dc(this); // device context for painting<br />BITMAPFILEHEADER *pBitmapFileHeader;<br />ULONG bfoffBits= 0;<br />CPoint Wid;</font> </p> <p> <font face="宋体" size="2">// 囑Ş文g名有?(=0 BMP)<br />if( mBitmapFileType < ID_BITMAP_BMP ) return;</font> </p> <p> <font face="宋体" size="2">// 囑Ş文g名有?(=0 BMP)<br />// 准备昄真彩位图<br />pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;<br />bfoffBits= pBitmapFileHeader->bfOffBits;</font> </p> <p> <font face="宋体" size="2">// 使用普通函数显CZ?/font> </p> <p> <font face="宋体" size="2">if( m_hDrawDib == NULL || mDispMethod == 0)<br />{<br />HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,<br />mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,<br />(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS); <br />// 建立位图<br />HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存<br />HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象<br />// 成员CRect mDispR用于指示囑Ş昄区域的大?<br />// 成员CPoint mPos用于指示囑Ş昄起始位置坐标.<br />if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))<br />mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;<br />if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))<br />mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();<br />if( mPos.x < 0 ) mPos.x= 0;<br />if( mPos.y < 0 ) mPos.y= 0;</font> </p> <p> <font face="宋体" size="2">if( mFullViewTog == 0)<br />{<br />// 昄真彩位图<br />::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),<br />hMemDC,mPos.x,mPos.y, SRCCOPY);<br />} else {<br />::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),<br />hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-<br />>biHeight, SRCCOPY);<br />}<br />// l束昄真彩位图<br />::DeleteObject(SelectObject(hMemDC,hBitmapOld)); <br />// ????br />} else {</font> </p> <p> <font face="宋体" size="2">// 使用视频函数昄位图</font> </p> <p> <font face="宋体" size="2">if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))<br />mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;<br />if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))<br />mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();<br />if( mPos.x < 0 ) mPos.x= 0;<br />if( mPos.y < 0 ) mPos.y= 0;</font> </p> <p> <font face="宋体" size="2">// 昄真彩位图<br />DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);</font> </p> <p> <font face="宋体" size="2">if( mFullViewTog == 0)<br />{<br />Wid.x= mDispR.Width();<br />Wid.y= mDispR.Height();<br />// 1:1 昄? 不能大于囑Ş大小<br />if( Wid.x > mpBitmapInfo- >biWidth )<br />Wid.x = mpBitmapInfo- >biWidth;<br />if( Wid.y > mpBitmapInfo- >biHeight)<br />Wid.y = mpBitmapInfo- >biHeight;</font> </p> <p> <font face="宋体" size="2">DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()<br />, 0, 0, Wid.x, Wid.y,<br />mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),<br />mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);<br />} else {<br />DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),<br />0, 0, mDispR.Width(), mDispR.Height(),<br />mpBitmapInfo, (LPVOID)</font> </p> </span> <img src ="http://www.shnenglu.com/swo2006/aggbug/14750.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-11-06 22:25 <a href="http://www.shnenglu.com/swo2006/articles/14750.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>位图[转蝲]http://www.shnenglu.com/swo2006/articles/11285.htmlswoswoWed, 16 Aug 2006 05:09:00 GMThttp://www.shnenglu.com/swo2006/articles/11285.htmlhttp://www.shnenglu.com/swo2006/comments/11285.htmlhttp://www.shnenglu.com/swo2006/articles/11285.html#Feedback0http://www.shnenglu.com/swo2006/comments/commentRss/11285.htmlhttp://www.shnenglu.com/swo2006/services/trackbacks/11285.html阅读全文

swo 2006-08-16 13:09 发表评论
]]>
一U位囄攄快速算?amp;PSD格式的开?amp;PSD格式文g的读?/title><link>http://www.shnenglu.com/swo2006/articles/11279.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Wed, 16 Aug 2006 02:42:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/11279.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/11279.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/11279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/11279.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/11279.html</trackback:ping><description><![CDATA[ <table border="0" cellpadding="4" width="100%"> <tbody> <tr> <td height="19"> <table border="0" cellpadding="3" cellspacing="3" width="100%"> <tbody> <tr> <td> <a >CSDN</a> - <a >文档中心</a> - <font color="#003399"><a id="ArticleTitle1_ArticleTitle1_hlClass" >其他开发语a </a></font></td> <td align="right"> 阅读Q?span id="ArticleTitle1_ArticleTitle1_lblReadCount">42</span>   评论Q? <span id="ArticleTitle1_ArticleTitle1_lblCommentCount">0</span>    <a >参与评论</a></td> </tr> </tbody> </table> <table bgcolor="#eeeeee" border="0" cellpadding="3" cellspacing="3" width="100%"> <tbody> <tr> <td height="0" nowrap="nowrap" width="60"> <br /> </td> <td> <br /> </td> </tr> <tr> <td align="center" bgcolor="#003399" height="16" nowrap="nowrap"> <font color="#ffffff">标题</font> </td> <td> <b>  <span id="ArticleTitle1_ArticleTitle1_lblTitle">一U位囄攄快速算?amp;PSD格式的开?amp;PSD格式文g的读?/span></b>     选择?<a id="ArticleTitle1_ArticleTitle1_AuthorLink" >byxdaz</a> ?Blog </td> </tr> <tr> <td align="center" bgcolor="#003399" height="16"> <font color="#ffffff">关键?/font> </td> <td width="500">  <span id="ArticleTitle1_ArticleTitle1_lblKeywords">一U位囄攄快速算?amp;PSD格式的开?amp;PSD格式文g的读?/span></td> </tr> <tr> <td align="center" bgcolor="#003399" height="16"> <font color="#ffffff">出处</font> </td> <td>  <span id="ArticleTitle1_ArticleTitle1_lblSource"></span></td> </tr> </tbody> </table> </td> </tr> <tr> <td width="10"> <br /> </td> <td> <span id="ArticleContent1_ArticleContent1_lblContent"> <p>一U位囄攄快速算?amp;PSD格式的开?amp;PSD格式文g的读?/p> <p>一U位囄攄快速算法?img src="E:%5CBaseInfoImage.bmp" /><br /><br />  l定一个位图,如何它~放至Q意尺寸?很明显,唯一的方法是Q放大时Q在像素中间d一些重复像 素,使图像拉宽;~小Ӟ把部分像素删除掉Q囑փ收羃。但是如何确定哪些像素该重复Q哪些像素该删除呢?下面的方法是我自已想的,如果你有更好的方法, 请告诉我。我们只考虑水^方向Q垂直方向跟水^方向是同L道理Q。下面先从简单的例子来说Q最后再推出一个通用的算法:<br /><br />若要攑֤1倍,应将每一个像素都重复一ơ,N个像素变成了2N个像素,囑փ攑֤?倍。这个不难;<br /><br />若要~小1/2Q应该每隔一个像素删除一个像素,2N个像素变成了N个像素,囑փ~小一半。这个也不难Q?br /><br />若要攑֤1.5倍,怎么办?假设原有2N个像素,现在Ʋ变?N个像素,L加N个像素,所以应对原图每隔一个像素添加一个重复像素: <br /><br />若要~小1/3Q就是C的逆过E:每隔两个像素删除一个像素。?br />   上面四个例子都是比较Ҏ的特例。现在来考虑通用的算法。在四个例子的羃放过E可以这L解。假设欲长度ؓN1的像素列变成长度为N2的像素列Q首 先,讄两个指针Q一个作为源指针Q指向原来的像素列,d源像素,另一个作为目的指针,指向变换后的像素列,写入d到的像素。然后,以拉伸后像素列的 长度为@环次敎ͼ循环N2ơ,每次循环中由源指针处COPY一个像素到目的指针处,然后目的指针加一Q源指针Ҏ每次循环的不同需要增加一定步长(攑֤? 步长是零或一Q羃时步长大于{于一Q?br />  法的框架解决了Q但是中心内容仍没有解决Q如何确定每ơ@环里源指针增加的步长Q或者说Q每ơ@? 里如何更新源指针的位|?Ҏ看出Q通过点q算很容易解册个问题:讄一个初gؓ零的点变量Q每ơ@环中Q把q个点变量加上N1/N2Qƈ其l? 果的整数部分作ؓ源指针距v始位|的偏移量;q样Q经qN2ơ@环,点变量的值恰好达到N1Q源指针也恰好“走”到原像素列的末?br />  q个 Ҏ可行Q但是太慢。如果能Q点运{化成整数q算快多了。那么如何{化呢Q我们可以设立一个值域为N1*N2的整数计数器Q每ơ@环递增N1Qƈ? 规定Q计数器每增加N2Q源指针前q一个像素。这Pl过N2ơ@环,计数器共增加了N1*N2Q源指针则增加了N1个单元,恰好“走”完全程。实际编 E中Q我们是用一个值域为N2的整数计数器Q超出值域部分取模处理。算法大致如下:<br /><br />  void StrechPixels(int N1, int N2, PIXEL src_pixels[], PIXEL dest_pixels[])<br />  {<br />    ASSERT(N1 <= N2);  // N1 must <= N2<br />    int p1 = 0, count = 0;<br />    for (int p2 = 0; p2 < N2; p2++)<br />    {<br />      dest_pixels[p2] = src_pixels[p1];<br />      count += N1;<br />      while (count >= N2)<br />      {<br />        count -= N2;<br />        p1++;<br />      }<br />    }<br />  }<br /><br />   上面法只是水^~放单行像素Q对垂直方向也采用同L法Q便实现了Q意比例的位图~放。经q以上算法的处理Q放大时囑փ出现马赛克,~小时图像出? 闪砾。若要获得高质量的羃攑֛形,采用插倹{过滤等技术。但是因些技术所需计算量太大,在游戏中通常靠硬件加速来实现Q不宜Y件解冟뀂 ?br /><br /><br />================================================================<br />PSD格式的开发?br /><br /><br /><br />   我在做游戏时Q因用到PSD格式转换成BMP或者JPG格式的程序,而且Q在转换Ӟ要将PSD中的I格转成游戏中约定的透明Ԍq样的程序,? 能自己去写了。所以,我在|上搜了一阵子Q找C“中国游戏开发者”的|站Q看C一关于PSD格式的文章(q也是我开始向q个|站投稿的原因,也许q? 叫~)?br />  本来是想L懒,省去了自qI之苦,可以抄一抄别人现在的代码Q再自己ҎQ又能省旉Q又能学C西,何乐而不为呢Q可是,? 抄下q篇文章的代码之后,发现其运行居然是不能通过的。看来天下没有免费的午餐Q我q是得自qI。一个多时的苦战之后,l于发现了问题所在,也许qƈ 不是一个问题,只是对于没有q个l验人来_q确实是个大问题。我现在这文章的一些地方进行改正,望各位朋友在开发PSD格式的读取问题上Q不再有? 烦。原文《PSD格式文g的读取》在q里http: //cgd.pages.com.cn/cgd/develop/effect/200109/ReadPSD.htmQ各位可以看看。我只将我的Ҏ? 分写在下面: <br /><br />  1Q文件头?个字节,只能?个字节?br />  2QPhotoshop的PSD格式用的是LIT格式存储?br /><br />   q个LIT格式我以前只是听说过Q没惛_会被PSD用上。这个格式是数据的高低位码交换了的Q如果直接用ReadFile或者fread函数其d 来,它的高低位码是被交换了的。例如:640?6q制值是1E0Q用DWORD方式存在盘里是0001E000Q用L件的函数d来以后,变成: 00E00100。所以,光低位码被交换了,解决的方法是用{换函敎ͼ代码如下Q?br /><br />  WORD WORDBIGtoLIT(WORD code) // 字型的处?br />  {<br />    return ((a >> 8 & 0xFF) | ((a & 0x00FF) << 8); // 把高低位码再交换q来<br />  }<br /><br />  DWORD DWORDBIGtoLIT(DWORD code) // 双字型的处理<br />  {<br />    WORD HiCode, LowCode;<br /><br />    HiCode = code & 0xFFFF0000;<br />    LowCode = code & 0x0000FFFF;<br />    HiCode = ((HiCode >> 8) & 0xFF) | ((HiCode & 0x00FF) << 8);<br />    LowCode ((LowCode >> 8) & 0xFF) | ((LowCode & 0x00FF) << 8);<br />    return MAKELONG((WORD)(LowCode << 16), (WORD)HiCode);<br />  }<br /><br />  当然Q也可以定义成宏形式Q如下:<br /><br />  #define BIG2LIT(a) (WORD((a >> 8 & 0xFF) | ((a & 0x00FF) << 8)))<br />  #define DWORDBIG2LIT(b) MAKELONG(BIG2LIT(HIWORD(b)), BIG2LIT(LOWORD(b)))<br /><br />  看v来简单一些,哈哈……。其它的Q原文没有什么错误,不过Q我大家q是最好自己去解决问题Q呵呵,因ؓ有一句话说得很好Q老师能教你读书写字,但是不能教你做天下文章。?br /><br /><br />================================================================<br />PSD格式文g的读取?br /><br /><br />   PhotoShopQ我x有h会不知道吧。如今最新的版本?.0Q其图象文g*.PSD?.5相比变化q不太大。以下我׃l?.PSD文g的读 取方法,q提供完整读取函数。其中:m_Rect为目标区域,m_lpDDS7为目标DirectDraw表面Qm_pbAlphaMask为目? Aplha通告指针。Read16函数Z指定文g当前位置d一个WORDQRead32函数Z指定文g当前位置d一个DWORD? MAX_PSD_CHANNELS?4。以下就?.PSD文g的读取方法,有兴的朋友可以l箋深入研究Q到时可别忘了发我一份?br /><br />  HRESULT LoadPSD( LPSTR strFilename ) // dPSD文g<br />  {<br />    DWORD dwWidth, dwHeight; // 宽高<br />    long lSurfWidth = m_Rect.right - m_Rect.left;<br />    long lSurfHeight = m_Rect.bottom - m_Rect.top;<br />    WORD CompressionType; // 压羃cd<br />    HDC hDC;<br />    FILE *fpPSD;<br />    WORD ChannelCount; // 通道?br /><br />    // 打开PSD文g<br />    if ( ( fpPSD = fopen ( strFilename, "rb" ) ) == NULL ) {<br />      return E_FAIL;<br />    }<br /><br />    // 头四个字节ؓ"8BPS"<br />    char signature[5];<br />    signature[0] = fgetc( fpPSD );<br />    signature[1] = fgetc( fpPSD );<br />    signature[2] = fgetc( fpPSD );<br />    signature[3] = fgetc( fpPSD );<br />    signature[4] = '\0';<br />    if ( strcmp( signature,"8BPS" ) != 0 ) {<br />      return E_FAIL;<br />    }<br /><br />    // 版本必须?<br />    if ( Read16( fpPSD ) != 1 ) {<br />      return E_FAIL;<br />    }<br /><br />    // 跌一些数据?L0)<br />    Read32( fpPSD );<br />    Read16( fpPSD );<br /><br />    // d通道?br />    ChannelCount = Read16( fpPSD );<br /><br />    // 定臛_有一个通道<br />    if ( ( ChannelCount < 0 ) || ( ChannelCount > MAX_PSD_CHANNELS ) ) {<br />      return E_FAIL;<br />    }<br /><br />    // d宽和?br />    dwHeight = Read32( fpPSD );<br />    dwWidth = Read32( fpPSD );<br />    if ( dwWidth != ( DWORD )lSurfWidth || dwHeight != ( DWORD )lSurfHeight ) {<br />      return E_FAIL;<br />    }<br /><br />    // 只读?位通道<br />    if ( Read16( fpPSD ) != 8 ) {<br />      return E_FAIL;<br />    }<br /><br />    // 定模式为RGB.<br />    // 可能|<br />    // 0: 位图<br />    // 1: 灰阶<br />    // 2: 索引<br />    // 3: RGB<br />    // 4: CMYK<br />    // 7: Multichannel<br />    // 8: Duotone<br />    // 9: Lab<br />    if ( Read16( fpPSD ) != 3 ) {<br />      return E_FAIL;<br />    }<br /><br />    // 跌数据Q如调色板)<br />    int ModeDataCount = Read32( fpPSD );<br />    if ( ModeDataCount )<br />      fseek( fpPSD, ModeDataCount, SEEK_CUR );<br /><br />    // 跌数据Q如Qpen tool paths, etcQ?br />    int ResourceDataCount = Read32( fpPSD );<br />    if ( ResourceDataCount )<br />      fseek( fpPSD, ResourceDataCount, SEEK_CUR );<br /><br />    // 条过保留数据<br />    int ReservedDataCount = Read32( fpPSD );<br />    if ( ReservedDataCount )<br />      fseek( fpPSD, ReservedDataCount, SEEK_CUR );<br /><br />    // 0: 非压~?br />    // 1: RLE压羃<br />    CompressionType = Read16( fpPSD );<br />    if ( CompressionType > 1 ) {<br />      return E_FAIL;<br />    }<br /><br />    BYTE* PSDPixels = new BYTE[ ( lSurfWidth * lSurfHeight ) * 4 ];<br /><br />    // 解包数据<br />    UnPackPSD( fpPSD, lSurfWidth, lSurfHeight, PSDPixels, ChannelCount, CompressionType );<br /><br />    fclose( fpPSD );<br /><br />    // 复制信息<br />    BITMAPINFO BitmapInfo;<br />    ZeroMemory( &BitmapInfo, sizeof( BitmapInfo ) );<br />    BitmapInfo.bmiHeader.biSize = sizeof( BitmapInfo.bmiHeader );<br />    BitmapInfo.bmiHeader.biWidth = lSurfWidth;<br />    BitmapInfo.bmiHeader.biHeight = -lSurfHeight;<br />    BitmapInfo.bmiHeader.biPlanes = 1;<br />    BitmapInfo.bmiHeader.biBitCount = 32;<br /><br />    m_lpDDS7->GetDC( &hDC );<br /><br />    int rc = StretchDIBits( hDC,<br />                0,<br />                0,<br />                lSurfWidth,<br />                lSurfHeight,<br />                0,<br />                0,<br />                lSurfWidth,<br />                lSurfHeight,<br />                PSDPixels,<br />                &BitmapInfo,<br />                DIB_RGB_COLORS,<br />                SRCCOPY );<br /><br />    m_lpDDS7->ReleaseDC( hDC );<br /><br />    if ( rc == GDI_ERROR ) {<br />      H_ARRAY_DELETE( PSDPixels );<br /><br />  #ifdef _DEBUG<br />    g_pHERR->OutDebugMsg( 3, H2DSERR_INVALID_PSD );<br />  #endif<br />    return E_FAIL;<br /><br />    }<br /><br />    // 是否dAlpha混合通道<br />    if( ChannelCount > 3 ) {<br />      m_pbAlphaMask = new BYTE[ lSurfWidth * lSurfHeight ];<br /><br />    for ( int x = 0; x < lSurfWidth; x++ )<br />      for ( int y = 0; y < lSurfHeight; y++ ) {<br />        m_pbAlphaMask[ ( y * lSurfWidth ) + x ] =<br />                PSDPixels[ ( ( ( y * lSurfHeight ) + x ) * 4 ) + 3 ];<br />      }<br />    }<br />    else {<br />      m_pbAlphaMask = NULL;<br />    }<br /><br />    H_ARRAY_DELETE( PSDPixels );<br /><br />    return DD_OK;<br />  }<br /><br />  // PSD文g解包<br /><br />  void CHades2DSurface::UnPackPSD( FILE *fp,     // fp为PSD文g指针Q?br />                   DWORD dwWidth,   // dwWidth、dwHeight为宽高,<br />                   DWORD dwHeight,<br />                   BYTE* pixels,   // pixels包目标指针,<br />                   WORD ChannelCnt,  // ChannelCnt为通道敎ͼ<br />                   WORD Compression ) // Compression位压~类型。?br />                <br />                 <br />  {<br />    int Default[4] = { 0, 0, 0, 255 };<br />    int chn[4] = { 2, 1, 0, 3};<br />    int PixelCount = dwWidth * dwHeight;<br /><br />    if ( Compression ) {<br />      fseek( fp, dwHeight * ChannelCnt * 2, SEEK_CUR );<br /><br />      for ( int c = 0; c < 4; c++ ) {<br />        int pn = 0;<br />        int channel = chn[c];<br /><br />        if ( channel >= ChannelCnt ) {<br />          for ( pn=0; pn < PixelCount ;pn++ ) {<br />            pixels[ ( pn * 4 ) + channel ] = Default[ channel ];<br />          }<br />        }<br />        else // 非压~?br />        {<br />          int count = 0;<br />          while( count < PixelCount ) {<br />            int len = fgetc( fp );<br />            if( len == 128 ) { }<br />            else if ( len < 128 ) // 非RLE<br />            {<br />              len++;<br />              count += len;<br />              while(len) {<br />                pixels[ ( pn * 4 ) + channel ] = fgetc( fp );<br />                pn++;<br />                len--;<br />              }<br />            }<br />             else if ( len > 128 ) // RLE打包<br />            {<br />              len ^= 0x0FF;<br />              len += 2;<br />              unsigned char val = fgetc( fp );<br />              count += len;<br />              while( len ) {<br />                pixels[ ( pn * 4 ) + channel ] = val;<br />                pn++;<br />                len--;<br />              }<br />            }<br />          }<br />        }<br />      }<br />    }<br />    else<br />    {<br />      for ( int c=0; c < 4; c++ ) {<br />        int channel = chn[c];<br />        if ( channel > ChannelCnt ) {<br />          for( int pn = 0; pn < PixelCount; pn++ ) {<br />            pixels[ ( pn * 4 ) + channel ] = Default[ channel ];<br />          }<br />        }<br />        else {<br />          for( int n = 0; n < PixelCount; n++ ) {<br />            pixels[ ( n * 4 ) + channel ] = fgetc( fp );<br />          }<br />        }<br />      }<br />    }<br />  }  </p> </span> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/swo2006/aggbug/11279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-08-16 10:42 <a href="http://www.shnenglu.com/swo2006/articles/11279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用GDI+在内存中转换囄cd [转蝲]http://www.shnenglu.com/swo2006/articles/11004.htmlswoswoTue, 08 Aug 2006 09:02:00 GMThttp://www.shnenglu.com/swo2006/articles/11004.htmlhttp://www.shnenglu.com/swo2006/comments/11004.htmlhttp://www.shnenglu.com/swo2006/articles/11004.html#Feedback0http://www.shnenglu.com/swo2006/comments/commentRss/11004.htmlhttp://www.shnenglu.com/swo2006/services/trackbacks/11004.html 使用GDI+在内存中转换囄cd [转蝲]


  首先Q在StdAfx.h中静态调用diplus.libQ即q译系l完成对DLL的加载,应用E序l束时卸载DLL的编码。如下:

#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#include "GdiPlus.h"
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
#endif
在类的头文g中定义,以下成员变量Q用来初始化GDI+的用和l束使用?
GdiplusStartupInput m_gdiplusStartupInput; 
ULONG_PTR m_gdiplusToken;
然后在OnCreate()函数中加入初始化GDI+的函敎ͼ
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL); 	
在OnDestroy()函数中加入结束GDI+使用的函敎ͼ
	GdiplusShutdown(m_gdiplusToken);
接着Q定义{换函敎ͼ
BOOL MBmpToMImage(CMemFile& cbfBmp, CMemFile& cbfImage, CString strType)
其中Q?
CMemFile& cbfBmp表示原位图文?
CMemFile& cbfImage表示转换后的囑Ş文g;
CString strType表示转换的图片类型?br />
该函C主要的处理ؓ以下几步Q?ol>
  • 原位图文g转换为IStream
  • 定义Imagecd例,q用第1步获得的IStream初始?/li>
  • 获取转换的图片类型的CLSID
  • Image以{换的囄cd保存到IStream?/li>
  • IStream转换为CMemFile内存文g(也可为CFile)
  • 详细代码如下Q?

    BOOL MBmpToMImage(CMemFile& cbfBmp, CMemFile& cbfImage, CString strType)
    {
    int iBmpSize = cbfBmp.GetLength();
    HGLOBAL hMemBmp = GlobalAlloc(GMEM_FIXED, iBmpSize);
    if (hMemBmp == NULL) return FALSE;
    IStream* pStmBmp = NULL;
    CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp);
    if (pStmBmp == NULL)
    {
    GlobalFree(hMemBmp);
    return FALSE;
    }
    BYTE* pbyBmp = (BYTE *)GlobalLock(hMemBmp);
    cbfBmp.SeekToBegin();
    cbfBmp.Read(pbyBmp, iBmpSize);

    Image* imImage = NULL;
    imImage = Image::FromStream(pStmBmp, FALSE);
    if (imImage == NULL)
    {
    GlobalUnlock(hMemBmp);
    GlobalFree(hMemBmp);
    return FALSE;
    }
    USES_CONVERSION;
    CLSID clImageClsid;
    GetImageCLSID(A2W("image/"+strType.GetBuffer(0)), &clImageClsid);

    HGLOBAL hMemImage = GlobalAlloc(GMEM_MOVEABLE, 0);
    if (hMemImage == NULL)
    {
    pStmBmp->Release();
    GlobalUnlock(hMemBmp);
    GlobalFree(hMemBmp);
    if (imImage != NULL) delete imImage;
    return FALSE;
    }
    IStream* pStmImage = NULL;
    CreateStreamOnHGlobal(hMemImage, TRUE, &pStmImage);
    if (pStmImage == NULL)
    {
    pStmBmp->Release();
    GlobalUnlock(hMemBmp);
    GlobalFree(hMemBmp);
    GlobalFree(hMemImage);
    if (imImage != NULL) delete imImage
    return FALSE;
    }
    imImage->Save(pStmImage, &clJpgClsid);
    if (pStmImage == NULL)
    {
    pStmBmp->Release();
    pStmImage>Release();
    GlobalUnlock(hMemBmp);
    GlobalFree(hMemBmp);
    GlobalFree(hMemImage;
    if (imImage != NULL) delete imImage;
    return FALSE;
    }
    LARGE_INTEGER liBegin = {0};
    pStmImage->Seek(liBegin, STREAM_SEEK_SET, NULL);
    BYTE* pbyImage = (BYTE *)GlobalLock(hMemImage);
    cbfImage.SeekToBegin();
    cbfImage.Write(pbyImage, GlobalSize(hMemImage));

    if (imImage != NULL) delete imImage;
    pStmBmp->Release();
    pStmImage->Release();
    GlobalUnlock(hMemBmp);
    GlobalUnlock(hMemImage);
    GlobalFree(hMemBmp);
    GlobalFree(hMemImage);
    return TRUE;
    }


    swo 2006-08-08 17:02 发表评论
    ]]>
    Reading and Writing Metadatahttp://www.shnenglu.com/swo2006/articles/11002.htmlswoswoTue, 08 Aug 2006 08:46:00 GMThttp://www.shnenglu.com/swo2006/articles/11002.htmlhttp://www.shnenglu.com/swo2006/comments/11002.htmlhttp://www.shnenglu.com/swo2006/articles/11002.html#Feedback0http://www.shnenglu.com/swo2006/comments/commentRss/11002.htmlhttp://www.shnenglu.com/swo2006/services/trackbacks/11002.html Reading and Writing Metadata [转蝲]

    Some image files contain metadata that you can read to determine features of the image. For example, a digital photograph might contain metadata that you can read to determine the make and model of the camera used to capture the image. With Microsoft Windows GDI+, you can read existing metadata, and you can also write new metadata to image files.

    GDI+ provides a uniform way of storing and retrieving metadata from image files in various formats. In GDI+, a piece of metadata is called a property item. You can store and retrieve metadata by calling the SetPropertyItem and GetPropertyItem methods of the Image class, and you don't have to be concerned about the details of how a particular file format stores that metadata.

    GDI+ currently supports metadata for the TIFF, JPEG, Exif, and PNG file formats. The Exif format, which specifies how to store images captured by digital still cameras, is built on top of the TIFF and JPEG formats. Exif uses the TIFF format for uncompressed pixel data and the JPEG format for compressed pixel data.

    GDI+ defines a set of property tags that identify property items. Certain tags are general-purpose; that is, they are supported by all of the file formats mentioned in the preceding paragraph. Other tags are special-purpose and apply only to certain formats. If you try to save a property item to a file that does not support that property item, GDI+ ignores the request. More specifically, the Image::SetPropertyItem method returns PropertyNotSupported.

    You can determine the property items that are stored in an image file by calling Image::GetPropertyIdList. If you try to retrieve a property item that is not in the file, GDI+ ignores the request. More specifically, the Image::GetPropertyItem method returns PropertyNotFound.

    Reading Metadata from a File

    The following console application calls the GetPropertySize method of an Image object to determine how many pieces of metadata are in the file FakePhoto.jpg.

    				#include <windows.h>
    #include <gdiplus.h>
    #include <stdio.h>
    using namespace Gdiplus;
    INT main()
    {
    // Initialize <tla rid="tla_gdiplus"/>.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    UINT size = 0;
    UINT count = 0;
    Bitmap* bitmap = new Bitmap(L"FakePhoto.jpg");
    bitmap->GetPropertySize(&size, &count);
    printf("There are %d pieces of metadata in the file.\n", count);
    printf("The total size of the metadata is %d bytes.\n", size);

    delete bitmap;
    GdiplusShutdown(gdiplusToken);
    return 0;
    }

    The preceding code, along with a particular file, FakePhoto.jpg, produced the following output:

    				There are 7 pieces of metadata in the file.
    The total size of the metadata is 436 bytes.

    GDI+ stores an individual piece of metadata in a PropertyItem object. You can call the GetAllPropertyItems method of the Image class to retrieve all the metadata from a file. The GetAllPropertyItems method returns an array of PropertyItem objects. Before you call GetAllPropertyItems, you must allocate a buffer large enough to receive that array. You can call the GetPropertySize method of the Image class to get the size (in bytes) of the required buffer.

    A PropertyItem object has the following four public members:

    id A tag that identifies the metadata item. The values that can be assigned to id (PropertyTagImageTitle, PropertyTagEquipMake, PropertyTagExifExposureTime, and the like) are defined in Gdiplusimaging.h.
    length The length, in bytes, of the array of values pointed to by the value data member. Note that if the type data member is set to PropertyTagTypeASCII, then the length data member is the length of a null-terminated character string, including the NULL terminator.
    type The data type of the values in the array pointed to by the value data member. Constants (PropertyTagTypeByte, PropertyTagTypeASCII, and the like) that represent various data types are described in Image Property Tag Type Constants.
    value A pointer to an array of values.

    The following console application reads and displays the seven pieces of metadata in the file FakePhoto.jpg. The main function relies on the helper function PropertyTypeFromWORD, which is shown following the main function.

    				#include <windows.h>
    #include <gdiplus.h>
    #include <strsafe.h>
    using namespace Gdiplus;

    INT main()
    {
    // Initialize GDI+
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    UINT size = 0;
    UINT count = 0;

    #define MAX_PROPTYPE_SIZE 30
    WCHAR strPropertyType[MAX_PROPTYPE_SIZE] = L"";

    Bitmap* bitmap = new Bitmap(L"FakePhoto.jpg");

    bitmap->GetPropertySize(&size, &count);
    printf("There are %d pieces of metadata in the file.\n\n", count);

    // GetAllPropertyItems returns an array of PropertyItem objects.
    // Allocate a buffer large enough to receive that array.
    PropertyItem* pPropBuffer =(PropertyItem*)malloc(size);

    // Get the array of PropertyItem objects.
    bitmap->GetAllPropertyItems(size, count, pPropBuffer);

    // For each PropertyItem in the array, display the id, type, and length.
    for(UINT j = 0; j < count; ++j)
    {
    // Convert the property type from a WORD to a string.
    PropertyTypeFromWORD(
    pPropBuffer[j].type, strPropertyType, MAX_PROPTYPE_SIZE);

    printf("Property Item %d\n", j);
    printf(" id: 0x%x\n", pPropBuffer[j].id);
    wprintf(L" type: %s\n", strPropertyType);
    printf(" length: %d bytes\n\n", pPropBuffer[j].length);
    }

    free(pPropBuffer);
    delete bitmap;
    GdiplusShutdown(gdiplusToken);
    return 0;
    } // main

    // Helper function
    HRESULT PropertyTypeFromWORD(WORD index, WCHAR* string, UINT maxChars)
    {
    HRESULT hr = E_FAIL;

    WCHAR* propertyTypes[] = {
    L"Nothing", // 0
    L"PropertyTagTypeByte", // 1
    L"PropertyTagTypeASCII", // 2
    L"PropertyTagTypeShort", // 3
    L"PropertyTagTypeLong", // 4
    L"PropertyTagTypeRational", // 5
    L"Nothing", // 6
    L"PropertyTagTypeUndefined", // 7
    L"Nothing", // 8
    L"PropertyTagTypeSLONG", // 9
    L"PropertyTagTypeSRational"}; // 10

    hr = StringCchCopyW(string, maxChars, propertyTypes[index]);
    return hr;
    }

    The preceding console application produces the following output:

    				Property Item 0
    id: 0x320
    type: PropertyTagTypeASCII
    length: 16 bytes
    Property Item 1
    id: 0x10f
    type: PropertyTagTypeASCII
    length: 17 bytes
    Property Item 2
    id: 0x110
    type: PropertyTagTypeASCII
    length: 7 bytes
    Property Item 3
    id: 0x9003
    type: PropertyTagTypeASCII
    length: 20 bytes
    Property Item 4
    id: 0x829a
    type: PropertyTagTypeRational
    length: 8 bytes
    Property Item 5
    id: 0x5090
    type: PropertyTagTypeShort
    length: 128 bytes
    Property Item 6
    id: 0x5091
    type: PropertyTagTypeShort
    length: 128 bytes

    The preceding output shows a hexadecimal ID number for each property item. You can look up those ID numbers in Image Property Tag Constants and find out that they represent the following property tags.

    Hexadecimal value Property tag
    0x0320

    0x010f

    0x0110

    0x9003

    0x829a

    0x5090

    0x5091

    PropertyTagImageTitle

    PropertyTagEquipMake

    PropertyTagEquipModel

    PropertyTagExifDTOriginal

    PropertyTagExifExposureTime

    PropertyTagLuminanceTable

    PropertyTagChrominanceTable

    The second (index 1) property item in the list has id PropertyTagEquipMake and type PropertyTagTypeASCII. The following example, which is a continuation of the previous console application, displays the value of that property item:

    				printf("The equipment make is %s.\n", pPropBuffer[1].value);
    		

    The preceding line of code produces the following output:

    				The equipment make is Northwind Traders.
    		

    The fifth (index 4) property item in the list has id PropertyTagExifExposureTime and type PropertyTagTypeRational. That data type (PropertyTagTypeRational) is a pair of LONGs. The following example, which is a continuation of the previous console application, displays those two LONG values as a fraction. That fraction, 1/125, is the exposure time measured in seconds.

    				long* ptrLong = (long*)(pPropBuffer[4].value);
    printf("The exposure time is %d/%d.\n", ptrLong[0], ptrLong[1]);

    The preceding code produces the following output:

    				The exposure time is 1/125.
    		

    Writing Metadata to a File

    To write an item of metadata to an Image object, initialize a PropertyItem object and then pass the address of that PropertyItem object to the SetPropertyItem method of the Image object.

    The following console application writes one item (the image title) of metadata to an Image object and then saves the image in the disk file FakePhoto2.jpg. The main function relies on the helper function GetEncoderClsid, which is shown in the topic Retrieving the Class Identifier for an Encoder.

    				#include <windows.h>
    #include <gdiplus.h>
    #include <stdio.h>
    using namespace Gdiplus;
    INT main()
    {
    // Initialize <tla rid="tla_gdiplus"/>.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    Status stat;
    CLSID clsid;
    char propertyValue[] = "Fake Photograph";
    Bitmap* bitmap = new Bitmap(L"FakePhoto.jpg");
    PropertyItem* propertyItem = new PropertyItem;
    // Get the CLSID of the JPEG encoder.
    GetEncoderClsid(L"image/jpeg", &clsid);
    propertyItem->id = PropertyTagImageTitle;
    propertyItem->length = 16; // string length including NULL terminator
    propertyItem->type = PropertyTagTypeASCII;
    propertyItem->value = propertyValue;
    bitmap->SetPropertyItem(propertyItem);
    stat = bitmap->Save(L"FakePhoto2.jpg", &clsid, NULL);
    if(stat == Ok)
    printf("FakePhoto2.jpg saved successfully.\n");

    delete propertyItem;
    delete bitmap;
    GdiplusShutdown(gdiplusToken);
    return 0;
    }


    swo 2006-08-08 16:46 发表评论
    ]]>
    在GDI+中绘制GIFhttp://www.shnenglu.com/swo2006/articles/11000.htmlswoswoTue, 08 Aug 2006 08:24:00 GMThttp://www.shnenglu.com/swo2006/articles/11000.htmlhttp://www.shnenglu.com/swo2006/comments/11000.htmlhttp://www.shnenglu.com/swo2006/articles/11000.html#Feedback0http://www.shnenglu.com/swo2006/comments/commentRss/11000.htmlhttp://www.shnenglu.com/swo2006/services/trackbacks/11000.html
    GDI+中绘制一个图片的代码如下:
    void CMyWnd::OnPaint()
    {
    CPaintDC dc(this);
    Graphics graphics(&dc); // Create a GDI+ graphics object

    Image image(L"Test.Gif"); // Construct an image
    graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
    }

    Gif 分ؓ两种Q一U是静态的Q对于这U格式的GifQ在GDI+中无需采用MҎp够直接显C?上面的代码就属于q种情况)。另一U是动态的Q? q种文g能够昄单的动画。动态的实际上由多幅静态的l成Q在昄GifӞ每幅囄按照一定的旉间隔依次q行昄Q从而实C动画效果?
    我把GIF装成了一个类ImageEx,q个cȝ承了GDI+中的ImagecR我们首先要做的工作是判断GIF是动态的q是静态的?
    bool ImageEx::TestForAnimatedGIF()
    {
    UINT count = 0;
    count = GetFrameDimensionsCount();
    GUID* pDimensionIDs = new GUID[count];

    // 得到子的对象列?br /> GetFrameDimensionsList(pDimensionIDs, count);

    //获取d?br /> m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);

    // 假设囑փh属性条?PropertyItemEquipMake.
    // 获取此条目的大小.
    int nSize = GetPropertyItemSize(PropertyTagFrameDelay);

    // 为属性条目分配空?
    m_pPropertyItem = (PropertyItem*) malloc(nSize);
    GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
    delete pDimensionIDs;
    return m_nFrameCount > 1;

    }
    m_pPropertyItem->value 是一个长整Ş数组, 每个长整形代表每帧的延时。由于获取的属性不同,GetPropertyItem会获得不同大的对象Q? 因此要由用户来获得的对象大小Q开辟与删除 GetPropertyItem相关的内存。对象的大小是通过GetPropertyItemSize 获取的,其参数是你所感兴的属性条目?一旦获取了帧的数量与gӞ我们可生成一个线E来调用 DrawFrameGIFQ)来显C?
    bool ImageEx::DrawFrameGIF()
    {
    ::WaitForSingleObject(m_hPause, INFINITE);
    GUID pageGuid = FrameDimensionTime;
    long hmWidth = GetWidth();
    long hmHeight = GetHeight();
    HDC hDC = GetDC(m_hWnd);
    if (hDC)
    {
    Graphics graphics(hDC);
    graphics.DrawImage(this, m_rc.left, m_rc.top, hmWidth, hmHeight);
    ReleaseDC(m_hWnd, hDC);
    }
    SelectActiveFrame(&pageGuid, m_nFramePosition++);
    if (m_nFramePosition == m_nFrameCount)
    m_nFramePosition = 0;

    long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
    DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
    return dwErr == WAIT_OBJECT_0;
    }

    swo 2006-08-08 16:24 发表评论
    ]]>
    在VC中如果实现GIF的播放?http://www.shnenglu.com/swo2006/articles/10996.htmlswoswoTue, 08 Aug 2006 06:51:00 GMThttp://www.shnenglu.com/swo2006/articles/10996.htmlhttp://www.shnenglu.com/swo2006/comments/10996.htmlhttp://www.shnenglu.com/swo2006/articles/10996.html#Feedback1http://www.shnenglu.com/swo2006/comments/commentRss/10996.htmlhttp://www.shnenglu.com/swo2006/services/trackbacks/10996.html 在VC中如果实现GIF的播放?
    void   CImageView::OnDraw(CDC*   pDC)  
      {  
              CImageDoc*   pDoc   =   GetDocument();  
              ASSERT_VALID(pDoc);  
              //   TODO:   add   draw   code   for   native   data   here  
              IPicture   *pPic;    
              IStream   *pStm;    
               
              CFileStatus   fstatus;    
              CFile   file;    
              LONG   cb;    
               
              if   (file.Open("c:/a.jpg",CFile::modeRead)  
                      &&file.GetStatus("c:/a.jpg",   fstatus)  
                      &&((cb   =   fstatus.m_size)   !=   -1))    
              {    
                      HGLOBAL   hGlobal   =   GlobalAlloc(GMEM_MOVEABLE,   cb);    
                      LPVOID   pvData   =   NULL;    
                      if   (hGlobal   !=   NULL)    
                      {    
                              if   ((pvData   =   GlobalLock(hGlobal))   !=   NULL)    
                              {    
                                      file.ReadHuge(pvData,   cb);    
                                      GlobalUnlock(hGlobal);    
                                      CreateStreamOnHGlobal(hGlobal,   TRUE,   &pStm);    
                                       
                                      if(SUCCEEDED(::OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*   )&pPic)))    
                                      {    
                                              OLE_XSIZE_HIMETRIC   hmWidth;    
                                              OLE_YSIZE_HIMETRIC   hmHeight;    
                                               
                                              pPic->get_Width(&hmWidth);    
                                              pPic->get_Height(&hmHeight);    
                                               
                                              double   fX,fY;    
                                              fX   =   (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);    
                                              fY   =   (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);    
                                              if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL)))    
                                                      AfxMessageBox("Failed   To   Render   The   picture!");    
                                              pPic->Release();    
                                      }    
                                      else    
                                              AfxMessageBox("Error   Loading   Picture   From   Stream!");    
                              }    
                      }    
              }    
              else    
                      AfxMessageBox("Can't   Open   Image   File!");    
       
      }  


    swo 2006-08-08 14:51 发表评论
    ]]>
    在VC下显CJPEG、GIF格式囑փ的一U简便方?/title><link>http://www.shnenglu.com/swo2006/articles/10995.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Tue, 08 Aug 2006 06:48:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/10995.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/10995.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/10995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/10995.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/10995.html</trackback:ping><description><![CDATA[ <h1> <font size="4"> <span id="3tjd15x" class="f16b">在VC下显CJPEG、GIF格式囑փ的一U简便方?/span> </font> </h1> <font face="Arial"> <br /> </font> <span id="xjvvfj7" class="f141"> <font face="Arial">一?引言 <br />    JPEG囑փ压羃标准随然是一U有损图像压~标准,但由于hD觉的不敏感,l压~后的画质基本没有发生变化,很快便以较高的压~率得到了广泛的认可? GIF格式虽然仅支?56色但它对于颜色较的囑փ有着很高的压~率Q甚臌qJPEG标准Q也得到了广泛的认同。但作ؓ众多E序员的一个重要的开发工 ?-Microsoft Visual C++ 6.0的MFC库却仅对没有l过M压羃的BMP位图文g有着良好的支持,可以d、显C、存储甚臛_内存中创Z块内存位图。由于BMP格式的图像没? l过M的压~,不论是作为程序的外部文gQ还是作为程序的内部资源都要占据大量的空_其是后者会大大增加可执行文件的长度。可以看出,如果能用l过 压羃、具有较好的压羃率的JPEG或GIF格式的图像来取代BMP文g在VC中的应用Q无疑还是很有吸引力的?<br /> 二?设计思\ <br />    虽然有一些操作、处理JPEG、GIF{其他格式图像的Active X控gQ但ȝ来说使用hq不太方便,W者经q实验摸索,ȝZ一U借助于COM接口的OLEҎ来实Cq功能的一U简便方法,Cl如下以飨广大读者: <br /> 下面我们要用IPicture 的COM接口Q有必要对该囑փ接口做些了解Q该接口主要理囑փ对象及其属性,囑փ对象Z图、图标和囑օ{提供一U与语言无关的抽象。和标准的字体对? 一Ppȝ也提供了对图像对象的标准实现。其主要的接口是IPicture和IPictureDispQ后者是由IDispatch接口z以便通过自动 化对囑փ的属性进行访问。图像对象也支持外部接口IPropertyNotifySinkQ以便用戯在图像属性发生改变时作出军_。图像对象也支持 IPersistStream接口Q所以它能从一个IStream接口的实例对象保存、装载自己,而IStream接口也支持对对象的数据d?<br />    我们可以用函数OleLoadPicture从包含有囑փ数据的流中装载图像。该函数化了Z的囑փ对象的创E,可以创徏一个新的图像对象ƈ且用中的内容对它进行初始化。其函数原型为: <br /> STDAPI OleLoadPicture( IStream * pStream, //指向包含有图像数据的的指针LONG lSize, //从流中读取的字节数BOOL fRunmode, //囑փ属性对应的初值REFIID riid, //涉及到的接口标识Q描q要q回的接口指针的cdVOID ppvObj // 在rrid中用到的接口指针变量的地址); <br /><br /> 三?具体的实?<br />    在显C图像之前,首先要获取到囑փ文g的存放\径,q里采用标准的文件打开对话框来选取囑փ文gQ文件名存放在CString型的变量m_sPath中: <br /> CFileDialog dlg(TRUE,"jpg","*.jpg", <br /> OFN_HIDEREADONLY|OFN_OVERWR99vEPROMPT, <br /> "JPEG文g(*.jpg)|*.jpg|GIF文g(*.gif)|*.gif||",NULL); <br /> if(dlg.DoModal()==IDOK) <br /> { <br /> m_sPath=dlg.GetPathName(); <br /> Invalidate(); <br /> } <br /> 为简单计Q图形显C的代码直接在视cM的OnDraw中编写,首先打开文gq判断文件的可用性,q把文g内容攑ֈ接口IStream的对象pStm中: <br /> IStream *pStm; <br /> CFileStatus fstatus; <br /> CFile file; <br /> LONG cb; <br /> …?<br /> if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1)) <br /> { <br /> HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb); <br /> LPVOID pvData = NULL; <br /> if (hGlobal != NULL) <br /> { <br /> if ((pvData = GlobalLock(hGlobal)) != NULL) <br /> { <br /> file.ReadHuge(pvData, cb); <br /> GlobalUnlock(hGlobal); <br /> CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); <br /> } <br /> } <br /> } <br /><br /><br />    然后Q就直接调用OleLoadPicture函数从流中装载图像: <br /> IPicture *pPic; <br /> …?<br /> OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)); <br /><br /><br />    ׃该函数有时会Dp|Q所以应当用SUCCEEDED宏来做一些适当的保护工?只有在数据装载成功的前提下才能l下面的囑փ昄工作Q?<br /> if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic))) <br /> { <br /> OLE_XSIZE_HIMETRIC hmWidth; <br /> OLE_YSIZE_HIMETRIC hmHeight; <br /> pPic-Qget_Width(&hmWidth); <br /> pPic-Qget_Height(&hmHeight); <br /> double fX,fY; <br /> …?<br /> fX = (double)pDC-QGetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC-QGetDeviceCaps(HORZSIZE)*100.0); <br /> fY = (double)pDC-QGetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC-QGetDeviceCaps(VERTSIZE)*100.0); <br /> if(FAILED(pPic-QRender(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) <br /> AfxMessageBox("渲染囑փp|Q?); <br /> pPic-QRelease(); <br /> } <br /> else <br /> AfxMessageBox("从流中装载图像失败!"); <br /><br /><br /><br />    其中Q显C工作主要是由IPicture接口对象的Render函数来完成的Q该函数主要用来图片的指定部分d指定的设备环境的指定位置。原型如下: <br /> HRESULT Render( HDC hdc, //渲染囑փ用的讑֤环境句柄 <br /> long x, //在hdc上的水^坐标 <br /> long y, //在hdc上的垂直坐标 <br /> long cx, //囑փ宽度 <br /> long cy, //囑փ高度 <br /> OLE_XPOS_HIMETRIC xSrc, //在源囑փ上的水^偏移 <br /> OLE_YPOS_HIMETRIC ySrc, //在源囑փ上的垂直偏移 <br /> OLE_XSIZE_HIMETRIC cxSrc,//在源囑փ上水qx贝的数量 <br /> OLE_YSIZE_HIMETRIC cySrc,//在源囑փ上垂直拷贝的数量 <br /> LPCRECT prcWBounds //指向目标囑օ讑֤环境句柄的指?; <br /><br /><br />    结Q到此ؓ止,通过上述代码已经能够在程序的客户区内昄JPEG、GIF{标准的囑փ了,但对于有多囄Q即有动画)的GIF格式的图像,目前q只能显C第一帧,如要完整的显CGIF 动画的全q程Q还需要外部Active X控g的支持。? </font> <br /> </span> <img src ="http://www.shnenglu.com/swo2006/aggbug/10995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-08-08 14:48 <a href="http://www.shnenglu.com/swo2006/articles/10995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Visual C++实现AVI文g的图像截?/title><link>http://www.shnenglu.com/swo2006/articles/10982.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Tue, 08 Aug 2006 05:05:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/10982.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/10982.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/10982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/10982.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/10982.html</trackback:ping><description><![CDATA[ <table border="0" cellpadding="0" cellspacing="2" width="550"> <tbody> <tr> <td align="center"> <b> <font class="BHEAD" color="#333399">利用Visual C++实现AVI文g的图像截?/font> </b> </td> </tr> <tr> <td bgcolor="#bbbbbb" height="1"> <br /> </td> </tr> <tr> <td align="center"> <font face="Arial, Helvetica, sans-serif"> <span id="fpdj17n" class="nava">2001-10-22· ·??··yesky<br /><br /></span> </font> </td> </tr> <tr> <td> <span id="j7tjjdl" class="txt"> <br />  AVI文g是我们所说的多媒体文Ӟ所谓的AVI囑փ是视频囑փQ该文g是一个RIFF说明文gQ它用于获取、编辑、演C音频、视频序列。一般的AVI文g包含音频和视频,有的Ҏ的AVIq包含一个控制\径或MIDI路径作ؓ附加的数据流?br /><br />   现在播放AVI文g的Y件很多,但大多无法从AVI视频文g中读取一帧图像ƈ生成BMP格式的文件。笔者在使用AVI文g开发项目过E中对AVI文g? 操作U篏了一些经验,对于如何实现从AVI视频中获取L帧的囑փ数据q存储成BMP文gQ其中最关键的是要从AVI文g中获取具体某一帧的囑փ数据Q? 为此我利用Windows提供的API函数实现了自定义的CAvic,用于操作AVI文g?br /><br />  在用API函数操作AVI文gӞ一? 要注意用AVIFileInit()来初始化AVI库,E序l束时用AVIFileExit()释放AVI库,否则API函数无法使用。现以操作包含真? 色图像的AVI文gZQ给出Cavicȝ部分函数的具体实玎ͼ其中CaviCreate()函数用于dAVI文g信息q初始化Cavicȝ成员Q例? ҎAVI文g信息定义每囑փ的宽、高、每帧图像的信息头结构等{;函数AviRead(int mFrame)用于从AVI文g中读取第mFrame帧。实C码显C如下:<br /><br /><table align="center" bgcolor="#ebe9eb" border="0" width="600"><tbody><tr><td>//Cavicd文g定义Q?br />class CAvi file://AVIc,处理AVI文g<br />{<br /> public:<br /> int cy;//图象?br /> int cx;//图象?br /> file://long m_maxFrame;<br /> BYTE *pData;//寸储图象数据<br /> BITMAPINFO *m_pBMI;//位图文g信息?br /> PAVISTREAM pavi;//AVI?br /> PAVIFILE pfile;//AVI文g指针<br /> AVIFILEINFO * pfi; file://AVI信息<br /> BOOL AviRead(int mFrame);//读AVI文g的第mFrame?br /> CAvi();//标准构造函?br /> CAviCreate(CString &string);//用文件名初始化AVIcȝ成员<br /> virtual ~CAvi();<br />}; <br />//CavicL件实现部分;<br />CAvi::CAvi()<br />{ AVIFileInit();//初始化AVI?br /> cx=0;//定义图象宽、高、等成员<br /> cy=0;<br /> m_pBMI=NULL;<br /> pData=NULL;<br /> file://m_maxFrame=0;<br /> pfi=NULL;<br />}<br />CAvi::~CAvi()//析构、释放指?br />{<br /> // AVIFileClose(pfile);<br /> AVIFileExit();<br /> if(pData!=NULL)<br />  delete pData;<br />  pData=NULL;<br /><br /> if(m_pBMI!=NULL)<br />  delete m_pBMI;<br />  m_pBMI=NULL;<br />  if(pfi!=NULL)<br />   delete pfi;<br />   pfi=NULL;<br />}<br />CAvi::CAviCreate(CString &string)//L件初始化该类<br />{ <br /> HRESULT hr;<br /> pfi=new AVIFILEINFO;<br /> hr = AVIFileOpen(&pfile, // returned file pointer<br /> string, // file name<br /> OF_READ, // mode to open file with<br /> NULL);<br /> hr= AVIFileInfo(pfile, file://获取AVI信息Q放入pfi?br /> pfi, <br /> sizeof(AVIFILEINFO) <br />);<br />cx=pfi->dwWidth;//图象宽、高<br />cy=pfi->dwHeight;<br />hr=AVIFileGetStream(//AVI变成视频?br />pfile, <br />&pavi, <br />streamtypeVIDEO, <br />0//LONG lParam <br />);<br />m_pBMI=new BITMAPINFO;//定义BMP信息?br />m_pBMI->bmiHeader.biBitCount=24;<br />m_pBMI->bmiHeader.biClrImportant=0;<br />m_pBMI->bmiHeader.biClrUsed=0;<br />m_pBMI->bmiHeader.biCompression=BI_RGB;<br />m_pBMI->bmiHeader.biHeight=cy;<br />m_pBMI->bmiHeader.biWidth=cx;<br />m_pBMI->bmiHeader.biPlanes=1;<br />m_pBMI->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);<br />m_pBMI->bmiHeader.biXPelsPerMeter=0;<br />m_pBMI->bmiHeader.biYPelsPerMeter=0;<br />m_pBMI->bmiHeader.biSizeImage=cx*cy*3;<br />pData=(BYTE*)new char[cx*cy*3];//ҎAVI中BMP图象的信息定义缓冲区<br />}<br />BOOL CAvi::AviRead(int mFrame)//AVI文g的M帧数据读入PData~冲?br />{<br />HRESULT hr;<br />hr= AVIStreamRead( pavi, <br />mFrame, <br />1, <br />pData, <br />cx*cy*3, <br />NULL, <br />NULL<br />);<br />if(hr==0)<br />return TRUE;<br />else<br />return FALSE;<br />}<br /></td></tr></tbody></table><br /><br />   上述Cavicd现部分所涉及到的API函数可以参考微软提供的MSDN。CavicM的pData~冲区存放AVI文g中的具体某一帧图像数据,同时 Cavicȝm_pBMI为BMP囑փ文g信息l构Q这时可以根据图像的大小定义BMP囑փ文g头结构,关于BMP文g的存储,׃幅的原因,我不在多 讲了Q有兴趣的读者可以参见笔者的拙作"Visual C++6.0开发灰度位囑֤?Q天极网软g栏目2001.9.10发表Q,该文里面讲述了如何存取BMP文g。以上程序在Windows2000? Visual C++6.0环境下顺利编译通过Q运行正常?/span> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/swo2006/aggbug/10982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-08-08 13:05 <a href="http://www.shnenglu.com/swo2006/articles/10982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual C++中DDB与DIB位图~程全攻?/title><link>http://www.shnenglu.com/swo2006/articles/10980.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Tue, 08 Aug 2006 05:00:00 GMT</pubDate><guid>http://www.shnenglu.com/swo2006/articles/10980.html</guid><wfw:comment>http://www.shnenglu.com/swo2006/comments/10980.html</wfw:comment><comments>http://www.shnenglu.com/swo2006/articles/10980.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/swo2006/comments/commentRss/10980.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/swo2006/services/trackbacks/10980.html</trackback:ping><description><![CDATA[ <p align="center">Visual C++中DDB与DIB位图~程全攻?br />来源: 天极|?/p> <p align="left"> <strong>1. 基本概念<br /><br /></strong>先来用通俗的语句讲解位囑֒调色板的概念?br />? 们知道,自然界中的所有颜色都可以q、绿、蓝(RQGQB)三基色组合而成。针对含有红、绿、蓝色成分的多少Q可以对其分别分??55个等U,? U、绿、蓝的不同组合共?56×256×256U,因此U能表示1600万种颜色。对于hD言Q这已经?真彩?了?br /><br />Ҏ个像素进行了QRQGQBQ量化的囑փ是位图Q其在计机中对应文件的扩展名一般ؓ.bmp。既然用RQGQB的量化值就可以直接记录一张位囄所有像素,那我们需要调色板q什么呢Q?br /><br />首先Q我们可以计完全利用(RQGQBQ组合来存储一?00×600的位图所需要的I间为:<br /><br />800×600×3 = 1440000Q字节)Q?1.37MQ字节)<br /><br />惊h的大Q因此,调色板横I出世了Q它的功能在于缓解位图文件存储空间过大的问题?br /><br />假设一个位图ؓ16Ԍ其像素L?00×600。我们只需要用4个bit可以存储这个位囄每个像素?6U颜色中所处的{Q然后调色板提供了这16U等U对应的QRQGQBQ|q样Q存储这?6色位囑֏需要:<br /><br />800×600×4/8 = 240000Q字节)= 0.22 MQ字节)<br /><br />额外的存储RQGQB表的开销Q即调色板PaletteQ也UCؓ颜色查找表LUTQ仅仅ؓ16×3Q?8字节?br /><br />存储I间被大为减!<br /><br />常见的位图有单色?6艌Ӏ?56艌Ӏ?6位及24位真彩色5U,对于前三者(即不大于256Ԍ都可以调色板方式q行存储Q而对16位及24位真彩色以调色板q行存储是不划算的,它们直接按照RQGQB分量q行存储?br /><br />在此基础上我们来分析DDB位图QDevice-dependent bitmapQ与讑֤相关的位图)与DIB位图QDevice-independent bitmapQ与讑֤无关的位图)的概念以及二者的区别?br /><br />DDB依赖于具体设备,它只能存在于内存中(视频内存或系l内存)Q其颜色模式必须与特定的输出讑֤怸_使用pȝ调色ѝ一般只能蝲入色彩较单的DDB位图Q对于颜色较丰富的位图,需使用DIB才能长期保存?br /><br />DIB 不依赖于具体讑֤Q可以用来永久性地保存图象。DIB一般是?.BMP文g的Ş式保存在盘中的Q有时也会保存在*.DIB文g中? DIB位图的特Ҏ颜色信息储存在位图文g自n的颜色表中,应用E序要根据此颜色表ؓDIB创徏逻辑调色ѝ因此,在输ZqDIB位图之前Q程序应? 其逻辑调色杉K入到相关的讑֤上下文ƈ实现到系l调色板中?br /><br /><strong>2. 例程q?br /></strong><br />本文后箋的讲解都Zq样的一个例子工E,它是一个基于对话框的MFC应用E序Q包?个父菜单Q?br /><br />Q?Q?DDB位图<br /><br />DDB位图父菜单又包括两个子菜单:<br /><br />a. IDQIDM_LOADDDBPIC captionQ加?br /><br />单击事gQ加载资源中的DDB位图q显CZ<br /><br />b. IDQIDM_MARK_DDBPIC captionQ标?br /><br />单击事gQ在DIB位图中透明地添加天极网logo<br /><br />Q?Q?DIB位图<br /><br />DIB位图父菜单又包括两个子菜单:<br /><br />a. IDQIDM_OPENDIBPIC captionQ打开<br /><br />单击事gQ弹出文件对话框Q打开.bmp位图文gQƈ昄<br /><br />b. IDQIDM_MARK_DIBPIC captionQ标?br /><br />单击事gQ在DIB位图中透明地添加天极网logo<br /><br />工程中还包含下列位图资源Q?br /><br />Q?QIDB_LOADED_BITMAPQ要加蝲的位图资?br /><br />Q?QIDB_YESKY_BITMAPQ天极网logo<br /><br />后箋章集中在?个子菜单单击事g消息处理函数的讲解,下面的代码是整个对话框类CBitMapExampleDlg的消息映:<br /><br /><code>BEGIN_MESSAGE_MAP(CBitMapExampleDlg, CDialog)<br />//{{AFX_MSG_MAP(CBitMapExampleDlg)<br />ON_WM_SYSCOMMAND()<br />ON_WM_PAINT()<br />ON_WM_QUERYDRAGICON()<br />ON_COMMAND(IDM_LOADDDBPIC, OnLoadddbpic)<br />ON_COMMAND(IDM_MARK_DDBPIC, OnMarkDdbpic)<br />ON_COMMAND(IDM_OPENDIBPIC, OnOpendibpic)<br />ON_COMMAND(IDM_MARK_DIBPIC,OnMarkDibpic) //}}AFX_MSG_MAP<br />END_MESSAGE_MAP()</code></p> <p> </p> <p> <strong>3. DDB位图~程<br /><br /></strong>先看DDB加蝲按钮的单M件代码:<br /><br /><code>void CBitMapExampleDlg::OnLoadddbpic() <br />{<br />1: CBitmap bmpDraw;<br />2: bmpDraw.LoadBitmap( IDB_LOADED_BITMAP );//装入要加载的DDB位图 <br />3: BITMAP bmpInfo;<br />4: bmpDraw.GetBitmap( &bmpInfo ); //获取要加载DDB位图的尺?<br />5: CDC memDC;//定义一个兼容DC<br />6: CClientDC dc( this );<br />7: memDC.CreateCompatibleDC( &dc );//创徏兼容DC<br />8: CBitmap* pbmpOld = memDC.SelectObject( &bmpDraw );//保存原有DDBQƈ选入新DDB入DC<br /><br />9: dc.BitBlt( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY );<br /><br />10: memDC.SelectObject( pbmpOld );//选入原DDB<br />}</code><br />上述代码生如?所C的效果Q位图被安置在对话框Q?,0Q坐标开始的位置上?/p> <p> <img src="http://cimg.163.com/catchpic/F/F8/F8F94958CE8F80443F1BDF1E43BFEA87.jpg" alt="" border="0" /> </p> <p>? 加蝲DDB位图资源</p> <p> </p> <p> <br />我们来逐行解析上述代码是怎样产生?的效果的?br /><br />W??行定义了一个CBitmap对象Qƈ调用其成员函? LoadBitmap加蝲工程中的位图资源IDB_LOADED_BITMAP。第3?行定义了BITMAPl构体的实例q调用CBitmap的成员函 数GetBitmap获得位图信息QBITMAPl构体定义在<wingdi.h></wingdi.h>头文件中Q其形式为:<br /><br /><code>/* Bitmap Header Definition */<br />typedef struct tagBITMAP<br />{<br />LONG bmType; //必需?<br />LONG bmWidth; //位图的宽?以像素ؓ单位)<br />LONG bmHeight; //位图的高?以像素ؓ单位)<br />LONG bmWidthBytes; //每一扫描行所需的字节数Q应是偶?br />WORD bmPlanes; //色^面数<br />WORD bmBitsPixel; //色^面的颜色位数<br />LPVOID bmBits; //指向存储像素阵列的数l?br />} BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;</code><br />W?~8行的作用是:构徏一个CDC对象Q调用CDC::CreateCompatibleDC创徏一个兼容的内存讑֤上下文,接着调用CDC::SelectObjectDDB选入内存讑֤上下文中?br /><br />W?行调用函数CDC::BitBltl制位图QCDC::BitBlt的原型ؓQ?br /><br /><code>CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int xSrc, int ySrc, DWORD dwRop)</code><br />CDC::BitBlt执行的操作ؓ源DC中位囑֤制到目的DC中。其中前四个参数为目的区域的坐标Qx,yQ及长度和宽度(Width, nHeightQ,W五个参数是源DC指针Q接下来的参数是源DC中的起始坐标Q最后一个参Cؓ光栅操作的类型?br /><br />W?0行调用CDC::SelectObject把原来的DDB选入到内存设备上下文中ƈ使新DDBq出来?br /><br />与CDC::BitBlt对应的还有另一个函数CDC::StretchBltQ它h~放功能Q其原型为:<br /><br /><code>BOOL CDC::StretchBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int<br />xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop);</code><br />该函数把位图从源矩Ş拯到目的矩形中Q如果源和目的矩形尺怸同,那么羃放位囄功能以适应目的矩Ş的大。函数的大部分参CBitBlt的相同,但多了两个参数nSrcWidth和nSrcHeight用来指定源矩形的宽和高?br /><br />如果我们函数CBitMapExampleDlg::OnLoadddbpic() 中的W?行改为:<br /><br /><code>CRect clientRect;<br />GetClientRect(&clientRect); //获得对话框窗口的大小<br />dc.StretchBlt(0, 0, clientRect.right, clientRect.bottom, &memDC, 0, 0,<br />bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY);</code><br />则单d载按钮后的对话框如图2所C,位图被拉伸至整个对话框的范围?br /></p> <p> <br /> </p> <p align="center"> <img src="http://cimg.163.com/catchpic/4/4F/4F91CC4A105C69E77279A52F4FB2A9EE.jpg" alt="" border="0" /> </p> <p align="center"> <br />? 拉位图<br /></p> <p>CDC::BitBlt和dc.StretchBlt函数中的dwRop参数较ؓ有用Q它定义光栅操作的类型。请?DDB位图"父菜单下"标记"子菜单单M件的消息处理函数代码Q?br /><br /><code>void CBitMapExampleDlg::OnMarkDdbpic()<br />{<br />CBitmap bmpDraw;<br />bmpDraw.LoadBitmap(IDB_YESKY_BITMAP); //装入天极|logo DDB位图资源<br />BITMAP bmpInfo;<br />bmpDraw.GetBitmap(&bmpInfo); //获取天极|logo位图的尺?<br /><br />CDC memDC; //定义一个兼容DC<br />CClientDC dc(this);<br />memDC.CreateCompatibleDC(&dc); //创徏DC<br /><br />CBitmap *pbmpOld = memDC.SelectObject(&bmpDraw);<br />//保存原有DDBQƈ选入天极|logo位图入DC<br />dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND);<br />memDC.SelectObject(pbmpOld); //选入原DDB <br />}</code><br />单击该按钮后Q将产生如图3的效果,天极|的logo被透明地添加到了位图中Q?br /></p> <p> <br /> </p> <p align="center"> <img src="http://cimg.163.com/catchpic/A/AE/AE56DF89FB6B969070E26137BC6C5041.jpg" alt="" border="0" /> </p> <p align="center"> <br />? 在DDB位图中加入天极网logo<br /></p> <p>能生这个效果的原因在于我们在代码行Q?br /><br /><code>dc.BitBlt ( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND );</code></p> <p> <code>中用了参数SRCANDQ不同于先前代码中SRCCOPYQ它仅仅意味着复制源位囑ֈ目的位图Q,它的含义为源和目的间q行AND? 作。我们不知道天极|的~辑同志是怎么为文章中的图片加logo的,有可能他们就使用了具有自动AND功能的图像加logo批处理Y件。的,我们可以? 用例E中的原理写一个批处理软gQ一ơ对一堆图片自动添加logo?br /><br />参数dwRop除了可以为SRCAND和SRCCOPY外,q可以有如下取|<br /><br />BLACKNESSQ输出区域ؓ黑色<br /><br />DSTINVERTQ反转目的位?<br /><br />MERGECOPYQ用与操作把图案(Pattern)与源位图融合h <br /><br />MERGEPAINTQ用或操作把反{的源位图与目的位图融合v?<br /><br />NOTSRCCOPYQ把源位囑֏转然后拷贝到目的?<br /><br />NOTSRCERASEQ用或操作融合源和目的位图,然后再反?<br /><br />PATCOPYQ把图案拯到目的位图中 <br /><br />PATINVERTQ用异或操作把图案与目的位图相融?<br /><br />PATPAINTQ用或操作融合图案和反{的源位图Q然后用或操作把l果与目的位图融?<br /><br />SRCERASEQ先反{目的位图Q再用与操作其与源位图融合 <br /><br />SRCINVERTQ用异或操作融合源位囑֒目的位图 <br /><br />SRCPAINTQ用或操作融合源位图和目的位?<br /><br />WHITENESSQ输出区域ؓ白色<br /><br />合理利用q些取值将帮助我们制作出特定要求的囑փ处理软g?br /><br />从上q实例我们可以看出,在VC中用CBitmapc,必须位图放入工E的资源中,q用类 CBitmap的成员函数LoadBitmap加蝲之,再通过CDCcȝ成员函数BitBltq行DC拯{操作达到显C的目的。CBitmap有显C的不Q?br /><br />Q?Q?位图需要放入工E资源中Q这导致工E的可执行文件变大;<br /><br />Q?Q?因ؓ位图需攑օ工程资源中,而资源中不能无穷无尽地包含位图,应用E序无法自适应地选取其它位图Q能使用的位囑֍分有限的Q?br /><br />Q?Q?cCBitmap只是DDB位图操作API的封装,不能独立于^台?br /><br />DIB位图则可以解决上q问题,其特Ҏ?BMP位图文g格式存储独立于^台的囑փ数据Q下面我们来详细分析?br /><strong>4. DIB位图~程<br /><br /></strong>4.1位图文g格式<br /><br />先来分析DIB位图文g的格式。位图文件分为四部分Q?<br /><br />Q?Q位图文件头BITMAPFILEHEADER<br /><br />位图文g头BITMAPFILEHEADER是一个结构体Q长度ؓ14字节Q定义ؓQ?br /><br /><code>typedef struct tagBITMAPFILEHEADER<br />{<br />WORD bfType; //文gcdQ必L0x424DQ即字符?BM"<br />DWORD bfSize; //文g大小Q包括BITMAPFILEHEADER?4个字?br />WORD bfReserved1; //保留?br />WORD bfReserved2; //保留?br />DWORD bfOffBits; //从文件头到实际的位图数据的偏Ud节数<br />} BITMAPFILEHEADER;</code><br />Q?Q位图信息头BITMAPINFOHEADER<br /><br />位图信息头BITMAPINFOHEADER也是一个结构体Q长度ؓ40字节Q定义ؓQ?br /><br /><code>typedef struct tagBITMAPINFOHEADER<br />{<br />DWORD biSize; //本结构的长度Qؓ40<br />LONG biWidth; //图象的宽度,单位是象?br />LONG biHeight; //图象的高度,单位是象?br />WORD biPlanes; //必须?<br />WORD biBitCount;<br />//表示颜色时要用到的位敎ͼ1(单色), 4(16?, 8(256?, 24(真彩?<br />DWORD biCompression;<br />//指定位图是否压羃Q有效的gؓBI_RGBQBI_RLE8QBI_RLE4QBI_BITFIELDS{,BI_RGB表示不压~?br />DWORD biSizeImage;<br />//实际的位图数据占用的字节敎ͼ?biSizeImage=biWidth?× biHeightQbiWidth’是biWidth 按照4的整倍数调整后的l果 <br />LONG biXPelsPerMeter; //目标讑֤的水q_辨率Q单位是每米的象素个?br />LONG biYPelsPerMeter; //目标讑֤的垂直分辨率Q单位是每米的象素个?br />DWORD biClrUsed; //位图实际用到的颜色数Q?表示颜色Cؓ2biBitCount<br />DWORD biClrImportant; //位图中重要的颜色敎ͼ0表示所有颜色都重要<br />} BITMAPINFOHEADER;</code><br />Q?Q调色板Palette<br /><br />? 色板Palette针对的是需要调色板的位图,卛_艌Ӏ?6色和256色位图。对于不以调色板方式存储的位图,则无此项信息。调色板是一个数l,共有 biClrUsed个元?如果该gؓ0Q则?biBitCount个元?。数l中每个元素是一个RGBQUADl构体,长度?个字节,定义为:<br /><br /><code>typedef struct tagRGBQUAD<br />{<br />BYTE rgbBlue; //蓝色分量<br />BYTE rgbGreen; //l色分量<br />BYTE rgbRed; //U色分量<br />BYTE rgbReserved; //保留?br />} RGBQUAD;</code></code> </p> <p> <code> <code>Q?Q实际的位图数据ImageDate<br /><br />对于用到调色板的位图Q实际的图象数据ImageDate象素的颜色在调色板中的烦引|对于真彩色图Q图象数据则为实际的R、G、B|<br /><br />a.单色位图Q用1bit可以表C素的颜色索引|<br /><br />b.16色位图:?bit可以表示象素的颜色烦引|<br /><br />c. 256色位图:1个字节表C?个象素的颜色索引| <br /><br />d.真彩Ԍ3个字节表C?个象素的颜色RQGQB倹{?br /><br />此外Q位图数据每一行的字节数必Mؓ4的整倍数Q如果不是,则需要补齐。奇怪的是,位图文g中的数据是从下到上(而不是从上到下)、从左到x式存储的?br />4.2位图的显C?br /><br />Visual C++ MFC中没有提供一个专门的cL处理DIB位图Q因此,Z方便C用位图文Ӟ我们有必要派生一个CDibcR类的源代码如下Q?br /><br />(1) CDibcȝ声明<br /><br /><code>// DIB.hQ类CDib声明头文?br />#ifndef __DIB_H__<br />#define __DIB_H__<br />#include <wingdi.h></wingdi.h><br />class CDib<br />{<br />public:<br />CDib();<br />~CDib();<br /><br />BOOL Load( const char * );<br />BOOL Save( const char * );<br />BOOL Draw( CDC *, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1, int mode = SRCCOPY);<br />BOOL SetPalette( CDC * );<br /><br />private:<br />CPalette m_Palette;<br />unsigned char *m_pDib, *m_pDibBits;<br />DWORD m_dwDibSize;<br />BITMAPINFOHEADER *m_pBIH;<br />RGBQUAD *m_pPalette;<br />int m_nPaletteEntries;<br />};<br />#endif<br /></code><br />(2) CDibcȝ实现<br /><br /><code>// DIB.cppQ类CDib实现文g<br />#include "stdafx.h"<br />#include "DIB.h"<br /><br />CDib::CDib()<br />{<br />m_pDib = NULL;<br />}<br /><br />CDib::~CDib()<br />{<br />// 如果位图已经被加载,释放内存<br />if (m_pDib != NULL)<br />delete []m_pDib;<br />}</code><br />下面q个函数非常重要Q其功能为加载位图,cM于CBitmapcȝLoadBitmap函数Q?br /><br /><code>BOOL CDib::Load(const char *pszFilename)<br />{<br />CFile cf;<br /><br />// 打开位图文g<br />if (!cf.Open(pszFilename, CFile::modeRead))<br />return (FALSE);<br /><br />// 获得位图文g大小Qƈ减去BITMAPFILEHEADER的长?br />DWORD dwDibSize;<br />dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER);<br /><br />// 为DIB位图分配内存<br />unsigned char *pDib;<br />pDib = new unsigned char[dwDibSize];<br />if (pDib == NULL)<br />return (FALSE);<br /><br />BITMAPFILEHEADER BFH;<br /><br />// d位图文g数据<br />try<br />{<br />// 文g格式是否正确有效<br />if ( cf.Read(&BFH, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER) ||<br />BFH.bfType != ’MB?|| cf.Read(pDib, dwDibSize) != dwDibSize)<br />{<br />delete []pDib;<br />return (FALSE);<br />}<br />}<br />catch (CFileException *e)<br />{<br />e->Delete();<br />delete []pDib;<br />return (FALSE);<br />}<br /><br />// delete先前加蝲的位?br />if (m_pDib != NULL) <br />delete m_pDib;<br /><br />// 时Dib数据指针和Dib大小变量赋给cL员变?br />m_pDib = pDib;<br />m_dwDibSize = dwDibSize;<br /><br />// 为相应类成员变量赋BITMAPINFOHEADER和调色板指针<br />m_pBIH = (BITMAPINFOHEADER*)m_pDib;<br />m_pPalette = (RGBQUAD*) &m_pDib[sizeof(BITMAPINFOHEADER)];<br /><br />// 计算调色板中实际颜色数量<br />m_nPaletteEntries = 1 << m_pBIH->biBitCount;<br />if (m_pBIH->biBitCount >8)<br />m_nPaletteEntries = 0;<br />else if (m_pBIH->biClrUsed != 0)<br />m_nPaletteEntries = m_pBIH->biClrUsed;<br /><br />// 为相应类成员变量赋image data指针<br />m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof (RGBQUAD)];<br /><br />// delete先前的调色板<br />if (m_Palette.GetSafeHandle() != NULL)<br />m_Palette.DeleteObject();<br /><br />// 如果位图中存在调色板Q创建LOGPALETTE 及CPalette<br />if (m_nPaletteEntries != 0)<br />{<br />LOGPALETTE *pLogPal = (LOGPALETTE*)new char[sizeof(LOGPALETTE) + m_nPaletteEntries *sizeof(PALETTEENTRY)];<br /><br />if (pLogPal != NULL)<br />{<br />pLogPal->palVersion = 0x300;<br />pLogPal->palNumEntries = m_nPaletteEntries;<br /><br />for (int i = 0; i < m_nPaletteEntries; i++)<br />{<br />pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed;<br />pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen;<br />pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue;<br />}<br /><br />//创徏CPaletteq放LOGPALETTE的内?br />m_Palette.CreatePalette(pLogPal);<br />delete []pLogPal;<br />}<br />}<br /><br />return (TRUE);<br />}<br /><br />//函数功能Q保存位囑օBMP文g<br />BOOL CDib::Save(const char *pszFilename)<br />{<br />if (m_pDib == NULL)<br />return (FALSE);<br /><br />CFile cf;<br />if (!cf.Open(pszFilename, CFile::modeCreate | CFile::modeWrite))<br />return (FALSE);<br /><br />try<br />{<br />BITMAPFILEHEADER BFH;<br />memset(&BFH, 0, sizeof(BITMAPFILEHEADER));<br />BFH.bfType = ’MB?<br />BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_dwDibSize;<br />BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + <br />sizeof(BITMAPINFOHEADER) + m_nPaletteEntries *sizeof(RGBQUAD);<br /><br />cf.Write(&BFH, sizeof(BITMAPFILEHEADER));<br />cf.Write(m_pDib, m_dwDibSize);<br />}<br />catch (CFileException *e)<br />{<br />e->Delete();<br />return (FALSE);<br />}<br />return (TRUE);<br />}</code><br />下面q个函数也非帔R要,其功能ؓ在pDC指向的CDC中绘制位图,L坐标?nX,nY)Q绘制宽度和高度为nWidth、nHeightQ最后一个参数是光栅模式Q?br /><br /><code>BOOL CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)<br />{<br />if (m_pDib == NULL)<br />return (FALSE);<br /><br />// 获取位图宽度和高度赋?br />if (nWidth == - 1)<br />nWidth = m_pBIH->biWidth;<br />if (nHeight == - 1)<br />nHeight = m_pBIH->biHeight;<br /><br />// l制位图<br />StretchDIBits(pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0, m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, (BITMAPINFO*)m_pBIH, BI_RGB, mode);<br /><br />return (TRUE);<br />}<br /><br />//函数功能Q设|调色板<br />BOOL CDib::SetPalette(CDC *pDC)<br />{<br />if (m_pDib == NULL)<br />return (FALSE);<br /><br />// 查当前是否有一个调色板句柄Q对于大?56色的位图QؓNULL<br />if (m_Palette.GetSafeHandle() == NULL)<br />return (TRUE);<br /><br />// 选择调色板,接着实施之,最后恢复老的调色?br />CPalette *pOldPalette;<br />pOldPalette = pDC->SelectPalette(&m_Palette, FALSE);<br />pDC->RealizePalette();<br />pDC->SelectPalette(pOldPalette, FALSE);<br /><br />return (TRUE);<br />}</code><br />从整个CDibcȝ代码中我们可以看出,DIB位图的显C需遵@如下步骤Q?br /><br />Q?Q读取位图,本类中用pDib = new unsigned char[dwDibSize]Z图中的信息分配内存,另一U方法是调用API函数CreateDIBSectionQ譬如:<br /><br /><code>m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), <br />(LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS,<br />(LPVOID*) &m_lpDIBits, NULL, 0);</code><br />m_hBitmap定义为:<br /><br /><code>HBITMAP m_hBitmap;</code><br />Q?Q根据读取的位图信息Q计出调色板大,然后创徏调色板;<br /><br />Q?Q调用CDib::SetPalette( CDC *pDC )讄调色板,需要用到CDC::SelectPalette及CDC::RealizePalette两个函数Q?br /><br />Q?Q? 调用CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)函数l制位图。在此函CQ真正发挥显CZ图作用的是对StretchDIBits API函数的调用。StretchDIBits函数h~放功能Q其最后一个参C是光栅操作的模式?br /><br />下面l出DIB位图的打开及显Cƈ在其中加入天极网logo的函数源代码?DIB位图"父菜单下"打开"子菜单的单击事g消息处理函数为(其功能ؓ打开位图q显CZQ: <br /><br /><code>void CBitMapExampleDlg::OnOpendibpic()<br />{<br />// 弹出文g对话框,让用户选择位图文g<br />CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL,"位图文g(*.BMP)|*.bmp;*.BMP|");<br />if (IDOK == fileDialog.DoModal())<br />{<br />// 加蝲位图q显CZ<br />CDib dib;<br />if (dib.Load(fileDialog.GetPathName()))<br />{<br />CClientDC dc(this);<br />dib.SetPalette(&dc);<br />dib.Draw(&dc);<br />}<br />}<br />}</code><br />"DIB位图"父菜单下"标记"子菜单的单击事g消息处理函数为(其功能ؓl位囑֊上天极网logoQ:<br /><br /><code>void CBitMapExampleDlg::OnMarkDibpic()<br />{<br />// 弹出文g对话框,让用户选择标记logo<br />CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL, "标记位图文g(*.BMP)|*.bmp;*.BMP|");<br />if (IDOK == fileDialog.DoModal())<br />{<br />// 加蝲标记logo位图q与目标位图怸<br />CDib dib;<br />if (dib.Load(fileDialog.GetPathName()))<br />{<br />CClientDC dc(this);<br />dib.SetPalette(&dc);<br />dib.Draw(&dc, 0, 0, - 1, - 1, SRCAND);<br />}<br />}<br />}</code><br />?昄了DIB位图加蝲天极|logo后的效果Q要好于?中加天极|logo后的DDB位图。图4昄的是真彩色位囄互与的结果,而图3中的囑փ颜色被减了?br /><br /></code> </code> </p> <p align="center"> <img src="http://cimg.163.com/catchpic/E/E6/E683A3F6D12F0BFB25E9FC01B42FAC52.jpg" alt="" border="0" /> </p> <p align="center"> <br />? 在DIB位图中加入天极网logo<br /></p> <strong> </strong> <p> <strong>5. l束?br /></strong> <br />本文介绍了位囑֏调色板的概念Qƈ讲解了DDB位图与DIB位图的区别。在此基 上,本文以实例讲解了DDB位图和DIB位图的操作方式。DDB位图的处理相Ҏ较简单,对于DIB位图Q我们需要定义一个MFC所没有的新cCDibQ? 它屏蔽位图信息的d及调色板创徏的技术细节,应用E序可以方便C用之?br /><br />本文中的所有程序在Visual C++6.0及Windows XPq_上调试通过?/p> <img src ="http://www.shnenglu.com/swo2006/aggbug/10980.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/swo2006/" target="_blank">swo</a> 2006-08-08 13:00 <a href="http://www.shnenglu.com/swo2006/articles/10980.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.fkmlt.cn" target="_blank">Ʒþþþþþþҹ</a>| <a href="http://www.vxbw.cn" target="_blank">޹Ʒľþþ</a>| <a href="http://www.pedl.cn" target="_blank">ƷþùƷ99</a>| <a href="http://www.more1.cn" target="_blank">ëƬþþþþùëƬ </a>| <a href="http://www.zhhhtch.cn" target="_blank">þþƷһӰԺ</a>| <a href="http://www.adidas2009.cn" target="_blank">һձ˾þۺӰ</a>| <a href="http://www.9yyg.cn" target="_blank">뾫ƷþѼ</a>| <a href="http://www.ruan8.cn" target="_blank">þۺһ</a>| <a href="http://www.baojingqi88.org.cn" target="_blank">ھƷþþþӰԺ޹²</a>| <a href="http://www.jmjrt.cn" target="_blank">ھƷþþþù</a>| <a href="http://www.mdg163.cn" target="_blank">þþþavרˮ </a>| <a href="http://www.vygd.cn" target="_blank">պAVþһ</a>| <a href="http://www.glhu.cn" target="_blank">ھƷ99þ</a>| <a href="http://www.telaviv.com.cn" target="_blank">þAV뾫Ʒɫҹ</a>| <a href="http://www.aqbfrmi.cn" target="_blank">žžþþƷ</a>| <a href="http://www.8806699.cn" target="_blank">ھƷþþžŹƷ</a>| <a href="http://www.ilovegou.cn" target="_blank">ӰȷŮAV³ɫԴþ </a>| <a href="http://www.gnkk.net.cn" target="_blank">99þþþþѿ</a>| <a href="http://www.888happy.cn" target="_blank">޾Ʒþþþþ</a>| <a href="http://www.028sihai.cn" target="_blank">ղþǿѵĿ</a>| <a href="http://www.aion999.cn" target="_blank">޺ݺݾþۺһ77777</a>| <a href="http://www.dw172.cn" target="_blank">þˬˬ</a>| <a href="http://www.p8595.cn" target="_blank">޹˾þһҳ</a>| <a href="http://www.z42195.cn" target="_blank">ŷһƷþ</a>| <a href="http://www.1rizu.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.csjhc.cn" target="_blank">þþþþþž99Ʒ</a>| <a href="http://www.fuwumianyang.cn" target="_blank">޾þһح</a>| <a href="http://www.51xinjia.cn" target="_blank">þþ޾Ʒ</a>| <a href="http://www.08fq.cn" target="_blank">þþþþùƷ</a>| <a href="http://www.aylzys.cn" target="_blank">91Ʒպþò</a>| <a href="http://www.cn-sina.cn" target="_blank">99þóĻ</a>| <a href="http://www.zyxslswx.cn" target="_blank">þþƷ˘AV</a>| <a href="http://www.zhaoyang-db.com.cn" target="_blank">þAV</a>| <a href="http://www.loreng.cn" target="_blank">ŷ˾þô߽ۺ</a>| <a href="http://www.dgjiajun.net.cn" target="_blank">þþþþþ</a>| <a href="http://www.http2009.cn" target="_blank">þþƷ޾Ʒŷ</a>| <a href="http://www.erbp.cn" target="_blank">þAAAAƬһ</a>| <a href="http://www.qinhaichang.cn" target="_blank">þ޹Ʒ123</a>| <a href="http://www.hwtk.net.cn" target="_blank">þþþרav</a>| <a href="http://www.niuhongtao.cn" target="_blank">þĻƵ</a>| <a href="http://www.889kk8.cn" target="_blank">þü޾Ʒ?V</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>