158 řádky
3.7 KiB

  1. /*
  2. * libpipi Pathetic image processing interface library
  3. * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. /*
  15. * gdi.c: Windows GDI I/O functions (BMP only)
  16. */
  17. #include "config.h"
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <windows.h>
  22. #include <Gdiplus.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. extern "C" pipi_image_t *pipi_load_gdiplus(const char *name)
  26. {
  27. size_t len;
  28. len = mbstowcs(NULL, name, 0);
  29. wchar_t *wname = new wchar_t[len + 1];
  30. if(mbstowcs(wname, name, len + 1) != (size_t)-1)
  31. {
  32. delete[] wname;
  33. return NULL;
  34. }
  35. ULONG_PTR token;
  36. Gdiplus::GdiplusStartupInput input;
  37. Gdiplus::GdiplusStartup(&token, &input, NULL);
  38. Gdiplus::Bitmap *b = Gdiplus::Bitmap::FromFile(wname, 0);
  39. if(!b)
  40. {
  41. delete[] wname;
  42. return NULL;
  43. }
  44. delete[] wname;
  45. Gdiplus::BitmapData bdata;
  46. Gdiplus::Rect rect(0, 0, b->GetWidth(), b->GetHeight());
  47. if(b->LockBits(rect, Gdiplus::ImageLockModeRead,
  48. PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
  49. {
  50. delete b;
  51. return NULL;
  52. }
  53. pipi_image_t *img = pipi_new(b->GetWidth(), b->GetHeight());
  54. pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
  55. memcpy(p->pixels, bdata.Scan0, bdata.Width * bdata.Height * 4);
  56. b->UnlockBits(&bdata);
  57. delete b;
  58. img->codec_priv = NULL;
  59. img->wrap = 0;
  60. img->u8 = 1;
  61. return img;
  62. }
  63. extern "C" int pipi_save_gdiplus(pipi_image_t *img, const char *name)
  64. {
  65. wchar_t const *fmt;
  66. if(strstr(name, ".gif"))
  67. fmt = L"image/gif";
  68. else if(strstr(name, ".jpeg") || strstr(name, ".jpeg"))
  69. fmt = L"image/jpeg";
  70. else if(strstr(name, ".png"))
  71. fmt = L"image/png";
  72. else if(strstr(name, ".tiff"))
  73. fmt = L"image/tiff";
  74. unsigned int num = 0, size = 0;
  75. Gdiplus::GetImageEncodersSize(&num, &size);
  76. if(size == 0)
  77. return -1;
  78. Gdiplus::ImageCodecInfo *codecs
  79. = (Gdiplus::ImageCodecInfo *)(malloc(size));
  80. if(!codecs)
  81. return -1;
  82. Gdiplus::GetImageEncoders(num, size, codecs);
  83. CLSID clsid;
  84. for(unsigned int i = 0; i < num; i++)
  85. {
  86. if(wcscmp(codecs[i].MimeType, fmt) == 0)
  87. {
  88. clsid = codecs[i].Clsid;
  89. break;
  90. }
  91. }
  92. size_t len;
  93. len = mbstowcs(NULL, name, 0);
  94. wchar_t *wname = new wchar_t[len + 1];
  95. if(mbstowcs(wname, name, len + 1) != (size_t)-1)
  96. {
  97. delete[] wname;
  98. return -1;
  99. }
  100. ULONG_PTR token;
  101. Gdiplus::GdiplusStartupInput input;
  102. Gdiplus::GdiplusStartup(&token, &input, NULL);
  103. Gdiplus::Bitmap *b = new Gdiplus::Bitmap(img->w, img->h,
  104. PixelFormat32bppARGB);
  105. Gdiplus::BitmapData bdata;
  106. Gdiplus::Rect rect(0, 0, img->w, img->h);
  107. if(b->LockBits(rect, (unsigned int)Gdiplus::ImageLockModeWrite,
  108. PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
  109. {
  110. delete b;
  111. return -1;
  112. }
  113. pipi_pixels_t *p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
  114. memcpy(bdata.Scan0, p->pixels, bdata.Width * bdata.Height * 4);
  115. b->UnlockBits(&bdata);
  116. if(b->Save(wname, &clsid, NULL) != Gdiplus::Ok)
  117. {
  118. delete[] wname;
  119. delete b;
  120. return -1;
  121. }
  122. delete[] wname;
  123. delete b;
  124. return 0;
  125. }
  126. /*
  127. * XXX: The following functions are local.
  128. */