mixed 8c tabs+spaces -> spaces

This commit is contained in:
wiredfool 2016-03-16 04:23:45 -07:00
parent ac6e86765d
commit b1a190ad78
6 changed files with 696 additions and 696 deletions

View File

@ -39,14 +39,14 @@ ImagingGetModeDIB(int size_out[2])
mode = "P"; mode = "P";
if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) { if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {
mode = "RGB"; mode = "RGB";
if (GetDeviceCaps(dc, BITSPIXEL) == 1) if (GetDeviceCaps(dc, BITSPIXEL) == 1)
mode = "1"; mode = "1";
} }
if (size_out) { if (size_out) {
size_out[0] = GetDeviceCaps(dc, HORZRES); size_out[0] = GetDeviceCaps(dc, HORZRES);
size_out[1] = GetDeviceCaps(dc, VERTRES); size_out[1] = GetDeviceCaps(dc, VERTRES);
} }
DeleteDC(dc); DeleteDC(dc);
@ -66,18 +66,18 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
/* Check mode */ /* Check mode */
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
strcmp(mode, "RGB") != 0) strcmp(mode, "RGB") != 0)
return (ImagingDIB) ImagingError_ModeError(); return (ImagingDIB) ImagingError_ModeError();
/* Create DIB context and info header */ /* Create DIB context and info header */
dib = (ImagingDIB) malloc(sizeof(*dib)); dib = (ImagingDIB) malloc(sizeof(*dib));
if (!dib) if (!dib)
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB) ImagingError_MemoryError();
dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
256 * sizeof(RGBQUAD)); 256 * sizeof(RGBQUAD));
if (!dib->info) { if (!dib->info) {
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB) ImagingError_MemoryError();
} }
memset(dib->info, 0, sizeof(BITMAPINFOHEADER)); memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
@ -91,17 +91,17 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
/* Create DIB */ /* Create DIB */
dib->dc = CreateCompatibleDC(NULL); dib->dc = CreateCompatibleDC(NULL);
if (!dib->dc) { if (!dib->dc) {
free(dib->info); free(dib->info);
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB) ImagingError_MemoryError();
} }
dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
&dib->bits, NULL, 0); &dib->bits, NULL, 0);
if (!dib->bitmap) { if (!dib->bitmap) {
free(dib->info); free(dib->info);
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB) ImagingError_MemoryError();
} }
strcpy(dib->mode, mode); strcpy(dib->mode, mode);
@ -112,10 +112,10 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
dib->linesize = (xsize * dib->pixelsize + 3) & -4; dib->linesize = (xsize * dib->pixelsize + 3) & -4;
if (dib->pixelsize == 1) if (dib->pixelsize == 1)
dib->pack = dib->unpack = (ImagingShuffler) memcpy; dib->pack = dib->unpack = (ImagingShuffler) memcpy;
else { else {
dib->pack = ImagingPackBGR; dib->pack = ImagingPackBGR;
dib->unpack = ImagingPackBGR; dib->unpack = ImagingPackBGR;
} }
/* Bind the DIB to the device context */ /* Bind the DIB to the device context */
@ -125,88 +125,88 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
/* Bind a palette to it as well (only required for 8-bit DIBs) */ /* Bind a palette to it as well (only required for 8-bit DIBs) */
if (dib->pixelsize == 1) { if (dib->pixelsize == 1) {
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
palette[i].rgbRed = palette[i].rgbRed =
palette[i].rgbGreen = palette[i].rgbGreen =
palette[i].rgbBlue = i; palette[i].rgbBlue = i;
palette[i].rgbReserved = 0; palette[i].rgbReserved = 0;
} }
SetDIBColorTable(dib->dc, 0, 256, palette); SetDIBColorTable(dib->dc, 0, 256, palette);
} }
/* Create an associated palette (for 8-bit displays only) */ /* Create an associated palette (for 8-bit displays only) */
if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) { if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
LPLOGPALETTE pal = (LPLOGPALETTE) palbuf; LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
int i, r, g, b; int i, r, g, b;
/* Load system palette */ /* Load system palette */
pal->palVersion = 0x300; pal->palVersion = 0x300;
pal->palNumEntries = 256; pal->palNumEntries = 256;
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry); GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
if (strcmp(mode, "L") == 0) { if (strcmp(mode, "L") == 0) {
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp /* Greyscale DIB. Fill all 236 slots with a greyscale ramp
* (this is usually overkill on Windows since VGA only offers * (this is usually overkill on Windows since VGA only offers
* 6 bits greyscale resolution). Ignore the slots already * 6 bits greyscale resolution). Ignore the slots already
* allocated by Windows */ * allocated by Windows */
i = 10; i = 10;
for (r = 0; r < 236; r++) { for (r = 0; r < 236; r++) {
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peRed =
pal->palPalEntry[i].peGreen = pal->palPalEntry[i].peGreen =
pal->palPalEntry[i].peBlue = i; pal->palPalEntry[i].peBlue = i;
i++; i++;
} }
dib->palette = CreatePalette(pal); dib->palette = CreatePalette(pal);
} else if (strcmp(mode, "RGB") == 0) { } else if (strcmp(mode, "RGB") == 0) {
#ifdef CUBE216 #ifdef CUBE216
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
* add 20 extra greylevels for best result with greyscale * add 20 extra greylevels for best result with greyscale
* images. */ * images. */
i = 10; i = 10;
for (r = 0; r < 256; r += 51) for (r = 0; r < 256; r += 51)
for (g = 0; g < 256; g += 51) for (g = 0; g < 256; g += 51)
for (b = 0; b < 256; b += 51) { for (b = 0; b < 256; b += 51) {
pal->palPalEntry[i].peRed = r; pal->palPalEntry[i].peRed = r;
pal->palPalEntry[i].peGreen = g; pal->palPalEntry[i].peGreen = g;
pal->palPalEntry[i].peBlue = b; pal->palPalEntry[i].peBlue = b;
i++; i++;
} }
for (r = 1; r < 22-1; r++) { for (r = 1; r < 22-1; r++) {
/* Black and white are already provided by the cube. */ /* Black and white are already provided by the cube. */
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peRed =
pal->palPalEntry[i].peGreen = pal->palPalEntry[i].peGreen =
pal->palPalEntry[i].peBlue = r * 255 / (22-1); pal->palPalEntry[i].peBlue = r * 255 / (22-1);
i++; i++;
} }
#else #else
/* Colour DIB. Alternate palette. */ /* Colour DIB. Alternate palette. */
i = 10; i = 10;
for (r = 0; r < 256; r += 37) for (r = 0; r < 256; r += 37)
for (g = 0; g < 256; g += 32) for (g = 0; g < 256; g += 32)
for (b = 0; b < 256; b += 64) { for (b = 0; b < 256; b += 64) {
pal->palPalEntry[i].peRed = r; pal->palPalEntry[i].peRed = r;
pal->palPalEntry[i].peGreen = g; pal->palPalEntry[i].peGreen = g;
pal->palPalEntry[i].peBlue = b; pal->palPalEntry[i].peBlue = b;
i++; i++;
} }
#endif #endif
dib->palette = CreatePalette(pal); dib->palette = CreatePalette(pal);
} }
} }
@ -222,8 +222,8 @@ ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
int y; int y;
for (y = 0; y < im->ysize; y++) for (y = 0; y < im->ysize; y++)
dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
xy[0]*dib->pixelsize, im->image[y], im->xsize); xy[0]*dib->pixelsize, im->image[y], im->xsize);
} }
@ -233,7 +233,7 @@ ImagingExposeDIB(ImagingDIB dib, void *dc)
/* Copy bitmap to display */ /* Copy bitmap to display */
if (dib->palette != 0) if (dib->palette != 0)
SelectPalette((HDC) dc, dib->palette, FALSE); SelectPalette((HDC) dc, dib->palette, FALSE);
BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
} }
@ -266,15 +266,15 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
if (dib->palette != 0) { if (dib->palette != 0) {
/* Realize associated palette */ /* Realize associated palette */
HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE); HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
n = RealizePalette((HDC) dc); n = RealizePalette((HDC) dc);
/* Restore palette */ /* Restore palette */
SelectPalette((HDC) dc, now, FALSE); SelectPalette((HDC) dc, now, FALSE);
} else } else
n = 0; n = 0;
return n; /* number of colours that was changed */ return n; /* number of colours that was changed */
} }
@ -285,13 +285,13 @@ ImagingDeleteDIB(ImagingDIB dib)
/* Clean up */ /* Clean up */
if (dib->palette) if (dib->palette)
DeleteObject(dib->palette); DeleteObject(dib->palette);
if (dib->bitmap) { if (dib->bitmap) {
SelectObject(dib->dc, dib->old_bitmap); SelectObject(dib->dc, dib->old_bitmap);
DeleteObject(dib->bitmap); DeleteObject(dib->bitmap);
} }
if (dib->dc) if (dib->dc)
DeleteDC(dib->dc); DeleteDC(dib->dc);
free(dib->info); free(dib->info);
} }

