summaryrefslogtreecommitdiff
path: root/src/main/bit-ops.c
diff options
context:
space:
mode:
authorRoger Leigh <rleigh@debian.org>2008-10-26 16:11:41 +0000
committerRoger Leigh <rleigh@debian.org>2008-10-26 16:11:41 +0000
commitdfae5860833782af557deb35e286d7e186fe3cf5 (patch)
treee3b4282ae08e120f78cd0c097f7cb3b570e94da2 /src/main/bit-ops.c
parent3b59bb0a607ec27ea60f07d1cd5d1bbb4483c832 (diff)
Imported Upstream version 4.3.99+cvs20050702
Diffstat (limited to 'src/main/bit-ops.c')
-rw-r--r--src/main/bit-ops.c1199
1 files changed, 1199 insertions, 0 deletions
diff --git a/src/main/bit-ops.c b/src/main/bit-ops.c
new file mode 100644
index 0000000..5cff81d
--- /dev/null
+++ b/src/main/bit-ops.c
@@ -0,0 +1,1199 @@
+/*
+ * "$Id: bit-ops.c,v 1.8 2005/06/29 01:42:34 rlk Exp $"
+ *
+ * Softweave calculator for Gutenprint.
+ *
+ * Copyright 2000 Charles Briscoe-Smith <cpbs@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file must include only standard C header files. The core code must
+ * compile on generic platforms that don't support glib, gimp, gtk, etc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <gutenprint/gutenprint.h>
+#include "gutenprint-internal.h"
+#include <gutenprint/gutenprint-intl-internal.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+void
+stp_fold(const unsigned char *line,
+ int single_length,
+ unsigned char *outbuf)
+{
+ int i;
+ memset(outbuf, 0, single_length * 2);
+ for (i = 0; i < single_length; i++)
+ {
+ unsigned char l0 = line[0];
+ unsigned char l1 = line[single_length];
+ if (l0 || l1)
+ {
+ outbuf[0] =
+ ((l0 & (1 << 7)) >> 1) +
+ ((l0 & (1 << 6)) >> 2) +
+ ((l0 & (1 << 5)) >> 3) +
+ ((l0 & (1 << 4)) >> 4) +
+ ((l1 & (1 << 7)) >> 0) +
+ ((l1 & (1 << 6)) >> 1) +
+ ((l1 & (1 << 5)) >> 2) +
+ ((l1 & (1 << 4)) >> 3);
+ outbuf[1] =
+ ((l0 & (1 << 3)) << 3) +
+ ((l0 & (1 << 2)) << 2) +
+ ((l0 & (1 << 1)) << 1) +
+ ((l0 & (1 << 0)) << 0) +
+ ((l1 & (1 << 3)) << 4) +
+ ((l1 & (1 << 2)) << 3) +
+ ((l1 & (1 << 1)) << 2) +
+ ((l1 & (1 << 0)) << 1);
+ }
+ line++;
+ outbuf += 2;
+ }
+}
+
+static void
+stpi_split_2_1(int length,
+ const unsigned char *in,
+ unsigned char *outhi,
+ unsigned char *outlo)
+{
+ unsigned char *outs[2];
+ int i;
+ int row = 0;
+ int limit = length;
+ outs[0] = outhi;
+ outs[1] = outlo;
+ memset(outs[1], 0, limit);
+ for (i = 0; i < limit; i++)
+ {
+ unsigned char inbyte = in[i];
+ outs[0][i] = 0;
+ if (inbyte == 0)
+ continue;
+ /* For some reason gcc isn't unrolling this, even with -funroll-loops */
+ if (inbyte & 1)
+ {
+ outs[row][i] |= 1 & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 1))
+ {
+ outs[row][i] |= (1 << 1) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 2))
+ {
+ outs[row][i] |= (1 << 2) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 3))
+ {
+ outs[row][i] |= (1 << 3) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 4))
+ {
+ outs[row][i] |= (1 << 4) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 5))
+ {
+ outs[row][i] |= (1 << 5) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 6))
+ {
+ outs[row][i] |= (1 << 6) & inbyte;
+ row = row ^ 1;
+ }
+ if (inbyte & (1 << 7))
+ {
+ outs[row][i] |= (1 << 7) & inbyte;
+ row = row ^ 1;
+ }
+ }
+}
+
+static void
+stp_split_2_2(int length,
+ const unsigned char *in,
+ unsigned char *outhi,
+ unsigned char *outlo)
+{
+ unsigned char *outs[2];
+ int i;
+ unsigned row = 0;
+ int limit = length * 2;
+ outs[0] = outhi;
+ outs[1] = outlo;
+ memset(outs[1], 0, limit);
+ for (i = 0; i < limit; i++)
+ {
+ unsigned char inbyte = in[i];
+ outs[0][i] = 0;
+ if (inbyte == 0)
+ continue;
+ /* For some reason gcc isn't unrolling this, even with -funroll-loops */
+ if (inbyte & 3)
+ {
+ outs[row][i] |= (3 & inbyte);
+ row = row ^ 1;
+ }
+ if (inbyte & (3 << 2))
+ {
+ outs[row][i] |= ((3 << 2) & inbyte);
+ row = row ^ 1;
+ }
+ if (inbyte & (3 << 4))
+ {
+ outs[row][i] |= ((3 << 4) & inbyte);
+ row = row ^ 1;
+ }
+ if (inbyte & (3 << 6))
+ {
+ outs[row][i] |= ((3 << 6) & inbyte);
+ row = row ^ 1;
+ }
+ }
+}
+
+void
+stp_split_2(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *outhi,
+ unsigned char *outlo)
+{
+ if (bits == 2)
+ stp_split_2_2(length, in, outhi, outlo);
+ else
+ stpi_split_2_1(length, in, outhi, outlo);
+}
+
+static void
+stpi_split_4_1(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ unsigned char *outs[4];
+ int i;
+ int row = 0;
+ int limit = length;
+ outs[0] = out0;
+ outs[1] = out1;
+ outs[2] = out2;
+ outs[3] = out3;
+ memset(outs[1], 0, limit);
+ memset(outs[2], 0, limit);
+ memset(outs[3], 0, limit);
+ for (i = 0; i < limit; i++)
+ {
+ unsigned char inbyte = in[i];
+ outs[0][i] = 0;
+ if (inbyte == 0)
+ continue;
+ /* For some reason gcc isn't unrolling this, even with -funroll-loops */
+ if (inbyte & 1)
+ {
+ outs[row][i] |= 1 & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 1))
+ {
+ outs[row][i] |= (1 << 1) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 2))
+ {
+ outs[row][i] |= (1 << 2) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 3))
+ {
+ outs[row][i] |= (1 << 3) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 4))
+ {
+ outs[row][i] |= (1 << 4) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 5))
+ {
+ outs[row][i] |= (1 << 5) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 6))
+ {
+ outs[row][i] |= (1 << 6) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (1 << 7))
+ {
+ outs[row][i] |= (1 << 7) & inbyte;
+ row = (row + 1) & 3;
+ }
+ }
+}
+
+static void
+stpi_split_4_2(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ unsigned char *outs[4];
+ int i;
+ int row = 0;
+ int limit = length * 2;
+ outs[0] = out0;
+ outs[1] = out1;
+ outs[2] = out2;
+ outs[3] = out3;
+ memset(outs[1], 0, limit);
+ memset(outs[2], 0, limit);
+ memset(outs[3], 0, limit);
+ for (i = 0; i < limit; i++)
+ {
+ unsigned char inbyte = in[i];
+ outs[0][i] = 0;
+ if (inbyte == 0)
+ continue;
+ /* For some reason gcc isn't unrolling this, even with -funroll-loops */
+ if (inbyte & 3)
+ {
+ outs[row][i] |= 3 & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (3 << 2))
+ {
+ outs[row][i] |= (3 << 2) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (3 << 4))
+ {
+ outs[row][i] |= (3 << 4) & inbyte;
+ row = (row + 1) & 3;
+ }
+ if (inbyte & (3 << 6))
+ {
+ outs[row][i] |= (3 << 6) & inbyte;
+ row = (row + 1) & 3;
+ }
+ }
+}
+
+void
+stp_split_4(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ if (bits == 2)
+ stpi_split_4_2(length, in, out0, out1, out2, out3);
+ else
+ stpi_split_4_1(length, in, out0, out1, out2, out3);
+}
+
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SH20 0
+#define SH21 8
+#else
+#define SH20 8
+#define SH21 0
+#endif
+
+static void
+stpi_unpack_2_1(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1)
+{
+ unsigned char tempin, bit, temp0, temp1;
+
+ if (length <= 0)
+ return;
+ for (bit = 128, temp0 = 0, temp1 = 0;
+ length > 0;
+ length --)
+ {
+ tempin = *in++;
+
+ if (tempin & 128)
+ temp0 |= bit;
+ if (tempin & 64)
+ temp1 |= bit;
+ bit >>= 1;
+ if (tempin & 32)
+ temp0 |= bit;
+ if (tempin & 16)
+ temp1 |= bit;
+ bit >>= 1;
+ if (tempin & 8)
+ temp0 |= bit;
+ if (tempin & 4)
+ temp1 |= bit;
+ bit >>= 1;
+ if (tempin & 2)
+ temp0 |= bit;
+ if (tempin & 1)
+ temp1 |= bit;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ *out0++ = temp0;
+ *out1++ = temp1;
+
+ temp0 = 0;
+ temp1 = 0;
+ }
+ }
+
+ if (bit < 128)
+ {
+ *out0++ = temp0;
+ *out1++ = temp1;
+ }
+}
+
+static void
+stpi_unpack_2_2(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1)
+{
+ if (length <= 0)
+ return;
+
+ for (;length;length --)
+ {
+ unsigned char ti0, ti1;
+ ti0 = in[0];
+ ti1 = in[1];
+
+ *out0++ = (ti0 & 0xc0) << 0
+ | (ti0 & 0x0c) << 2
+ | (ti1 & 0xc0) >> 4
+ | (ti1 & 0x0c) >> 2;
+ *out1++ = (ti0 & 0x30) << 2
+ | (ti0 & 0x03) << 4
+ | (ti1 & 0x30) >> 2
+ | (ti1 & 0x03) >> 0;
+ in += 2;
+ }
+}
+
+void
+stp_unpack_2(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *outlo,
+ unsigned char *outhi)
+{
+ if (bits == 1)
+ stpi_unpack_2_1(length, in, outlo, outhi);
+ else
+ stpi_unpack_2_2(length, in, outlo, outhi);
+}
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SH40 0
+#define SH41 8
+#define SH42 16
+#define SH43 24
+#else
+#define SH40 24
+#define SH41 16
+#define SH42 8
+#define SH43 0
+#endif
+
+static void
+stpi_unpack_4_1(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ unsigned char tempin, bit, temp0, temp1, temp2, temp3;
+
+ if (length <= 0)
+ return;
+ for (bit = 128, temp0 = 0, temp1 = 0, temp2 = 0, temp3 = 0;
+ length > 0;
+ length --)
+ {
+ tempin = *in++;
+
+ if (tempin & 128)
+ temp0 |= bit;
+ if (tempin & 64)
+ temp1 |= bit;
+ if (tempin & 32)
+ temp2 |= bit;
+ if (tempin & 16)
+ temp3 |= bit;
+ bit >>= 1;
+ if (tempin & 8)
+ temp0 |= bit;
+ if (tempin & 4)
+ temp1 |= bit;
+ if (tempin & 2)
+ temp2 |= bit;
+ if (tempin & 1)
+ temp3 |= bit;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+
+ temp0 = 0;
+ temp1 = 0;
+ temp2 = 0;
+ temp3 = 0;
+ }
+ }
+
+ if (bit < 128)
+ {
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ }
+}
+
+static void
+stpi_unpack_4_2(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ unsigned char tempin,
+ shift,
+ temp0,
+ temp1,
+ temp2,
+ temp3;
+
+ length *= 2;
+
+ for (shift = 0, temp0 = 0, temp1 = 0, temp2 = 0, temp3 = 0;
+ length > 0;
+ length --)
+ {
+ /*
+ * Note - we can't use (tempin & N) >> (shift - M) since negative
+ * right-shifts are not always implemented.
+ */
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp0 |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp1 |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp2 |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp3 |= ((tempin & 3) << 6) >> shift;
+
+ if (shift < 6)
+ shift += 2;
+ else
+ {
+ shift = 0;
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+
+ temp0 = 0;
+ temp1 = 0;
+ temp2 = 0;
+ temp3 = 0;
+ }
+ }
+
+ if (shift)
+ {
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ }
+}
+
+void
+stp_unpack_4(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3)
+{
+ if (bits == 1)
+ stpi_unpack_4_1(length, in, out0, out1, out2, out3);
+ else
+ stpi_unpack_4_2(length, in, out0, out1, out2, out3);
+}
+
+static void
+stpi_unpack_8_1(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7)
+{
+ unsigned char tempin, bit, temp0, temp1, temp2, temp3, temp4, temp5, temp6,
+ temp7;
+
+ if (length <= 0)
+ return;
+
+ for (bit = 128, temp0 = 0, temp1 = 0, temp2 = 0,
+ temp3 = 0, temp4 = 0, temp5 = 0, temp6 = 0, temp7 = 0;
+ length > 0;
+ length --)
+ {
+ tempin = *in++;
+
+ if (tempin & 128)
+ temp0 |= bit;
+ if (tempin & 64)
+ temp1 |= bit;
+ if (tempin & 32)
+ temp2 |= bit;
+ if (tempin & 16)
+ temp3 |= bit;
+ if (tempin & 8)
+ temp4 |= bit;
+ if (tempin & 4)
+ temp5 |= bit;
+ if (tempin & 2)
+ temp6 |= bit;
+ if (tempin & 1)
+ temp7 |= bit;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ *out4++ = temp4;
+ *out5++ = temp5;
+ *out6++ = temp6;
+ *out7++ = temp7;
+
+ temp0 = 0;
+ temp1 = 0;
+ temp2 = 0;
+ temp3 = 0;
+ temp4 = 0;
+ temp5 = 0;
+ temp6 = 0;
+ temp7 = 0;
+ }
+ }
+
+ if (bit < 128)
+ {
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ *out4++ = temp4;
+ *out5++ = temp5;
+ *out6++ = temp6;
+ *out7++ = temp7;
+ }
+}
+
+static void
+stpi_unpack_8_2(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7)
+{
+ unsigned char tempin,
+ shift,
+ temp0,
+ temp1,
+ temp2,
+ temp3,
+ temp4,
+ temp5,
+ temp6,
+ temp7;
+
+
+ for (shift = 0, temp0 = 0, temp1 = 0,
+ temp2 = 0, temp3 = 0, temp4 = 0, temp5 = 0, temp6 = 0, temp7 = 0;
+ length > 0;
+ length --)
+ {
+ /*
+ * Note - we can't use (tempin & N) >> (shift - M) since negative
+ * right-shifts are not always implemented.
+ */
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp0 |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp1 |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp2 |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp3 |= ((tempin & 3) << 6) >> shift;
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp4 |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp5 |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp6 |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp7 |= ((tempin & 3) << 6) >> shift;
+
+ if (shift < 6)
+ shift += 2;
+ else
+ {
+ shift = 0;
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ *out4++ = temp4;
+ *out5++ = temp5;
+ *out6++ = temp6;
+ *out7++ = temp7;
+
+ temp0 = 0;
+ temp1 = 0;
+ temp2 = 0;
+ temp3 = 0;
+ temp4 = 0;
+ temp5 = 0;
+ temp6 = 0;
+ temp7 = 0;
+ }
+ }
+
+ if (shift)
+ {
+ *out0++ = temp0;
+ *out1++ = temp1;
+ *out2++ = temp2;
+ *out3++ = temp3;
+ *out4++ = temp4;
+ *out5++ = temp5;
+ *out6++ = temp6;
+ *out7++ = temp7;
+ }
+}
+
+void
+stp_unpack_8(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7)
+{
+ if (bits == 1)
+ stpi_unpack_8_1(length, in, out0, out1, out2, out3,
+ out4, out5, out6, out7);
+ else
+ stpi_unpack_8_2(length, in, out0, out1, out2, out3,
+ out4, out5, out6, out7);
+}
+
+
+static void
+stpi_unpack_16_1(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7,
+ unsigned char *out8,
+ unsigned char *out9,
+ unsigned char *out10,
+ unsigned char *out11,
+ unsigned char *out12,
+ unsigned char *out13,
+ unsigned char *out14,
+ unsigned char *out15)
+{
+ unsigned char tempin, bit;
+ unsigned char temp[16];
+
+ if (length <= 0)
+ return;
+
+ memset(temp, 0, 16);
+
+ for (bit = 128; length > 0; length--)
+ {
+ tempin = *in++;
+
+ if (tempin & 128)
+ temp[0] |= bit;
+ if (tempin & 64)
+ temp[1] |= bit;
+ if (tempin & 32)
+ temp[2] |= bit;
+ if (tempin & 16)
+ temp[3] |= bit;
+ if (tempin & 8)
+ temp[4] |= bit;
+ if (tempin & 4)
+ temp[5] |= bit;
+ if (tempin & 2)
+ temp[6] |= bit;
+ if (tempin & 1)
+ temp[7] |= bit;
+
+ tempin = *in++;
+
+ if (tempin & 128)
+ temp[8] |= bit;
+ if (tempin & 64)
+ temp[9] |= bit;
+ if (tempin & 32)
+ temp[10] |= bit;
+ if (tempin & 16)
+ temp[11] |= bit;
+ if (tempin & 8)
+ temp[12] |= bit;
+ if (tempin & 4)
+ temp[13] |= bit;
+ if (tempin & 2)
+ temp[14] |= bit;
+ if (tempin & 1)
+ temp[15] |= bit;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ *out0++ = temp[0];
+ *out1++ = temp[1];
+ *out2++ = temp[2];
+ *out3++ = temp[3];
+ *out4++ = temp[4];
+ *out5++ = temp[5];
+ *out6++ = temp[6];
+ *out7++ = temp[7];
+ *out8++ = temp[8];
+ *out9++ = temp[9];
+ *out10++ = temp[10];
+ *out11++ = temp[11];
+ *out12++ = temp[12];
+ *out13++ = temp[13];
+ *out14++ = temp[14];
+ *out15++ = temp[15];
+
+ memset(temp, 0, 16);
+ }
+ }
+
+ if (bit < 128)
+ {
+ *out0++ = temp[0];
+ *out1++ = temp[1];
+ *out2++ = temp[2];
+ *out3++ = temp[3];
+ *out4++ = temp[4];
+ *out5++ = temp[5];
+ *out6++ = temp[6];
+ *out7++ = temp[7];
+ *out8++ = temp[8];
+ *out9++ = temp[9];
+ *out10++ = temp[10];
+ *out11++ = temp[11];
+ *out12++ = temp[12];
+ *out13++ = temp[13];
+ *out14++ = temp[14];
+ *out15++ = temp[15];
+ }
+}
+
+static void
+stpi_unpack_16_2(int length,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7,
+ unsigned char *out8,
+ unsigned char *out9,
+ unsigned char *out10,
+ unsigned char *out11,
+ unsigned char *out12,
+ unsigned char *out13,
+ unsigned char *out14,
+ unsigned char *out15)
+{
+ unsigned char tempin, shift;
+ unsigned char temp[16];
+
+ if (length <= 0)
+ return;
+
+ memset(temp, 0, 16);
+
+ for (shift = 0; length > 0; length--)
+ {
+ /*
+ * Note - we can't use (tempin & N) >> (shift - M) since negative
+ * right-shifts are not always implemented.
+ */
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp[0] |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp[1] |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp[2] |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp[3] |= ((tempin & 3) << 6) >> shift;
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp[4] |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp[5] |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp[6] |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp[7] |= ((tempin & 3) << 6) >> shift;
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp[8] |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp[9] |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp[10] |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp[11] |= ((tempin & 3) << 6) >> shift;
+
+ tempin = *in++;
+
+ if (tempin & 192)
+ temp[12] |= (tempin & 192) >> shift;
+ if (tempin & 48)
+ temp[13] |= ((tempin & 48) << 2) >> shift;
+ if (tempin & 12)
+ temp[14] |= ((tempin & 12) << 4) >> shift;
+ if (tempin & 3)
+ temp[15] |= ((tempin & 3) << 6) >> shift;
+
+ if (shift < 6)
+ shift += 2;
+ else
+ {
+ shift = 0;
+ *out0++ = temp[0];
+ *out1++ = temp[1];
+ *out2++ = temp[2];
+ *out3++ = temp[3];
+ *out4++ = temp[4];
+ *out5++ = temp[5];
+ *out6++ = temp[6];
+ *out7++ = temp[7];
+ *out8++ = temp[8];
+ *out9++ = temp[9];
+ *out10++ = temp[10];
+ *out11++ = temp[11];
+ *out12++ = temp[12];
+ *out13++ = temp[13];
+ *out14++ = temp[14];
+ *out15++ = temp[15];
+
+ memset(temp, 0, 16);
+ }
+ }
+
+ if (shift)
+ {
+ *out0++ = temp[0];
+ *out1++ = temp[1];
+ *out2++ = temp[2];
+ *out3++ = temp[3];
+ *out4++ = temp[4];
+ *out5++ = temp[5];
+ *out6++ = temp[6];
+ *out7++ = temp[7];
+ *out8++ = temp[8];
+ *out9++ = temp[9];
+ *out10++ = temp[10];
+ *out11++ = temp[11];
+ *out12++ = temp[12];
+ *out13++ = temp[13];
+ *out14++ = temp[14];
+ *out15++ = temp[15];
+ }
+}
+
+void
+stp_unpack_16(int length,
+ int bits,
+ const unsigned char *in,
+ unsigned char *out0,
+ unsigned char *out1,
+ unsigned char *out2,
+ unsigned char *out3,
+ unsigned char *out4,
+ unsigned char *out5,
+ unsigned char *out6,
+ unsigned char *out7,
+ unsigned char *out8,
+ unsigned char *out9,
+ unsigned char *out10,
+ unsigned char *out11,
+ unsigned char *out12,
+ unsigned char *out13,
+ unsigned char *out14,
+ unsigned char *out15)
+{
+ if (bits == 1)
+ stpi_unpack_16_1(length, in,
+ out0, out1, out2, out3, out4, out5, out6, out7,
+ out8, out9, out10, out11, out12, out13, out14, out15);
+ else
+ stpi_unpack_16_2(length, in,
+ out0, out1, out2, out3, out4, out5, out6, out7,
+ out8, out9, out10, out11, out12, out13, out14, out15);
+}
+
+static void
+find_first_and_last(const unsigned char *line, int length,
+ int *first, int *last)
+{
+ int i;
+ int found_first = 0;
+ if (!first || !last)
+ return;
+ *first = 0;
+ *last = 0;
+ for (i = 0; i < length; i++)
+ {
+ if (line[i] == 0)
+ {
+ if (!found_first)
+ (*first)++;
+ }
+ else
+ {
+ *last = i;
+ found_first = 1;
+ }
+ }
+}
+
+int
+stp_pack_uncompressed(stp_vars_t *v,
+ const unsigned char *line,
+ int length,
+ unsigned char *comp_buf,
+ unsigned char **comp_ptr,
+ int *first,
+ int *last)
+{
+ find_first_and_last(line, length, first, last);
+ memcpy(comp_buf, line, length);
+ *comp_ptr = comp_buf + length;
+ if (first > last)
+ return 0;
+ else
+ return 1;
+}
+
+int
+stp_pack_tiff(stp_vars_t *v,
+ const unsigned char *line,
+ int length,
+ unsigned char *comp_buf,
+ unsigned char **comp_ptr,
+ int *first,
+ int *last)
+{
+ const unsigned char *start; /* Start of compressed data */
+ unsigned char repeat; /* Repeating char */
+ int count; /* Count of compressed bytes */
+ int tcount; /* Temporary count < 128 */
+ register const unsigned char *xline = line;
+ register int xlength = length;
+ find_first_and_last(line, length, first, last);
+
+ /*
+ * Compress using TIFF "packbits" run-length encoding...
+ */
+
+ (*comp_ptr) = comp_buf;
+
+ while (xlength > 0)
+ {
+ /*
+ * Get a run of non-repeated chars...
+ */
+
+ start = xline;
+ xline += 2;
+ xlength -= 2;
+
+ while (xlength > 0 && (xline[-2] != xline[-1] || xline[-1] != xline[0]))
+ {
+ xline ++;
+ xlength --;
+ }
+
+ xline -= 2;
+ xlength += 2;
+
+ /*
+ * Output the non-repeated sequences (max 128 at a time).
+ */
+
+ count = xline - start;
+ while (count > 0)
+ {
+ tcount = count > 128 ? 128 : count;
+
+ (*comp_ptr)[0] = tcount - 1;
+ memcpy((*comp_ptr) + 1, start, tcount);
+
+ (*comp_ptr) += tcount + 1;
+ start += tcount;
+ count -= tcount;
+ }
+
+ if (xlength <= 0)
+ break;
+
+ /*
+ * Find the repeated sequences...
+ */
+
+ start = xline;
+ repeat = xline[0];
+
+ xline ++;
+ xlength --;
+
+ if (xlength > 0)
+ {
+ int ylength = xlength;
+ while (ylength && *xline == repeat)
+ {
+ xline ++;
+ ylength --;
+ }
+ xlength = ylength;
+ }
+
+ /*
+ * Output the repeated sequences (max 128 at a time).
+ */
+
+ count = xline - start;
+ while (count > 0)
+ {
+ tcount = count > 128 ? 128 : count;
+
+ (*comp_ptr)[0] = 1 - tcount;
+ (*comp_ptr)[1] = repeat;
+
+ (*comp_ptr) += 2;
+ count -= tcount;
+ }
+ }
+ if (first && last && *first > *last)
+ return 0;
+ else
+ return 1;
+}