mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
052ea606bf
1) Renamed USE_INLINE to PIL_USE_INLINE to avoid conflicts with other headers/libraries. 2) Replace __WIN32__ and WIN32 with _WIN32 3) Don't define WIN32 when the compiler is MSVC but not on Windows Why would you even... 4) Don't define strcasecmp if you're not even going to use it. 5) Don't include Windows.h with undefs for compilers newer than 1998 everywhere. 6) Don't surpress warnings for MSVC++ 4.0. People still using MSVC++ 4.0 deserve it. 7) Don't include things that are already included in Windows.h
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 */
|