C++ GDI实现图片格式转换

 更新时间:2023年12月15日 15:14:56   作者:XXYBMOOO  
GDI+(Graphics Device Interface Plus)是一种用于图形绘制和图像处理的应用程序编程接口(API),在Windows平台上广泛使用,本文就来介绍一下如何使用GDI实现图片格式转换吧

GDI+(Graphics Device Interface Plus)是一种用于图形绘制和图像处理的应用程序编程接口(API),在Windows平台上广泛使用。在GDI+中,可以使用Bitmap类来加载、保存和处理图像。

要进行图像格式转换,需要加载源图像并创建一个新的目标图像,然后使用GDI+提供的方法将源图像的像素数据复制到目标图像中。以下是一个详细的步骤解释:

1.引入GDI+库:在使用GDI+之前,需要引入相应的GDI+库,通常是gdiplus.dll。

2.初始化GDI+:在使用GDI+之前,需要先初始化GDI+库。在开始使用GDI+之前,调用GdiplusStartup函数来初始化GDI+。在处理完图像后,应调用GdiplusShutdown函数来释放GDI+资源。

#include <windows.h>
#include <gdiplus.h>
 
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
 
int main()
{
    // 初始化GDI+
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
    // 进行图像处理操作
    
    // 关闭GDI+
    Gdiplus::GdiplusShutdown(gdiplusToken);
    
    return 0;
}

3.加载源图像:使用Bitmap类的构造函数或Bitmap::FromFile方法加载源图像。例如,可以使用以下代码加载一个名为input.jpg的JPEG图像:

Gdiplus::Bitmap* sourceImage = Gdiplus::Bitmap::FromFile(L"input.jpg");

4.创建目标图像:创建一个空的目标图像,使用Bitmap类的构造函数或Bitmap::Clone方法。目标图像的大小和像素格式应根据需要进行设置。例如,可以使用以下代码创建一个与源图像相同大小和像素格式的新图像:

Gdiplus::Bitmap* targetImage = new Gdiplus::Bitmap(sourceImage->GetWidth(), sourceImage->GetHeight(), sourceImage->GetPixelFormat());

5.执行图像格式转换:使用Graphics类和DrawImage方法将源图像的像素数据复制到目标图像中。DrawImage方法可以接受多种不同的参数组合,以实现不同的绘制和转换效果。以下是一个示例,将源图像完全复制到目标图像中:

Gdiplus::Graphics graphics(targetImage);
graphics.DrawImage(sourceImage, 0, 0, sourceImage->GetWidth(), sourceImage->GetHeight());

6.保存目标图像:使用Bitmap::Save方法将目标图像保存到磁盘文件或内存流中。可以指定所需的图像格式和保存选项。例如,可以使用以下代码将目标图像保存为名为output.png的PNG图像:

targetImage->Save(L"output.png", Gdiplus::ImageFormatPNG);

7.释放资源:在完成图像处理后,需要释放所分配的内存。使用delete运算符释放源图像和目标图像的内存。

delete sourceImage;
delete targetImage;

以上是使用GDI+进行图像格式转换的一般步骤。请注意,这只是一个概述,并且在实际应用中可能需要处理更多的细节和错误检查。确保正确处理错误和异常情况,以及适当释放资源,以避免内存泄漏和其他问题。

完整示例代码

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <string>
using namespace Gdiplus;
 
#pragma comment(lib,"gdiplus")
 
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;
 
    // Get the number of image encoders and the size of the array
    GetImageEncodersSize(&num, &size);
    if (size == 0)
        return -1;  // Failure
 
    // Allocate memory for the image encoder array
    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL)
        return -1;  // Failure
 
    // Get all image encoders
    GetImageEncoders(num, size, pImageCodecInfo);
 
    // Find the image encoder that matches the specified format
    for (UINT j = 0; j < num; ++j)
    {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
        {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;  // Success
        }
    }
 
    // Free the allocated memory
    free(pImageCodecInfo);
    return -1;  // Failure
}
 
