36 #if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(ULONG_PTR)
37 #define ULONG_PTR ULONG
47 #ifdef HAVE_GDIPLUS_LOCKBITS_RECTARG_POINTER
48 #define LOCKBITS_RECT_CAST(arg) &arg
52 #define LOCKBITS_RECT_CAST(arg) arg
81 static Gdiplus::PixelFormat
85 Gdiplus::PixelFormat format = bitmap.GetPixelFormat();
87 if (Gdiplus::IsIndexedPixelFormat(format)) {
88 INT palettesize = bitmap.GetPaletteSize();
89 Gdiplus::ColorPalette * palette =
90 reinterpret_cast<Gdiplus::ColorPalette *
>(
new char[palettesize]);
91 bitmap.GetPalette(palette, palettesize);
92 bool alphaflag = (palette->Flags & Gdiplus::PaletteFlagsHasAlpha) != 0;
93 bool grayflag = (palette->Flags & Gdiplus::PaletteFlagsGrayScale) != 0;
94 delete[]
reinterpret_cast<char *
>(palette);
96 if (!grayflag && !alphaflag)
97 return PixelFormat24bppRGB;
98 if (!grayflag && alphaflag)
99 return PixelFormat32bppARGB;
100 if (grayflag && !alphaflag)
101 return PixelFormat16bppGrayScale;
108 return PixelFormat32bppARGB;
111 if (format == PixelFormat16bppGrayScale) {
112 return PixelFormat16bppGrayScale;
115 if ((format == PixelFormat16bppRGB555) ||
116 (format == PixelFormat16bppRGB565) ||
117 (format == PixelFormat24bppRGB) ||
118 (format == PixelFormat32bppRGB) ||
119 (format == PixelFormat48bppRGB)) {
120 return PixelFormat24bppRGB;
123 return PixelFormat32bppARGB;
141 static unsigned char *
144 unsigned int numcomponents,
unsigned int stride)
147 assert(stride >= (width * numcomponents));
148 assert((numcomponents == 3) || (numcomponents == 4));
149 if ((numcomponents != 3) && (numcomponents != 4)) {
return NULL; }
151 unsigned char * dst =
152 (
unsigned char *)malloc(width * height * numcomponents);
153 if (!dst) {
return NULL; }
157 dst += width * height * numcomponents;
159 if (numcomponents == 3) {
160 for (
unsigned int y = 0; y < height; y++) {
161 dst -= width * numcomponents;
162 for (
unsigned int x = 0; x < width; ++x) {
165 unsigned int offset = numcomponents * x;
166 dst[offset] = src[offset + 2];
167 dst[offset + 1] = src[offset + 1];
168 dst[offset + 2] = src[offset];
173 for (
unsigned int y = 0; y < height; y++) {
174 dst -= width * numcomponents;
175 for (
unsigned int x = 0; x < width; ++x) {
178 unsigned int offset = numcomponents * x;
179 dst[offset] = src[offset + 2];
180 dst[offset + 1] = src[offset + 1];
181 dst[offset + 2] = src[offset];
182 dst[offset + 3] = src[offset + 3];
204 static unsigned char *
206 unsigned int height,
unsigned int stride)
209 assert(stride >= (width * 4));
211 unsigned char * dst = (
unsigned char *)malloc(width * height * 2);
212 if (!dst) {
return NULL; }
216 dst += width * height * 2;
218 for (
unsigned int y = 0; y < height; y++) {
220 for (
unsigned int x = 0; x < width * 2;
226 dst[x + 1] = src[x + 3];
246 static unsigned char *
248 unsigned int height,
unsigned int stride)
250 assert(stride >= (2 * width));
252 unsigned char * dst = (
unsigned char *)malloc(width * height);
253 if (!dst) {
return NULL; }
257 dst += width * height;
259 unsigned short * shortsrc = (
unsigned short *)src;
261 for (
unsigned int y = 0; y < height; ++y) {
263 for (
unsigned int x = 0; x < width; ++x) {
265 dst[x] = (
unsigned char)((shortsrc[x] / 65535.0) * 255.0);
276 static int did_init = 0;
286 unsigned long long gdiplusToken = 0;
288 unsigned long gdiplusToken = 0;
290 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
291 if (Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Gdiplus::Ok) {
304 strncpy(buffer,
"GDI+ loader: Error initializing GDI+", buflen);
307 strncpy(buffer,
"GDI+ loader: Error opening file", buflen);
310 strncpy(buffer,
"GDI+ loader: Error reading file", buflen);
313 strncpy(buffer,
"GDI+ loader: Out of memory error", buflen);
316 strncpy(buffer,
"GDI+ saver: Error opening file", buflen);
319 strncpy(buffer,
"GDI+ loader: Error writing file", buflen);
322 strncpy(buffer,
"GDI+ loader: Feature not implemented", buflen);
325 strncpy(buffer,
"GDI+ loader: Interesting unknown error you got", buflen);
333 const unsigned char * header,
340 wchar_t *
filename =
new wchar_t[strlen(ptr)+1];
342 if (!filename) {
return 0; }
343 mbstowcs(filename, ptr, strlen(ptr)+1);
345 Gdiplus::Bitmap bitmap(filename);
347 if (bitmap.GetFlags() == Gdiplus::ImageFlagsNone) {
362 Gdiplus::Bitmap * bitmap =
365 if (!bitmap) {
return NULL; }
367 bool grayscale =
false;
368 Gdiplus::PixelFormat format =
getReadFormat(*bitmap, grayscale);
370 Gdiplus::BitmapData bitmapdata;
371 Gdiplus::Rect rect(0, 0, *width, *height);
374 Gdiplus::ImageLockModeRead,
375 format, &bitmapdata);
377 if (result != Gdiplus::Ok) {
378 if (result == Gdiplus::OutOfMemory)
382 bitmap->UnlockBits(&bitmapdata);
387 unsigned char * src = (
unsigned char *)bitmapdata.Scan0;
389 unsigned char * dst = NULL;
392 case PixelFormat16bppGrayScale:
393 (*numcomponents) = 1;
397 case PixelFormat24bppRGB:
398 (*numcomponents) = 3;
403 case PixelFormat32bppARGB:
405 (*numcomponents) = 2;
409 (*numcomponents) = 4;
419 bitmap->UnlockBits(&bitmapdata);
438 UINT num = 0, size = 0;
439 Gdiplus::GetImageEncodersSize(&num, &size);
441 Gdiplus::ImageCodecInfo * pImageCodecInfo = (Gdiplus::ImageCodecInfo *) malloc(size);
443 Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
445 char * formats = NULL;
446 size_t formats_size = 0;
447 size_t format_len = 0;
449 for (
unsigned int i = 0; i < num; i++) {
451 const wchar_t * w_format = pImageCodecInfo[i].FormatDescription;
452 size_t w_format_len = wcslen(w_format);
453 char * format = (
char *)malloc(w_format_len+10);
454 wcstombs(format, w_format, w_format_len);
455 format[w_format_len] =
'\0';
456 format_len = strlen(format);
458 formats_size += format_len + ((i == 0) ? 1 : 2);
459 formats = (
char *) realloc(formats, formats_size);
463 if (format_len == 4) {
464 if (!strncmp(format,
"JPEG", 4)) {
465 format[2] =
'G'; format[3] =
'\0';
466 }
else if (!strncmp(format,
"TIFF", 4)) {
472 strncpy(formats, format, format_len + 1);
474 strncat(formats,
",", 2);
475 strncat(formats, format, format_len + 1);
481 free(pImageCodecInfo);
489 Gdiplus::ImageCodecInfo * pImageCodecInfo = NULL;
490 unsigned int num = 0, size = 0;
492 Gdiplus::GetImageEncodersSize(&num, &size);
493 if (size == 0) {
return -1; }
495 pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
496 if (!pImageCodecInfo) {
return -1; }
498 Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
501 wchar_t * format_wide =
new wchar_t[strlen(format)+1];
503 if (!format_wide) {
return -1; }
504 mbstowcs(format_wide, format, strlen(format)+1);
506 for (
unsigned int i = 0; i < num; i++) {
507 if (wcsstr(pImageCodecInfo[i].MimeType, format_wide)) {
508 *pClsid = pImageCodecInfo[i].Clsid;
510 free(pImageCodecInfo);
516 free(pImageCodecInfo);
523 const unsigned char * bytes,
527 const char * filetypeext)
530 wchar_t * filename_wide =
new wchar_t[strlen(filename)+1];
533 mbstowcs(filename_wide, filename, strlen(filename)+1);
535 Gdiplus::PixelFormat pixelFormat =
536 ((numcomponents == 1) || (numcomponents == 3)) ?
537 PixelFormat24bppRGB : PixelFormat32bppARGB;
539 Gdiplus::Bitmap * bitmap =
new Gdiplus::Bitmap(width, height, pixelFormat);
540 Gdiplus::BitmapData * bitmapData =
new Gdiplus::BitmapData;
541 Gdiplus::Rect rect(0, 0, width, height);
544 Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite,
545 pixelFormat, bitmapData);
547 unsigned char * dst = ((
unsigned char *)bitmapData->Scan0);
548 const unsigned char * src = bytes + (width*height*numcomponents);
550 int numcomp34 = ((numcomponents==1) || (numcomponents==3)) ? 3 : 4;
551 unsigned int stride = bitmapData->Stride - width*numcomp34;
553 switch (numcomponents) {
560 for (
int y = 0; y < height; y++) {
561 src -= width*numcomponents;
562 for (
int x = 0; x < width*numcomponents; x+=numcomponents) {
563 *dst++ = src[x]; *dst++ = src[x]; *dst++ = src[x];
565 if (numcomponents == 2) { *dst++ = src[x+1]; }
574 for (
int y = 0; y < height; y++) {
575 src -= width*numcomponents;
576 for (
int x = 0; x < width*numcomponents; x+=numcomponents) {
577 *dst++ = src[x+2]; *dst++ = src[x+1]; *dst++ = src[x];
579 if (numcomponents == 4) { *dst++ = src[x+3]; }
589 delete filename_wide;
593 bitmap->UnlockBits(bitmapData);
600 if (!strncmp(filetypeext,
"jpg", 3)) {
602 }
else if (!strncmp(filetypeext,
"tif", 3)) {
609 bitmap->Save(filename_wide, &imgClsid, NULL);
614 delete filename_wide;
630 wchar_t * filename_wide =
new wchar_t[strlen(filename)+1];
633 mbstowcs(filename_wide, filename, strlen(filename)+1);
635 Gdiplus::Bitmap * bitmap =
new Gdiplus::Bitmap(filename_wide);
637 if (bitmap && (bitmap->GetLastStatus() == Gdiplus::Ok)) {
638 *width = bitmap->GetWidth();
639 *height = bitmap->GetHeight();
641 Gdiplus::PixelFormat pixelFormat = bitmap->GetPixelFormat();
643 (*numcomponents) = (pixelFormat == PixelFormat8bppIndexed) ? 1 :
644 (pixelFormat == PixelFormat24bppRGB) ? 3 : 4;
650 GUID guid; bitmap->GetRawFormat(&guid);
651 if (guid == Gdiplus::ImageFormatGIF) { (*numcomponents) = 4; }
653 delete filename_wide;
657 if (bitmap) {
delete bitmap; }
658 delete filename_wide;
667 Gdiplus::Bitmap * bitmap = (Gdiplus::Bitmap*)opendata;
668 if (bitmap) {
delete bitmap; }
674 Gdiplus::Bitmap * bitmap = (Gdiplus::Bitmap*)opendata;
677 Gdiplus::PixelFormat pixelFormat = bitmap->GetPixelFormat();
679 int width = bitmap->GetWidth();
680 int height = bitmap->GetHeight();
684 int numcomponents = (pixelFormat == PixelFormat8bppIndexed) ? 1 :
685 (pixelFormat == PixelFormat24bppRGB) ? 3 : 4;
691 GUID guid; bitmap->GetRawFormat(&guid);
692 if (guid == Gdiplus::ImageFormatGIF) { numcomponents = 4; }
695 if (numcomponents == 4) { pixelFormat = PixelFormat32bppARGB; }
697 Gdiplus::BitmapData bitmapData;
698 Gdiplus::Rect rect(0, height-y-1, width, 1);
701 pixelFormat, &bitmapData);
703 unsigned char * src = (
unsigned char *)bitmapData.Scan0;
705 switch (numcomponents) {
707 memcpy(buf, src, width);
712 for (
int x = 0; x < width*numcomponents; x+=numcomponents) {
713 buf[x+2] = *src++; buf[x+1] = *src++; buf[x] = *src++;
715 if (numcomponents == 4) { buf[x+3] = *src++; }
724 bitmap->UnlockBits(&bitmapData);
738 int x,
int y,
int w,
int h,
741 Gdiplus::Bitmap * bitmap = (Gdiplus::Bitmap*)opendata;
744 Gdiplus::PixelFormat pixelFormat = bitmap->GetPixelFormat();
746 int width = bitmap->GetWidth();
747 int height = bitmap->GetHeight();
749 if (x < 0 || y < 0 || w <= 0 || h <= 0 ||
752 int numcomponents = (pixelFormat == PixelFormat8bppIndexed) ? 1 :
753 (pixelFormat == PixelFormat24bppRGB) ? 3 : 4;
759 GUID guid; bitmap->GetRawFormat(&guid);
760 if (guid == Gdiplus::ImageFormatGIF) { numcomponents = 4; }
763 if (numcomponents == 4) { pixelFormat = PixelFormat32bppARGB; }
765 Gdiplus::BitmapData bitmapData;
766 Gdiplus::Rect rect(x, y, w, h);
769 pixelFormat, &bitmapData);
771 unsigned int stride = bitmapData.Stride - w*numcomponents;
772 unsigned char * src = (
unsigned char *)bitmapData.Scan0;
773 unsigned char * dst = buf + w*h*numcomponents;
775 switch (numcomponents) {
778 for (
int i = 0; i < h; i++) {
781 src += bitmapData.Stride;
788 for (
int i = 0; i < h; i++) {
789 dst -= w*numcomponents;
790 for (
int j = 0; j < w*numcomponents; j+=numcomponents) {
791 dst[j+2] = *src++; dst[j+1] = *src++; dst[j] = *src++;
793 if (numcomponents == 4) { dst[j+3] = *src++; }
804 bitmap->UnlockBits(&bitmapData);
#define LOCKBITS_RECT_CAST(arg)
static unsigned char * copy32bppGrayScaleBuffer(unsigned char *src, unsigned int width, unsigned int height, unsigned int stride)
static int gdiplus_init(void)
int simage_gdiplus_read_region(void *opendata, int x, int y, int w, int h, unsigned char *buf)
static Gdiplus::PixelFormat getReadFormat(Gdiplus::Bitmap &bitmap, bool &grayscale)
void simage_gdiplus_close(void *opendata)
void * simage_gdiplus_open(const char *filename, int *width, int *height, int *numcomponents)
static unsigned char * copyImageBuffer(unsigned char *src, unsigned int width, unsigned int height, unsigned int numcomponents, unsigned int stride)
static unsigned char * copy16bppGrayScaleBuffer(unsigned char *src, unsigned int width, unsigned int height, unsigned int stride)
int simage_gdiplus_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *filetypeext)
int simage_gdiplus_error(char *buffer, int buflen)
unsigned char * simage_gdiplus_load(const char *filename, int *width, int *height, int *numcomponents)
int simage_gdiplus_read_line(void *opendata, int y, unsigned char *buf)
int simage_gdiplus_identify(const char *ptr, const unsigned char *header, int headerlen)
char * simage_gdiplus_get_savers(void)
static int GetEncoderClsid(const char *format, CLSID *pClsid)