View File

@ -31,20 +31,20 @@ ImagingPaletteNew(const char* mode)
ImagingPalette palette; ImagingPalette palette;
if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) if (strcmp(mode, "RGB") && strcmp(mode, "RGBA"))
return (ImagingPalette) ImagingError_ModeError(); return (ImagingPalette) ImagingError_ModeError();
palette = calloc(1, sizeof(struct ImagingPaletteInstance)); palette = calloc(1, sizeof(struct ImagingPaletteInstance));
if (!palette) if (!palette)
return (ImagingPalette) ImagingError_MemoryError(); return (ImagingPalette) ImagingError_MemoryError();
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH); strncpy(palette->mode, mode, IMAGING_MODE_LENGTH);
/* Initialize to ramp */ /* Initialize to ramp */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
palette->palette[i*4+0] = palette->palette[i*4+0] =
palette->palette[i*4+1] = palette->palette[i*4+1] =
palette->palette[i*4+2] = (UINT8) i; palette->palette[i*4+2] = (UINT8) i;
palette->palette[i*4+3] = 255; /* opaque */ palette->palette[i*4+3] = 255; /* opaque */
} }
return palette; return palette;
@ -60,35 +60,35 @@ ImagingPaletteNewBrowser(void)
palette = ImagingPaletteNew("RGB"); palette = ImagingPaletteNew("RGB");
if (!palette) if (!palette)
return NULL; return NULL;
/* Blank out unused entries */ /* Blank out unused entries */
/* FIXME: Add 10-level windows palette here? */ /* FIXME: Add 10-level windows palette here? */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
palette->palette[i*4+0] = palette->palette[i*4+0] =
palette->palette[i*4+1] = palette->palette[i*4+1] =
palette->palette[i*4+2] = 0; palette->palette[i*4+2] = 0;
} }
/* Simple 6x6x6 colour cube */ /* Simple 6x6x6 colour cube */
for (b = 0; b < 256; b += 51) for (b = 0; b < 256; b += 51)
for (g = 0; g < 256; g += 51) for (g = 0; g < 256; g += 51)
for (r = 0; r < 256; r += 51) { for (r = 0; r < 256; r += 51) {
palette->palette[i*4+0] = r; palette->palette[i*4+0] = r;
palette->palette[i*4+1] = g; palette->palette[i*4+1] = g;
palette->palette[i*4+2] = b; palette->palette[i*4+2] = b;
i++; i++;
} }
/* Blank out unused entries */ /* Blank out unused entries */
/* FIXME: add 30-level greyscale wedge here? */ /* FIXME: add 30-level greyscale wedge here? */
for (; i < 256; i++) { for (; i < 256; i++) {
palette->palette[i*4+0] = palette->palette[i*4+0] =
palette->palette[i*4+1] = palette->palette[i*4+1] =
palette->palette[i*4+2] = 0; palette->palette[i*4+2] = 0;
} }
return palette; return palette;
@ -102,11 +102,11 @@ ImagingPaletteDuplicate(ImagingPalette palette)
ImagingPalette new_palette; ImagingPalette new_palette;
if (!palette) if (!palette)
return NULL; return NULL;
new_palette = malloc(sizeof(struct ImagingPaletteInstance)); new_palette = malloc(sizeof(struct ImagingPaletteInstance));
if (!new_palette) if (!new_palette)
return (ImagingPalette) ImagingError_MemoryError(); return (ImagingPalette) ImagingError_MemoryError();
memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance)); memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
@ -122,15 +122,15 @@ ImagingPaletteDelete(ImagingPalette palette)
/* Destroy palette object */ /* Destroy palette object */
if (palette) { if (palette) {
if (palette->cache) if (palette->cache)
free(palette->cache); free(palette->cache);
free(palette); free(palette);
} }
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Colour mapping */ /* Colour mapping */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* This code is used to map RGB triplets to palette indices, using /* This code is used to map RGB triplets to palette indices, using
@ -143,26 +143,26 @@ ImagingPaletteDelete(ImagingPalette palette)
* *
* The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */ * The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */
#define DIST(a, b, s) (a - b) * (a - b) * s #define DIST(a, b, s) (a - b) * (a - b) * s
/* Colour weights (no scaling, for now) */ /* Colour weights (no scaling, for now) */
#define RSCALE 1 #define RSCALE 1
#define GSCALE 1 #define GSCALE 1
#define BSCALE 1 #define BSCALE 1
/* Calculated scaled distances */ /* Calculated scaled distances */
#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE) #define RDIST(a, b) DIST(a, b, RSCALE*RSCALE)
#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE) #define GDIST(a, b) DIST(a, b, GSCALE*GSCALE)
#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE) #define BDIST(a, b) DIST(a, b, BSCALE*BSCALE)
/* Incremental steps */ /* Incremental steps */
#define RSTEP (4 * RSCALE) #define RSTEP (4 * RSCALE)
#define GSTEP (4 * GSCALE) #define GSTEP (4 * GSCALE)
#define BSTEP (4 * BSCALE) #define BSTEP (4 * BSCALE)
#define BOX 8 #define BOX 8
#define BOXVOLUME BOX*BOX*BOX #define BOXVOLUME BOX*BOX*BOX
void void
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
@ -191,25 +191,25 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
int r, g, b; int r, g, b;
unsigned int tmin, tmax; unsigned int tmin, tmax;
/* Find min and max distances to any point in the box */ /* Find min and max distances to any point in the box */
r = palette->palette[i*4+0]; r = palette->palette[i*4+0];
tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0; tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0;
tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0); tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
g = palette->palette[i*4+1]; g = palette->palette[i*4+1];
tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0; tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0;
tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0); tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
b = palette->palette[i*4+2]; b = palette->palette[i*4+2];
tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0; tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0;
tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
dmin[i] = tmin; dmin[i] = tmin;
if (tmax < dmax) if (tmax < dmax)
dmax = tmax; /* keep the smallest max distance only */ dmax = tmax; /* keep the smallest max distance only */
} }
@ -220,47 +220,47 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
* distance is less than or equal the smallest max distance */ * distance is less than or equal the smallest max distance */
for (i = 0; i < BOXVOLUME; i++) for (i = 0; i < BOXVOLUME; i++)
d[i] = (unsigned int) ~0; d[i] = (unsigned int) ~0;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
if (dmin[i] <= dmax) { if (dmin[i] <= dmax) {
int rd, gd, bd; int rd, gd, bd;
int ri, gi, bi; int ri, gi, bi;
int rx, gx, bx; int rx, gx, bx;
ri = (r0 - palette->palette[i*4+0]) * RSCALE; ri = (r0 - palette->palette[i*4+0]) * RSCALE;
gi = (g0 - palette->palette[i*4+1]) * GSCALE; gi = (g0 - palette->palette[i*4+1]) * GSCALE;
bi = (b0 - palette->palette[i*4+2]) * BSCALE; bi = (b0 - palette->palette[i*4+2]) * BSCALE;
rd = ri*ri + gi*gi + bi*bi; rd = ri*ri + gi*gi + bi*bi;
ri = ri * (2 * RSTEP) + RSTEP * RSTEP; ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
gi = gi * (2 * GSTEP) + GSTEP * GSTEP; gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
bi = bi * (2 * BSTEP) + BSTEP * BSTEP; bi = bi * (2 * BSTEP) + BSTEP * BSTEP;
rx = ri; rx = ri;
for (r = j = 0; r < BOX; r++) { for (r = j = 0; r < BOX; r++) {
gd = rd; gx = gi; gd = rd; gx = gi;
for (g = 0; g < BOX; g++) { for (g = 0; g < BOX; g++) {
bd = gd; bx = bi; bd = gd; bx = bi;
for (b = 0; b < BOX; b++) { for (b = 0; b < BOX; b++) {
if ((unsigned int) bd < d[j]) { if ((unsigned int) bd < d[j]) {
d[j] = bd; d[j] = bd;
c[j] = (UINT8) i; c[j] = (UINT8) i;
} }
bd += bx; bd += bx;
bx += 2 * BSTEP * BSTEP; bx += 2 * BSTEP * BSTEP;
j++; j++;
} }
gd += gx; gd += gx;
gx += 2 * GSTEP * GSTEP; gx += 2 * GSTEP * GSTEP;
} }
rd += rx; rd += rx;
rx += 2 * RSTEP * RSTEP; rx += 2 * RSTEP * RSTEP;
} }
} }
/* Step 3 -- Update cache */ /* Step 3 -- Update cache */
@ -269,9 +269,9 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
j = 0; j = 0;
for (r = r0; r < r1; r+=4) for (r = r0; r < r1; r+=4)
for (g = g0; g < g1; g+=4) for (g = g0; g < g1; g+=4)
for (b = b0; b < b1; b+=4) for (b = b0; b < b1; b+=4)
ImagingPaletteCache(palette, r, g, b) = c[j++]; ImagingPaletteCache(palette, r, g, b) = c[j++];
} }
@ -285,18 +285,18 @@ ImagingPaletteCachePrepare(ImagingPalette palette)
if (palette->cache == NULL) { if (palette->cache == NULL) {
/* The cache is 512k. It might be a good idea to break it /* The cache is 512k. It might be a good idea to break it
up into a pointer array (e.g. an 8-bit image?) */ up into a pointer array (e.g. an 8-bit image?) */
palette->cache = (INT16*) malloc(entries * sizeof(INT16)); palette->cache = (INT16*) malloc(entries * sizeof(INT16));
if (!palette->cache) { if (!palette->cache) {
(void) ImagingError_MemoryError(); (void) ImagingError_MemoryError();
return -1; return -1;
} }
/* Mark all entries as empty */ /* Mark all entries as empty */
for (i = 0; i < entries; i++) for (i = 0; i < entries; i++)
palette->cache[i] = 0x100; palette->cache[i] = 0x100;
} }
@ -310,7 +310,7 @@ ImagingPaletteCacheDelete(ImagingPalette palette)
/* Release the colour cache, if any */ /* Release the colour cache, if any */
if (palette && palette->cache) { if (palette && palette->cache) {
free(palette->cache); free(palette->cache);
palette->cache = NULL; palette->cache = NULL;
} }
} }

