Factor tinyjpeg out by colorspace, so we don't pull in everything
authorH. Peter Anvin <hpa@zytor.com>
Tue, 5 Sep 2006 18:04:57 +0000 (11:04 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 5 Sep 2006 18:04:57 +0000 (11:04 -0700)
com32/include/tinyjpeg.h
com32/lib/Makefile
com32/lib/jpeg/bgr24.c [new file with mode: 0644]
com32/lib/jpeg/decode1.c [new file with mode: 0644]
com32/lib/jpeg/decode3.c [new file with mode: 0644]
com32/lib/jpeg/grey.c [new file with mode: 0644]
com32/lib/jpeg/rgb24.c [new file with mode: 0644]
com32/lib/jpeg/tinyjpeg-internal.h
com32/lib/jpeg/tinyjpeg.c
com32/lib/jpeg/yuv420p.c [new file with mode: 0644]

index 33e126c..b800a4b 100644 (file)
@@ -45,18 +45,18 @@ struct jdec_private;
 #define TINYJPEG_FLAGS_MJPEG_TABLE     (1<<1)
 
 /* Format accepted in outout */
-enum tinyjpeg_fmt {
-   TINYJPEG_FMT_GREY = 1,
-   TINYJPEG_FMT_BGR24,
-   TINYJPEG_FMT_RGB24,
-   TINYJPEG_FMT_YUV420P,
-};
+struct tinyjpeg_colorspace;
+typedef const struct tinyjpeg_colorspace *tinyjpeg_colorspace_t;
+
+extern const tinyjpeg_colorspace_t TINYJPEG_FMT_GREY, TINYJPEG_FMT_BGR24,
+  TINYJPEG_FMT_RGB24, TINYJPEG_FMT_YUV420P, TINYJPEG_FMT_BGRA32,
+  TINYJPEG_FMT_RGBA32;
 
 struct jdec_private *tinyjpeg_init(void);
 void tinyjpeg_free(struct jdec_private *priv);
 
 int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size);
-int tinyjpeg_decode(struct jdec_private *priv, int pixel_format);
+int tinyjpeg_decode(struct jdec_private *priv, tinyjpeg_colorspace_t pixel_format);
 const char *tinyjpeg_get_errorstring(struct jdec_private *priv);
 void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height);
 int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components);
index 88d0b2f..44d9496 100644 (file)
@@ -55,7 +55,8 @@ LIBOBJS = \
        libpng/pngrtran.o libpng/pngwtran.o libpng/pngmem.o             \
        libpng/pngerror.o libpng/pngpread.o                             \
        \
-       jpeg/tinyjpeg.o jpeg/jidctflt.o                                 \
+       jpeg/tinyjpeg.o jpeg/jidctflt.o jpeg/decode1.o jpeg/decode3.o   \
+       jpeg/rgb24.o jpeg/bgr24.o jpeg/yuv420p.o jpeg/grey.o            \
        \
        sys/x86_init_fpu.o math/pow.o math/strtod.o
 
