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++图片格式转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Qt使用QCustomPlot的实现示例

    Qt使用QCustomPlot的实现示例

    QCustomPlot是一个基于Qt C++的图形库,用于绘制和数据可视化,并为实时可视化应用程序提供高性能服务,本文主要介绍了Qt使用QCustomPlot的实现示例,感兴趣的可以了解一下
    2024-01-01
  • 详解QT使用QtGui显示QImage的几种方法

    详解QT使用QtGui显示QImage的几种方法

    本文主要介绍了QT使用QtGui显示QImage的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • C++如何去除cpp文件的注释详解

    C++如何去除cpp文件的注释详解

    在日常工作中,我们会给c/c++代码写上一些注释,但是往往为了保持最终的代码尽可能小,我们需要删除注释,手动删除太缓慢了,下面这篇文章主要给大家介绍了关于C++如何去除cpp文件注释的相关资料,需要的朋友可以参考下
    2022-09-09
  • c++超细致讲解引用

    c++超细致讲解引用

    在我们日常的生活中每个人都或多或少存在一个"外号",例如《西游记》中孙悟空就有诸多外号:美猴王,孙行者,齐天大圣等等。那么在C++中,也可以给一个已经存在的变量取别名,这就是引用。那么接下来深入来探讨一下引用
    2022-05-05
  • C++冒泡排序与选择排序详解

    C++冒泡排序与选择排序详解

    大家好,本篇文章主要讲的是C++冒泡排序与选择排序详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 使用C语言中的time函数获取系统时间

    使用C语言中的time函数获取系统时间

    在C语言中可以使用time函数来获取系统时间,以下对time函数进行了介绍,需要的朋友可以过来参考下
    2013-07-07
  • C语言图文并茂讲解分支语句用法

    C语言图文并茂讲解分支语句用法

    分支结构的执行是依据一定的条件选择执行路径,而不是严格按照语句出现的物理顺序。分支结构的程序设计方法的关键在于构造合适的分支条件和分析程序流程,根据不同的程序流程选择适当的分支语句
    2022-04-04
  • C++超详细讲解运算符重载

    C++超详细讲解运算符重载

    本文包括了对C++类的6个默认成员函数中的赋值运算符重载和取地址和const对象取地址操作符的重载。运算符是程序中最最常见的操作,例如对于内置类型的赋值我们直接使用=赋值即可,因为这些编译器已经帮我们做好了,但是对象的赋值呢?能直接赋值吗
    2022-06-06
  • C++实现学生信息管理系统

    C++实现学生信息管理系统

    这篇文章主要为大家详细介绍了C++实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • C++11 lambda(匿名函数)表达式详细介绍

    C++11 lambda(匿名函数)表达式详细介绍

    lambda 表达式(lambda expression)是一个匿名函数,C++11中的lambda表达式用于定义并创建匿名的函数对象,以简化编程工作,下面这篇文章主要给大家介绍了关于C++11 lambda(匿名函数)表达式的相关资料,需要的朋友可以参考下
    2022-07-07

最新评论