gpt4 book ai didi

c++ - 如何使用 Win32 解码 JPEG?

转载 作者:太空宇宙 更新时间:2023-11-04 01:49:53 24 4
gpt4 key购买 nike

我有一 block 包含 JPEG 原始字节的内存,我想将其转换为 24 位 RGB,以便我可以使用 StretchDIBits 渲染它。我环顾了 msdn,但是天哪……我真的不想使用任何第三方库,如果不需要的话,甚至不想使用 C++。有什么建议么?我希望只有一些像 DecodeJpeg() 之类的函数......

最佳答案

我想出了一个使用 WIC 的解决方案,它似乎没有使用 C++,但我无法将以下代码编译为 C,所以不确定。花了很多时间将各个部分拼凑在一起,但就是这样!

#include <Wincodec.h>
#include <stdio.h>

#pragma comment(lib, "Ole32.lib")
#pragma comment(lib, "Windowscodecs.lib")

#define MIN(A, B) (A < B ? A : B)

void
Win32DecodeJpeg(unsigned int ImageDataSize, void *ImageData,
unsigned int DestSize, void *Dest)
{
static IWICImagingFactory *IWICFactory;
if(IWICFactory == NULL)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&IWICFactory));
}

IWICStream *Stream;
IWICFactory->CreateStream(&Stream);
Stream->InitializeFromMemory((unsigned char *)ImageData, ImageDataSize);

IWICBitmapDecoder *BitmapDecoder;
IWICFactory->CreateDecoderFromStream(Stream, NULL, WICDecodeMetadataCacheOnDemand, &BitmapDecoder);

IWICBitmapFrameDecode *FrameDecode;
BitmapDecoder->GetFrame(0, &FrameDecode);

IWICFormatConverter *FormatConverter;
IWICFactory->CreateFormatConverter(&FormatConverter);

FormatConverter->Initialize(FrameDecode,
GUID_WICPixelFormat24bppBGR,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom);

IWICBitmap *Bitmap;
IWICFactory->CreateBitmapFromSource(FormatConverter, WICBitmapCacheOnDemand, &Bitmap);

unsigned int Width, Height;
Bitmap->GetSize(&Width, &Height);
WICRect Rect = {0, 0, (int)Width, (int)Height};

IWICBitmapLock *Lock;
Bitmap->Lock(&Rect, WICBitmapLockRead, &Lock);

unsigned int PixelDataSize = 0;
unsigned char *PixelData;
Lock->GetDataPointer(&PixelDataSize, &PixelData);

memcpy(Dest, PixelData, MIN(DestSize, PixelDataSize));

Stream->Release();
BitmapDecoder->Release();
FrameDecode->Release();
FormatConverter->Release();
Bitmap->Release();
Lock->Release();
}

int
main()
{
int ImageWidth = 640;
int ImageHeight = 480;

int DecodedBufferSize = ImageWidth * ImageHeight * 3;
void *DecodedBuffer = malloc(DecodedBufferSize);

FILE *ImageFile = fopen("test.jpg", "rb");

fseek(ImageFile, 0, SEEK_END);
int ImageSize = ftell(ImageFile);
rewind(ImageFile);

void *ImageData = malloc(ImageSize);
fread(ImageData, 1, ImageSize, ImageFile);

fclose(ImageFile);

Win32DecodeJpeg(ImageSize, ImageData, DecodedBufferSize, DecodedBuffer);
}

编辑:应大众需求,这里有一个带有基本错误检查和一些基本解释的版本:

#include <Wincodec.h>
#include <stdio.h>

#pragma comment(lib, "Ole32.lib")
#pragma comment(lib, "Windowscodecs.lib")

void
Win32DecodeJpeg(unsigned int ImageDataSize, void *ImageData,
unsigned int DestSize, void *Dest)
{
// IWICImagingFactory is a structure containing the function pointers of the WIC API
static IWICImagingFactory *IWICFactory;
if(IWICFactory == NULL)
{
if(CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK)
{
printf("failed to initialize the COM library\n");
return;
}

if(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&IWICFactory)) != S_OK)
{
printf("failed to create an instance of WIC\n");
return;
}
}

IWICStream *Stream;
if(IWICFactory->CreateStream(&Stream) != S_OK)
{
printf("failed to create stream\n");
return;
}

if(Stream->InitializeFromMemory((unsigned char *)ImageData, ImageDataSize) != S_OK)
{
printf("failed to initialize stream from memory\n");
return;
}

IWICBitmapDecoder *BitmapDecoder;
if(IWICFactory->CreateDecoderFromStream(Stream, NULL, WICDecodeMetadataCacheOnDemand, &BitmapDecoder) != S_OK)
{
printf("failed to create bitmap decoder from stream\n");
return;
}

IWICBitmapFrameDecode *FrameDecode;
// frames apply mostly to GIFs and other animated media. JPEGs just have a single frame.
if(BitmapDecoder->GetFrame(0, &FrameDecode) != S_OK)
{
printf("failed to get 0th frame from frame decoder\n");
return;
}

IWICFormatConverter *FormatConverter;
if(IWICFactory->CreateFormatConverter(&FormatConverter) != S_OK)
{
printf("failed to create format converter\n");
return;
}

// this function does not do any actual decoding
if(FormatConverter->Initialize(FrameDecode,
GUID_WICPixelFormat24bppBGR,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom) != S_OK)
{
printf("failed to initialize format converter\n");
return;
}

IWICBitmap *Bitmap;
if(IWICFactory->CreateBitmapFromSource(FormatConverter, WICBitmapCacheOnDemand, &Bitmap) != S_OK)
{
printf("failed to create bitmap from format converter\n");
return;
}

unsigned int Width, Height;
if(Bitmap->GetSize(&Width, &Height) != S_OK)
{
printf("failed to get the size of the bitmap\n");
return;
}
WICRect Rect = {0, 0, (int)Width, (int)Height};

IWICBitmapLock *Lock;
// this is the function that does the actual decoding. seems like they defer the decoding until it's actually needed
if(Bitmap->Lock(&Rect, WICBitmapLockRead, &Lock) != S_OK)
{
printf("failed to lock bitmap\n");
return;
}

unsigned int PixelDataSize = 0;
unsigned char *PixelData;
if(Lock->GetDataPointer(&PixelDataSize, &PixelData) != S_OK)
{
printf("failed to get data pointer\n");
return;
}

memcpy(Dest, PixelData, DestSize < PixelDataSize ? DestSize : PixelDataSize);

Stream->Release();
BitmapDecoder->Release();
FrameDecode->Release();
FormatConverter->Release();
Bitmap->Release();
Lock->Release();
}

int
main()
{
int ImageWidth = 640;
int ImageHeight = 480;

int DecodedBufferSize = ImageWidth * ImageHeight * 3;
void *DecodedBuffer = malloc(DecodedBufferSize);

FILE *ImageFile = fopen("test.jpg", "rb");

fseek(ImageFile, 0, SEEK_END);
int ImageSize = ftell(ImageFile);
rewind(ImageFile);

void *ImageData = malloc(ImageSize);
fread(ImageData, 1, ImageSize, ImageFile);

fclose(ImageFile);

Win32DecodeJpeg(ImageSize, ImageData, DecodedBufferSize, DecodedBuffer);
}

关于c++ - 如何使用 Win32 解码 JPEG?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45809347/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com