diff --git a/com32/lib/jpeg/bgr24.c b/com32/lib/jpeg/bgr24.c
new file mode 100644 (file)
index 0000000..465d58e
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/*******************************************************************************
+ *
+ * Colorspace conversion routine
+ *
+ *
+ * Note:
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ *      R = Y                + 1.40200 * Cr
+ *      G = Y - 0.34414 * Cb - 0.71414 * Cr
+ *      B = Y + 1.77200 * Cb
+ * 
+ ******************************************************************************/
+static unsigned char clamp(int i)
+{
+  if (i<0)
+    return 0;
+  else if (i>255)
+    return 255;
+  else
+    return i;
+}   
+
+/**
+ *  YCrCb -> BGR24 (1x1)
+ *  .---.
+ *  | 1 |
+ *  `---'
+ */
+static void YCrCB_to_BGR24_1x1(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = priv->width*3 - 8*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0;j<8;j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       y  = (*Y++) << SCALEBITS;
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+    }
+
+    p += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+
+/*
+ *  YCrCb -> BGR24 (2x1)
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void YCrCB_to_BGR24_2x1(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = priv->width*3 - 16*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0; j<8; j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       y  = (*Y++) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+       y  = (*Y++) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+    }
+
+    p += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+/*
+ *  YCrCb -> BGR24 (1x2)
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void YCrCB_to_BGR24_1x2(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p, *p2;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  p2 = priv->plane[0] + priv->width*3;
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = 2*priv->width*3 - 8*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0; j<8; j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       y  = (*Y++) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+       y  = (Y[8-1]) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+
+    }
+    Y += 8;
+    p += offset_to_next_row;
+    p2 += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+
+/*
+ *  YCrCb -> BGR24 (2x2)
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void YCrCB_to_BGR24_2x2(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p, *p2;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  p2 = priv->plane[0] + priv->width*3;
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = (priv->width*3*2) - 16*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0;j<8;j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       y  = (*Y++) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+       y  = (*Y++) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+
+       y  = (Y[16-2]) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+
+       y  = (Y[16-1]) << SCALEBITS;
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+    }
+    Y  += 16;
+    p  += offset_to_next_row;
+    p2 += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+static int initialize_bgr24(struct jdec_private *priv,
+                           unsigned int *bytes_per_blocklines,
+                           unsigned int *bytes_per_mcu)
+{
+  if (priv->components[0] == NULL)
+    priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);
+  bytes_per_blocklines[0] = priv->width * 3;
+  bytes_per_mcu[0] = 3*8;
+
+  return !priv->components[0];
+}
+
+static const struct tinyjpeg_colorspace format_bgr24 =
+  {
+    {
+      YCrCB_to_BGR24_1x1,
+      YCrCB_to_BGR24_1x2,
+      YCrCB_to_BGR24_2x1,
+      YCrCB_to_BGR24_2x2,
+    },
+    tinyjpeg_decode_mcu_3comp_table,
+    initialize_bgr24
+  };
+
+const tinyjpeg_colorspace_t TINYJPEG_FMT_BGR24 = &format_bgr24;
diff --git a/com32/lib/jpeg/decode1.c b/com32/lib/jpeg/decode1.c
new file mode 100644 (file)
index 0000000..9d76a05
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/*
+ * Decode a 1x1 directly in 1 color
+ */
+static void decode_MCU_1x1_1plane(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 8);
+  
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
+
+/*
+ * Decode a 2x1
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void decode_MCU_2x1_1plane(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+}
+
+
+/*
+ * Decode a 2x2 directly in GREY format (8bits)
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void decode_MCU_2x2_1plane(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+}
+
+/*
+ * Decode a 1x2 mcu
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void decode_MCU_1x2_1plane(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 8);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64, 8);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+}
+
+const decode_MCU_fct tinyjpeg_decode_mcu_1comp_table[4] = {
+   decode_MCU_1x1_1plane,
+   decode_MCU_1x2_1plane,
+   decode_MCU_2x1_1plane,
+   decode_MCU_2x2_1plane,
+};
diff --git a/com32/lib/jpeg/decode3.c b/com32/lib/jpeg/decode3.c
new file mode 100644 (file)
index 0000000..9e49eee
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/*
+ * Decode all the 3 components for 1x1 
+ */
+static void decode_MCU_1x1_3planes(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 8);
+  
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
+/*
+ * Decode a 2x1
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void decode_MCU_2x1_3planes(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
+/*
+ * Decode a 2x2
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void decode_MCU_2x2_3planes(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
+/*
+ * Decode a 1x2 mcu
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void decode_MCU_1x2_3planes(struct jdec_private *priv)
+{
+  // Y
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y, 8);
+  tinyjpeg_process_Huffman_data_unit(priv, cY);
+  IDCT(&priv->component_infos[cY], priv->Y+64, 8);
+
+  // Cb
+  tinyjpeg_process_Huffman_data_unit(priv, cCb);
+  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+  // Cr
+  tinyjpeg_process_Huffman_data_unit(priv, cCr);
+  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
+const decode_MCU_fct tinyjpeg_decode_mcu_3comp_table[4] = {
+   decode_MCU_1x1_3planes,
+   decode_MCU_1x2_3planes,
+   decode_MCU_2x1_3planes,
+   decode_MCU_2x2_3planes,
+};
diff --git a/com32/lib/jpeg/grey.c b/com32/lib/jpeg/grey.c
new file mode 100644 (file)
index 0000000..edeb74a
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/**
+ *  YCrCb -> Grey (1x1)
+ *  .---.
+ *  | 1 |
+ *  `---'
+ */
+static void YCrCB_to_Grey_1x1(struct jdec_private *priv)
+{
+  const unsigned char *y;
+  unsigned char *p;
+  unsigned int i;
+  int offset_to_next_row;
+
+  p = priv->plane[0];
+  y = priv->Y;
+  offset_to_next_row = priv->width;
+
+  for (i=0; i<8; i++) {
+     memcpy(p, y, 8);
+     y+=8;
+     p += offset_to_next_row;
+  }
+}
+
+/**
+ *  YCrCb -> Grey (2x1)
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void YCrCB_to_Grey_2x1(struct jdec_private *priv)
+{
+  const unsigned char *y;
+  unsigned char *p;
+  unsigned int i;
+
+  p = priv->plane[0];
+  y = priv->Y;
+
+  for (i=0; i<8; i++) {
+     memcpy(p, y, 16);
+     y += 16;
+     p += priv->width;
+  }
+}
+
+
+/**
+ *  YCrCb -> Grey (1x2)
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void YCrCB_to_Grey_1x2(struct jdec_private *priv)
+{
+  const unsigned char *y;
+  unsigned char *p;
+  unsigned int i;
+
+  p = priv->plane[0];
+  y = priv->Y;
+
+  for (i=0; i<16; i++) {
+     memcpy(p, y, 8);
+     y += 8;
+     p += priv->width;
+  }
+}
+
+/**
+ *  YCrCb -> Grey (2x2)
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void YCrCB_to_Grey_2x2(struct jdec_private *priv)
+{
+  const unsigned char *y;
+  unsigned char *p;
+  unsigned int i;
+
+  p = priv->plane[0];
+  y = priv->Y;
+
+  for (i=0; i<16; i++) {
+     memcpy(p, y, 16);
+     y += 16;
+     p += priv->width;
+  }
+}
+
+static int initialize_grey(struct jdec_private *priv,
+                           unsigned int *bytes_per_blocklines,
+                           unsigned int *bytes_per_mcu)
+{
+  if (priv->components[0] == NULL)
+    priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);
+  bytes_per_blocklines[0] = priv->width * 3;
+  bytes_per_mcu[0] = 3*8;
+
+  return !priv->components[0];
+}
+
+static const struct tinyjpeg_colorspace format_grey =
+  {
+    {
+      YCrCB_to_Grey_1x1,
+      YCrCB_to_Grey_1x2,
+      YCrCB_to_Grey_2x1,
+      YCrCB_to_Grey_2x2,
+    },
+    tinyjpeg_decode_mcu_1comp_table,
+    initialize_grey
+  };
+
+const tinyjpeg_colorspace_t TINYJPEG_FMT_GREY = &format_grey;
diff --git a/com32/lib/jpeg/rgb24.c b/com32/lib/jpeg/rgb24.c
new file mode 100644 (file)
index 0000000..65c0695
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/*******************************************************************************
+ *
+ * Colorspace conversion routine
+ *
+ *
+ * Note:
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ *      R = Y                + 1.40200 * Cr
+ *      G = Y - 0.34414 * Cb - 0.71414 * Cr
+ *      B = Y + 1.77200 * Cb
+ * 
+ ******************************************************************************/
+static unsigned char clamp(int i)
+{
+  if (i<0)
+    return 0;
+  else if (i>255)
+    return 255;
+  else
+    return i;
+}   
+
+/**
+ *  YCrCb -> RGB24 (1x1)
+ *  .---.
+ *  | 1 |
+ *  `---'
+ */
+static void YCrCB_to_RGB24_1x1(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = priv->width*3 - 8*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0;j<8;j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       y  = (*Y++) << SCALEBITS;
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+    }
+
+    p += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+/**
+ *  YCrCb -> RGB24 (2x1)
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void YCrCB_to_RGB24_2x1(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = priv->width*3 - 16*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0; j<8; j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       y  = (*Y++) << SCALEBITS;
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+       y  = (*Y++) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+    }
+
+    p += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+
+/**
+ *  YCrCb -> RGB24 (1x2)
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void YCrCB_to_RGB24_1x2(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p, *p2;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  p2 = priv->plane[0] + priv->width*3;
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = 2*priv->width*3 - 8*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0; j<8; j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       y  = (*Y++) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+       y  = (Y[8-1]) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+
+    }
+    Y += 8;
+    p += offset_to_next_row;
+    p2 += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+/**
+ *  YCrCb -> RGB24 (2x2)
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void YCrCB_to_RGB24_2x2(struct jdec_private *priv)
+{
+  const unsigned char *Y, *Cb, *Cr;
+  unsigned char *p, *p2;
+  int i,j;
+  int offset_to_next_row;
+
+#define SCALEBITS       10
+#define ONE_HALF        (1UL << (SCALEBITS-1))
+#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
+
+  p = priv->plane[0];
+  p2 = priv->plane[0] + priv->width*3;
+  Y = priv->Y;
+  Cb = priv->Cb;
+  Cr = priv->Cr;
+  offset_to_next_row = (priv->width*3*2) - 16*3;
+  for (i=0; i<8; i++) {
+
+    for (j=0;j<8;j++) {
+
+       int y, cb, cr;
+       int add_r, add_g, add_b;
+       int r, g , b;
+
+       cb = *Cb++ - 128;
+       cr = *Cr++ - 128;
+       add_r = FIX(1.40200) * cr + ONE_HALF;
+       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
+       add_b = FIX(1.77200) * cb + ONE_HALF;
+
+       y  = (*Y++) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+       y  = (*Y++) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p++ = clamp(b);
+
+       y  = (Y[16-2]) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+
+       y  = (Y[16-1]) << SCALEBITS;
+       r = (y + add_r) >> SCALEBITS;
+       *p2++ = clamp(r);
+       g = (y + add_g) >> SCALEBITS;
+       *p2++ = clamp(g);
+       b = (y + add_b) >> SCALEBITS;
+       *p2++ = clamp(b);
+    }
+    Y  += 16;
+    p  += offset_to_next_row;
+    p2 += offset_to_next_row;
+  }
+
+#undef SCALEBITS
+#undef ONE_HALF
+#undef FIX
+
+}
+
+static int initialize_rgb24(struct jdec_private *priv,
+                           unsigned int *bytes_per_blocklines,
+                           unsigned int *bytes_per_mcu)
+{
+  if (priv->components[0] == NULL)
+    priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);
+  bytes_per_blocklines[0] = priv->width * 3;
+  bytes_per_mcu[0] = 3*8;
+
+  return !priv->components[0];
+}
+
+static const struct tinyjpeg_colorspace format_rgb24 =
+  {
+    {
+      YCrCB_to_RGB24_1x1,
+      YCrCB_to_RGB24_1x2,
+      YCrCB_to_RGB24_2x1,
+      YCrCB_to_RGB24_2x2,
+    },
+    tinyjpeg_decode_mcu_3comp_table,
+    initialize_rgb24
+  };
+
+const tinyjpeg_colorspace_t TINYJPEG_FMT_RGB24 = &format_rgb24;
index 8ae0c1b..abad084 100644 (file)
@@ -100,8 +100,87 @@ struct jdec_private
 
 };
 
+struct tinyjpeg_colorspace {
+  convert_colorspace_fct convert_colorspace[4];
+  const decode_MCU_fct *decode_mcu_table;
+  int (*initialize)(struct jdec_private *, unsigned int *, unsigned int *);
+};
+
 #define IDCT jpeg_idct_float
 void jpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride);
 
+void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component);
+
+extern const decode_MCU_fct tinyjpeg_decode_mcu_3comp_table[4];
+extern const decode_MCU_fct tinyjpeg_decode_mcu_1comp_table[4];
+
+enum std_markers {
+   DQT  = 0xDB, /* Define Quantization Table */
+   SOF  = 0xC0, /* Start of Frame (size information) */
+   DHT  = 0xC4, /* Huffman Table */
+   SOI  = 0xD8, /* Start of Image */
+   SOS  = 0xDA, /* Start of Scan */
+   EOI  = 0xD9, /* End of Image */
+   APP0 = 0xE0,
+};
+
+#define cY     1
+#define cCb    2
+#define cCr    3
+
+#define BLACK_Y 0
+#define BLACK_U 127
+#define BLACK_V 127
+
+#define SANITY_CHECK 1
+
+#if DEBUG
+#define error(fmt, args...) do { \
+   snprintf(error_string, sizeof(error_string), fmt, ## args); \
+   return -1; \
+} while(0)
+
+#define trace(fmt, args...) do { \
+   fprintf(stderr, fmt, ## args); \
+   fflush(stderr); \
+} while(0)
+#else
+#define error(fmt, args...) do { return -1; } while(0)
+#define trace(fmt, args...) do { } while (0)
+#endif
+
+#if 0
+static char *print_bits(unsigned int value, char *bitstr)
+{
+  int i, j;
+  i=31;
+  while (i>0)
+   {
+     if (value & (1UL<<i))
+       break;
+     i--;
+   }
+  j=0;
+  while (i>=0)
+   {
+     bitstr[j++] = (value & (1UL<<i))?'1':'0';
+     i--;
+   }
+  bitstr[j] = 0;
+  return bitstr;
+}
+
+static void print_next_16bytes(int offset, const unsigned char *stream)
+{
+  trace("%4.4x: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+       offset,
+       stream[0], stream[1], stream[2], stream[3], 
+       stream[4], stream[5], stream[6], stream[7],
+       stream[8], stream[9], stream[10], stream[11], 
+       stream[12], stream[13], stream[14], stream[15]);
+}
+
+#endif
+
 #endif
 
