mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-15 01:34:45 +03:00
change pixelsize of La/LA/LA modes from 4 to 2
This commit is contained in:
parent
5a087ccbb9
commit
2643a3d971
|
@ -26,7 +26,11 @@ import sys
|
|||
try:
|
||||
from cffi import FFI
|
||||
|
||||
# Pixel_XA uses "r" instead of "x" for backwards compatibility.
|
||||
defs = """
|
||||
struct Pixel_XA {
|
||||
unsigned char r,a;
|
||||
};
|
||||
struct Pixel_RGBA {
|
||||
unsigned char r,g,b,a;
|
||||
};
|
||||
|
@ -127,11 +131,11 @@ class PyAccess:
|
|||
return xy
|
||||
|
||||
|
||||
class _PyAccess32_2(PyAccess):
|
||||
"""PA, LA, stored in first and last bytes of a 32 bit word"""
|
||||
class _PyAccess16(PyAccess):
|
||||
"""La, LA, and PA stored in first and last bytes of a 16 bit word"""
|
||||
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
||||
self.pixels = ffi.cast("struct Pixel_XA **", self.image)
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
|
@ -314,9 +318,9 @@ mode_map = {
|
|||
"1": _PyAccess8,
|
||||
"L": _PyAccess8,
|
||||
"P": _PyAccess8,
|
||||
"LA": _PyAccess32_2,
|
||||
"La": _PyAccess32_2,
|
||||
"PA": _PyAccess32_2,
|
||||
"LA": _PyAccess16,
|
||||
"La": _PyAccess16,
|
||||
"PA": _PyAccess16,
|
||||
"RGB": _PyAccess32_3,
|
||||
"LAB": _PyAccess32_3,
|
||||
"HSV": _PyAccess32_3,
|
||||
|
|
|
@ -45,6 +45,11 @@ add_item(const char *mode) {
|
|||
|
||||
/* fetch pointer to pixel line */
|
||||
|
||||
static void *
|
||||
line(Imaging im, int x, int y) {
|
||||
return &im->image[y][x * im->pixelsize];
|
||||
}
|
||||
|
||||
static void *
|
||||
line_8(Imaging im, int x, int y) {
|
||||
return &im->image8[y][x];
|
||||
|
@ -64,21 +69,8 @@ line_32(Imaging im, int x, int y) {
|
|||
|
||||
static void
|
||||
get_pixel(Imaging im, int x, int y, void *color) {
|
||||
char *out = color;
|
||||
|
||||
/* generic pixel access*/
|
||||
|
||||
if (im->image8) {
|
||||
out[0] = im->image8[y][x];
|
||||
} else {
|
||||
UINT8 *p = (UINT8 *)&im->image32[y][x];
|
||||
if (im->type == IMAGING_TYPE_UINT8 && im->bands == 2) {
|
||||
out[0] = p[0];
|
||||
out[1] = p[3];
|
||||
return;
|
||||
}
|
||||
memcpy(out, p, im->pixelsize);
|
||||
}
|
||||
int pixelsize = im->pixelsize;
|
||||
memcpy(color, &im->image[y][x * pixelsize], pixelsize);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -140,11 +132,8 @@ get_pixel_32B(Imaging im, int x, int y, void *color) {
|
|||
|
||||
static void
|
||||
put_pixel(Imaging im, int x, int y, const void *color) {
|
||||
if (im->image8) {
|
||||
im->image8[y][x] = *((UINT8 *)color);
|
||||
} else {
|
||||
memcpy(&im->image32[y][x], color, sizeof(INT32));
|
||||
}
|
||||
int pixelsize = im->pixelsize;
|
||||
memcpy(&im->image[y][x * pixelsize], color, pixelsize);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -198,8 +187,8 @@ ImagingAccessInit() {
|
|||
/* populate access table */
|
||||
ADD("1", line_8, get_pixel_8, put_pixel_8);
|
||||
ADD("L", line_8, get_pixel_8, put_pixel_8);
|
||||
ADD("LA", line_32, get_pixel, put_pixel);
|
||||
ADD("La", line_32, get_pixel, put_pixel);
|
||||
ADD("LA", line, get_pixel, put_pixel);
|
||||
ADD("La", line, get_pixel, put_pixel);
|
||||
ADD("I", line_32, get_pixel_32, put_pixel_32);
|
||||
ADD("I;16", line_16, get_pixel_16L, put_pixel_16L);
|
||||
ADD("I;16L", line_16, get_pixel_16L, put_pixel_16L);
|
||||
|
@ -208,7 +197,7 @@ ImagingAccessInit() {
|
|||
ADD("I;32B", line_32, get_pixel_32B, put_pixel_32B);
|
||||
ADD("F", line_32, get_pixel_32, put_pixel_32);
|
||||
ADD("P", line_8, get_pixel_8, put_pixel_8);
|
||||
ADD("PA", line_32, get_pixel, put_pixel);
|
||||
ADD("PA", line, get_pixel, put_pixel);
|
||||
ADD("RGB", line_32, get_pixel_32, put_pixel_32);
|
||||
ADD("RGBA", line_32, get_pixel_32, put_pixel_32);
|
||||
ADD("RGBa", line_32, get_pixel_32, put_pixel_32);
|
||||
|
|
|
@ -31,34 +31,33 @@ ImagingGetBand(Imaging imIn, int band) {
|
|||
return (Imaging)ImagingError_ValueError("band index out of range");
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
/* Shortcut */
|
||||
if (imIn->bands == 1) {
|
||||
return ImagingCopy(imIn);
|
||||
}
|
||||
|
||||
/* Special case for LXXA etc */
|
||||
if (imIn->bands == 2 && band == 1) {
|
||||
band = 3;
|
||||
}
|
||||
|
||||
/* Allocate memory for result */
|
||||
imOut = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Extract band from image */
|
||||
int pixelsize = imIn->pixelsize;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8 *in = (UINT8 *)imIn->image[y] + band;
|
||||
UINT8 *out = imOut->image8[y];
|
||||
x = 0;
|
||||
/* Copy four values at a time */
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
UINT32 v = MAKE_UINT32(in[0], in[pixelsize], in[pixelsize * 2], in[pixelsize * 3]);
|
||||
memcpy(out + x, &v, sizeof(v));
|
||||
in += 16;
|
||||
in += pixelsize * 4;
|
||||
}
|
||||
/* Copy any remaining values on this line */
|
||||
for (; x < imIn->xsize; x++) {
|
||||
out[x] = *in;
|
||||
in += 4;
|
||||
in += pixelsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,8 +65,8 @@ ImagingGetBand(Imaging imIn, int band) {
|
|||
}
|
||||
|
||||
int
|
||||
ImagingSplit(Imaging imIn, Imaging bands[4]) {
|
||||
int i, j, x, y;
|
||||
ImagingSplit(Imaging imIn, Imaging *bands) {
|
||||
int i, j, band, x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
|
||||
|
@ -75,12 +74,13 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
/* Shortcut */
|
||||
if (imIn->bands == 1) {
|
||||
bands[0] = ImagingCopy(imIn);
|
||||
return imIn->bands;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate memory for "bands" */
|
||||
for (i = 0; i < imIn->bands; i++) {
|
||||
bands[i] = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
|
||||
if (!bands[i]) {
|
||||
|
@ -92,73 +92,22 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) {
|
|||
}
|
||||
|
||||
/* Extract bands from image */
|
||||
if (imIn->bands == 2) {
|
||||
int pixelsize = imIn->pixelsize;
|
||||
for (band = 0; band < imIn->bands; band++) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y] + band;
|
||||
UINT8 *out = bands[band]->image8[y];
|
||||
x = 0;
|
||||
/* Copy four values at a time */
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
memcpy(out0 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 3], in[4 + 3], in[8 + 3], in[12 + 3]);
|
||||
memcpy(out1 + x, &v, sizeof(v));
|
||||
in += 16;
|
||||
UINT32 v = MAKE_UINT32(in[0], in[pixelsize], in[pixelsize * 2], in[pixelsize * 3]);
|
||||
memcpy(out + x, &v, sizeof(v));
|
||||
in += pixelsize * 4;
|
||||
}
|
||||
/* Copy any remaining values on this line */
|
||||
for (; x < imIn->xsize; x++) {
|
||||
out0[x] = in[0];
|
||||
out1[x] = in[3];
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
} else if (imIn->bands == 3) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
UINT8 *out2 = bands[2]->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
memcpy(out0 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
|
||||
memcpy(out1 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 2], in[4 + 2], in[8 + 2], in[12 + 2]);
|
||||
memcpy(out2 + x, &v, sizeof(v));
|
||||
in += 16;
|
||||
}
|
||||
for (; x < imIn->xsize; x++) {
|
||||
out0[x] = in[0];
|
||||
out1[x] = in[1];
|
||||
out2[x] = in[2];
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
UINT8 *out2 = bands[2]->image8[y];
|
||||
UINT8 *out3 = bands[3]->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
memcpy(out0 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
|
||||
memcpy(out1 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 2], in[4 + 2], in[8 + 2], in[12 + 2]);
|
||||
memcpy(out2 + x, &v, sizeof(v));
|
||||
v = MAKE_UINT32(in[0 + 3], in[4 + 3], in[8 + 3], in[12 + 3]);
|
||||
memcpy(out3 + x, &v, sizeof(v));
|
||||
in += 16;
|
||||
}
|
||||
for (; x < imIn->xsize; x++) {
|
||||
out0[x] = in[0];
|
||||
out1[x] = in[1];
|
||||
out2[x] = in[2];
|
||||
out3[x] = in[3];
|
||||
in += 4;
|
||||
out[x] = *in;
|
||||
in += pixelsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,23 +133,19 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band) {
|
|||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
/* Shortcut */
|
||||
if (imOut->bands == 1) {
|
||||
return ImagingCopy2(imOut, imIn);
|
||||
}
|
||||
|
||||
/* Special case for LXXA etc */
|
||||
if (imOut->bands == 2 && band == 1) {
|
||||
band = 3;
|
||||
}
|
||||
|
||||
/* Insert band into image */
|
||||
int pixelsize = imOut->pixelsize;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8 *in = imIn->image8[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y] + band;
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
*out = in[x];
|
||||
out += 4;
|
||||
out += pixelsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,19 +165,15 @@ ImagingFillBand(Imaging imOut, int band, int color) {
|
|||
return (Imaging)ImagingError_ValueError("band index out of range");
|
||||
}
|
||||
|
||||
/* Special case for LXXA etc */
|
||||
if (imOut->bands == 2 && band == 1) {
|
||||
band = 3;
|
||||
}
|
||||
|
||||
color = CLIP8(color);
|
||||
|
||||
/* Insert color into image */
|
||||
int pixelsize = imOut->pixelsize;
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8 *out = (UINT8 *)imOut->image[y] + band;
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
*out = (UINT8)color;
|
||||
out += 4;
|
||||
out += pixelsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,73 +181,67 @@ ImagingFillBand(Imaging imOut, int band, int color) {
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingMerge(const char *mode, Imaging bands[4]) {
|
||||
ImagingMerge(const char *mode, Imaging *bands) {
|
||||
int i, x, y;
|
||||
int bandsCount = 0;
|
||||
int xsize, ysize;
|
||||
int bandsCount;
|
||||
Imaging imOut;
|
||||
Imaging firstBand;
|
||||
Imaging band;
|
||||
|
||||
/* Check the first band. The size of this band is used as the size of the output image. */
|
||||
firstBand = bands[0];
|
||||
if (!firstBand) {
|
||||
return (Imaging)ImagingError_ValueError("wrong number of bands");
|
||||
}
|
||||
xsize = firstBand->xsize;
|
||||
ysize = firstBand->ysize;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (!bands[i]) {
|
||||
break;
|
||||
}
|
||||
if (bands[i]->bands != 1) {
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
if (bands[i]->xsize != firstBand->xsize ||
|
||||
bands[i]->ysize != firstBand->ysize) {
|
||||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
}
|
||||
bandsCount = i;
|
||||
|
||||
imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize);
|
||||
/* Allocate memory for the output image. This also allows us to get the number of bands this image should have. */
|
||||
imOut = ImagingNewDirty(mode, xsize, ysize);
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check that the given bands have the right mode and size */
|
||||
for (bandsCount = 0; bandsCount < imOut->bands; ++bandsCount) {
|
||||
band = bands[bandsCount];
|
||||
if (!band) {
|
||||
break;
|
||||
}
|
||||
if (band->bands != 1) {
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
if (band->xsize != xsize || band->ysize != ysize) {
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that we have enough bands for the output image */
|
||||
if (imOut->bands != bandsCount) {
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging)ImagingError_ValueError("wrong number of bands");
|
||||
}
|
||||
|
||||
if (imOut->bands == 1) {
|
||||
/* TODO: Check that we weren't given too many bands? How? */
|
||||
|
||||
/* Shortcut */
|
||||
if (bandsCount == 1) {
|
||||
return ImagingCopy2(imOut, firstBand);
|
||||
}
|
||||
|
||||
if (imOut->bands == 2) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]);
|
||||
}
|
||||
}
|
||||
} else if (imOut->bands == 3) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT8 *in2 = bands[2]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0);
|
||||
}
|
||||
}
|
||||
} else if (imOut->bands == 4) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT8 *in2 = bands[2]->image8[y];
|
||||
UINT8 *in3 = bands[3]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]);
|
||||
/* Insert the bands into the image */
|
||||
int pixelsize = imOut->pixelsize;
|
||||
for (i = 0; i < bandsCount; i++) {
|
||||
band = bands[i];
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8 *in = band->image8[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y] + i;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = in[x];
|
||||
out += pixelsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,18 @@ round(double x) {
|
|||
static void
|
||||
bit2l(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++) *out++ = (*in++ != 0) ? 255 : 0;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out++ = (*in++ != 0) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bit2la(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out++ = (*in++ != 0) ? 255 : 0;
|
||||
*out++ = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -106,9 +117,9 @@ bit2hsv(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
}
|
||||
}
|
||||
|
||||
/* ----------------- */
|
||||
/* RGB/L conversions */
|
||||
/* ----------------- */
|
||||
/* ---------------- */
|
||||
/* L/LA conversions */
|
||||
/* ---------------- */
|
||||
|
||||
static void
|
||||
l2bit(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
|
@ -122,32 +133,28 @@ static void
|
|||
lA2la(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
unsigned int alpha, pixel, tmp;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
alpha = in[3];
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
alpha = in[1];
|
||||
pixel = MULDIV255(in[0], alpha, tmp);
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)alpha;
|
||||
}
|
||||
}
|
||||
|
||||
/* RGBa -> RGBA conversion to remove premultiplication
|
||||
Needed for correct transforms/resizing on RGBA images */
|
||||
/* La -> LA conversion to remove premultiplication
|
||||
Needed for correct transforms/resizing on LA images */
|
||||
static void
|
||||
la2lA(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
unsigned int alpha, pixel;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
alpha = in[3];
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
alpha = in[1];
|
||||
if (alpha == 255 || alpha == 0) {
|
||||
pixel = in[0];
|
||||
} else {
|
||||
pixel = CLIP8((255 * in[0]) / alpha);
|
||||
}
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)pixel;
|
||||
*out++ = (UINT8)alpha;
|
||||
}
|
||||
}
|
||||
|
@ -158,8 +165,6 @@ l2la(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
for (x = 0; x < xsize; x++) {
|
||||
UINT8 v = *in++;
|
||||
*out++ = v;
|
||||
*out++ = v;
|
||||
*out++ = v;
|
||||
*out++ = 255;
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +196,7 @@ l2hsv(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
la2l(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = in[0];
|
||||
}
|
||||
}
|
||||
|
@ -199,27 +204,46 @@ la2l(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
la2rgb(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
UINT8 v = in[0];
|
||||
*out++ = v;
|
||||
*out++ = v;
|
||||
*out++ = v;
|
||||
*out++ = in[3];
|
||||
*out++ = in[1];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
la2hsv(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||
UINT8 v = in[0];
|
||||
for (x = 0; x < xsize; x++, in += 2, out += 4) {
|
||||
out[0] = 0;
|
||||
out[1] = 0;
|
||||
out[2] = v;
|
||||
out[3] = in[3];
|
||||
out[2] = in[0];
|
||||
out[3] = in[1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conversion of LA + single transparent color to LA,
|
||||
* where any pixel that matches the color will have the
|
||||
* alpha channel set to 0
|
||||
*/
|
||||
|
||||
static void
|
||||
laT2la(UINT8 *out, int xsize, UINT8 l) {
|
||||
int i;
|
||||
for (i = 0; i < xsize; i++, out += 2) {
|
||||
if (out[0] == l) {
|
||||
out[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
/* RGB conversions */
|
||||
/* --------------- */
|
||||
|
||||
static void
|
||||
rgb2bit(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
|
@ -433,10 +457,10 @@ rgb2rgba(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
rgba2la(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 2) {
|
||||
/* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
|
||||
out[0] = out[1] = out[2] = L24(in) >> 16;
|
||||
out[3] = in[3];
|
||||
out[0] = L24(in) >> 16;
|
||||
out[1] = in[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,7 +555,7 @@ l2cmyk(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
la2cmyk(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = 0;
|
||||
*out++ = 0;
|
||||
*out++ = 0;
|
||||
|
@ -619,6 +643,23 @@ i2l(UINT8 *out, const UINT8 *in_, int xsize) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i2la(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
INT32 v;
|
||||
memcpy(&v, in, sizeof(v));
|
||||
if (v <= 0) {
|
||||
*out++ = 0;
|
||||
} else if (v >= 255) {
|
||||
*out++ = 255;
|
||||
} else {
|
||||
*out++ = (UINT8)v;
|
||||
}
|
||||
*out++ = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i2f(UINT8 *out_, const UINT8 *in_, int xsize) {
|
||||
int x;
|
||||
|
@ -735,7 +776,7 @@ l2ycbcr(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
la2ycbcr(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = in[0];
|
||||
*out++ = 128;
|
||||
*out++ = 128;
|
||||
|
@ -754,9 +795,9 @@ ycbcr2l(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
static void
|
||||
ycbcr2la(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||
out[0] = out[1] = out[2] = in[0];
|
||||
out[3] = 255;
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 2) {
|
||||
out[0] = in[0];
|
||||
out[1] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -873,6 +914,7 @@ static struct {
|
|||
} converters[] = {
|
||||
|
||||
{"1", "L", bit2l},
|
||||
{"1", "LA", bit2la},
|
||||
{"1", "I", bit2i},
|
||||
{"1", "F", bit2f},
|
||||
{"1", "RGB", bit2rgb},
|
||||
|
@ -905,6 +947,7 @@ static struct {
|
|||
{"La", "LA", la2lA},
|
||||
|
||||
{"I", "L", i2l},
|
||||
{"I", "LA", i2la},
|
||||
{"I", "F", i2f},
|
||||
{"I", "RGB", i2rgb},
|
||||
{"I", "RGBA", i2rgb},
|
||||
|
@ -982,7 +1025,8 @@ static struct {
|
|||
{"I;16L", "F", I16L_F},
|
||||
{"I;16B", "F", I16B_F},
|
||||
|
||||
{NULL}};
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/* FIXME: translate indexed versions to pointer versions below this line */
|
||||
|
||||
|
@ -1003,7 +1047,7 @@ static void
|
|||
pa2bit(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = (L(&palette->palette[in[0] * 4]) >= 128000) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -1021,11 +1065,43 @@ static void
|
|||
pa2l(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
p2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, out += 2) {
|
||||
const UINT8 *rgba = &palette->palette[*in++ * 4];
|
||||
out[0] = L24(rgba) >> 16;
|
||||
out[1] = rgba[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pa2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, in += 2, out += 2) {
|
||||
out[0] = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||
out[1] = in[1];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pa2p(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
UINT8 *rgba = &palette->palette[in[0] * 4];
|
||||
*out++ = in[0];
|
||||
rgba[3] = in[1];
|
||||
}
|
||||
strncpy(palette->mode, "RGBA", IMAGING_MODE_LENGTH - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
p2pa(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
|
@ -1033,33 +1109,10 @@ p2pa(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
|||
for (x = 0; x < xsize; x++, in++) {
|
||||
const UINT8 *rgba = &palette->palette[in[0] * 4];
|
||||
*out++ = in[0];
|
||||
*out++ = in[0];
|
||||
*out++ = in[0];
|
||||
*out++ = rgb == 0 ? 255 : rgba[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
p2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, out += 4) {
|
||||
const UINT8 *rgba = &palette->palette[*in++ * 4];
|
||||
out[0] = out[1] = out[2] = L24(rgba) >> 16;
|
||||
out[3] = rgba[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pa2la(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
/* FIXME: precalculate greyscale palette? */
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||
out[0] = out[1] = out[2] = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||
out[3] = in[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
p2i(UINT8 *out_, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
|
@ -1073,7 +1126,7 @@ static void
|
|||
pa2i(UINT8 *out_, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
INT32 *out = (INT32 *)out_;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = L24(&palette->palette[in[0] * 4]) >> 16;
|
||||
}
|
||||
}
|
||||
|
@ -1091,7 +1144,7 @@ static void
|
|||
pa2f(UINT8 *out_, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
FLOAT32 *out = (FLOAT32 *)out_;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
*out++ = (float)L(&palette->palette[in[0] * 4]) / 1000.0F;
|
||||
}
|
||||
}
|
||||
|
@ -1111,7 +1164,7 @@ p2rgb(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
|||
static void
|
||||
pa2rgb(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
const UINT8 *rgb = &palette->palette[in[0] * 4];
|
||||
*out++ = rgb[0];
|
||||
*out++ = rgb[1];
|
||||
|
@ -1133,7 +1186,7 @@ p2hsv(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
|||
static void
|
||||
pa2hsv(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2, out += 4) {
|
||||
const UINT8 *rgb = &palette->palette[in[0] * 4];
|
||||
rgb2hsv_row(out, rgb);
|
||||
out[3] = 255;
|
||||
|
@ -1155,25 +1208,39 @@ p2rgba(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
|||
static void
|
||||
pa2rgba(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
const UINT8 *rgb = &palette->palette[in[0] * 4];
|
||||
*out++ = rgb[0];
|
||||
*out++ = rgb[1];
|
||||
*out++ = rgb[2];
|
||||
*out++ = in[3];
|
||||
*out++ = in[1];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
p2cmyk(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
p2rgb(out, in, xsize, palette);
|
||||
rgb2cmyk(out, out, xsize);
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
/* Note: no undercolour removal */
|
||||
const UINT8 *rgb = &palette->palette[*in++ * 4];
|
||||
*out++ = ~rgb[0];
|
||||
*out++ = ~rgb[1];
|
||||
*out++ = ~rgb[2];
|
||||
*out++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pa2cmyk(UINT8 *out, const UINT8 *in, int xsize, ImagingPalette palette) {
|
||||
pa2rgb(out, in, xsize, palette);
|
||||
rgb2cmyk(out, out, xsize);
|
||||
int x;
|
||||
for (x = 0; x < xsize; x++, in += 2) {
|
||||
/* Note: no undercolour removal */
|
||||
const UINT8 *rgb = &palette->palette[in[0] * 4];
|
||||
*out++ = ~rgb[0];
|
||||
*out++ = ~rgb[1];
|
||||
*out++ = ~rgb[2];
|
||||
*out++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1195,7 +1262,7 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode) {
|
|||
int y;
|
||||
void (*convert)(UINT8 *, const UINT8 *, int, ImagingPalette);
|
||||
|
||||
/* Map palette image to L, RGB, RGBA, or CMYK */
|
||||
/* Map palette image to bit, L, LA, P, PA, I, F, RGB, RGBA, RGBX, CMYK, YCbCr, or HSV */
|
||||
|
||||
if (!imIn->palette) {
|
||||
return (Imaging)ImagingError_ValueError("no palette");
|
||||
|
@ -1209,7 +1276,15 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode) {
|
|||
convert = alpha ? pa2l : p2l;
|
||||
} else if (strcmp(mode, "LA") == 0) {
|
||||
convert = alpha ? pa2la : p2la;
|
||||
} else if (strcmp(mode, "P") == 0) {
|
||||
if (!alpha) {
|
||||
return ImagingCopy2(imOut, imIn);
|
||||
}
|
||||
convert = pa2p;
|
||||
} else if (strcmp(mode, "PA") == 0) {
|
||||
if (alpha) {
|
||||
return ImagingCopy2(imOut, imIn);
|
||||
}
|
||||
convert = p2pa;
|
||||
} else if (strcmp(mode, "I") == 0) {
|
||||
convert = alpha ? pa2i : p2i;
|
||||
|
@ -1261,7 +1336,6 @@ topalette(
|
|||
int alpha;
|
||||
int x, y;
|
||||
ImagingPalette palette = inpalette;
|
||||
;
|
||||
|
||||
/* Map L or RGB/RGBX/RGBA to palette image */
|
||||
if (strcmp(imIn->mode, "L") != 0 && strncmp(imIn->mode, "RGB", 3) != 0) {
|
||||
|
@ -1307,7 +1381,6 @@ topalette(
|
|||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else {
|
||||
/* colour image */
|
||||
|
||||
|
@ -1337,7 +1410,7 @@ topalette(
|
|||
int g, g0, g1, g2;
|
||||
int b, b0, b1, b2;
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out = alpha ? (UINT8 *)imOut->image32[y] : imOut->image8[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
int *e = errors;
|
||||
|
||||
r = r0 = r1 = 0;
|
||||
|
@ -1358,8 +1431,8 @@ topalette(
|
|||
ImagingPaletteCacheUpdate(palette, r, g, b);
|
||||
}
|
||||
if (alpha) {
|
||||
out[x * 4] = out[x * 4 + 1] = out[x * 4 + 2] = (UINT8)cache[0];
|
||||
out[x * 4 + 3] = 255;
|
||||
out[x * 2] = (UINT8)cache[0];
|
||||
out[x * 2 + 1] = 255;
|
||||
} else {
|
||||
out[x] = (UINT8)cache[0];
|
||||
}
|
||||
|
@ -1403,14 +1476,13 @@ topalette(
|
|||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
free(errors);
|
||||
|
||||
} else {
|
||||
/* closest colour */
|
||||
ImagingSectionEnter(&cookie);
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
int r, g, b;
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out = alpha ? (UINT8 *)imOut->image32[y] : imOut->image8[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
for (x = 0; x < imIn->xsize; x++, in += 4) {
|
||||
INT16 *cache;
|
||||
|
@ -1425,8 +1497,8 @@ topalette(
|
|||
ImagingPaletteCacheUpdate(palette, r, g, b);
|
||||
}
|
||||
if (alpha) {
|
||||
out[x * 4] = out[x * 4 + 1] = out[x * 4 + 2] = (UINT8)cache[0];
|
||||
out[x * 4 + 3] = 255;
|
||||
out[x * 2] = (UINT8)cache[0];
|
||||
out[x * 2 + 1] = 255;
|
||||
} else {
|
||||
out[x] = (UINT8)cache[0];
|
||||
}
|
||||
|
@ -1634,21 +1706,22 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
|
|||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (strcmp(imIn->mode, "RGB") == 0 && strcmp(mode, "RGBA") == 0) {
|
||||
int rgbIn = strcmp(mode, "rgb") == 0;
|
||||
int bitIn = strcmp(mode, "1") == 0;
|
||||
int iIn = strcmp(mode, "I") == 0;
|
||||
int lIn = strcmp(mode, "L") == 0;
|
||||
int rgbaOut = strcmp(mode, "RGBA") == 0;
|
||||
int laOut = strcmp(mode, "LA") == 0;
|
||||
|
||||
if (rgbIn && rgbaOut) {
|
||||
convert = rgb2rgba;
|
||||
} else if ((strcmp(imIn->mode, "1") == 0 ||
|
||||
strcmp(imIn->mode, "I") == 0 ||
|
||||
strcmp(imIn->mode, "L") == 0
|
||||
) && (
|
||||
strcmp(mode, "RGBA") == 0 ||
|
||||
strcmp(mode, "LA") == 0
|
||||
)) {
|
||||
if (strcmp(imIn->mode, "1") == 0) {
|
||||
convert = bit2rgb;
|
||||
} else if (strcmp(imIn->mode, "I") == 0) {
|
||||
convert = i2rgb;
|
||||
} else if ((bitIn || iIn || lIn) && (rgbaOut || laOut)) {
|
||||
if (bitIn) {
|
||||
convert = rgbaOut ? bit2rgb : bit2la;
|
||||
} else if (iIn) {
|
||||
convert = rgbaOut ? i2rgb : i2la;
|
||||
} else {
|
||||
convert = l2rgb;
|
||||
convert = rgbaOut ? l2rgb : l2la;
|
||||
}
|
||||
g = b = r;
|
||||
} else {
|
||||
|
@ -1668,10 +1741,17 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
|
|||
}
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
if (rgbaOut) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
(*convert)((UINT8 *)imOut->image[y], (UINT8 *)imIn->image[y], imIn->xsize);
|
||||
rgbT2rgba((UINT8 *)imOut->image[y], imIn->xsize, r, g, b);
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
(*convert)((UINT8 *)imOut->image[y], (UINT8 *)imIn->image[y], imIn->xsize);
|
||||
laT2la((UINT8 *)imOut->image[y], imIn->xsize, r);
|
||||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
return imOut;
|
||||
|
|
|
@ -442,35 +442,13 @@ quad_transform(double *xout, double *yout, int x, int y, void *data) {
|
|||
/* transform filters (ImagingTransformFilter) */
|
||||
|
||||
static int
|
||||
nearest_filter8(void *out, Imaging im, double xin, double yin) {
|
||||
nearest_filter(void *out, Imaging im, double xin, double yin) {
|
||||
int x = COORD(xin);
|
||||
int y = COORD(yin);
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
return 0;
|
||||
}
|
||||
((UINT8 *)out)[0] = im->image8[y][x];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nearest_filter16(void *out, Imaging im, double xin, double yin) {
|
||||
int x = COORD(xin);
|
||||
int y = COORD(yin);
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, im->image8[y] + x * sizeof(INT16), sizeof(INT16));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nearest_filter32(void *out, Imaging im, double xin, double yin) {
|
||||
int x = COORD(xin);
|
||||
int y = COORD(yin);
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, &im->image32[y][x], sizeof(INT32));
|
||||
memcpy(out, (UINT8 *)im->image[y] + x * im->pixelsize, im->pixelsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -512,9 +490,12 @@ nearest_filter32(void *out, Imaging im, double xin, double yin) {
|
|||
|
||||
static int
|
||||
bilinear_filter8(void *out, Imaging im, double xin, double yin) {
|
||||
int b, pixelsize = im->pixelsize;
|
||||
BILINEAR_HEAD(UINT8);
|
||||
BILINEAR_BODY(UINT8, im->image8, 1, 0);
|
||||
((UINT8 *)out)[0] = (UINT8)v1;
|
||||
for (b = 0; b < im->bands; b++) {
|
||||
BILINEAR_BODY(UINT8, im->image, pixelsize, b);
|
||||
((UINT8 *)out)[b] = (UINT8)v1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -538,29 +519,6 @@ bilinear_filter32F(void *out, Imaging im, double xin, double yin) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bilinear_filter32LA(void *out, Imaging im, double xin, double yin) {
|
||||
BILINEAR_HEAD(UINT8);
|
||||
BILINEAR_BODY(UINT8, im->image, 4, 0);
|
||||
((UINT8 *)out)[0] = (UINT8)v1;
|
||||
((UINT8 *)out)[1] = (UINT8)v1;
|
||||
((UINT8 *)out)[2] = (UINT8)v1;
|
||||
BILINEAR_BODY(UINT8, im->image, 4, 3);
|
||||
((UINT8 *)out)[3] = (UINT8)v1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bilinear_filter32RGB(void *out, Imaging im, double xin, double yin) {
|
||||
int b;
|
||||
BILINEAR_HEAD(UINT8);
|
||||
for (b = 0; b < im->bands; b++) {
|
||||
BILINEAR_BODY(UINT8, im->image, 4, b);
|
||||
((UINT8 *)out)[b] = (UINT8)v1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef BILINEAR
|
||||
#undef BILINEAR_HEAD
|
||||
#undef BILINEAR_BODY
|
||||
|
@ -624,14 +582,17 @@ bilinear_filter32RGB(void *out, Imaging im, double xin, double yin) {
|
|||
|
||||
static int
|
||||
bicubic_filter8(void *out, Imaging im, double xin, double yin) {
|
||||
int b, pixelsize = im->pixelsize;
|
||||
BICUBIC_HEAD(UINT8);
|
||||
BICUBIC_BODY(UINT8, im->image8, 1, 0);
|
||||
for (b = 0; b < im->bands; b++) {
|
||||
BICUBIC_BODY(UINT8, im->image, pixelsize, b);
|
||||
if (v1 <= 0.0) {
|
||||
((UINT8 *)out)[0] = 0;
|
||||
((UINT8 *)out)[b] = 0;
|
||||
} else if (v1 >= 255.0) {
|
||||
((UINT8 *)out)[0] = 255;
|
||||
((UINT8 *)out)[b] = 255;
|
||||
} else {
|
||||
((UINT8 *)out)[0] = (UINT8)v1;
|
||||
((UINT8 *)out)[b] = (UINT8)v1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -656,51 +617,6 @@ bicubic_filter32F(void *out, Imaging im, double xin, double yin) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bicubic_filter32LA(void *out, Imaging im, double xin, double yin) {
|
||||
BICUBIC_HEAD(UINT8);
|
||||
BICUBIC_BODY(UINT8, im->image, 4, 0);
|
||||
if (v1 <= 0.0) {
|
||||
((UINT8 *)out)[0] = 0;
|
||||
((UINT8 *)out)[1] = 0;
|
||||
((UINT8 *)out)[2] = 0;
|
||||
} else if (v1 >= 255.0) {
|
||||
((UINT8 *)out)[0] = 255;
|
||||
((UINT8 *)out)[1] = 255;
|
||||
((UINT8 *)out)[2] = 255;
|
||||
} else {
|
||||
((UINT8 *)out)[0] = (UINT8)v1;
|
||||
((UINT8 *)out)[1] = (UINT8)v1;
|
||||
((UINT8 *)out)[2] = (UINT8)v1;
|
||||
}
|
||||
BICUBIC_BODY(UINT8, im->image, 4, 3);
|
||||
if (v1 <= 0.0) {
|
||||
((UINT8 *)out)[3] = 0;
|
||||
} else if (v1 >= 255.0) {
|
||||
((UINT8 *)out)[3] = 255;
|
||||
} else {
|
||||
((UINT8 *)out)[3] = (UINT8)v1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bicubic_filter32RGB(void *out, Imaging im, double xin, double yin) {
|
||||
int b;
|
||||
BICUBIC_HEAD(UINT8);
|
||||
for (b = 0; b < im->bands; b++) {
|
||||
BICUBIC_BODY(UINT8, im->image, 4, b);
|
||||
if (v1 <= 0.0) {
|
||||
((UINT8 *)out)[b] = 0;
|
||||
} else if (v1 >= 255.0) {
|
||||
((UINT8 *)out)[b] = 255;
|
||||
} else {
|
||||
((UINT8 *)out)[b] = (UINT8)v1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef BICUBIC
|
||||
#undef BICUBIC_HEAD
|
||||
#undef BICUBIC_BODY
|
||||
|
@ -709,59 +625,26 @@ static ImagingTransformFilter
|
|||
getfilter(Imaging im, int filterid) {
|
||||
switch (filterid) {
|
||||
case IMAGING_TRANSFORM_NEAREST:
|
||||
if (im->image8) {
|
||||
switch (im->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
return nearest_filter8;
|
||||
case IMAGING_TYPE_SPECIAL:
|
||||
switch (im->pixelsize) {
|
||||
case 1:
|
||||
return nearest_filter8;
|
||||
case 2:
|
||||
return nearest_filter16;
|
||||
case 4:
|
||||
return nearest_filter32;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nearest_filter32;
|
||||
}
|
||||
break;
|
||||
return nearest_filter;
|
||||
case IMAGING_TRANSFORM_BILINEAR:
|
||||
if (im->image8) {
|
||||
return bilinear_filter8;
|
||||
} else if (im->image32) {
|
||||
switch (im->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
if (im->bands == 2) {
|
||||
return bilinear_filter32LA;
|
||||
} else {
|
||||
return bilinear_filter32RGB;
|
||||
}
|
||||
return bilinear_filter8;
|
||||
case IMAGING_TYPE_INT32:
|
||||
return bilinear_filter32I;
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
return bilinear_filter32F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IMAGING_TRANSFORM_BICUBIC:
|
||||
if (im->image8) {
|
||||
return bicubic_filter8;
|
||||
} else if (im->image32) {
|
||||
switch (im->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
if (im->bands == 2) {
|
||||
return bicubic_filter32LA;
|
||||
} else {
|
||||
return bicubic_filter32RGB;
|
||||
}
|
||||
return bicubic_filter8;
|
||||
case IMAGING_TYPE_INT32:
|
||||
return bicubic_filter32I;
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
return bicubic_filter32F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* no such filter */
|
||||
|
@ -786,7 +669,7 @@ ImagingGenericTransform(
|
|||
ImagingScaleAffine where possible. */
|
||||
|
||||
ImagingSectionCookie cookie;
|
||||
int x, y;
|
||||
int x, y, pixelsize;
|
||||
char *out;
|
||||
double xx, yy;
|
||||
|
||||
|
@ -816,16 +699,17 @@ ImagingGenericTransform(
|
|||
y1 = imOut->ysize;
|
||||
}
|
||||
|
||||
pixelsize = imOut->pixelsize;
|
||||
for (y = y0; y < y1; y++) {
|
||||
out = imOut->image[y] + x0 * imOut->pixelsize;
|
||||
out = imOut->image[y] + x0 * pixelsize;
|
||||
for (x = x0; x < x1; x++) {
|
||||
if (!transform(&xx, &yy, x - x0, y - y0, transform_data) ||
|
||||
!filter(out, imIn, xx, yy)) {
|
||||
if (fill) {
|
||||
memset(out, 0, imOut->pixelsize);
|
||||
memset(out, 0, pixelsize);
|
||||
}
|
||||
}
|
||||
out += imOut->pixelsize;
|
||||
out += pixelsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ ImagingGetBBox(Imaging im, int bbox[4]) {
|
|||
bbox[1] = -1;
|
||||
bbox[2] = bbox[3] = 0;
|
||||
|
||||
#define GETBBOX(image, mask) \
|
||||
#define GETBBOX(type) \
|
||||
for (y = 0; y < im->ysize; y++) { \
|
||||
has_data = 0; \
|
||||
for (x = 0; x < im->xsize; x++) { \
|
||||
if (im->image[y][x] & mask) { \
|
||||
if (((type *)im->image[y])[x] & mask) { \
|
||||
has_data = 1; \
|
||||
if (x < bbox[0]) { \
|
||||
bbox[0] = x; \
|
||||
|
@ -52,23 +52,35 @@ ImagingGetBBox(Imaging im, int bbox[4]) {
|
|||
} \
|
||||
}
|
||||
|
||||
if (im->image8) {
|
||||
GETBBOX(image8, 0xff);
|
||||
} else {
|
||||
INT32 mask = 0xffffffff;
|
||||
switch (im->pixelsize) {
|
||||
case 1: {
|
||||
UINT8 mask = 0xff;
|
||||
GETBBOX(UINT8);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
UINT16 mask = 0xffff;
|
||||
if (strcmp(im->mode, "La") == 0 ||
|
||||
strcmp(im->mode, "LA") == 0 ||
|
||||
strcmp(im->mode, "PA") == 0) {
|
||||
((UINT8 *)&mask)[0] = 0;
|
||||
}
|
||||
GETBBOX(UINT16);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
UINT32 mask = 0xffffffff;
|
||||
if (im->bands == 3) {
|
||||
((UINT8 *)&mask)[3] = 0;
|
||||
} else if (
|
||||
strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 ||
|
||||
strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 ||
|
||||
strcmp(im->mode, "PA") == 0) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
mask = 0x000000ff;
|
||||
#else
|
||||
mask = 0xff000000;
|
||||
#endif
|
||||
strcmp(im->mode, "RGBa") == 0 ||
|
||||
strcmp(im->mode, "RGBA") == 0) {
|
||||
mask = 0;
|
||||
((UINT8 *)&mask)[3] = 0xff;
|
||||
}
|
||||
GETBBOX(UINT32);
|
||||
break;
|
||||
}
|
||||
GETBBOX(image32, mask);
|
||||
}
|
||||
|
||||
/* Check that we got a box */
|
||||
|
@ -90,11 +102,11 @@ ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj) {
|
|||
memset(xproj, 0, im->xsize);
|
||||
memset(yproj, 0, im->ysize);
|
||||
|
||||
#define GETPROJ(image, mask) \
|
||||
#define GETPROJ(type) \
|
||||
for (y = 0; y < im->ysize; y++) { \
|
||||
has_data = 0; \
|
||||
for (x = 0; x < im->xsize; x++) { \
|
||||
if (im->image[y][x] & mask) { \
|
||||
if (((type *)im->image[y])[x] & mask) { \
|
||||
has_data = 1; \
|
||||
xproj[x] = 1; \
|
||||
} \
|
||||
|
@ -104,14 +116,25 @@ ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj) {
|
|||
} \
|
||||
}
|
||||
|
||||
if (im->image8) {
|
||||
GETPROJ(image8, 0xff);
|
||||
} else {
|
||||
INT32 mask = 0xffffffff;
|
||||
switch (im->pixelsize) {
|
||||
case 1: {
|
||||
UINT8 mask = 0xff;
|
||||
GETPROJ(UINT8);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
UINT16 mask = 0xffff;
|
||||
GETPROJ(UINT16);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
UINT32 mask = 0xffffffff;
|
||||
if (im->bands == 3) {
|
||||
((UINT8 *)&mask)[3] = 0;
|
||||
}
|
||||
GETPROJ(image32, mask);
|
||||
GETPROJ(UINT32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1; /* ok */
|
||||
|
|
|
@ -39,8 +39,8 @@ extern "C" {
|
|||
* Lab 4 L, a, b, -
|
||||
*
|
||||
* experimental modes (incomplete):
|
||||
* LA 4 L, -, -, A
|
||||
* PA 4 P, -, -, A
|
||||
* LA 2 L, A
|
||||
* PA 2 P, A
|
||||
* I;16 2 I (16-bit integer, native byte order)
|
||||
*
|
||||
* "P" is an 8-bit palette mode, which should be mapped through the
|
||||
|
@ -69,6 +69,7 @@ typedef struct ImagingPaletteInstance *ImagingPalette;
|
|||
#define IMAGING_TYPE_FLOAT32 2
|
||||
#define IMAGING_TYPE_SPECIAL 3 /* check mode for details */
|
||||
|
||||
/* array size required to store any image mode string */
|
||||
#define IMAGING_MODE_LENGTH \
|
||||
6 + 1 /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
|
||||
|
||||
|
@ -108,9 +109,9 @@ struct ImagingMemoryInstance {
|
|||
|
||||
#define IMAGING_PIXEL_1(im, x, y) ((im)->image8[(y)][(x)])
|
||||
#define IMAGING_PIXEL_L(im, x, y) ((im)->image8[(y)][(x)])
|
||||
#define IMAGING_PIXEL_LA(im, x, y) ((im)->image[(y)][(x)*4])
|
||||
#define IMAGING_PIXEL_LA(im, x, y) ((im)->image[(y)][(x)*2])
|
||||
#define IMAGING_PIXEL_P(im, x, y) ((im)->image8[(y)][(x)])
|
||||
#define IMAGING_PIXEL_PA(im, x, y) ((im)->image[(y)][(x)*4])
|
||||
#define IMAGING_PIXEL_PA(im, x, y) ((im)->image[(y)][(x)*2])
|
||||
#define IMAGING_PIXEL_I(im, x, y) ((im)->image32[(y)][(x)])
|
||||
#define IMAGING_PIXEL_F(im, x, y) (((FLOAT32 *)(im)->image32[y])[x])
|
||||
#define IMAGING_PIXEL_RGB(im, x, y) ((im)->image[(y)][(x)*4])
|
||||
|
|
|
@ -302,6 +302,85 @@ j2ku_graya_la(
|
|||
|
||||
atiledata = tiledata + csiz * w * h;
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[csiz * y * w];
|
||||
const UINT8 *adata = &atiledata[acsiz * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 2;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT32 word = 0, aword = 0, byte;
|
||||
|
||||
switch (csiz) {
|
||||
case 1:
|
||||
word = *data++;
|
||||
break;
|
||||
case 2:
|
||||
word = *(const UINT16 *)data;
|
||||
data += 2;
|
||||
break;
|
||||
case 4:
|
||||
word = *(const UINT32 *)data;
|
||||
data += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (acsiz) {
|
||||
case 1:
|
||||
aword = *adata++;
|
||||
break;
|
||||
case 2:
|
||||
aword = *(const UINT16 *)adata;
|
||||
adata += 2;
|
||||
break;
|
||||
case 4:
|
||||
aword = *(const UINT32 *)adata;
|
||||
adata += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
byte = j2ku_shift(offset + word, shift);
|
||||
row[0] = byte;
|
||||
row[1] = j2ku_shift(aoffset + aword, ashift);
|
||||
row += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
j2ku_graya_rgba(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
||||
int shift = 8 - in->comps[0].prec;
|
||||
int offset = in->comps[0].sgnd ? 1 << (in->comps[0].prec - 1) : 0;
|
||||
int csiz = (in->comps[0].prec + 7) >> 3;
|
||||
int ashift = 8 - in->comps[1].prec;
|
||||
int aoffset = in->comps[1].sgnd ? 1 << (in->comps[1].prec - 1) : 0;
|
||||
int acsiz = (in->comps[1].prec + 7) >> 3;
|
||||
const UINT8 *atiledata;
|
||||
|
||||
unsigned x, y;
|
||||
|
||||
if (csiz == 3) {
|
||||
csiz = 4;
|
||||
}
|
||||
if (acsiz == 3) {
|
||||
acsiz = 4;
|
||||
}
|
||||
|
||||
if (shift < 0) {
|
||||
offset += 1 << (-shift - 1);
|
||||
}
|
||||
if (ashift < 0) {
|
||||
aoffset += 1 << (-ashift - 1);
|
||||
}
|
||||
|
||||
atiledata = tiledata + csiz * w * h;
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[csiz * y * w];
|
||||
const UINT8 *adata = &atiledata[acsiz * y * w];
|
||||
|
@ -625,7 +704,7 @@ static const struct j2k_decode_unpacker j2k_unpackers[] = {
|
|||
{"RGB", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgb_rgb},
|
||||
{"RGB", OPJ_CLRSPC_SYCC, 4, 1, j2ku_sycc_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_la},
|
||||
{"RGBA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_rgba},
|
||||
{"RGBA", OPJ_CLRSPC_SRGB, 3, 1, j2ku_srgb_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_SYCC, 3, 1, j2ku_sycc_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgba_rgba},
|
||||
|
|
|
@ -129,11 +129,11 @@ j2k_pack_la(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsign
|
|||
UINT8 *ptra = buf + w * h;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + 2 * x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
*ptr++ = data[0];
|
||||
*ptra++ = data[3];
|
||||
data += 4;
|
||||
*ptra++ = data[1];
|
||||
data += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,26 +231,14 @@ packL16B(UINT8 *out, const UINT8 *in, int pixels) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packLA(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LA, pixel interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[0] = in[R];
|
||||
out[1] = in[A];
|
||||
out += 2;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packLAL(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LA, line interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[i] = in[R];
|
||||
out[i + pixels] = in[A];
|
||||
in += 4;
|
||||
out[i] = in[0];
|
||||
out[i + pixels] = in[1];
|
||||
in += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,6 +423,7 @@ packI16N_I16B(UINT8 *out, const UINT8 *in, int pixels) {
|
|||
tmp += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packI16N_I16(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
|
@ -555,11 +544,11 @@ static struct {
|
|||
{"L", "L;16B", 16, packL16B},
|
||||
|
||||
/* greyscale w. alpha */
|
||||
{"LA", "LA", 16, packLA},
|
||||
{"LA", "LA", 16, copy2},
|
||||
{"LA", "LA;L", 16, packLAL},
|
||||
|
||||
/* greyscale w. alpha premultiplied */
|
||||
{"La", "La", 16, packLA},
|
||||
{"La", "La", 16, copy2},
|
||||
|
||||
/* palette */
|
||||
{"P", "P;1", 1, pack1},
|
||||
|
@ -568,7 +557,7 @@ static struct {
|
|||
{"P", "P", 8, copy1},
|
||||
|
||||
/* palette w. alpha */
|
||||
{"PA", "PA", 16, packLA},
|
||||
{"PA", "PA", 16, copy2},
|
||||
{"PA", "PA;L", 16, packLAL},
|
||||
|
||||
/* true colour */
|
||||
|
|
|
@ -139,6 +139,53 @@ paste_mask_L(
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
paste_mask_LA(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste with mode "LA" matte */
|
||||
|
||||
int x, y;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *in = imIn->image8[y + sy] + sx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 2 + 1;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, *in, tmp1);
|
||||
out++, in++, mask += 2;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
|
||||
UINT8 *in = (UINT8 *)imIn->image[y + sy] + sx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 2;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
UINT8 a = mask[1];
|
||||
out[0] = BLEND(a, out[0], in[0], tmp1);
|
||||
out[1] = BLEND(a, out[1], in[1], tmp1);
|
||||
out[2] = BLEND(a, out[2], in[2], tmp1);
|
||||
out[3] = BLEND(a, out[3], in[3], tmp1);
|
||||
out += 4;
|
||||
in += 4;
|
||||
mask += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
paste_mask_RGBA(
|
||||
Imaging imOut,
|
||||
|
@ -295,7 +342,12 @@ ImagingPaste(
|
|||
paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "LA") == 0 || strcmp(imMask->mode, "RGBA") == 0) {
|
||||
} else if (strcmp(imMask->mode, "LA") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_LA(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "RGBA") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_RGBA(
|
||||
imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
|
@ -414,47 +466,37 @@ fill_mask_L(
|
|||
int x, y, i;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
if (strncmp(imOut->mode, "I;16", 4) == 0) {
|
||||
out += dx;
|
||||
}
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
if (strncmp(imOut->mode, "I;16", 4) == 0) {
|
||||
out++;
|
||||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
}
|
||||
out++, mask++;
|
||||
}
|
||||
const int isI16 = strncmp(imOut->mode, "I;16", 4) == 0;
|
||||
const int isRGBA = strcmp(imOut->mode, "RGBa") == 0 || strcmp(imOut->mode, "RGBA") == 0;
|
||||
const int isXA = strcmp(imOut->mode, "La") == 0 || strcmp(imOut->mode, "LA") == 0 || strcmp(imOut->mode, "PA") == 0;
|
||||
|
||||
int alphaChannel = -1;
|
||||
if (isRGBA) {
|
||||
alphaChannel = 3;
|
||||
} else if (isXA) {
|
||||
alphaChannel = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
for (i = 0; i < pixelsize; i++) {
|
||||
UINT8 channel_mask = *mask;
|
||||
if ((strcmp(imOut->mode, "RGBa") == 0 ||
|
||||
strcmp(imOut->mode, "RGBA") == 0 ||
|
||||
strcmp(imOut->mode, "La") == 0 ||
|
||||
strcmp(imOut->mode, "LA") == 0 ||
|
||||
strcmp(imOut->mode, "PA") == 0) &&
|
||||
i != 3 && channel_mask != 0) {
|
||||
channel_mask =
|
||||
255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255);
|
||||
if (alphaChannel >= 0 && i != alphaChannel && channel_mask != 0) {
|
||||
channel_mask = 255 - (255 - channel_mask) *
|
||||
(1 - (255 - out[alphaChannel]) / 255);
|
||||
}
|
||||
out[i] = BLEND(channel_mask, out[i], ink[i], tmp1);
|
||||
// The I;16 modes use the same "ink" for both bytes because its single
|
||||
// channel is two bytes wide.
|
||||
// TODO: Should BGR, F, and I modes do this too? Something more generic?
|
||||
out[i] = BLEND(channel_mask, out[i], isI16 ? ink[0] : ink[i], tmp1);
|
||||
}
|
||||
out += pixelsize;
|
||||
mask++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
fill_mask_RGBA(
|
||||
|
|
|
@ -76,9 +76,8 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
|||
|
||||
} else if (strcmp(mode, "PA") == 0) {
|
||||
/* 8-bit palette with alpha */
|
||||
im->bands = 2;
|
||||
im->pixelsize = 4; /* store in image32 memory */
|
||||
im->linesize = xsize * 4;
|
||||
im->bands = im->pixelsize = 2;
|
||||
im->linesize = xsize * 2;
|
||||
im->palette = ImagingPaletteNew("RGB");
|
||||
|
||||
} else if (strcmp(mode, "L") == 0) {
|
||||
|
@ -88,15 +87,13 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
|||
|
||||
} else if (strcmp(mode, "LA") == 0) {
|
||||
/* 8-bit greyscale (luminance) with alpha */
|
||||
im->bands = 2;
|
||||
im->pixelsize = 4; /* store in image32 memory */
|
||||
im->linesize = xsize * 4;
|
||||
im->bands = im->pixelsize = 2;
|
||||
im->linesize = xsize * 2;
|
||||
|
||||
} else if (strcmp(mode, "La") == 0) {
|
||||
/* 8-bit greyscale (luminance) with premultiplied alpha */
|
||||
im->bands = 2;
|
||||
im->pixelsize = 4; /* store in image32 memory */
|
||||
im->linesize = xsize * 4;
|
||||
im->bands = im->pixelsize = 2;
|
||||
im->linesize = xsize * 2;
|
||||
|
||||
} else if (strcmp(mode, "F") == 0) {
|
||||
/* 32-bit floating point images */
|
||||
|
|
|
@ -413,24 +413,13 @@ unpackL4IR(UINT8 *out, const UINT8 *in, int pixels) {
|
|||
}
|
||||
|
||||
static void
|
||||
unpackLA(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LA, pixel interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[1]);
|
||||
memcpy(_out, &iv, sizeof(iv));
|
||||
in += 2;
|
||||
_out += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpackLAL(UINT8 *_out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
unpackLAL(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
UINT8 *in1 = in;
|
||||
UINT8 *in2 = in + pixels;
|
||||
/* LA, line interleaved */
|
||||
for (i = 0; i < pixels; i++, _out += 4) {
|
||||
UINT32 iv = MAKE_UINT32(in[i], in[i], in[i], in[i + pixels]);
|
||||
memcpy(_out, &iv, sizeof(iv));
|
||||
for (int i = 0; i < pixels; ++i) {
|
||||
*out++ = *in1++;
|
||||
*out++ = *in2++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1528,11 +1517,11 @@ static struct {
|
|||
{"L", "L;16B", 16, unpackL16B},
|
||||
|
||||
/* greyscale w. alpha */
|
||||
{"LA", "LA", 16, unpackLA},
|
||||
{"LA", "LA", 16, copy2},
|
||||
{"LA", "LA;L", 16, unpackLAL},
|
||||
|
||||
/* greyscale w. alpha premultiplied */
|
||||
{"La", "La", 16, unpackLA},
|
||||
{"La", "La", 16, copy2},
|
||||
|
||||
/* palette */
|
||||
{"P", "P;1", 1, unpackP1},
|
||||
|
@ -1544,7 +1533,7 @@ static struct {
|
|||
{"P", "P;R", 8, unpackLR},
|
||||
|
||||
/* palette w. alpha */
|
||||
{"PA", "PA", 16, unpackLA},
|
||||
{"PA", "PA", 16, copy2},
|
||||
{"PA", "PA;L", 16, unpackLAL},
|
||||
|
||||
/* true colour */
|
||||
|
|
Loading…
Reference in New Issue
Block a user