Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Imaging/libImaging/Pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'Imaging/libImaging/Pack.c')
-rw-r--r--Imaging/libImaging/Pack.c531
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;
+}