index a1b62db..ca180a0 100644 (file)
 #include "tinyjpeg.h"
 #include "tinyjpeg-internal.h"
 
-enum std_markers {
-   DQT  = 0xDB, /* Define Quantization Table */
-   SOF  = 0xC0, /* Start of Frame (size information) */
-   DHT  = 0xC4, /* Huffman Table */
-   SOI  = 0xD8, /* Start of Image */
-   SOS  = 0xDA, /* Start of Scan */
-   EOI  = 0xD9, /* End of Image */
-   APP0 = 0xE0,
-};
-
-#define cY     1
-#define cCb    2
-#define cCr    3
-
-#define BLACK_Y 0
-#define BLACK_U 127
-#define BLACK_V 127
-
-#define SANITY_CHECK 1
-
-#if DEBUG
-#define error(fmt, args...) do { \
-   snprintf(error_string, sizeof(error_string), fmt, ## args); \
-   return -1; \
-} while(0)
-
-#define trace(fmt, args...) do { \
-   fprintf(stderr, fmt, ## args); \
-   fflush(stderr); \
-} while(0)
-#else
-#define error(fmt, args...) do { return -1; } while(0)
-#define trace(fmt, args...) do { } while (0)
-#endif
-
-#if 0
-static char *print_bits(unsigned int value, char *bitstr)
-{
-  int i, j;
-  i=31;
-  while (i>0)
-   {
-     if (value & (1UL<<i))
-       break;
-     i--;
-   }
-  j=0;
-  while (i>=0)
-   {
-     bitstr[j++] = (value & (1UL<<i))?'1':'0';
-     i--;
-   }
-  bitstr[j] = 0;
-  return bitstr;
-}
-
-static void print_next_16bytes(int offset, const unsigned char *stream)
-{
-  trace("%4.4x: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-       offset,
-       stream[0], stream[1], stream[2], stream[3], 
-       stream[4], stream[5], stream[6], stream[7],
-       stream[8], stream[9], stream[10], stream[11], 
-       stream[12], stream[13], stream[14], stream[15]);
-}
-
-#endif
-
 /* Global variable to return the last error found while deconding */
 static char error_string[256];
 