View File

@ -55,20 +55,20 @@ ImagingRankFilter(Imaging im, int size, int rank)
int i, margin, size2; int i, margin, size2;
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL)
return (Imaging) ImagingError_ModeError(); return (Imaging) ImagingError_ModeError();
if (!(size & 1)) if (!(size & 1))
return (Imaging) ImagingError_ValueError("bad filter size"); return (Imaging) ImagingError_ValueError("bad filter size");
size2 = size * size; size2 = size * size;
margin = (size-1) / 2; margin = (size-1) / 2;
if (rank < 0 || rank >= size2) if (rank < 0 || rank >= size2)
return (Imaging) ImagingError_ValueError("bad rank value"); return (Imaging) ImagingError_ValueError("bad rank value");
imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin);
if (!imOut) if (!imOut)
return NULL; return NULL;
#define RANK_BODY(type) do {\ #define RANK_BODY(type) do {\
type* buf = malloc(size2 * sizeof(type));\ type* buf = malloc(size2 * sizeof(type));\

View File

@ -18,7 +18,7 @@
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
#include "Zip.h" #include "Zip.h"
@ -37,7 +37,7 @@ static int get_row_len(ImagingCodecState state, int pass)
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Decoder */ /* Decoder */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int int
@ -52,50 +52,50 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
if (!state->state) { if (!state->state) {
/* Initialization */ /* Initialization */
if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE)
context->prefix = 1; /* PNG */ context->prefix = 1; /* PNG */
/* Expand standard buffer to make room for the (optional) filter /* Expand standard buffer to make room for the (optional) filter
prefix, and allocate a buffer to hold the previous line */ prefix, and allocate a buffer to hold the previous line */
free(state->buffer); free(state->buffer);
state->buffer = (UINT8*) malloc(state->bytes+1); state->buffer = (UINT8*) malloc(state->bytes+1);
context->previous = (UINT8*) malloc(state->bytes+1); context->previous = (UINT8*) malloc(state->bytes+1);
if (!state->buffer || !context->previous) { if (!state->buffer || !context->previous) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return -1; return -1;
} }
context->last_output = 0; context->last_output = 0;
/* Initialize to black */ /* Initialize to black */
memset(context->previous, 0, state->bytes+1); memset(context->previous, 0, state->bytes+1);
/* Setup decompression context */ /* Setup decompression context */
context->z_stream.zalloc = (alloc_func) NULL; context->z_stream.zalloc = (alloc_func) NULL;
context->z_stream.zfree = (free_func) NULL; context->z_stream.zfree = (free_func) NULL;
context->z_stream.opaque = (voidpf) NULL; context->z_stream.opaque = (voidpf) NULL;
err = inflateInit(&context->z_stream); err = inflateInit(&context->z_stream);
if (err < 0) { if (err < 0) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
return -1; return -1;
} }
if (context->interlaced) { if (context->interlaced) {
context->pass = 0; context->pass = 0;
state->y = STARTING_ROW[context->pass]; state->y = STARTING_ROW[context->pass];
} }
/* Ready to decode */ /* Ready to decode */
state->state = 1; state->state = 1;
} }
if (context->interlaced) { if (context->interlaced) {
row_len = get_row_len(state, context->pass); row_len = get_row_len(state, context->pass);
} else { } else {
row_len = state->bytes; row_len = state->bytes;
} }
/* Setup the source buffer */ /* Setup the source buffer */
@ -105,162 +105,162 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* Decompress what we've got this far */ /* Decompress what we've got this far */
while (context->z_stream.avail_in > 0) { while (context->z_stream.avail_in > 0) {
context->z_stream.next_out = state->buffer + context->last_output; context->z_stream.next_out = state->buffer + context->last_output;
context->z_stream.avail_out = context->z_stream.avail_out =
row_len + context->prefix - context->last_output; row_len + context->prefix - context->last_output;
err = inflate(&context->z_stream, Z_NO_FLUSH); err = inflate(&context->z_stream, Z_NO_FLUSH);
if (err < 0) { if (err < 0) {
/* Something went wrong inside the compression library */ /* Something went wrong inside the compression library */
if (err == Z_DATA_ERROR) if (err == Z_DATA_ERROR)
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
else if (err == Z_MEM_ERROR) else if (err == Z_MEM_ERROR)
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
else else
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
free(context->previous); free(context->previous);
inflateEnd(&context->z_stream); inflateEnd(&context->z_stream);
return -1; return -1;
} }
n = row_len + context->prefix - context->z_stream.avail_out; n = row_len + context->prefix - context->z_stream.avail_out;
if (n < row_len + context->prefix) { if (n < row_len + context->prefix) {
context->last_output = n; context->last_output = n;
break; /* need more input data */ break; /* need more input data */
} }
/* Apply predictor */ /* Apply predictor */
switch (context->mode) { switch (context->mode) {
case ZIP_PNG: case ZIP_PNG:
switch (state->buffer[0]) { switch (state->buffer[0]) {
case 0: case 0:
break; break;
case 1: case 1:
/* prior */ /* prior */
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
for (i = bpp+1; i <= row_len; i++) for (i = bpp+1; i <= row_len; i++)
state->buffer[i] += state->buffer[i-bpp]; state->buffer[i] += state->buffer[i-bpp];
break; break;
case 2: case 2:
/* up */ /* up */
for (i = 1; i <= row_len; i++) for (i = 1; i <= row_len; i++)
state->buffer[i] += context->previous[i]; state->buffer[i] += context->previous[i];
break; break;
case 3: case 3:
/* average */ /* average */
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) for (i = 1; i <= bpp; i++)
state->buffer[i] += context->previous[i]/2; state->buffer[i] += context->previous[i]/2;
for (; i <= row_len; i++) for (; i <= row_len; i++)
state->buffer[i] += state->buffer[i] +=
(state->buffer[i-bpp] + context->previous[i])/2; (state->buffer[i-bpp] + context->previous[i])/2;
break; break;
case 4: case 4:
/* paeth filtering */ /* paeth filtering */
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) for (i = 1; i <= bpp; i++)
state->buffer[i] += context->previous[i]; state->buffer[i] += context->previous[i];
for (; i <= row_len; i++) { for (; i <= row_len; i++) {
int a, b, c; int a, b, c;
int pa, pb, pc; int pa, pb, pc;
/* fetch pixels */ /* fetch pixels */
a = state->buffer[i-bpp]; a = state->buffer[i-bpp];
b = context->previous[i]; b = context->previous[i];
c = context->previous[i-bpp]; c = context->previous[i-bpp];
/* distances to surrounding pixels */ /* distances to surrounding pixels */
pa = abs(b - c); pa = abs(b - c);
pb = abs(a - c); pb = abs(a - c);
pc = abs(a + b - 2*c); pc = abs(a + b - 2*c);
/* pick predictor with the shortest distance */ /* pick predictor with the shortest distance */
state->buffer[i] += state->buffer[i] +=
(pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
} }
break; break;
default: default:
state->errcode = IMAGING_CODEC_UNKNOWN; state->errcode = IMAGING_CODEC_UNKNOWN;
free(context->previous); free(context->previous);
inflateEnd(&context->z_stream); inflateEnd(&context->z_stream);
return -1; return -1;
} }
break; break;
case ZIP_TIFF_PREDICTOR: case ZIP_TIFF_PREDICTOR:
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
for (i = bpp+1; i <= row_len; i++) for (i = bpp+1; i <= row_len; i++)
state->buffer[i] += state->buffer[i-bpp]; state->buffer[i] += state->buffer[i-bpp];
break; break;
} }
/* Stuff data into the image */ /* Stuff data into the image */
if (context->interlaced) { if (context->interlaced) {
int col = STARTING_COL[context->pass]; int col = STARTING_COL[context->pass];
if (state->bits >= 8) { if (state->bits >= 8) {
/* Stuff pixels in their correct location, one by one */ /* Stuff pixels in their correct location, one by one */
for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) { for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) {
state->shuffle((UINT8*) im->image[state->y] + state->shuffle((UINT8*) im->image[state->y] +
col * im->pixelsize, col * im->pixelsize,
state->buffer + context->prefix + i, 1); state->buffer + context->prefix + i, 1);
col += COL_INCREMENT[context->pass]; col += COL_INCREMENT[context->pass];
} }
} else { } else {
/* Handle case with more than a pixel in each byte */ /* Handle case with more than a pixel in each byte */
int row_bits = ((state->xsize + OFFSET[context->pass]) int row_bits = ((state->xsize + OFFSET[context->pass])
/ COL_INCREMENT[context->pass]) * state->bits; / COL_INCREMENT[context->pass]) * state->bits;
for (i = 0; i < row_bits; i += state->bits) { for (i = 0; i < row_bits; i += state->bits) {
UINT8 byte = *(state->buffer + context->prefix + (i / 8)); UINT8 byte = *(state->buffer + context->prefix + (i / 8));
byte <<= (i % 8); byte <<= (i % 8);
state->shuffle((UINT8*) im->image[state->y] + state->shuffle((UINT8*) im->image[state->y] +
col * im->pixelsize, &byte, 1); col * im->pixelsize, &byte, 1);
col += COL_INCREMENT[context->pass]; col += COL_INCREMENT[context->pass];
} }
} }
/* Find next valid scanline */ /* Find next valid scanline */
state->y += ROW_INCREMENT[context->pass]; state->y += ROW_INCREMENT[context->pass];
while (state->y >= state->ysize || row_len <= 0) { while (state->y >= state->ysize || row_len <= 0) {
context->pass++; context->pass++;
if (context->pass == 7) { if (context->pass == 7) {
/* Force exit below */ /* Force exit below */
state->y = state->ysize; state->y = state->ysize;
break; break;
} }
state->y = STARTING_ROW[context->pass]; state->y = STARTING_ROW[context->pass];
row_len = get_row_len(state, context->pass); row_len = get_row_len(state, context->pass);
/* Since we're moving to the "first" line, the previous line /* Since we're moving to the "first" line, the previous line
* should be black to make filters work corectly */ * should be black to make filters work corectly */
memset(state->buffer, 0, state->bytes+1); memset(state->buffer, 0, state->bytes+1);
} }
} else { } else {
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle((UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->xoff * im->pixelsize,
state->buffer + context->prefix, state->buffer + context->prefix,
state->xsize); state->xsize);
state->y++; state->y++;
} }
/* all inflate output has been consumed */ /* all inflate output has been consumed */
context->last_output = 0; context->last_output = 0;
if (state->y >= state->ysize || err == Z_STREAM_END) { if (state->y >= state->ysize || err == Z_STREAM_END) {
/* The image and the data should end simultaneously */ /* The image and the data should end simultaneously */
/* if (state->y < state->ysize || err != Z_STREAM_END) /* if (state->y < state->ysize || err != Z_STREAM_END)
state->errcode = IMAGING_CODEC_BROKEN; */ state->errcode = IMAGING_CODEC_BROKEN; */
free(context->previous); free(context->previous);
inflateEnd(&context->z_stream); inflateEnd(&context->z_stream);
return -1; /* end of file (errcode=0) */ return -1; /* end of file (errcode=0) */
} }
/* Swap buffer pointers */ /* Swap buffer pointers */
ptr = state->buffer; ptr = state->buffer;
state->buffer = context->previous; state->buffer = context->previous;
context->previous = ptr; context->previous = ptr;
} }

