mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			312 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * The Python Imaging Library
 | |
|  * $Id$
 | |
|  *
 | |
|  * 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 */
 |