diff options
Diffstat (limited to 'Imaging/libImaging/Dib.c')
-rw-r--r-- | Imaging/libImaging/Dib.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/Imaging/libImaging/Dib.c b/Imaging/libImaging/Dib.c new file mode 100644 index 0000000..597f6ef --- /dev/null +++ b/Imaging/libImaging/Dib.c @@ -0,0 +1,311 @@ +/* + * The Python Imaging Library + * $Id: Dib.c 2134 2004-10-06 08:55:20Z fredrik $ + * + * imaging display object for Windows + * + * history: + * 1996-05-12 fl Created + * 1996-05-17 fl Up and running + * 1996-05-21 fl Added palette stuff + * 1996-05-26 fl Added query palette and mode inquery + * 1997-09-21 fl Added draw primitive + * 1998-01-20 fl Use StretchDIBits instead of StretchBlt + * 1998-12-30 fl Plugged a resource leak in DeleteDIB (from Roger Burnham) + * + * Copyright (c) Secret Labs AB 1997-2001. + * Copyright (c) Fredrik Lundh 1996. + * + * See the README file for information on usage and redistribution. + */ + + +#include "Imaging.h" + +#ifdef WIN32 + +#include "ImDib.h" + + +char* +ImagingGetModeDIB(int size_out[2]) +{ + /* Get device characteristics */ + + HDC dc; + char* mode; + + dc = CreateCompatibleDC(NULL); + + mode = "P"; + if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) { + mode = "RGB"; + if (GetDeviceCaps(dc, BITSPIXEL) == 1) + mode = "1"; + } + + if (size_out) { + size_out[0] = GetDeviceCaps(dc, HORZRES); + size_out[1] = GetDeviceCaps(dc, VERTRES); + } + + DeleteDC(dc); + + return mode; +} + + +ImagingDIB +ImagingNewDIB(const char *mode, int xsize, int ysize) +{ + /* Create a Windows bitmap */ + + ImagingDIB dib; + RGBQUAD *palette; + int i; + + /* Check mode */ + if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && + strcmp(mode, "RGB") != 0) + return (ImagingDIB) ImagingError_ModeError(); + + /* Create DIB context and info header */ + dib = (ImagingDIB) malloc(sizeof(*dib)); + if (!dib) + return (ImagingDIB) ImagingError_MemoryError(); + dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + + 256 * sizeof(RGBQUAD)); + if (!dib->info) { + free(dib); + return (ImagingDIB) ImagingError_MemoryError(); + } + + memset(dib->info, 0, sizeof(BITMAPINFOHEADER)); + dib->info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + dib->info->bmiHeader.biWidth = xsize; + dib->info->bmiHeader.biHeight = ysize; + dib->info->bmiHeader.biPlanes = 1; + dib->info->bmiHeader.biBitCount = strlen(mode)*8; + dib->info->bmiHeader.biCompression = BI_RGB; + + /* Create DIB */ + dib->dc = CreateCompatibleDC(NULL); + if (!dib->dc) { + free(dib->info); + free(dib); + return (ImagingDIB) ImagingError_MemoryError(); + } + + dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, + &dib->bits, NULL, 0); + if (!dib->bitmap) { + free(dib->info); + free(dib); + return (ImagingDIB) ImagingError_MemoryError(); + } + + strcpy(dib->mode, mode); + dib->xsize = xsize; + dib->ysize = ysize; + + dib->pixelsize = strlen(mode); + dib->linesize = (xsize * dib->pixelsize + 3) & -4; + + if (dib->pixelsize == 1) + dib->pack = dib->unpack = (ImagingShuffler) memcpy; + else { + dib->pack = ImagingPackBGR; + dib->unpack = ImagingPackBGR; + } + + /* Bind the DIB to the device context */ + dib->old_bitmap = SelectObject(dib->dc, dib->bitmap); + + palette = dib->info->bmiColors; + + /* Bind a palette to it as well (only required for 8-bit DIBs) */ + if (dib->pixelsize == 1) { + for (i = 0; i < 256; i++) { + palette[i].rgbRed = + palette[i].rgbGreen = + palette[i].rgbBlue = i; + palette[i].rgbReserved = 0; + } + SetDIBColorTable(dib->dc, 0, 256, palette); + } + + /* Create an associated palette (for 8-bit displays only) */ + if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) { + + char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; + LPLOGPALETTE pal = (LPLOGPALETTE) palbuf; + int i, r, g, b; + + /* Load system palette */ + pal->palVersion = 0x300; + pal->palNumEntries = 256; + GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry); + + if (strcmp(mode, "L") == 0) { + + /* Greyscale DIB. Fill all 236 slots with a greyscale ramp + * (this is usually overkill on Windows since VGA only offers + * 6 bits greyscale resolution). Ignore the slots already + * allocated by Windows */ + + i = 10; + for (r = 0; r < 236; r++) { + pal->palPalEntry[i].peRed = + pal->palPalEntry[i].peGreen = + pal->palPalEntry[i].peBlue = i; + i++; + } + + dib->palette = CreatePalette(pal); + + } else if (strcmp(mode, "RGB") == 0) { + +#ifdef CUBE216 + + /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and + * add 20 extra greylevels for best result with greyscale + * images. */ + + i = 10; + for (r = 0; r < 256; r += 51) + for (g = 0; g < 256; g += 51) + for (b = 0; b < 256; b += 51) { + pal->palPalEntry[i].peRed = r; + pal->palPalEntry[i].peGreen = g; + pal->palPalEntry[i].peBlue = b; + i++; + } + for (r = 1; r < 22-1; r++) { + /* Black and white are already provided by the cube. */ + pal->palPalEntry[i].peRed = + pal->palPalEntry[i].peGreen = + pal->palPalEntry[i].peBlue = r * 255 / (22-1); + i++; + } + +#else + + /* Colour DIB. Alternate palette. */ + + i = 10; + for (r = 0; r < 256; r += 37) + for (g = 0; g < 256; g += 32) + for (b = 0; b < 256; b += 64) { + pal->palPalEntry[i].peRed = r; + pal->palPalEntry[i].peGreen = g; + pal->palPalEntry[i].peBlue = b; + i++; + } + +#endif + +#if 0 + { + /* DEBUG: dump palette to file */ + FILE *err = fopen("dib.pal", "w"); + for (i = 0; i < 256; i++) + fprintf(err, "%d: %d/%d/%d\n", i, + pal->palPalEntry[i].peRed, + pal->palPalEntry[i].peGreen, + pal->palPalEntry[i].peBlue); + fclose(err); + } +#endif + + dib->palette = CreatePalette(pal); + + } + + } + + return dib; +} + +void +ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) +{ + /* Paste image data into a bitmap */ + + /* FIXME: check size! */ + + int y; + for (y = 0; y < im->ysize; y++) + dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + + xy[0]*dib->pixelsize, im->image[y], im->xsize); + +} + +void +ImagingExposeDIB(ImagingDIB dib, int dc) +{ + /* Copy bitmap to display */ + + if (dib->palette != 0) + SelectPalette((HDC) dc, dib->palette, FALSE); + BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); +} + +void +ImagingDrawDIB(ImagingDIB dib, int dc, int dst[4], int src[4]) +{ + /* Copy bitmap to printer/display */ + + if (GetDeviceCaps((HDC) dc, RASTERCAPS) & RC_STRETCHDIB) { + /* stretchdib (printers) */ + StretchDIBits((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], + src[0], src[1], src[2]-src[0], src[3]-src[1], dib->bits, + dib->info, DIB_RGB_COLORS, SRCCOPY); + } else { + /* stretchblt (displays) */ + if (dib->palette != 0) + SelectPalette((HDC) dc, dib->palette, FALSE); + StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], + dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1], + SRCCOPY); + } +} + +int +ImagingQueryPaletteDIB(ImagingDIB dib, int dc) +{ + /* Install bitmap palette */ + + int n; + + if (dib->palette != 0) { + + /* Realize associated palette */ + HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE); + n = RealizePalette((HDC) dc); + + /* Restore palette */ + SelectPalette((HDC) dc, now, FALSE); + + } else + n = 0; + + return n; /* number of colours that was changed */ +} + +void +ImagingDeleteDIB(ImagingDIB dib) +{ + /* Clean up */ + + if (dib->palette) + DeleteObject(dib->palette); + if (dib->bitmap) { + SelectObject(dib->dc, dib->old_bitmap); + DeleteObject(dib->bitmap); + } + if (dib->dc) + DeleteDC(dib->dc); + free(dib->info); +} + +#endif /* WIN32 */ |