bool ConvertImageFormatFromMemory(const char* imageData, ULONG imageDataSize, const std::string& outputFilePath, const wchar_t* outputFormat)
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
 
    // Initialize GDI+
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
    CLSID encoderClsid;
    Status stat;
 
    // Create a stream from the image data
    IStream* pStream = NULL;
    CreateStreamOnHGlobal(NULL, TRUE, &pStream);
    pStream->Write(imageData, imageDataSize, NULL);
    pStream->Seek({ 0 }, STREAM_SEEK_SET, NULL);
 
    // Load the image from the stream
    Bitmap* bitmap = new Bitmap(pStream, FALSE);
    Image* image = static_cast<Image*>(bitmap);
 
    // Get the CLSID of the output format encoder
    GetEncoderClsid(outputFormat, &encoderClsid);
 
    // Convert the output file path to wide-character string
    int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, outputFilePath.c_str(), -1, NULL, 0);
    wchar_t* wideCharPath = new wchar_t[wideCharLen];
    MultiByteToWideChar(CP_UTF8, 0, outputFilePath.c_str(), -1, wideCharPath, wideCharLen);
 
    // Save the image in the desired format
    stat = image->Save(wideCharPath, &encoderClsid, NULL);
 
    // Clean up
    delete image;
    pStream->Release();
    GdiplusShutdown(gdiplusToken);
    delete[] wideCharPath;
 
    return (stat == Ok);
}
 
int main()
{
    // Assuming you have the BMP image data in a `char*` buffer named `imageData`
    char* imageData = /* Your BMP image data */;
    ULONG imageDataSize = /* Size of the BMP image data */;
 
    const std::string outputFilePath = "output.jpg";
    const wchar_t* outputFormat = L"image/jpeg";
 
    bool success = ConvertImageFormatFromMemory(imageData, imageDataSize, outputFilePath, outputFormat);
 
    if (success)
        printf("Image saved successfully.\n");
    else
        printf("Failed to save image.\n");
 
    return 0;
}

到此这篇关于C++ GDI实现图片格式转换的文章就介绍到这了,更多相关C++图片格式转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++ 中封装的含义和简单实现方式

    C++ 中封装的含义和简单实现方式

    这篇文章主要介绍了C++ 中封装的含义和简单实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • c语言main函数使用及其参数介绍

    c语言main函数使用及其参数介绍

    这篇文章主要介绍了c语言main函数使用及其参数介绍,需要的朋友可以参考下
    2014-04-04
  • C++文件相关函数CreateFile|ReadFile|WriteFile用法详解

    C++文件相关函数CreateFile|ReadFile|WriteFile用法详解

    这篇文章主要为大家详细介绍了c++有关文件创建、读取和写入的api:CreateFile、ReadFile、WriteFile的具体使用,需要的可以参考下
    2023-04-04
  • C++ 基础函数的介绍及使用(Vector+deque+STL)

    C++ 基础函数的介绍及使用(Vector+deque+STL)

    这篇文章主要介绍了C++ 基础函数的介绍及使用(Vector+deque+STL),文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • C++初阶教程之缺省参数与函数重载

    C++初阶教程之缺省参数与函数重载

    缺省参数是声明或定义函数时为函数的参数指定一个缺省值,在调用该函数时如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,这篇文章主要给大家介绍了关于C++初阶之缺省参数与函数重载的相关资料,需要的朋友可以参考下
    2023-04-04
  • QT5 Thread线程的具体实现

    QT5 Thread线程的具体实现

    本文主要介绍了QT5 Thread线程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • zlib库压缩和解压字符串STL string的实例详解

    zlib库压缩和解压字符串STL string的实例详解

    这篇文章主要介绍了zlib库压缩和解压字符串STL string的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-10-10
  • C++预定义的流对象基本示例详解

    C++预定义的流对象基本示例详解

    这篇文章主要为大家介绍了C++预定义的流对象基本示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • C语言连接并操作Sedna XML数据库的方法

    C语言连接并操作Sedna XML数据库的方法

    这篇文章主要介绍了C语言连接并操作Sedna XML数据库的方法,实例分析了C语言操作XML文件的相关技巧,需要的朋友可以参考下
    2015-06-06
  • C++二分查找(折半查找)算法实例详解

    C++二分查找(折半查找)算法实例详解

    这篇文章主要介绍了C++二分查找(折半查找)算法,结合实例形式详细分析了二分查找算法的原理、思想、实现方法与相关操作技巧,需要的朋友可以参考下
    2017-05-05

最新评论