Pillow/libImaging/Dib.c
Nicolas F 052ea606bf Clean up defines and includes for Windows
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
2014-05-09 21:05:30 +02:00

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 */