c++ - How to Decode JPEG Using Win32? -
i have chunk of memory containing raw bytes of jpeg , convert 24-bit rgb can render using stretchdibits. i've looked around msdn jeez... don't want use third party libraries or c++ if don't have to. suggestions? wish there function decodejpeg() or something...
i came solution uses wic, doesn't seem use c++, wasn't able following code compile c, not sure. took lot of time put pieces together, here is!
#include <wincodec.h> #include <stdio.h> #pragma comment(lib, "ole32.lib") #pragma comment(lib, "windowscodecs.lib") #define min(a, b) (a < b ? : 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); } edit: popular demand, here's version basic error checking , rudimentary explanations:
#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 structure containing function pointers of wic api static iwicimagingfactory *iwicfactory; if(iwicfactory == null) { if(coinitializeex(null, coinit_multithreaded) != s_ok) { printf("failed initialize com library\n"); return; } if(cocreateinstance(clsid_wicimagingfactory, nullptr, clsctx_inproc_server, iid_ppv_args(&iwicfactory)) != s_ok) { printf("failed create instance of wic\n"); return; } } iwicstream *stream; if(iwicfactory->createstream(&stream) != s_ok) { printf("failed create stream\n"); return; } if(stream->initializefrommemory((unsigned char *)imagedata, imagedatasize) != s_ok) { printf("failed initialize stream memory\n"); return; } iwicbitmapdecoder *bitmapdecoder; if(iwicfactory->createdecoderfromstream(stream, null, wicdecodemetadatacacheondemand, &bitmapdecoder) != s_ok) { printf("failed create bitmap decoder stream\n"); return; } iwicbitmapframedecode *framedecode; // frames apply gifs , other animated media. jpegs have single frame. if(bitmapdecoder->getframe(0, &framedecode) != s_ok) { printf("failed 0th frame frame decoder\n"); return; } iwicformatconverter *formatconverter; if(iwicfactory->createformatconverter(&formatconverter) != s_ok) { printf("failed create format converter\n"); return; } // function not actual decoding if(formatconverter->initialize(framedecode, guid_wicpixelformat24bppbgr, wicbitmapdithertypenone, nullptr, 0.0f, wicbitmappalettetypecustom) != s_ok) { printf("failed initialize format converter\n"); return; } iwicbitmap *bitmap; if(iwicfactory->createbitmapfromsource(formatconverter, wicbitmapcacheondemand, &bitmap) != s_ok) { printf("failed create bitmap format converter\n"); return; } unsigned int width, height; if(bitmap->getsize(&width, &height) != s_ok) { printf("failed size of bitmap\n"); return; } wicrect rect = {0, 0, (int)width, (int)height}; iwicbitmaplock *lock; // function actual decoding. seems defer decoding until it's needed if(bitmap->lock(&rect, wicbitmaplockread, &lock) != s_ok) { printf("failed lock bitmap\n"); return; } unsigned int pixeldatasize = 0; unsigned char *pixeldata; if(lock->getdatapointer(&pixeldatasize, &pixeldata) != s_ok) { printf("failed 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); } wiki
Comments
Post a Comment