Pillow
317 строк · 8.2 Кб
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
22#include "Imaging.h"23
24#ifdef _WIN3225
26#include "ImDib.h"27
28char *29ImagingGetModeDIB(int size_out[2]) {30/* Get device characteristics */31
32HDC dc;33char *mode;34
35dc = CreateCompatibleDC(NULL);36
37mode = "P";38if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {39mode = "RGB";40if (GetDeviceCaps(dc, BITSPIXEL) == 1) {41mode = "1";42}43}44
45if (size_out) {46size_out[0] = GetDeviceCaps(dc, HORZRES);47size_out[1] = GetDeviceCaps(dc, VERTRES);48}49
50DeleteDC(dc);51
52return mode;53}
54
55ImagingDIB
56ImagingNewDIB(const char *mode, int xsize, int ysize) {57/* Create a Windows bitmap */58
59ImagingDIB dib;60RGBQUAD *palette;61int i;62
63/* Check mode */64if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && strcmp(mode, "RGB") != 0) {65return (ImagingDIB)ImagingError_ModeError();66}67
68/* Create DIB context and info header */69/* malloc check ok, small constant allocation */70dib = (ImagingDIB)malloc(sizeof(*dib));71if (!dib) {72return (ImagingDIB)ImagingError_MemoryError();73}74/* malloc check ok, small constant allocation */75dib->info = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));76if (!dib->info) {77free(dib);78return (ImagingDIB)ImagingError_MemoryError();79}80
81memset(dib->info, 0, sizeof(BITMAPINFOHEADER));82dib->info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);83dib->info->bmiHeader.biWidth = xsize;84dib->info->bmiHeader.biHeight = ysize;85dib->info->bmiHeader.biPlanes = 1;86dib->info->bmiHeader.biBitCount = strlen(mode) * 8;87dib->info->bmiHeader.biCompression = BI_RGB;88
89/* Create DIB */90dib->dc = CreateCompatibleDC(NULL);91if (!dib->dc) {92free(dib->info);93free(dib);94return (ImagingDIB)ImagingError_MemoryError();95}96
97dib->bitmap = CreateDIBSection(98dib->dc, dib->info, DIB_RGB_COLORS, (void **)&dib->bits, NULL, 099);100if (!dib->bitmap) {101free(dib->info);102free(dib);103return (ImagingDIB)ImagingError_MemoryError();104}105
106strcpy(dib->mode, mode);107dib->xsize = xsize;108dib->ysize = ysize;109
110dib->pixelsize = strlen(mode);111dib->linesize = (xsize * dib->pixelsize + 3) & -4;112
113if (dib->pixelsize == 1) {114dib->pack = dib->unpack = (ImagingShuffler)memcpy;115} else {116dib->pack = ImagingPackBGR;117dib->unpack = ImagingPackBGR;118}119
120/* Bind the DIB to the device context */121dib->old_bitmap = SelectObject(dib->dc, dib->bitmap);122
123palette = dib->info->bmiColors;124
125/* Bind a palette to it as well (only required for 8-bit DIBs) */126if (dib->pixelsize == 1) {127for (i = 0; i < 256; i++) {128palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = i;129palette[i].rgbReserved = 0;130}131SetDIBColorTable(dib->dc, 0, 256, palette);132}133
134/* Create an associated palette (for 8-bit displays only) */135if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {136char palbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];137LPLOGPALETTE pal = (LPLOGPALETTE)palbuf;138int i, r, g, b;139
140/* Load system palette */141pal->palVersion = 0x300;142pal->palNumEntries = 256;143GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);144
145if (strcmp(mode, "L") == 0) {146/* Grayscale DIB. Fill all 236 slots with a grayscale ramp147* (this is usually overkill on Windows since VGA only offers
148* 6 bits grayscale resolution). Ignore the slots already
149* allocated by Windows */
150
151i = 10;152for (r = 0; r < 236; r++) {153pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =154pal->palPalEntry[i].peBlue = i;155i++;156}157
158dib->palette = CreatePalette(pal);159
160} else if (strcmp(mode, "RGB") == 0) {161#ifdef CUBE216162
163/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and164* add 20 extra graylevels for best result with grayscale
165* images. */
166
167i = 10;168for (r = 0; r < 256; r += 51) {169for (g = 0; g < 256; g += 51) {170for (b = 0; b < 256; b += 51) {171pal->palPalEntry[i].peRed = r;172pal->palPalEntry[i].peGreen = g;173pal->palPalEntry[i].peBlue = b;174i++;175}176}177}178for (r = 1; r < 22 - 1; r++) {179/* Black and white are already provided by the cube. */180pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =181pal->palPalEntry[i].peBlue = r * 255 / (22 - 1);182i++;183}184
185#else186
187/* Colour DIB. Alternate palette. */188
189i = 10;190for (r = 0; r < 256; r += 37) {191for (g = 0; g < 256; g += 32) {192for (b = 0; b < 256; b += 64) {193pal->palPalEntry[i].peRed = r;194pal->palPalEntry[i].peGreen = g;195pal->palPalEntry[i].peBlue = b;196i++;197}198}199}200
201#endif202
203dib->palette = CreatePalette(pal);204}205}206
207return dib;208}
209
210void
211ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) {212/* Paste image data into a bitmap */213
214/* FIXME: check size! */215
216int y;217for (y = 0; y < im->ysize; y++) {218dib->pack(219dib->bits + dib->linesize * (dib->ysize - (xy[1] + y) - 1) +220xy[0] * dib->pixelsize,221im->image[y],222im->xsize223);224}225}
226
227void
228ImagingExposeDIB(ImagingDIB dib, void *dc) {229/* Copy bitmap to display */230
231if (dib->palette != 0) {232SelectPalette((HDC)dc, dib->palette, FALSE);233}234BitBlt((HDC)dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);235}
236
237void
238ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]) {239/* Copy bitmap to printer/display */240
241if (GetDeviceCaps((HDC)dc, RASTERCAPS) & RC_STRETCHDIB) {242/* stretchdib (printers) */243StretchDIBits(244(HDC)dc,245dst[0],246dst[1],247dst[2] - dst[0],248dst[3] - dst[1],249src[0],250src[1],251src[2] - src[0],252src[3] - src[1],253dib->bits,254dib->info,255DIB_RGB_COLORS,256SRCCOPY
257);258} else {259/* stretchblt (displays) */260if (dib->palette != 0) {261SelectPalette((HDC)dc, dib->palette, FALSE);262}263StretchBlt(264(HDC)dc,265dst[0],266dst[1],267dst[2] - dst[0],268dst[3] - dst[1],269dib->dc,270src[0],271src[1],272src[2] - src[0],273src[3] - src[1],274SRCCOPY
275);276}277}
278
279int
280ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) {281/* Install bitmap palette */282
283int n;284
285if (dib->palette != 0) {286/* Realize associated palette */287HPALETTE now = SelectPalette((HDC)dc, dib->palette, FALSE);288n = RealizePalette((HDC)dc);289
290/* Restore palette */291SelectPalette((HDC)dc, now, FALSE);292
293} else {294n = 0;295}296
297return n; /* number of colours that was changed */298}
299
300void
301ImagingDeleteDIB(ImagingDIB dib) {302/* Clean up */303
304if (dib->palette) {305DeleteObject(dib->palette);306}307if (dib->bitmap) {308SelectObject(dib->dc, dib->old_bitmap);309DeleteObject(dib->bitmap);310}311if (dib->dc) {312DeleteDC(dib->dc);313}314free(dib->info);315}
316
317#endif /* _WIN32 */318