Dib.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * imaging display object for Windows
  6. *
  7. * history:
  8. * 1996-05-12 fl Created
  9. * 1996-05-17 fl Up and running
  10. * 1996-05-21 fl Added palette stuff
  11. * 1996-05-26 fl Added query palette and mode inquery
  12. * 1997-09-21 fl Added draw primitive
  13. * 1998-01-20 fl Use StretchDIBits instead of StretchBlt
  14. * 1998-12-30 fl Plugged a resource leak in DeleteDIB (from Roger Burnham)
  15. *
  16. * Copyright (c) Secret Labs AB 1997-2001.
  17. * Copyright (c) Fredrik Lundh 1996.
  18. *
  19. * See the README file for information on usage and redistribution.
  20. */
  21. #include "Imaging.h"
  22. #ifdef _WIN32
  23. #include "ImDib.h"
  24. char*
  25. ImagingGetModeDIB(int size_out[2])
  26. {
  27. /* Get device characteristics */
  28. HDC dc;
  29. char* mode;
  30. dc = CreateCompatibleDC(NULL);
  31. mode = "P";
  32. if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {
  33. mode = "RGB";
  34. if (GetDeviceCaps(dc, BITSPIXEL) == 1)
  35. mode = "1";
  36. }
  37. if (size_out) {
  38. size_out[0] = GetDeviceCaps(dc, HORZRES);
  39. size_out[1] = GetDeviceCaps(dc, VERTRES);
  40. }
  41. DeleteDC(dc);
  42. return mode;
  43. }
  44. ImagingDIB
  45. ImagingNewDIB(const char *mode, int xsize, int ysize)
  46. {
  47. /* Create a Windows bitmap */
  48. ImagingDIB dib;
  49. RGBQUAD *palette;
  50. int i;
  51. /* Check mode */
  52. if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
  53. strcmp(mode, "RGB") != 0)
  54. return (ImagingDIB) ImagingError_ModeError();
  55. /* Create DIB context and info header */
  56. /* malloc check ok, small constant allocation */
  57. dib = (ImagingDIB) malloc(sizeof(*dib));
  58. if (!dib)
  59. return (ImagingDIB) ImagingError_MemoryError();
  60. /* malloc check ok, small constant allocation */
  61. dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
  62. 256 * sizeof(RGBQUAD));
  63. if (!dib->info) {
  64. free(dib);
  65. return (ImagingDIB) ImagingError_MemoryError();
  66. }
  67. memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
  68. dib->info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  69. dib->info->bmiHeader.biWidth = xsize;
  70. dib->info->bmiHeader.biHeight = ysize;
  71. dib->info->bmiHeader.biPlanes = 1;
  72. dib->info->bmiHeader.biBitCount = strlen(mode)*8;
  73. dib->info->bmiHeader.biCompression = BI_RGB;
  74. /* Create DIB */
  75. dib->dc = CreateCompatibleDC(NULL);
  76. if (!dib->dc) {
  77. free(dib->info);
  78. free(dib);
  79. return (ImagingDIB) ImagingError_MemoryError();
  80. }
  81. dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
  82. &dib->bits, NULL, 0);
  83. if (!dib->bitmap) {
  84. free(dib->info);
  85. free(dib);
  86. return (ImagingDIB) ImagingError_MemoryError();
  87. }
  88. strcpy(dib->mode, mode);
  89. dib->xsize = xsize;
  90. dib->ysize = ysize;
  91. dib->pixelsize = strlen(mode);
  92. dib->linesize = (xsize * dib->pixelsize + 3) & -4;
  93. if (dib->pixelsize == 1)
  94. dib->pack = dib->unpack = (ImagingShuffler) memcpy;
  95. else {
  96. dib->pack = ImagingPackBGR;
  97. dib->unpack = ImagingPackBGR;
  98. }
  99. /* Bind the DIB to the device context */
  100. dib->old_bitmap = SelectObject(dib->dc, dib->bitmap);
  101. palette = dib->info->bmiColors;
  102. /* Bind a palette to it as well (only required for 8-bit DIBs) */
  103. if (dib->pixelsize == 1) {
  104. for (i = 0; i < 256; i++) {
  105. palette[i].rgbRed =
  106. palette[i].rgbGreen =
  107. palette[i].rgbBlue = i;
  108. palette[i].rgbReserved = 0;
  109. }
  110. SetDIBColorTable(dib->dc, 0, 256, palette);
  111. }
  112. /* Create an associated palette (for 8-bit displays only) */
  113. if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
  114. char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
  115. LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
  116. int i, r, g, b;
  117. /* Load system palette */
  118. pal->palVersion = 0x300;
  119. pal->palNumEntries = 256;
  120. GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
  121. if (strcmp(mode, "L") == 0) {
  122. /* Greyscale DIB. Fill all 236 slots with a greyscale ramp
  123. * (this is usually overkill on Windows since VGA only offers
  124. * 6 bits greyscale resolution). Ignore the slots already
  125. * allocated by Windows */
  126. i = 10;
  127. for (r = 0; r < 236; r++) {
  128. pal->palPalEntry[i].peRed =
  129. pal->palPalEntry[i].peGreen =
  130. pal->palPalEntry[i].peBlue = i;
  131. i++;
  132. }
  133. dib->palette = CreatePalette(pal);
  134. } else if (strcmp(mode, "RGB") == 0) {
  135. #ifdef CUBE216
  136. /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
  137. * add 20 extra greylevels for best result with greyscale
  138. * images. */
  139. i = 10;
  140. for (r = 0; r < 256; r += 51)
  141. for (g = 0; g < 256; g += 51)
  142. for (b = 0; b < 256; b += 51) {
  143. pal->palPalEntry[i].peRed = r;
  144. pal->palPalEntry[i].peGreen = g;
  145. pal->palPalEntry[i].peBlue = b;
  146. i++;
  147. }
  148. for (r = 1; r < 22-1; r++) {
  149. /* Black and white are already provided by the cube. */
  150. pal->palPalEntry[i].peRed =
  151. pal->palPalEntry[i].peGreen =
  152. pal->palPalEntry[i].peBlue = r * 255 / (22-1);
  153. i++;
  154. }
  155. #else
  156. /* Colour DIB. Alternate palette. */
  157. i = 10;
  158. for (r = 0; r < 256; r += 37)
  159. for (g = 0; g < 256; g += 32)
  160. for (b = 0; b < 256; b += 64) {
  161. pal->palPalEntry[i].peRed = r;
  162. pal->palPalEntry[i].peGreen = g;
  163. pal->palPalEntry[i].peBlue = b;
  164. i++;
  165. }
  166. #endif
  167. dib->palette = CreatePalette(pal);
  168. }
  169. }
  170. return dib;
  171. }
  172. void
  173. ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
  174. {
  175. /* Paste image data into a bitmap */
  176. /* FIXME: check size! */
  177. int y;
  178. for (y = 0; y < im->ysize; y++)
  179. dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
  180. xy[0]*dib->pixelsize, im->image[y], im->xsize);
  181. }
  182. void
  183. ImagingExposeDIB(ImagingDIB dib, void *dc)
  184. {
  185. /* Copy bitmap to display */
  186. if (dib->palette != 0)
  187. SelectPalette((HDC) dc, dib->palette, FALSE);
  188. BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
  189. }
  190. void
  191. ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4])
  192. {
  193. /* Copy bitmap to printer/display */
  194. if (GetDeviceCaps((HDC) dc, RASTERCAPS) & RC_STRETCHDIB) {
  195. /* stretchdib (printers) */
  196. StretchDIBits((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1],
  197. src[0], src[1], src[2]-src[0], src[3]-src[1], dib->bits,
  198. dib->info, DIB_RGB_COLORS, SRCCOPY);
  199. } else {
  200. /* stretchblt (displays) */
  201. if (dib->palette != 0)
  202. SelectPalette((HDC) dc, dib->palette, FALSE);
  203. StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1],
  204. dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1],
  205. SRCCOPY);
  206. }
  207. }
  208. int
  209. ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
  210. {
  211. /* Install bitmap palette */
  212. int n;
  213. if (dib->palette != 0) {
  214. /* Realize associated palette */
  215. HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
  216. n = RealizePalette((HDC) dc);
  217. /* Restore palette */
  218. SelectPalette((HDC) dc, now, FALSE);
  219. } else
  220. n = 0;
  221. return n; /* number of colours that was changed */
  222. }
  223. void
  224. ImagingDeleteDIB(ImagingDIB dib)
  225. {
  226. /* Clean up */
  227. if (dib->palette)
  228. DeleteObject(dib->palette);
  229. if (dib->bitmap) {
  230. SelectObject(dib->dc, dib->old_bitmap);
  231. DeleteObject(dib->bitmap);
  232. }
  233. if (dib->dc)
  234. DeleteDC(dib->dc);
  235. free(dib->info);
  236. }
  237. #endif /* _WIN32 */