View File

@ -5,8 +5,8 @@
* coder for ZIP (deflated) image data * coder for ZIP (deflated) image data
* *
* History: * History:
* 96-12-29 fl created * 96-12-29 fl created
* 96-12-30 fl adaptive filter selection, encoder tuning * 96-12-30 fl adaptive filter selection, encoder tuning
* *
* Copyright (c) Fredrik Lundh 1996. * Copyright (c) Fredrik Lundh 1996.
* Copyright (c) Secret Labs AB 1997. * Copyright (c) Secret Labs AB 1997.
@ -17,7 +17,7 @@
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
#include "Zip.h" #include "Zip.h"
@ -33,82 +33,82 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
if (!state->state) { if (!state->state) {
/* Initialization */ /* Initialization */
/* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */ /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */
/* Expand standard buffer to make room for the filter selector, /* Expand standard buffer to make room for the filter selector,
and allocate filter buffers */ and allocate filter buffers */
free(state->buffer); free(state->buffer);
state->buffer = (UINT8*) malloc(state->bytes+1); state->buffer = (UINT8*) malloc(state->bytes+1);
context->previous = (UINT8*) malloc(state->bytes+1); context->previous = (UINT8*) malloc(state->bytes+1);
context->prior = (UINT8*) malloc(state->bytes+1); context->prior = (UINT8*) malloc(state->bytes+1);
context->up = (UINT8*) malloc(state->bytes+1); context->up = (UINT8*) malloc(state->bytes+1);
context->average = (UINT8*) malloc(state->bytes+1); context->average = (UINT8*) malloc(state->bytes+1);
context->paeth = (UINT8*) malloc(state->bytes+1); context->paeth = (UINT8*) malloc(state->bytes+1);
if (!state->buffer || !context->previous || !context->prior || if (!state->buffer || !context->previous || !context->prior ||
!context->up || !context->average || !context->paeth) { !context->up || !context->average || !context->paeth) {
free(context->paeth); free(context->paeth);
free(context->average); free(context->average);
free(context->up); free(context->up);
free(context->prior); free(context->prior);
free(context->previous); free(context->previous);
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return -1; return -1;
} }
/* Initalise filter buffers */ /* Initalise filter buffers */
state->buffer[0] = 0; state->buffer[0] = 0;
context->prior[0] = 1; context->prior[0] = 1;
context->up[0] = 2; context->up[0] = 2;
context->average[0] = 3; context->average[0] = 3;
context->paeth[0] = 4; context->paeth[0] = 4;
/* Initialise previous buffer to black */ /* Initialise previous buffer to black */
memset(context->previous, 0, state->bytes+1); memset(context->previous, 0, state->bytes+1);
/* Setup compression context */ /* Setup compression context */
context->z_stream.zalloc = (alloc_func)0; context->z_stream.zalloc = (alloc_func)0;
context->z_stream.zfree = (free_func)0; context->z_stream.zfree = (free_func)0;
context->z_stream.opaque = (voidpf)0; context->z_stream.opaque = (voidpf)0;
context->z_stream.next_in = 0; context->z_stream.next_in = 0;
context->z_stream.avail_in = 0; context->z_stream.avail_in = 0;
compress_level = (context->optimize) ? Z_BEST_COMPRESSION compress_level = (context->optimize) ? Z_BEST_COMPRESSION
: context->compress_level; : context->compress_level;
if (context->compress_type == -1) { if (context->compress_type == -1) {
compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED
: Z_DEFAULT_STRATEGY; : Z_DEFAULT_STRATEGY;
} else { } else {
compress_type = context->compress_type; compress_type = context->compress_type;
} }
err = deflateInit2(&context->z_stream, err = deflateInit2(&context->z_stream,
/* compression level */ /* compression level */
compress_level, compress_level,
/* compression method */ /* compression method */
Z_DEFLATED, Z_DEFLATED,
/* compression memory resources */ /* compression memory resources */
15, 9, 15, 9,
/* compression strategy (image data are filtered)*/ /* compression strategy (image data are filtered)*/
compress_type); compress_type);
if (err < 0) { if (err < 0) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
return -1; return -1;
} }
if (context->dictionary && context->dictionary_size > 0) { if (context->dictionary && context->dictionary_size > 0) {
err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary, err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary,
context->dictionary_size); context->dictionary_size);
if (err < 0) { if (err < 0) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
return -1; return -1;
} }
} }
/* Ready to decode */ /* Ready to decode */
state->state = 1; state->state = 1;
} }
@ -116,222 +116,222 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->z_stream.next_out = buf; context->z_stream.next_out = buf;
context->z_stream.avail_out = bytes; context->z_stream.avail_out = bytes;
if (context->z_stream.next_in && context->z_stream.avail_in > 0) { if (context->z_stream.next_in && context->z_stream.avail_in > 0) {
/* We have some data from previous round, deflate it first */ /* We have some data from previous round, deflate it first */
err = deflate(&context->z_stream, Z_NO_FLUSH); err = deflate(&context->z_stream, Z_NO_FLUSH);
if (err < 0) { if (err < 0) {
/* Something went wrong inside the compression library */ /* Something went wrong inside the compression library */
if (err == Z_DATA_ERROR) if (err == Z_DATA_ERROR)
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
else if (err == Z_MEM_ERROR) else if (err == Z_MEM_ERROR)
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
else else
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
free(context->paeth); free(context->paeth);
free(context->average); free(context->average);
free(context->up); free(context->up);
free(context->prior); free(context->prior);
free(context->previous); free(context->previous);
deflateEnd(&context->z_stream); deflateEnd(&context->z_stream);
return -1; return -1;
} }
} }
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (;;) { for (;;) {
switch (state->state) { switch (state->state) {
case 1: case 1:
/* Compress image data */ /* Compress image data */
while (context->z_stream.avail_out > 0) { while (context->z_stream.avail_out > 0) {
if (state->y >= state->ysize) { if (state->y >= state->ysize) {
/* End of image; now flush compressor buffers */ /* End of image; now flush compressor buffers */
state->state = 2; state->state = 2;
break; break;
} }
/* Stuff image data into the compressor */ /* Stuff image data into the compressor */
state->shuffle(state->buffer+1, state->shuffle(state->buffer+1,
(UINT8*) im->image[state->y + state->yoff] + (UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->xoff * im->pixelsize,
state->xsize); state->xsize);
state->y++; state->y++;
context->output = state->buffer; context->output = state->buffer;
if (context->mode == ZIP_PNG) { if (context->mode == ZIP_PNG) {
/* Filter the image data. For each line, select /* Filter the image data. For each line, select
the filter that gives the least total distance the filter that gives the least total distance
from zero for the filtered data (taken from from zero for the filtered data (taken from
LIBPNG) */ LIBPNG) */
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
/* 0. No filter */ /* 0. No filter */
for (i = 1, sum = 0; i <= state->bytes; i++) { for (i = 1, sum = 0; i <= state->bytes; i++) {
UINT8 v = state->buffer[i]; UINT8 v = state->buffer[i];
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
} }
/* 2. Up. We'll test this first to save time when /* 2. Up. We'll test this first to save time when
an image line is identical to the one above. */ an image line is identical to the one above. */
if (sum > 0) { if (sum > 0) {
for (i = 1, s = 0; i <= state->bytes; i++) { for (i = 1, s = 0; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - context->previous[i]; UINT8 v = state->buffer[i] - context->previous[i];
context->up[i] = v; context->up[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
if (s < sum) { if (s < sum) {
context->output = context->up; context->output = context->up;
sum = s; /* 0 if line was duplicated */ sum = s; /* 0 if line was duplicated */
} }
} }
/* 1. Prior */ /* 1. Prior */
if (sum > 0) { if (sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) { for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i]; UINT8 v = state->buffer[i];
context->prior[i] = v; context->prior[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
for (; i <= state->bytes; i++) { for (; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - state->buffer[i-bpp]; UINT8 v = state->buffer[i] - state->buffer[i-bpp];
context->prior[i] = v; context->prior[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
if (s < sum) { if (s < sum) {
context->output = context->prior; context->output = context->prior;
sum = s; /* 0 if line is solid */ sum = s; /* 0 if line is solid */
} }
} }
/* 3. Average (not very common in real-life images, /* 3. Average (not very common in real-life images,
so its only used with the optimize option) */ so its only used with the optimize option) */
if (context->optimize && sum > 0) { if (context->optimize && sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) { for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i] - context->previous[i]/2; UINT8 v = state->buffer[i] - context->previous[i]/2;
context->average[i] = v; context->average[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
for (; i <= state->bytes; i++) { for (; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - UINT8 v = state->buffer[i] -
(state->buffer[i-bpp] + context->previous[i])/2; (state->buffer[i-bpp] + context->previous[i])/2;
context->average[i] = v; context->average[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
if (s < sum) { if (s < sum) {
context->output = context->average; context->output = context->average;
sum = s; sum = s;
} }
} }
/* 4. Paeth */ /* 4. Paeth */
if (sum > 0) { if (sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) { for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i] - context->previous[i]; UINT8 v = state->buffer[i] - context->previous[i];
context->paeth[i] = v; context->paeth[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
for (; i <= state->bytes; i++) { for (; i <= state->bytes; i++) {
UINT8 v; UINT8 v;
int a, b, c; int a, b, c;
int pa, pb, pc; int pa, pb, pc;
/* fetch pixels */ /* fetch pixels */
a = state->buffer[i-bpp]; a = state->buffer[i-bpp];
b = context->previous[i]; b = context->previous[i];
c = context->previous[i-bpp]; c = context->previous[i-bpp];
/* distances to surrounding pixels */ /* distances to surrounding pixels */
pa = abs(b - c); pa = abs(b - c);
pb = abs(a - c); pb = abs(a - c);
pc = abs(a + b - 2*c); pc = abs(a + b - 2*c);
/* pick predictor with the shortest distance */ /* pick predictor with the shortest distance */
v = state->buffer[i] - v = state->buffer[i] -
((pa <= pb && pa <= pc) ? a : ((pa <= pb && pa <= pc) ? a :
(pb <= pc) ? b : c); (pb <= pc) ? b : c);
context->paeth[i] = v; context->paeth[i] = v;
s += (v < 128) ? v : 256 - v; s += (v < 128) ? v : 256 - v;
} }
if (s < sum) { if (s < sum) {
context->output = context->paeth; context->output = context->paeth;
sum = s; sum = s;
} }
} }
} }
/* Compress this line */ /* Compress this line */
context->z_stream.next_in = context->output; context->z_stream.next_in = context->output;
context->z_stream.avail_in = state->bytes+1; context->z_stream.avail_in = state->bytes+1;
err = deflate(&context->z_stream, Z_NO_FLUSH); err = deflate(&context->z_stream, Z_NO_FLUSH);
if (err < 0) { if (err < 0) {
/* Something went wrong inside the compression library */ /* Something went wrong inside the compression library */
if (err == Z_DATA_ERROR) if (err == Z_DATA_ERROR)
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
else if (err == Z_MEM_ERROR) else if (err == Z_MEM_ERROR)
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
else else
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
free(context->paeth); free(context->paeth);
free(context->average); free(context->average);
free(context->up); free(context->up);
free(context->prior); free(context->prior);
free(context->previous); free(context->previous);
deflateEnd(&context->z_stream); deflateEnd(&context->z_stream);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
return -1; return -1;
} }
/* Swap buffer pointers */ /* Swap buffer pointers */
ptr = state->buffer; ptr = state->buffer;
state->buffer = context->previous; state->buffer = context->previous;
context->previous = ptr; context->previous = ptr;
} }
if (context->z_stream.avail_out == 0) if (context->z_stream.avail_out == 0)
break; /* Buffer full */ break; /* Buffer full */
case 2: case 2:
/* End of image data; flush compressor buffers */ /* End of image data; flush compressor buffers */
while (context->z_stream.avail_out > 0) { while (context->z_stream.avail_out > 0) {
err = deflate(&context->z_stream, Z_FINISH); err = deflate(&context->z_stream, Z_FINISH);
if (err == Z_STREAM_END) { if (err == Z_STREAM_END) {
free(context->paeth); free(context->paeth);
free(context->average); free(context->average);
free(context->up); free(context->up);
free(context->prior); free(context->prior);
free(context->previous); free(context->previous);
deflateEnd(&context->z_stream); deflateEnd(&context->z_stream);
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
break; break;
} }
if (context->z_stream.avail_out == 0) if (context->z_stream.avail_out == 0)
break; /* Buffer full */ break; /* Buffer full */
} }
} }
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
return bytes - context->z_stream.avail_out; return bytes - context->z_stream.avail_out;
} }

182
path.c
View File

@ -37,7 +37,7 @@ extern int PyImaging_CheckBuffer(PyObject* buffer);
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view); extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Class */ /* Class */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
typedef struct { typedef struct {
@ -86,7 +86,7 @@ path_new(Py_ssize_t count, double* xy, int duplicate)
path = PyObject_New(PyPathObject, &PyPathType); path = PyObject_New(PyPathObject, &PyPathType);
if (path == NULL) if (path == NULL)
return NULL; return NULL;
path->count = count; path->count = count;
path->xy = xy; path->xy = xy;
@ -102,7 +102,7 @@ path_dealloc(PyPathObject* path)
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Helpers */ /* Helpers */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
#define PyPath_Check(op) (Py_TYPE(op) == &PyPathType) #define PyPath_Check(op) (Py_TYPE(op) == &PyPathType)
@ -114,14 +114,14 @@ PyPath_Flatten(PyObject* data, double **pxy)
double *xy; double *xy;
if (PyPath_Check(data)) { if (PyPath_Check(data)) {
/* This was another path object. */ /* This was another path object. */
PyPathObject *path = (PyPathObject*) data; PyPathObject *path = (PyPathObject*) data;
xy = alloc_array(path->count); xy = alloc_array(path->count);
if (!xy) if (!xy)
return -1; return -1;
memcpy(xy, path->xy, 2 * path->count * sizeof(double)); memcpy(xy, path->xy, 2 * path->count * sizeof(double));
*pxy = xy; *pxy = xy;
return path->count; return path->count;
} }
if (PyImaging_CheckBuffer(data)) { if (PyImaging_CheckBuffer(data)) {
@ -143,8 +143,8 @@ PyPath_Flatten(PyObject* data, double **pxy)
} }
if (!PySequence_Check(data)) { if (!PySequence_Check(data)) {
PyErr_SetString(PyExc_TypeError, "argument must be sequence"); PyErr_SetString(PyExc_TypeError, "argument must be sequence");
return -1; return -1;
} }
j = 0; j = 0;
@ -156,7 +156,7 @@ PyPath_Flatten(PyObject* data, double **pxy)
/* Allocate for worst case */ /* Allocate for worst case */
xy = alloc_array(n); xy = alloc_array(n);
if (!xy) if (!xy)
return -1; return -1;
/* Copy table to path array */ /* Copy table to path array */
if (PyList_Check(data)) { if (PyList_Check(data)) {
@ -164,9 +164,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
double x, y; double x, y;
PyObject *op = PyList_GET_ITEM(data, i); PyObject *op = PyList_GET_ITEM(data, i);
if (PyFloat_Check(op)) if (PyFloat_Check(op))
xy[j++] = PyFloat_AS_DOUBLE(op); xy[j++] = PyFloat_AS_DOUBLE(op);
else if (PyInt_Check(op)) else if (PyInt_Check(op))
xy[j++] = (float) PyInt_AS_LONG(op); xy[j++] = (float) PyInt_AS_LONG(op);
else if (PyNumber_Check(op)) else if (PyNumber_Check(op))
xy[j++] = PyFloat_AsDouble(op); xy[j++] = PyFloat_AsDouble(op);
else if (PyArg_ParseTuple(op, "dd", &x, &y)) { else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
@ -182,9 +182,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
double x, y; double x, y;
PyObject *op = PyTuple_GET_ITEM(data, i); PyObject *op = PyTuple_GET_ITEM(data, i);
if (PyFloat_Check(op)) if (PyFloat_Check(op))
xy[j++] = PyFloat_AS_DOUBLE(op); xy[j++] = PyFloat_AS_DOUBLE(op);
else if (PyInt_Check(op)) else if (PyInt_Check(op))
xy[j++] = (float) PyInt_AS_LONG(op); xy[j++] = (float) PyInt_AS_LONG(op);
else if (PyNumber_Check(op)) else if (PyNumber_Check(op))
xy[j++] = PyFloat_AsDouble(op); xy[j++] = PyFloat_AsDouble(op);
else if (PyArg_ParseTuple(op, "dd", &x, &y)) { else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
@ -211,9 +211,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
} }
} }
if (PyFloat_Check(op)) if (PyFloat_Check(op))
xy[j++] = PyFloat_AS_DOUBLE(op); xy[j++] = PyFloat_AS_DOUBLE(op);
else if (PyInt_Check(op)) else if (PyInt_Check(op))
xy[j++] = (float) PyInt_AS_LONG(op); xy[j++] = (float) PyInt_AS_LONG(op);
else if (PyNumber_Check(op)) else if (PyNumber_Check(op))
xy[j++] = PyFloat_AsDouble(op); xy[j++] = PyFloat_AsDouble(op);
else if (PyArg_ParseTuple(op, "dd", &x, &y)) { else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
@ -229,9 +229,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
} }
if (j & 1) { if (j & 1) {
PyErr_SetString(PyExc_ValueError, "wrong number of coordinates"); PyErr_SetString(PyExc_ValueError, "wrong number of coordinates");
free(xy); free(xy);
return -1; return -1;
} }
*pxy = xy; *pxy = xy;
@ -240,7 +240,7 @@ PyPath_Flatten(PyObject* data, double **pxy)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Factories */ /* Factories */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject*
@ -274,7 +274,7 @@ PyPath_Create(PyObject* self, PyObject* args)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Methods */ /* Methods */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static PyObject* static PyObject*
@ -289,17 +289,17 @@ path_compact(PyPathObject* self, PyObject* args)
double cityblock = 2.0; double cityblock = 2.0;
if (!PyArg_ParseTuple(args, "|d:compact", &cityblock)) if (!PyArg_ParseTuple(args, "|d:compact", &cityblock))
return NULL; return NULL;
xy = self->xy; xy = self->xy;
/* remove bogus vertices */ /* remove bogus vertices */
for (i = j = 1; i < self->count; i++) { for (i = j = 1; i < self->count; i++) {
if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) { if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) {
xy[j+j] = xy[i+i]; xy[j+j] = xy[i+i];
xy[j+j+1] = xy[i+i+1]; xy[j+j+1] = xy[i+i+1];
j++; j++;
} }
} }
i = self->count - j; i = self->count - j;
@ -336,7 +336,7 @@ path_getbbox(PyPathObject* self, PyObject* args)
double x0, y0, x1, y1; double x0, y0, x1, y1;
if (!PyArg_ParseTuple(args, ":getbbox")) if (!PyArg_ParseTuple(args, ":getbbox"))
return NULL; return NULL;
xy = self->xy; xy = self->xy;
@ -344,14 +344,14 @@ path_getbbox(PyPathObject* self, PyObject* args)
y0 = y1 = xy[1]; y0 = y1 = xy[1];
for (i = 1; i < self->count; i++) { for (i = 1; i < self->count; i++) {
if (xy[i+i] < x0) if (xy[i+i] < x0)
x0 = xy[i+i]; x0 = xy[i+i];
if (xy[i+i] > x1) if (xy[i+i] > x1)
x1 = xy[i+i]; x1 = xy[i+i];
if (xy[i+i+1] < y0) if (xy[i+i+1] < y0)
y0 = xy[i+i+1]; y0 = xy[i+i+1];
if (xy[i+i+1] > y1) if (xy[i+i+1] > y1)
y1 = xy[i+i+1]; y1 = xy[i+i+1];
} }
return Py_BuildValue("dddd", x0, y0, x1, y1); return Py_BuildValue("dddd", x0, y0, x1, y1);
@ -363,8 +363,8 @@ path_getitem(PyPathObject* self, int i)
if (i < 0) if (i < 0)
i = self->count + i; i = self->count + i;
if (i < 0 || i >= self->count) { if (i < 0 || i >= self->count) {
PyErr_SetString(PyExc_IndexError, "path index out of range"); PyErr_SetString(PyExc_IndexError, "path index out of range");
return NULL; return NULL;
} }
return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]); return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
@ -403,22 +403,22 @@ path_map(PyPathObject* self, PyObject* args)
PyObject* function; PyObject* function;
if (!PyArg_ParseTuple(args, "O:map", &function)) if (!PyArg_ParseTuple(args, "O:map", &function))
return NULL; return NULL;
xy = self->xy; xy = self->xy;
/* apply function to coordinate set */ /* apply function to coordinate set */
for (i = 0; i < self->count; i++) { for (i = 0; i < self->count; i++) {
double x = xy[i+i]; double x = xy[i+i];
double y = xy[i+i+1]; double y = xy[i+i+1];
PyObject* item = PyObject_CallFunction(function, "dd", x, y); PyObject* item = PyObject_CallFunction(function, "dd", x, y);
if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) { if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) {
Py_XDECREF(item); Py_XDECREF(item);
return NULL; return NULL;
} }
xy[i+i] = x; xy[i+i] = x;
xy[i+i+1] = y; xy[i+i+1] = y;
Py_DECREF(item); Py_DECREF(item);
} }
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -458,7 +458,7 @@ path_tolist(PyPathObject* self, PyObject* args)
int flat = 0; int flat = 0;
if (!PyArg_ParseTuple(args, "|i:tolist", &flat)) if (!PyArg_ParseTuple(args, "|i:tolist", &flat))
return NULL; return NULL;
if (flat) { if (flat) {
list = PyList_New(self->count*2); list = PyList_New(self->count*2);
@ -498,32 +498,32 @@ path_transform(PyPathObject* self, PyObject* args)
double wrap = 0.0; double wrap = 0.0;
if (!PyArg_ParseTuple(args, "(dddddd)|d:transform", if (!PyArg_ParseTuple(args, "(dddddd)|d:transform",
&a, &b, &c, &d, &e, &f, &a, &b, &c, &d, &e, &f,
&wrap)) &wrap))
return NULL; return NULL;
xy = self->xy; xy = self->xy;
/* transform the coordinate set */ /* transform the coordinate set */
if (b == 0.0 && d == 0.0) if (b == 0.0 && d == 0.0)
/* scaling */ /* scaling */
for (i = 0; i < self->count; i++) { for (i = 0; i < self->count; i++) {
xy[i+i] = a*xy[i+i]+c; xy[i+i] = a*xy[i+i]+c;
xy[i+i+1] = e*xy[i+i+1]+f; xy[i+i+1] = e*xy[i+i+1]+f;
} }
else else
/* affine transform */ /* affine transform */
for (i = 0; i < self->count; i++) { for (i = 0; i < self->count; i++) {
double x = xy[i+i]; double x = xy[i+i];
double y = xy[i+i+1]; double y = xy[i+i+1];
xy[i+i] = a*x+b*y+c; xy[i+i] = a*x+b*y+c;
xy[i+i+1] = d*x+e*y+f; xy[i+i+1] = d*x+e*y+f;
} }
/* special treatment of geographical map data */ /* special treatment of geographical map data */
if (wrap != 0.0) if (wrap != 0.0)
for (i = 0; i < self->count; i++) for (i = 0; i < self->count; i++)
xy[i+i] = fmod(xy[i+i], wrap); xy[i+i] = fmod(xy[i+i], wrap);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
@ -543,7 +543,7 @@ static struct PyMethodDef methods[] = {
static PyObject* static PyObject*
path_getattr_id(PyPathObject* self, void* closure) path_getattr_id(PyPathObject* self, void* closure)
{ {
return Py_BuildValue("n", (Py_ssize_t) self->xy); return Py_BuildValue("n", (Py_ssize_t) self->xy);
} }
static struct PyGetSetDef getsetters[] = { static struct PyGetSetDef getsetters[] = {
@ -593,13 +593,13 @@ path_subscript(PyPathObject* self, PyObject* item) {
} }
static PySequenceMethods path_as_sequence = { static PySequenceMethods path_as_sequence = {
(lenfunc)path_len, /*sq_length*/ (lenfunc)path_len, /*sq_length*/
(binaryfunc)0, /*sq_concat*/ (binaryfunc)0, /*sq_concat*/
(ssizeargfunc)0, /*sq_repeat*/ (ssizeargfunc)0, /*sq_repeat*/
(ssizeargfunc)path_getitem, /*sq_item*/ (ssizeargfunc)path_getitem, /*sq_item*/
(ssizessizeargfunc)path_getslice, /*sq_slice*/ (ssizessizeargfunc)path_getslice, /*sq_slice*/
(ssizeobjargproc)path_setitem, /*sq_ass_item*/ (ssizeobjargproc)path_setitem, /*sq_ass_item*/
(ssizessizeobjargproc)0, /*sq_ass_slice*/ (ssizessizeobjargproc)0, /*sq_ass_slice*/
}; };
static PyMappingMethods path_as_mapping = { static PyMappingMethods path_as_mapping = {
@ -609,19 +609,19 @@ static PyMappingMethods path_as_mapping = {
}; };
static PyTypeObject PyPathType = { static PyTypeObject PyPathType = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0)
"Path", /*tp_name*/ "Path", /*tp_name*/
sizeof(PyPathObject), /*tp_size*/ sizeof(PyPathObject), /*tp_size*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
/* methods */ /* methods */
(destructor)path_dealloc, /*tp_dealloc*/ (destructor)path_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
&path_as_sequence, /*tp_as_sequence */ &path_as_sequence, /*tp_as_sequence */
&path_as_mapping, /*tp_as_mapping */ &path_as_mapping, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/