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