diff options
Diffstat (limited to 'Imaging/libImaging/Pack.c')
-rw-r--r-- | Imaging/libImaging/Pack.c | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/Imaging/libImaging/Pack.c b/Imaging/libImaging/Pack.c new file mode 100644 index 0000000..8e261f6 --- /dev/null +++ b/Imaging/libImaging/Pack.c @@ -0,0 +1,531 @@ +/* + * The Python Imaging Library. + * $Id: Pack.c 2763 2006-06-22 21:43:28Z fredrik $ + * + * code to pack raw data + * + * history: + * 1996-04-30 fl Created + * 1996-05-12 fl Published a few RGB packers + * 1996-11-01 fl More RGB packers (Tk booster stuff) + * 1996-12-30 fl Added P;1, P;2 and P;4 packers + * 1997-06-02 fl Added F (F;32NF) packer + * 1997-08-28 fl Added 1 as L packer + * 1998-02-08 fl Added I packer + * 1998-03-09 fl Added mode field, RGBA/RGBX as RGB packers + * 1998-07-01 fl Added YCbCr support + * 1998-07-12 fl Added I 16 packer + * 1999-02-03 fl Added BGR packers + * 2003-09-26 fl Added LA/PA packers + * 2006-06-22 fl Added CMYK;I packer + * + * Copyright (c) 1997-2006 by Secret Labs AB. + * Copyright (c) 1996-1997 by Fredrik Lundh. + * + * See the README file for information on usage and redistribution. + */ + + +#include "Imaging.h" + +#define R 0 +#define G 1 +#define B 2 +#define X 3 +#define A 3 + +#define C 0 +#define M 1 +#define Y 2 +#define K 3 + +/* byte swapping macros */ + +#define C16N\ + (out[0]=tmp[0], out[1]=tmp[1]); +#define C16S\ + (out[1]=tmp[0], out[0]=tmp[1]); +#define C32N\ + (out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3]); +#define C32S\ + (out[3]=tmp[0], out[2]=tmp[1], out[1]=tmp[2], out[0]=tmp[3]); +#define C64N\ + (out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3],\ + out[4]=tmp[4], out[5]=tmp[5], out[6]=tmp[6], out[7]=tmp[7]); +#define C64S\ + (out[7]=tmp[0], out[6]=tmp[1], out[5]=tmp[2], out[4]=tmp[3],\ + out[3]=tmp[4], out[2]=tmp[5], out[1]=tmp[6], out[0]=tmp[7]); + +#ifdef WORDS_BIGENDIAN +#define C16B C16N +#define C16L C16S +#define C32B C32N +#define C32L C32S +#define C64B C64N +#define C64L C64S +#else +#define C16B C16S +#define C16L C16N +#define C32B C32S +#define C32L C32N +#define C64B C64S +#define C64L C64N +#endif + +static void +pack1(UINT8* out, const UINT8* in, int pixels) +{ + int i, m, b; + /* bilevel (black is 0) */ + b = 0; m = 128; + for (i = 0; i < pixels; i++) { + if (in[i] != 0) + b |= m; + m >>= 1; + if (m == 0) { + *out++ = b; + b = 0; m = 128; + } + } + if (m != 128) + *out++ = b; +} + +static void +pack1I(UINT8* out, const UINT8* in, int pixels) +{ + int i, m, b; + /* bilevel (black is 1) */ + b = 0; m = 128; + for (i = 0; i < pixels; i++) { + if (in[i] == 0) + b |= m; + m >>= 1; + if (m == 0) { + *out++ = b; + b = 0; m = 128; + } + } + if (m != 128) + *out++ = b; +} + +static void +pack1R(UINT8* out, const UINT8* in, int pixels) +{ + int i, m, b; + /* bilevel, lsb first (black is 0) */ + b = 0; m = 1; + for (i = 0; i < pixels; i++) { + if (in[i] != 0) + b |= m; + m <<= 1; + if (m == 256){ + *out++ = b; + b = 0; m = 1; + } + } + if (m != 1) + *out++ = b; +} + +static void +pack1IR(UINT8* out, const UINT8* in, int pixels) +{ + int i, m, b; + /* bilevel, lsb first (black is 1) */ + b = 0; m = 1; + for (i = 0; i < pixels; i++) { + if (in[i] == 0) + b |= m; + m <<= 1; + if (m == 256){ + *out++ = b; + b = 0; m = 1; + } + } + if (m != 1) + *out++ = b; +} + +static void +pack1L(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* bilevel, stored as bytes */ + for (i = 0; i < pixels; i++) + out[i] = (in[i] != 0) ? 255 : 0; +} + +static void +packP4(UINT8* out, const UINT8* in, int pixels) +{ + while (pixels >= 2) { + *out++ = (in[0] << 4) | + (in[1] & 15); + in += 2; pixels -= 2; + } + + if (pixels) + out[0] = (in[0] << 4); +} + +static void +packP2(UINT8* out, const UINT8* in, int pixels) +{ + while (pixels >= 4) { + *out++ = (in[0] << 6) | + ((in[1] & 3) << 4) | + ((in[2] & 3) << 2) | + (in[3] & 3); + in += 4; pixels -= 4; + } + + switch (pixels) { + case 3: + out[0] = (in[0] << 6) | + ((in[1] & 3) << 4) | + ((in[2] & 3) << 2); + break; + case 2: + out[0] = (in[0] << 6) | + ((in[1] & 3) << 4); + case 1: + out[0] = (in[0] << 6); + } +} + +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; + } +} + +void +ImagingPackRGB(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* RGB triplets */ + for (i = 0; i < pixels; i++) { + out[0] = in[R]; + out[1] = in[G]; + out[2] = in[B]; + out += 3; in += 4; + } +} + +void +ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* XRGB, triplets with left padding */ + for (i = 0; i < pixels; i++) { + out[0] = 0; + out[1] = in[R]; + out[2] = in[G]; + out[3] = in[B]; + out += 4; in += 4; + } +} + +void +ImagingPackBGR(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* RGB, reversed bytes */ + for (i = 0; i < pixels; i++) { + out[0] = in[B]; + out[1] = in[G]; + out[2] = in[R]; + out += 3; in += 4; + } +} + +void +ImagingPackBGRX(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* BGRX, reversed bytes with right padding */ + for (i = 0; i < pixels; i++) { + out[0] = in[B]; + out[1] = in[G]; + out[2] = in[R]; + out[3] = 0; + out += 4; in += 4; + } +} + +void +ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* XBGR, reversed bytes with left padding */ + for (i = 0; i < pixels; i++) { + out[0] = 0; + out[1] = in[B]; + out[2] = in[G]; + out[3] = in[R]; + out += 4; in += 4; + } +} + +static void +packRGBL(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* RGB, line interleaved */ + for (i = 0; i < pixels; i++) { + out[i] = in[R]; + out[i+pixels] = in[G]; + out[i+pixels+pixels] = in[B]; + in += 4; + } +} + +static void +packRGBXL(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* RGBX, line interleaved */ + for (i = 0; i < pixels; i++) { + out[i] = in[R]; + out[i+pixels] = in[G]; + out[i+pixels+pixels] = in[B]; + out[i+pixels+pixels+pixels] = in[X]; + in += 4; + } +} + +static void +packI16B(UINT8* out, const UINT8* in_, int pixels) +{ + int i; + INT32* in = (INT32*) in_; + UINT16 tmp_; + UINT8* tmp = (UINT8*) &tmp_; + for (i = 0; i < pixels; i++) { + if (in[0] <= 0) + tmp_ = 0; + else if (in[0] > 65535) + tmp_ = 65535; + else + tmp_ = in[0]; + C16B; + out += 2; in++; + } +} + +static void +packI32S(UINT8* out, const UINT8* in, int pixels) +{ + int i; + UINT8* tmp = (UINT8*) in; + for (i = 0; i < pixels; i++) { + C32L; + out += 4; tmp += 4; + } +} + +static void +copy1(UINT8* out, const UINT8* in, int pixels) +{ + /* L, P */ + memcpy(out, in, pixels); +} + +static void +copy2(UINT8* out, const UINT8* in, int pixels) +{ + /* I;16, etc */ + memcpy(out, in, pixels*2); +} + +static void +copy3(UINT8* out, const UINT8* in, int pixels) +{ + /* BGR;24, etc */ + memcpy(out, in, pixels*3); +} + +static void +copy4(UINT8* out, const UINT8* in, int pixels) +{ + /* RGBA, CMYK quadruples */ + memcpy(out, in, 4*pixels); +} + +static void +copy4I(UINT8* out, const UINT8* in, int pixels) +{ + /* RGBA, CMYK quadruples, inverted */ + int i; + for (i = 0; i < pixels*4; i++) + out[i] = ~in[i]; +} + +static void +band0(UINT8* out, const UINT8* in, int pixels) +{ + int i; + for (i = 0; i < pixels; i++, in += 4) + out[i] = in[0]; +} + +static void +band1(UINT8* out, const UINT8* in, int pixels) +{ + int i; + for (i = 0; i < pixels; i++, in += 4) + out[i] = in[1]; +} + +static void +band2(UINT8* out, const UINT8* in, int pixels) +{ + int i; + for (i = 0; i < pixels; i++, in += 4) + out[i] = in[2]; +} + +static void +band3(UINT8* out, const UINT8* in, int pixels) +{ + int i; + for (i = 0; i < pixels; i++, in += 4) + out[i] = in[3]; +} + +static struct { + const char* mode; + const char* rawmode; + int bits; + ImagingShuffler pack; +} packers[] = { + + /* bilevel */ + {"1", "1", 1, pack1}, + {"1", "1;I", 1, pack1I}, + {"1", "1;R", 1, pack1R}, + {"1", "1;IR", 1, pack1IR}, + {"1", "L", 8, pack1L}, + + /* greyscale */ + {"L", "L", 8, copy1}, + + /* greyscale w. alpha */ + {"LA", "LA", 16, packLA}, + {"LA", "LA;L", 16, packLAL}, + + /* palette */ + {"P", "P;1", 1, pack1}, + {"P", "P;2", 2, packP2}, + {"P", "P;4", 4, packP4}, + {"P", "P", 8, copy1}, + + /* palette w. alpha */ + {"PA", "PA", 16, packLA}, + {"PA", "PA;L", 16, packLAL}, + + /* true colour */ + {"RGB", "RGB", 24, ImagingPackRGB}, + {"RGB", "RGBX", 32, copy4}, + {"RGB", "XRGB", 32, ImagingPackXRGB}, + {"RGB", "BGR", 24, ImagingPackBGR}, + {"RGB", "BGRX", 32, ImagingPackBGRX}, + {"RGB", "XBGR", 32, ImagingPackXBGR}, + {"RGB", "RGB;L", 24, packRGBL}, + {"RGB", "R", 8, band0}, + {"RGB", "G", 8, band1}, + {"RGB", "B", 8, band2}, + + /* true colour w. alpha */ + {"RGBA", "RGBA", 32, copy4}, + {"RGBA", "RGBA;L", 32, packRGBXL}, + {"RGBA", "RGB", 24, ImagingPackRGB}, + {"RGBA", "R", 8, band0}, + {"RGBA", "G", 8, band1}, + {"RGBA", "B", 8, band2}, + {"RGBA", "A", 8, band3}, + + /* true colour w. padding */ + {"RGBX", "RGBX", 32, copy4}, + {"RGBX", "RGBX;L", 32, packRGBXL}, + {"RGBX", "RGB", 32, ImagingPackRGB}, + {"RGBX", "R", 8, band0}, + {"RGBX", "G", 8, band1}, + {"RGBX", "B", 8, band2}, + {"RGBX", "X", 8, band3}, + + /* colour separation */ + {"CMYK", "CMYK", 32, copy4}, + {"CMYK", "CMYK;I", 32, copy4I}, + {"CMYK", "CMYK;L", 32, packRGBXL}, + {"CMYK", "C", 8, band0}, + {"CMYK", "M", 8, band1}, + {"CMYK", "Y", 8, band2}, + {"CMYK", "K", 8, band3}, + + /* video (YCbCr) */ + {"YCbCr", "YCbCr", 24, ImagingPackRGB}, + {"YCbCr", "YCbCr;L", 24, packRGBL}, + {"YCbCr", "YCbCrX", 32, copy4}, + {"YCbCr", "YCbCrK", 32, copy4}, + {"YCbCr", "Y", 8, band0}, + {"YCbCr", "Cb", 8, band1}, + {"YCbCr", "Cr", 8, band2}, + + /* integer */ + {"I", "I", 32, copy4}, + {"I", "I;16B", 16, packI16B}, + {"I", "I;32S", 32, packI32S}, + {"I", "I;32NS", 32, copy4}, + + /* floating point */ + {"F", "F", 32, copy4}, + {"F", "F;32F", 32, packI32S}, + {"F", "F;32NF", 32, copy4}, + + /* storage modes */ + {"I;16", "I;16", 16, copy2}, + {"I;16B", "I;16B", 16, copy2}, + {"BGR;15", "BGR;15", 16, copy2}, + {"BGR;16", "BGR;16", 16, copy2}, + {"BGR;24", "BGR;24", 24, copy3}, + + {NULL} /* sentinel */ +}; + + +ImagingShuffler +ImagingFindPacker(const char* mode, const char* rawmode, int* bits_out) +{ + int i; + + /* find a suitable pixel packer */ + for (i = 0; packers[i].rawmode; i++) + if (strcmp(packers[i].mode, mode) == 0 && + strcmp(packers[i].rawmode, rawmode) == 0) { + if (bits_out) + *bits_out = packers[i].bits; + return packers[i].pack; + } + return NULL; +} |