@@ -318,7 +250,7 @@ static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table
  * The table coefficients is already dezigzaged at the end of the operation.
  *
  */
-static void process_Huffman_data_unit(struct jdec_private *priv, int component)
+void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component)
 {
   unsigned char j;
   int huff_code;
@@ -489,1007 +421,6 @@ static void build_default_huffman_tables(struct jdec_private *priv)
  * 
  ******************************************************************************/
 
-static unsigned char clamp(int i)
-{
-  if (i<0)
-    return 0;
-  else if (i>255)
-    return 255;
-  else
-    return i;
-}   
-
-
-/**
- *  YCrCb -> YUV420P (1x1)
- *  .---.
- *  | 1 |
- *  `---'
- */
-static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv)
-{
-  const unsigned char *s, *y;
-  unsigned char *p;
-  int i,j;
-
-  p = priv->plane[0];
-  y = priv->Y;
-  for (i=0; i<8; i++)
-   {
-     memcpy(p, y, 8);
-     p+=priv->width;
-     y+=8;
-   }
-
-  p = priv->plane[1];
-  s = priv->Cb;
-  for (i=0; i<8; i+=2)
-   {
-     for (j=0; j<8; j+=2, s+=2)
-       *p++ = *s;
-     s += 8; /* Skip one line */
-     p += priv->width/2 - 4;
-   }
-
-  p = priv->plane[2];
-  s = priv->Cr;
-  for (i=0; i<8; i+=2)
-   {
-     for (j=0; j<8; j+=2, s+=2)
-       *p++ = *s;
-     s += 8; /* Skip one line */
-     p += priv->width/2 - 4;
-   }
-}
-
-/**
- *  YCrCb -> YUV420P (2x1)
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv)
-{
-  unsigned char *p;
-  const unsigned char *s, *y1;
-  int i,j;
-
-  p = priv->plane[0];
-  y1 = priv->Y;
-  for (i=0; i<8; i++)
-   {
-     memcpy(p, y1, 16);
-     p += priv->width;
-     y1 += 16;
-   }
-
-  p = priv->plane[1];
-  s = priv->Cb;
-  for (i=0; i<8; i+=2)
-   {
-     for (j=0; j<8; j+=1, s+=1)
-       *p++ = *s;
-     s += 8; /* Skip one line */
-     p += priv->width/2 - 8;
-   }
-
-  p = priv->plane[2];
-  s = priv->Cr;
-  for (i=0; i<8; i+=2)
-   {
-     for (j=0; j<8; j+=1, s+=1)
-       *p++ = *s;
-     s += 8; /* Skip one line */
-     p += priv->width/2 - 8;
-   }
-}
-
-
-/**
- *  YCrCb -> YUV420P (1x2)
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv)
-{
-  const unsigned char *s, *y;
-  unsigned char *p;
-  int i,j;
-
-  p = priv->plane[0];
-  y = priv->Y;
-  for (i=0; i<16; i++)
-   {
-     memcpy(p, y, 8);
-     p+=priv->width;
-     y+=8;
-   }
-
-  p = priv->plane[1];
-  s = priv->Cb;
-  for (i=0; i<8; i++)
-   {
-     for (j=0; j<8; j+=2, s+=2)
-       *p++ = *s;
-     p += priv->width/2 - 4;
-   }
-
-  p = priv->plane[2];
-  s = priv->Cr;
-  for (i=0; i<8; i++)
-   {
-     for (j=0; j<8; j+=2, s+=2)
-       *p++ = *s;
-     p += priv->width/2 - 4;
-   }
-}
-
-/**
- *  YCrCb -> YUV420P (2x2)
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv)
-{
-  unsigned char *p;
-  const unsigned char *s, *y1;
-  int i;
-
-  p = priv->plane[0];
-  y1 = priv->Y;
-  for (i=0; i<16; i++)
-   {
-     memcpy(p, y1, 16);
-     p += priv->width;
-     y1 += 16;
-   }
-
-  p = priv->plane[1];
-  s = priv->Cb;
-  for (i=0; i<8; i++)
-   {
-     memcpy(p, s, 8);
-     s += 8;
-     p += priv->width/2;
-   }
-
-  p = priv->plane[2];
-  s = priv->Cr;
-  for (i=0; i<8; i++)
-   {
-     memcpy(p, s, 8);
-     s += 8;
-     p += priv->width/2;
-   }
-}
-
-/**
- *  YCrCb -> RGB24 (1x1)
- *  .---.
- *  | 1 |
- *  `---'
- */
-static void YCrCB_to_RGB24_1x1(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = priv->width*3 - 8*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0;j<8;j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       y  = (*Y++) << SCALEBITS;
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-    }
-
-    p += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/**
- *  YCrCb -> BGR24 (1x1)
- *  .---.
- *  | 1 |
- *  `---'
- */
-static void YCrCB_to_BGR24_1x1(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = priv->width*3 - 8*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0;j<8;j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       y  = (*Y++) << SCALEBITS;
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-    }
-
-    p += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/**
- *  YCrCb -> RGB24 (2x1)
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void YCrCB_to_RGB24_2x1(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = priv->width*3 - 16*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0; j<8; j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       y  = (*Y++) << SCALEBITS;
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-       y  = (*Y++) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-    }
-
-    p += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/*
- *  YCrCb -> BGR24 (2x1)
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void YCrCB_to_BGR24_2x1(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = priv->width*3 - 16*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0; j<8; j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       y  = (*Y++) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-       y  = (*Y++) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-    }
-
-    p += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/**
- *  YCrCb -> RGB24 (1x2)
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void YCrCB_to_RGB24_1x2(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p, *p2;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  p2 = priv->plane[0] + priv->width*3;
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = 2*priv->width*3 - 8*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0; j<8; j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       y  = (*Y++) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-       y  = (Y[8-1]) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-
-    }
-    Y += 8;
-    p += offset_to_next_row;
-    p2 += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-/*
- *  YCrCb -> BGR24 (1x2)
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void YCrCB_to_BGR24_1x2(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p, *p2;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  p2 = priv->plane[0] + priv->width*3;
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = 2*priv->width*3 - 8*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0; j<8; j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       y  = (*Y++) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-       y  = (Y[8-1]) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-
-    }
-    Y += 8;
-    p += offset_to_next_row;
-    p2 += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/**
- *  YCrCb -> RGB24 (2x2)
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void YCrCB_to_RGB24_2x2(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p, *p2;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  p2 = priv->plane[0] + priv->width*3;
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = (priv->width*3*2) - 16*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0;j<8;j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       y  = (*Y++) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-       y  = (*Y++) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-
-       y  = (Y[16-2]) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-
-       y  = (Y[16-1]) << SCALEBITS;
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-    }
-    Y  += 16;
-    p  += offset_to_next_row;
-    p2 += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-/*
- *  YCrCb -> BGR24 (2x2)
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void YCrCB_to_BGR24_2x2(struct jdec_private *priv)
-{
-  const unsigned char *Y, *Cb, *Cr;
-  unsigned char *p, *p2;
-  int i,j;
-  int offset_to_next_row;
-
-#define SCALEBITS       10
-#define ONE_HALF        (1UL << (SCALEBITS-1))
-#define FIX(x)          ((int)((x) * (1UL<<SCALEBITS) + 0.5))
-
-  p = priv->plane[0];
-  p2 = priv->plane[0] + priv->width*3;
-  Y = priv->Y;
-  Cb = priv->Cb;
-  Cr = priv->Cr;
-  offset_to_next_row = (priv->width*3*2) - 16*3;
-  for (i=0; i<8; i++) {
-
-    for (j=0;j<8;j++) {
-
-       int y, cb, cr;
-       int add_r, add_g, add_b;
-       int r, g , b;
-
-       cb = *Cb++ - 128;
-       cr = *Cr++ - 128;
-       add_r = FIX(1.40200) * cr + ONE_HALF;
-       add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
-       add_b = FIX(1.77200) * cb + ONE_HALF;
-
-       y  = (*Y++) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-       y  = (*Y++) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p++ = clamp(r);
-
-       y  = (Y[16-2]) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-
-       y  = (Y[16-1]) << SCALEBITS;
-       b = (y + add_b) >> SCALEBITS;
-       *p2++ = clamp(b);
-       g = (y + add_g) >> SCALEBITS;
-       *p2++ = clamp(g);
-       r = (y + add_r) >> SCALEBITS;
-       *p2++ = clamp(r);
-    }
-    Y  += 16;
-    p  += offset_to_next_row;
-    p2 += offset_to_next_row;
-  }
-
-#undef SCALEBITS
-#undef ONE_HALF
-#undef FIX
-
-}
-
-
-
-/**
- *  YCrCb -> Grey (1x1)
- *  .---.
- *  | 1 |
- *  `---'
- */
-static void YCrCB_to_Grey_1x1(struct jdec_private *priv)
-{
-  const unsigned char *y;
-  unsigned char *p;
-  unsigned int i;
-  int offset_to_next_row;
-
-  p = priv->plane[0];
-  y = priv->Y;
-  offset_to_next_row = priv->width;
-
-  for (i=0; i<8; i++) {
-     memcpy(p, y, 8);
-     y+=8;
-     p += offset_to_next_row;
-  }
-}
-
-/**
- *  YCrCb -> Grey (2x1)
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void YCrCB_to_Grey_2x1(struct jdec_private *priv)
-{
-  const unsigned char *y;
-  unsigned char *p;
-  unsigned int i;
-
-  p = priv->plane[0];
-  y = priv->Y;
-
-  for (i=0; i<8; i++) {
-     memcpy(p, y, 16);
-     y += 16;
-     p += priv->width;
-  }
-}
-
-
-/**
- *  YCrCb -> Grey (1x2)
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void YCrCB_to_Grey_1x2(struct jdec_private *priv)
-{
-  const unsigned char *y;
-  unsigned char *p;
-  unsigned int i;
-
-  p = priv->plane[0];
-  y = priv->Y;
-
-  for (i=0; i<16; i++) {
-     memcpy(p, y, 8);
-     y += 8;
-     p += priv->width;
-  }
-}
-
-/**
- *  YCrCb -> Grey (2x2)
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void YCrCB_to_Grey_2x2(struct jdec_private *priv)
-{
-  const unsigned char *y;
-  unsigned char *p;
-  unsigned int i;
-
-  p = priv->plane[0];
-  y = priv->Y;
-
-  for (i=0; i<16; i++) {
-     memcpy(p, y, 16);
-     y += 16;
-     p += priv->width;
-  }
-}
-
-
-/*
- * Decode all the 3 components for 1x1 
- */
-static void decode_MCU_1x1_3planes(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 8);
-  
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 1x1 directly in 1 color
- */
-static void decode_MCU_1x1_1plane(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 8);
-  
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-
-/*
- * Decode a 2x1
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void decode_MCU_2x1_3planes(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 2x1
- *  .-------.
- *  | 1 | 2 |
- *  `-------'
- */
-static void decode_MCU_2x1_1plane(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-}
-
-
-/*
- * Decode a 2x2
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void decode_MCU_2x2_3planes(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 2x2 directly in GREY format (8bits)
- *  .-------.
- *  | 1 | 2 |
- *  |---+---|
- *  | 3 | 4 |
- *  `-------'
- */
-static void decode_MCU_2x2_1plane(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+8, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-}
-
-/*
- * Decode a 1x2 mcu
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void decode_MCU_1x2_3planes(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 8);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64, 8);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-  IDCT(&priv->component_infos[cCb], priv->Cb, 8);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-  IDCT(&priv->component_infos[cCr], priv->Cr, 8);
-}
-
-/*
- * Decode a 1x2 mcu
- *  .---.
- *  | 1 |
- *  |---|
- *  | 2 |
- *  `---'
- */
-static void decode_MCU_1x2_1plane(struct jdec_private *priv)
-{
-  // Y
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y, 8);
-  process_Huffman_data_unit(priv, cY);
-  IDCT(&priv->component_infos[cY], priv->Y+64, 8);
-
-  // Cb
-  process_Huffman_data_unit(priv, cCb);
-
-  // Cr
-  process_Huffman_data_unit(priv, cCr);
-}
-
 static void print_SOF(const unsigned char *stream)
 {
   int width, height, nr_components, precision;
@@ -1842,60 +773,18 @@ int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, u
   return ret;
 }
 
