gre*_*ast 3 c++ gdi+ codeblocks
我是新的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,0,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:\\test\\test.png", &pngClsid, NULL);
}
GdiplusShutdown(gdiplusToken);
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题如下:
"保存"代码无法编译,并提供错误消息"'GetEncoderClsid'未在此范围内声明".但是,我从微软网站的这种直接在这里.我不认为这是转换为png的正确方法,但我不知道另一种方法吗?
编译并运行代码时(通过注释掉保存代码),它会在"Bitmap*myBitmap = new Bitmap(width,height,PixelFormatCanonical);"行中崩溃.并给出一条错误消息,说我的可执行文件已停止工作.
我添加了'gdi32'链接库以及'-lgdiplus'作为链接器选项.此外,我已经使用这个网站来帮助gdi的东西,虽然位图部分只涉及加载现有的位图(不在内存中创建新的位图)
我完全迷失了该怎么做,所以对此事的任何帮助或建议都非常感谢.
核心问题是将错误的像素格式传递给Bitmap构造函数.PixelFormatCanonical不是受支持的像素格式之一.它是一个用于确定像素格式是否规范的掩码(参见IsCanonicalPixelFormat).你必须使用真正的像素格式,比如默认格式PixelFormat32bppARGB.
以下代码生成所需的输出:
首先,一个用于GDI +初始化的小助手类.这确保了GdiplusShutdown在所有其他对象被销毁之后执行d'tor(即调用).关于破坏的顺序,它与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_;
};
Run Code Online (Sandbox Code Playgroud)
此代码取自MSDN示例检索编码器的类标识符.
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
}
Run Code Online (Sandbox Code Playgroud)
最后,GDI +渲染代码.它使用具有自动存储持续时间的对象,使其更紧凑和更安全.
void drawImage( int width, int height ) {
GdiplusInit gdiplusinit;
//Create a bitmap
Bitmap myBitmap( width, height, PixelFormat32bppARGB );
Graphics g( &myBitmap );
Pen blackpen( Color( 255, 0, 0, 0 ), 3 );
//draw on bitmap
g.DrawLine( &blackpen, 1, 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:\\test\\test.png", &pngClsid, NULL ) )
throw runtime_error( "Bitmap::Save" );
}
int main()
{
drawImage( 200, 200 );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
注意:看起来GetEncoderClsid不应该是必需的,因为那些是众所周知的常量.但是,尝试传递适当的WIC CLSID(CLSID_WICPngEncoder)Bitmap::Save只会产生FileNotFound错误.