c – 在内存中创建GDI位图,然后另存为png
我是C的新手,在使用GDI库编写函数以在内存中创建新的位图时遇到了麻烦(因此不能打开/读取现有的位图);然后绘制位图;在保存到png之前.特别是,我在创建位图和保存代码方面遇到了问题.我被限制使用代码块,即使我想,我也不能使用视觉工作室.代码如下:
#include "drawImage.h" #include <windows.h> #include <objidl.h> #include <gdiplus.h> #include <stdio.h> #include <iostream> using namespace std; using namespace Gdiplus; drawImage::drawImage(){} void drawImage::DrawBitmap(int width,int height){ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL); { //Create a bitmap Bitmap myBitmap(width,height,PixelFormatCanonical); Graphics g(&myBitmap); Pen blackpen(Color(255,0),3); //draw on bitmap int x1 = 1; int x2 = 200; int y1 = 1; int y2 = 200; g.DrawLine(&blackpen,x1,y1,x2,y2); // Save bitmap (as a png) CLSID pngClsid; GetEncoderClsid(L"image/png",&pngClsid); myBitmap.Save(L"C:testtest.png",&pngClsid,NULL); } GdiplusShutdown(gdiplusToken); } 我遇到的问题如下: >“保存”代码无法编译,并提供错误消息“’GetEncoderClsid’未在此范围内声明”.但是,我从微软网站here直接得到了这个.我不认为这是转换为png的正确方法,但我不知道另一种方法吗? 我添加了’gdi32’链接库以及’-lgdiplus’作为链接器选项.另外,我使用this website来帮助处理gdi的东西,虽然位图部分只涉及加载现有的位图(不在内存中创建新的位图) 我完全迷失了该怎么做,所以对此事的任何帮助或建议都非常感谢. 解决方法
核心问题是将错误的像素格式传递给
Bitmap constructor.PixelFormatCanonical不是受支持的
pixel formats之一.它是一个用于确定像素格式是否规范的掩码(参见
IsCanonicalPixelFormat).你必须使用真正的像素格式,比如默认的PixelFormat32bppARGB.
以下代码生成所需的输出: 首先,一个用于GDI初始化的小助手类.这确保了在所有其他对象被销毁之后执行d’tor(即对GdiplusShutdown的调用).关于破坏的顺序,它与OP中的附加范围具有相同的目的.此外,它还允许抛出异常. #include <windows.h> #include <gdiplus.h> using namespace Gdiplus; #include <stdexcept> using std::runtime_error; struct GdiplusInit { GdiplusInit() { GdiplusStartupInput inp; GdiplusStartupOutput outp; if ( Ok != GdiplusStartup( &token_,&inp,&outp ) ) throw runtime_error( "GdiplusStartup" ); } ~GdiplusInit() { GdiplusShutdown( token_ ); } private: ULONG_PTR token_; }; 此代码取自MSDN示例Retrieving the Class Identifier for an Encoder. int GetEncoderClsid( const WCHAR* format,CLSID* pClsid ) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize( &num,&size ); if ( size == 0 ) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)( malloc( size ) ); if ( pImageCodecInfo == NULL ) return -1; // Failure GetImageEncoders( num,size,pImageCodecInfo ); for ( UINT j = 0; j < num; ++j ) { if ( wcscmp( pImageCodecInfo[j].MimeType,format ) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free( pImageCodecInfo ); return j; // Success } } free( pImageCodecInfo ); return -1; // Failure } 最后,GDI渲染代码.它使用具有自动存储持续时间的对象,使其更紧凑和更安全. void drawImage( int width,int height ) { GdiplusInit gdiplusinit; //Create a bitmap Bitmap myBitmap( width,PixelFormat32bppARGB ); Graphics g( &myBitmap ); Pen blackpen( Color( 255,0 ),3 ); //draw on bitmap g.DrawLine( &blackpen,1,200,200 ); // Save bitmap (as a png) CLSID pngClsid; int result = GetEncoderClsid( L"image/png",&pngClsid ); if ( result == -1 ) throw runtime_error( "GetEncoderClsid" ); if ( Ok != myBitmap.Save( L"C:testtest.png",NULL ) ) throw runtime_error( "Bitmap::Save" ); } int main() { drawImage( 200,200 ); return 0; } 注意:看起来不需要GetEncoderClsid,因为这些是众所周知的常量.但是,尝试将相应的WIC CLSID(CLSID_WICPngEncoder)传递给Bitmap :: Save只会产生FileNotFound错误. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |