aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libv4lconvert/jl2005bcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libv4lconvert/jl2005bcd.c')
-rw-r--r--lib/libv4lconvert/jl2005bcd.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/lib/libv4lconvert/jl2005bcd.c b/lib/libv4lconvert/jl2005bcd.c
new file mode 100644
index 00000000..f3dbf203
--- /dev/null
+++ b/lib/libv4lconvert/jl2005bcd.c
@@ -0,0 +1,211 @@
+/* jl2005bcd.c
+ *
+ * Converts raw output from Jeilin JL2005B/C/D to Bayer output.
+ *
+ * The code is based upon what is found in libgphoto2/camlibs/jl2005c,
+ * Copyright (c) 2010 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * The decompression code used is
+ * Copyright (c) 2010 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libv4lconvert-priv.h"
+#include "jpeg_memsrcdest.h"
+#include "libv4lsyscall-priv.h"
+
+
+#define JPEG_HEADER_SIZE 338
+#define JPEG_HEIGHT_OFFSET 94
+
+static int
+find_eoi(const unsigned char *jpeg_data, int jpeg_data_idx, int jpeg_data_size)
+{
+ int i;
+
+ for (i = jpeg_data_idx; i < (jpeg_data_size - 1); i++)
+ if (jpeg_data[i] == 0xff && jpeg_data[i + 1] == 0xd9)
+ break;
+
+ if (i >= (jpeg_data_size - 1)) {
+ printf("AAI\n");
+ return -1;
+ }
+
+ return i + 2; /* + 2 -> Point to after EOI marker */
+}
+
+
+int v4lconvert_decode_jl2005bcd(struct v4lconvert_data *data,
+ const unsigned char *src, int src_size,
+ unsigned char *dest, int width, int height)
+{
+ unsigned char jpeg_stripe[50000];
+ int q;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_decompress_struct dinfo;
+ struct jpeg_error_mgr jcerr, jderr;
+ JOCTET *jpeg_header = NULL;
+ unsigned long jpeg_header_size = 0;
+ int i, x, y, x1, y1, jpeg_data_size, jpeg_data_idx, eoi, size;
+
+ /* src_size had better be bigger than 16 */
+ if (src_size < 16)
+ return 1;
+
+ /* The first 16 bytes of src are a raw frame header */
+ q = src[13] & 0x7f;
+
+ if (height != src[4] << 3) {
+ printf("Height is %d, not %d\n", src[4] << 3, height);
+ return 1;
+ }
+
+ if (width != src[5] << 3) {
+ printf("Width is %d, not %d\n", src[5] << 3, width);
+ return 1;
+ }
+ printf("quality is %d\n", q);
+ printf("size: %dx%d\n", width, height);
+ /*
+ * And the fun begins, first of all create a dummy jpeg, which we use
+ * to get the headers from to feed to libjpeg when decompressing the
+ * stripes. This way we can use libjpeg's quant table handling
+ * (and built in default huffman tables).
+ */
+ cinfo.err = jpeg_std_error (&jcerr);
+ jpeg_create_compress (&cinfo);
+ jpeg_mem_dest (&cinfo, &jpeg_header, &jpeg_header_size);
+ cinfo.image_width = 16;
+ cinfo.image_height = 16;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults (&cinfo);
+ /* Make comp[0] (which will be green) 1x2 subsampled */
+ cinfo.comp_info[0].h_samp_factor = 1;
+ cinfo.comp_info[0].v_samp_factor = 2;
+ /* Make comp[1] and [2] use huffman table and quanttable 0, as all
+ * components use luminance settings with the jl2005c/d/e */
+ cinfo.comp_info[1].quant_tbl_no = 0;
+ cinfo.comp_info[1].dc_tbl_no = 0;
+ cinfo.comp_info[1].ac_tbl_no = 0;
+ cinfo.comp_info[2].quant_tbl_no = 0;
+ cinfo.comp_info[2].dc_tbl_no = 0;
+ cinfo.comp_info[2].ac_tbl_no = 0;
+ /* Apply the quality setting from the header */
+ if (q <= 0)
+ i = 5000;
+ else if (q <= 50)
+ i = 5000 / q;
+ else if (q <= 100)
+ i = 2 * (100 - q);
+ else
+ i = 0;
+ jpeg_set_linear_quality(&cinfo, i, TRUE);
+
+ jpeg_start_compress (&cinfo, TRUE);
+ while( cinfo.next_scanline < cinfo.image_height ) {
+ JOCTET row[16 * 3];
+ JSAMPROW row_pointer[1] = { row };
+ jpeg_write_scanlines (&cinfo, row_pointer, 1);
+ }
+ jpeg_finish_compress (&cinfo);
+ jpeg_destroy_compress (&cinfo);
+
+ JSAMPLE green[8 * 16];
+ JSAMPLE red[8 * 8];
+ JSAMPLE blue[8 * 8];
+ JSAMPROW green_row_pointer[16];
+ JSAMPROW red_row_pointer[8];
+ JSAMPROW blue_row_pointer[8];
+
+ for (i = 0; i < 16; i++)
+ green_row_pointer[i] = green + i * 8;
+
+ for (i = 0; i < 8; i++) {
+ red_row_pointer[i] = red + i * 8;
+ blue_row_pointer[i] = blue + i * 8;
+ }
+
+ JSAMPARRAY samp_image[3] = { green_row_pointer,
+ red_row_pointer,
+ blue_row_pointer };
+
+ memcpy(jpeg_stripe, jpeg_header, JPEG_HEADER_SIZE);
+ jpeg_stripe[JPEG_HEIGHT_OFFSET ] = height >> 8;
+ jpeg_stripe[JPEG_HEIGHT_OFFSET + 1] = height;
+ jpeg_stripe[JPEG_HEIGHT_OFFSET + 2] = 0;
+ jpeg_stripe[JPEG_HEIGHT_OFFSET + 3] = 8;
+ free (jpeg_header);
+ /* Get past the raw frame header. */
+ src += 16;
+ jpeg_data_size = src_size - 16;
+
+ jpeg_data_idx = 0;
+
+
+ dinfo.err = jpeg_std_error (&jderr);
+ jpeg_create_decompress (&dinfo);
+ for (x = 0; x < width; x += 16) {
+ eoi = find_eoi(src, jpeg_data_idx, jpeg_data_size);
+ if (eoi < 0)
+ return eoi;
+
+ size = eoi - jpeg_data_idx;
+ if ((JPEG_HEADER_SIZE + size) > sizeof(jpeg_stripe)) {
+ printf("AAAIIIIII\n");
+ return 1;
+ }
+ memcpy (jpeg_stripe + JPEG_HEADER_SIZE,
+ src + jpeg_data_idx, size);
+
+ jpeg_mem_src (&dinfo, jpeg_stripe, JPEG_HEADER_SIZE + size);
+ jpeg_read_header (&dinfo, TRUE);
+ dinfo.raw_data_out = TRUE;
+#if JPEG_LIB_VERSION >= 70
+ dinfo.do_fancy_upsampling = FALSE;
+#endif
+ jpeg_start_decompress (&dinfo);
+ for (y = 0; y < height; y += 16) {
+ jpeg_read_raw_data (&dinfo, samp_image, 16);
+ for (y1 = 0; y1 < 16; y1 += 2) {
+ for (x1 = 0; x1 < 16; x1 += 2) {
+ dest[((y + y1 + 0) * width
+ + x + x1 + 0)]
+ = red[y1 * 4 + x1 / 2];
+ dest[((y + y1 + 0) * width
+ + x + x1 + 1)]
+ = green[y1 * 8 + x1 / 2];
+ dest[((y + y1 + 1) * width
+ + x + x1 + 0)]
+ = green[y1 * 8 + 8 + x1 / 2];
+ dest[((y + y1 + 1) * width
+ + x + x1 + 1)]
+ = blue[y1 * 4 + x1 / 2];
+ }
+ }
+ }
+ jpeg_finish_decompress (&dinfo);
+
+ /* Set jpeg_data_idx for the next stripe */
+ jpeg_data_idx = (jpeg_data_idx + size + 0x0f) & ~0x0f;
+ }
+ jpeg_destroy_decompress(&dinfo);
+ return 0;
+}

Privacy Policy