• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * sn9c2028-decomp.c
3  *
4  * Decompression function for the Sonix SN9C2028 dual-mode cameras.
5  *
6  * Code adapted from libgphoto2/camlibs/sonix, original version of which was
7  * Copyright (c) 2005 Theodore Kilgore <kilgota@auburn.edu>
8  *
9  * History:
10  *
11  * This decoding algorithm originates from the work of Bertrik Sikken for the
12  * SN9C102 cameras. This version is an adaptation of work done by Mattias
13  * Krauss for the webcam-osx (macam) project. There, it was further adapted
14  * for use with the Vivitar Vivicam 3350B (an SN9C2028 camera) by
15  * Harald Ruda <hrx@users.sourceforge.net>. Harald brought to my attention the
16  * work done in the macam project and suggested that I use it. One improvement
17  * of my own was to notice that the even and odd columns of the image have been
18  * reversed by the decompression algorithm, and this needs to be corrected
19  * during the decompression.
20  *
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU Lesser General Public
24  * License as published by the Free Software Foundation; either
25  * version 2.1 of the License, or (at your option) any later version.
26  *
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31  * Lesser General Public License for more details.
32  *
33  * You should have received a copy of the GNU Lesser General Public
34  * License along with this program; if not, write to the
35  * Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
36  * Boston, MA 02111-1307, USA.
37  */
38 
39 #include "libv4lconvert-priv.h"
40 
41 /* Four defines for bitstream operations, used in the decode function */
42 
43 #define PEEK_BITS(num, to) { \
44 	if (bitBufCount < num) { \
45 		do { \
46 			bitBuf = (bitBuf << 8) | (*(src++)); \
47 			bitBufCount += 8; \
48 		} while (bitBufCount < 24); \
49 	} \
50 	to = bitBuf >> (bitBufCount - num); \
51 }
52 
53 /*
54  * PEEK_BITS puts the next <num> bits into the low bits of <to>.
55  * when the buffer is empty, it is completely refilled.
56  * This strategy tries to reduce memory access. Note that the high bits
57  * are NOT set to zero!
58  */
59 
60 #define EAT_BITS(num) { bitBufCount -= num; bits_eaten += num; }
61 
62 /*
63  * EAT_BITS consumes <num> bits (PEEK_BITS does not consume anything,
64  * it just peeks)
65  */
66 
67 #define PARSE_PIXEL(val) {\
68 	PEEK_BITS(10, bits);\
69 	if ((bits & 0x200) == 0) {\
70 		EAT_BITS(1);\
71 	} \
72 	else if ((bits & 0x380) == 0x280) {\
73 		EAT_BITS(3);\
74 		val += 3;\
75 		if (val > 255)\
76 			val = 255;\
77 	} \
78 	else if ((bits & 0x380) == 0x300) {\
79 		EAT_BITS(3);\
80 		val -= 3;\
81 		if (val < 0)\
82 			val = 0;\
83 	} \
84 	else if ((bits & 0x3c0) == 0x200) {\
85 		EAT_BITS(4);\
86 		val += 8;\
87 		if (val > 255)\
88 			val = 255;\
89 	} \
90 	else if ((bits & 0x3c0) == 0x240) {\
91 		EAT_BITS(4);\
92 		val -= 8;\
93 		if (val < 0)\
94 			val = 0;\
95 	} \
96 	else if ((bits & 0x3c0) == 0x3c0) {\
97 		EAT_BITS(4);\
98 		val -= 20;\
99 		if (val < 0)\
100 			val = 0;\
101 	} \
102 	else if ((bits & 0x3e0) == 0x380) {\
103 		EAT_BITS(5);\
104 		val += 20;\
105 		if (val > 255)\
106 			val = 255;\
107 	} \
108 	else {\
109 		EAT_BITS(10);\
110 		val = 8 * (bits & 0x1f);\
111 	} \
112 }
113 
114 
115 #define PUT_PIXEL_PAIR {\
116 	long pp;\
117 	pp = (c1val << 8) + c2val;\
118 	*((unsigned short *)(dst + dst_index)) = pp;\
119 	dst_index += 2;\
120 }
121 
122 /* Now the decode function itself */
123 
v4lconvert_decode_sn9c2028(const unsigned char * src,unsigned char * dst,int width,int height)124 void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst,
125 		int width, int height)
126 {
127 	long dst_index = 0;
128 	int starting_row = 0;
129 	unsigned short bits;
130 	short c1val, c2val;
131 	int x, y;
132 	unsigned long bitBuf = 0;
133 	unsigned long bitBufCount = 0;
134 	unsigned long bits_eaten = 0;
135 
136 	src += 12;    /* Remove the header */
137 
138 	for (y = starting_row; y < height; y++) {
139 		PEEK_BITS(8, bits);
140 		EAT_BITS(8);
141 		c2val = (bits & 0xff);
142 		PEEK_BITS(8, bits);
143 		EAT_BITS(8);
144 		c1val = (bits & 0xff);
145 
146 		PUT_PIXEL_PAIR;
147 
148 		for (x = 2; x < width ; x += 2) {
149 			/* The compression reversed the even and odd columns.*/
150 			PARSE_PIXEL(c2val);
151 			PARSE_PIXEL(c1val);
152 			PUT_PIXEL_PAIR;
153 		}
154 	}
155 }
156