-static const decode_MCU_fct decode_mcu_3comp_table[4] = {
-   decode_MCU_1x1_3planes,
-   decode_MCU_1x2_3planes,
-   decode_MCU_2x1_3planes,
-   decode_MCU_2x2_3planes,
-};
-
-static const decode_MCU_fct decode_mcu_1comp_table[4] = {
-   decode_MCU_1x1_1plane,
-   decode_MCU_1x2_1plane,
-   decode_MCU_2x1_1plane,
-   decode_MCU_2x2_1plane,
-};
-
-static const convert_colorspace_fct convert_colorspace_yuv420p[4] = {
-   YCrCB_to_YUV420P_1x1,
-   YCrCB_to_YUV420P_1x2,
-   YCrCB_to_YUV420P_2x1,
-   YCrCB_to_YUV420P_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_rgb24[4] = {
-   YCrCB_to_RGB24_1x1,
-   YCrCB_to_RGB24_1x2,
-   YCrCB_to_RGB24_2x1,
-   YCrCB_to_RGB24_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_bgr24[4] = {
-   YCrCB_to_BGR24_1x1,
-   YCrCB_to_BGR24_1x2,
-   YCrCB_to_BGR24_2x1,
-   YCrCB_to_BGR24_2x2,
-};
-
-static const convert_colorspace_fct convert_colorspace_grey[4] = {
-   YCrCB_to_Grey_1x1,
-   YCrCB_to_Grey_1x2,
-   YCrCB_to_Grey_2x1,
-   YCrCB_to_Grey_2x2,
-};
-
 /**
  * Decode and convert the jpeg image into @pixfmt@ image
  *
  * Note: components will be automaticaly allocated if no memory is attached.
  */
-int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
+int tinyjpeg_decode(struct jdec_private *priv,
+                   const struct tinyjpeg_colorspace *pixfmt)
 {
   unsigned int x, y, xstride_by_mcu, ystride_by_mcu;
   unsigned int bytes_per_blocklines[3], bytes_per_mcu[3];
   decode_MCU_fct decode_MCU;
   const decode_MCU_fct *decode_mcu_table;
-  const convert_colorspace_fct *colorspace_array_conv;
   convert_colorspace_fct convert_to_pixfmt;
 
   /* To keep gcc happy initialize some array */
@@ -1904,73 +793,30 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
   bytes_per_blocklines[1] = 0;
   bytes_per_blocklines[2] = 0;
 
-  decode_mcu_table = decode_mcu_3comp_table;
-  switch (pixfmt) {
-     case TINYJPEG_FMT_YUV420P:
-       colorspace_array_conv = convert_colorspace_yuv420p;
-       if (priv->components[0] == NULL)
-        priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);
-       if (priv->components[1] == NULL)
-        priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4);
-       if (priv->components[2] == NULL)
-        priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4);
-       bytes_per_blocklines[0] = priv->width;
-       bytes_per_blocklines[1] = priv->width/4;
-       bytes_per_blocklines[2] = priv->width/4;
-       bytes_per_mcu[0] = 8;
-       bytes_per_mcu[1] = 4;
-       bytes_per_mcu[2] = 4;
-       break;
-
-     case TINYJPEG_FMT_RGB24:
-       colorspace_array_conv = convert_colorspace_rgb24;
-       if (priv->components[0] == NULL)
-        priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);
-       bytes_per_blocklines[0] = priv->width * 3;
-       bytes_per_mcu[0] = 3*8;
-       break;
-
-     case TINYJPEG_FMT_BGR24:
-       colorspace_array_conv = convert_colorspace_bgr24;
-       if (priv->components[0] == NULL)
-        priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);
-       bytes_per_blocklines[0] = priv->width * 3;
-       bytes_per_mcu[0] = 3*8;
-       break;
-
-     case TINYJPEG_FMT_GREY:
-       decode_mcu_table = decode_mcu_1comp_table;
-       colorspace_array_conv = convert_colorspace_grey;
-       if (priv->components[0] == NULL)
-        priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);
-       bytes_per_blocklines[0] = priv->width;
-       bytes_per_mcu[0] = 8;
-       break;
-
-     default:
-       trace("Bad pixel format\n");
-       return -1;
-  }
+  decode_mcu_table = pixfmt->decode_mcu_table;
+
+  /* Fix: check return value */
+  pixfmt->initialize(priv, bytes_per_blocklines, bytes_per_mcu);
 
   xstride_by_mcu = ystride_by_mcu = 8;
   if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) {
      decode_MCU = decode_mcu_table[0];
-     convert_to_pixfmt = colorspace_array_conv[0];
+     convert_to_pixfmt = pixfmt->convert_colorspace[0];
      trace("Use decode 1x1 sampling\n");
   } else if (priv->component_infos[cY].Hfactor == 1) {
      decode_MCU = decode_mcu_table[1];
-     convert_to_pixfmt = colorspace_array_conv[1];
+     convert_to_pixfmt = pixfmt->convert_colorspace[1];
      ystride_by_mcu = 16;
      trace("Use decode 1x2 sampling (not supported)\n");
   } else if (priv->component_infos[cY].Vfactor == 2) {
      decode_MCU = decode_mcu_table[3];
-     convert_to_pixfmt = colorspace_array_conv[3];
+     convert_to_pixfmt = pixfmt->convert_colorspace[3];
      xstride_by_mcu = 16;
      ystride_by_mcu = 16;
      trace("Use decode 2x2 sampling\n");
   } else {
      decode_MCU = decode_mcu_table[2];
-     convert_to_pixfmt = colorspace_array_conv[2];
+     convert_to_pixfmt = pixfmt->convert_colorspace[2];
      xstride_by_mcu = 16;
      trace("Use decode 2x1 sampling\n");
   }
@@ -2042,4 +888,3 @@ int tinyjpeg_set_flags(struct jdec_private *priv, int flags)
   priv->flags = flags;
   return oldflags;
 }
-
diff --git a/com32/lib/jpeg/yuv420p.c b/com32/lib/jpeg/yuv420p.c
new file mode 100644 (file)
index 0000000..5411aa8
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Small jpeg decoder library
+ *
+ * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * - Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the author nor the names of its contributors may be
+ *  used to endorse or promote products derived from this software without
+ *  specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * yuv420p.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "tinyjpeg.h"
+#include "tinyjpeg-internal.h"
+
+/**
+ *  YCrCb -> YUV420P (1x1)
+ *  .---.
+ *  | 1 |
+ *  `---'
+ */
+static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv)
+{
+  const unsigned char *s, *y;
+  unsigned char *p;
+  int i,j;
+
+  p = priv->plane[0];
+  y = priv->Y;
+  for (i=0; i<8; i++)
+   {
+     memcpy(p, y, 8);
+     p+=priv->width;
+     y+=8;
+   }
+
+  p = priv->plane[1];
+  s = priv->Cb;
+  for (i=0; i<8; i+=2)
+   {
+     for (j=0; j<8; j+=2, s+=2)
+       *p++ = *s;
+     s += 8; /* Skip one line */
+     p += priv->width/2 - 4;
+   }
+
+  p = priv->plane[2];
+  s = priv->Cr;
+  for (i=0; i<8; i+=2)
+   {
+     for (j=0; j<8; j+=2, s+=2)
+       *p++ = *s;
+     s += 8; /* Skip one line */
+     p += priv->width/2 - 4;
+   }
+}
+
+/**
+ *  YCrCb -> YUV420P (2x1)
+ *  .-------.
+ *  | 1 | 2 |
+ *  `-------'
+ */
+static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv)
+{
+  unsigned char *p;
+  const unsigned char *s, *y1;
+  int i,j;
+
+  p = priv->plane[0];
+  y1 = priv->Y;
+  for (i=0; i<8; i++)
+   {
+     memcpy(p, y1, 16);
+     p += priv->width;
+     y1 += 16;
+   }
+
+  p = priv->plane[1];
+  s = priv->Cb;
+  for (i=0; i<8; i+=2)
+   {
+     for (j=0; j<8; j+=1, s+=1)
+       *p++ = *s;
+     s += 8; /* Skip one line */
+     p += priv->width/2 - 8;
+   }
+
+  p = priv->plane[2];
+  s = priv->Cr;
+  for (i=0; i<8; i+=2)
+   {
+     for (j=0; j<8; j+=1, s+=1)
+       *p++ = *s;
+     s += 8; /* Skip one line */
+     p += priv->width/2 - 8;
+   }
+}
+
+
+/**
+ *  YCrCb -> YUV420P (1x2)
+ *  .---.
+ *  | 1 |
+ *  |---|
+ *  | 2 |
+ *  `---'
+ */
+static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv)
+{
+  const unsigned char *s, *y;
+  unsigned char *p;
+  int i,j;
+
+  p = priv->plane[0];
+  y = priv->Y;
+  for (i=0; i<16; i++)
+   {
+     memcpy(p, y, 8);
+     p+=priv->width;
+     y+=8;
+   }
+
+  p = priv->plane[1];
+  s = priv->Cb;
+  for (i=0; i<8; i++)
+   {
+     for (j=0; j<8; j+=2, s+=2)
+       *p++ = *s;
+     p += priv->width/2 - 4;
+   }
+
+  p = priv->plane[2];
+  s = priv->Cr;
+  for (i=0; i<8; i++)
+   {
+     for (j=0; j<8; j+=2, s+=2)
+       *p++ = *s;
+     p += priv->width/2 - 4;
+   }
+}
+
+/**
+ *  YCrCb -> YUV420P (2x2)
+ *  .-------.
+ *  | 1 | 2 |
+ *  |---+---|
+ *  | 3 | 4 |
+ *  `-------'
+ */
+static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv)
+{
+  unsigned char *p;
+  const unsigned char *s, *y1;
+  int i;
+
+  p = priv->plane[0];
+  y1 = priv->Y;
+  for (i=0; i<16; i++)
+   {
+     memcpy(p, y1, 16);
+     p += priv->width;
+     y1 += 16;
+   }
+
+  p = priv->plane[1];
+  s = priv->Cb;
+  for (i=0; i<8; i++)
+   {
+     memcpy(p, s, 8);
+     s += 8;
+     p += priv->width/2;
+   }
+
+  p = priv->plane[2];
+  s = priv->Cr;
+  for (i=0; i<8; i++)
+   {
+     memcpy(p, s, 8);
+     s += 8;
+     p += priv->width/2;
+   }
+}
+
+static int initialize_yuv420p(struct jdec_private *priv,
+                             unsigned int *bytes_per_blocklines,
+                             unsigned int *bytes_per_mcu)
+{
+  if (priv->components[0] == NULL)
+    priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);
+  if (priv->components[1] == NULL)
+    priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4);
+  if (priv->components[2] == NULL)
+    priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4);
+  bytes_per_blocklines[0] = priv->width;
+  bytes_per_blocklines[1] = priv->width/4;
+  bytes_per_blocklines[2] = priv->width/4;
+  bytes_per_mcu[0] = 8;
+  bytes_per_mcu[1] = 4;
+  bytes_per_mcu[2] = 4;
+
+  /* Return nonzero on failure */
+  return !priv->components[0] || !priv->components[1] || !priv->components[2];
+}
+
+static const struct tinyjpeg_colorspace format_yuv420p =
+  {
+    {
+      YCrCB_to_YUV420P_1x1,
+      YCrCB_to_YUV420P_1x2,
+      YCrCB_to_YUV420P_2x1,
+      YCrCB_to_YUV420P_2x2,
+    },
+    tinyjpeg_decode_mcu_3comp_table,
+    initialize_yuv420p
+  };
+
+const tinyjpeg_colorspace_t TINYJPEG_FMT_YUV420P = &format_yuv420p;