4 * Here are the decompression function for the compressed photos and the
5 * postprocessing for uncompressed photos.
7 * Copyright (c) 2005 and 2007 Theodore Kilgore <kilgota@auburn.edu>
8 * Camera library support under libgphoto2.1.1 for camera(s)
9 * with chipset from Service & Quality Technologies, Taiwan.
10 * The chip supported by this driver is presumed to be the SQ905,
12 * Licensed under GNU Lesser General Public License, as part of Gphoto
13 * camera support project. For a copy of the license, see the file
14 * COPYING in the main source tree of libgphoto2.
30 #include <gphoto2/gphoto2.h>
31 #include <gphoto2/gphoto2-port.h>
35 #define GP_MODULE "digigr8"
38 # define MAX(a, b) ((a) > (b) ? (a) : (b))
41 # define MIN(a, b) ((a) < (b) ? (a) : (b))
45 digi_first_decompress (unsigned char *output, unsigned char *input,
46 unsigned int outputsize)
48 unsigned char parity = 0;
49 unsigned char nibble_to_keep[2];
50 unsigned char temp1 = 0, temp2 = 0;
51 unsigned char input_byte;
52 unsigned char lookup = 0;
54 unsigned int bytes_used = 0;
55 unsigned int bytes_done = 0;
56 unsigned int bit_counter = 8;
57 unsigned int cycles = 0;
58 int table[9] = { -1, 0, 2, 6, 0x0e, 0x0e, 0x0e, 0x0e, 0xfb};
59 unsigned char lookup_table[16]
60 ={0, 2, 6, 0x0e, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4,
61 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb};
62 unsigned char translator[16] =
63 {8, 7, 9, 6, 10, 11, 12, 13, 14, 15, 5, 4, 3, 2, 1, 0};
65 GP_DEBUG ("Running first_decompress.\n");
66 nibble_to_keep[0] = 0;
67 nibble_to_keep[1] = 0;
69 while (bytes_done < outputsize) {
71 while ( lookup > table[cycles]) {
72 if (bit_counter == 8) {
73 input_byte = input[bytes_used];
79 temp2 = (temp2 << 1) & 0xFF;
80 input_byte = input_byte >> 7;
81 temp2 = temp2 | input_byte;
82 temp1 = (temp1 <<1)&0xFF;
86 GP_DEBUG ("Too many cycles?\n");
89 lookup = temp2 & 0xff;
92 for (i=0; i < 17; i++ ) {
95 "Illegal lookup value during decomp\n");
98 if (lookup == lookup_table[i] ) {
99 nibble_to_keep[parity] = translator[i];
106 output[bytes_done] = (nibble_to_keep[0] << 4)
111 GP_DEBUG ("bytes_used = 0x%x = %i\n", bytes_used, bytes_used);
116 digi_second_decompress (unsigned char *uncomp, unsigned char *in,
117 int width, int height)
122 unsigned char delta_left = 0;
123 unsigned char delta_right = 0;
124 int input_counter = 0;
125 int delta_table[] = {-144, -110, -77, -53, -35, -21, -11, -3,
126 2, 10, 20, 34, 52, 76, 110, 144};
127 unsigned char *templine_red;
128 unsigned char *templine_green;
129 unsigned char *templine_blue;
130 templine_red = malloc(width);
132 return GP_ERROR_NO_MEMORY;
134 for(i=0; i < width; i++){
135 templine_red[i] = 0x80;
137 templine_green = malloc(width);
138 if (!templine_green) {
139 return GP_ERROR_NO_MEMORY;
141 for(i=0; i < width; i++){
142 templine_green[i] = 0x80;
144 templine_blue = malloc(width);
145 if (!templine_blue) {
146 return GP_ERROR_NO_MEMORY;
148 for(i=0; i < width; i++){
149 templine_blue[i] = 0x80;
151 GP_DEBUG ("Running second_decompress.\n");
152 for (m=0; m < height/2; m++) {
153 /* First we do an even-numbered line */
154 for (i=0; i< width/2; i++) {
156 delta_right = in[input_counter] &0x0f;
157 delta_left = (in[input_counter]>>4)&0xff;
159 /* left pixel (red) */
160 diff = delta_table[delta_left];
162 tempval = templine_red[0] + diff;
164 tempval = (templine_red[i]
165 + uncomp[2 *m * width + 2 * i - 2]) / 2
167 tempval = MIN(tempval, 0xff);
168 tempval = MAX(tempval, 0);
169 uncomp[2*m*width+2*i] = tempval;
170 templine_red[i] = tempval;
171 /* right pixel (green) */
172 diff = delta_table[delta_right];
174 tempval = templine_green[1] + diff;
175 else if (2*i == width - 2 )
176 tempval = (templine_green[i]
177 + uncomp[2*m*width+2*i-1])/2
180 tempval = (templine_green[i+1]
181 + uncomp[2*m*width+2*i-1])/2
183 tempval = MIN(tempval, 0xff);
184 tempval = MAX(tempval, 0);
185 uncomp[2*m*width+2*i+1] = tempval;
186 templine_green[i] = tempval;
188 /* then an odd-numbered line */
189 for (i=0; i< width/2; i++) {
190 delta_right = in[input_counter] &0x0f;
191 delta_left = (in[input_counter]>>4)&0xff;
193 /* left pixel (green) */
194 diff = delta_table[delta_left];
196 tempval = templine_green[0] + diff;
198 tempval = (templine_green[i]
199 + uncomp[(2 * m + 1) * width
200 + 2 * i - 2]) / 2 + diff;
201 tempval = MIN(tempval, 0xff);
202 tempval = MAX(tempval, 0);
203 uncomp[(2*m+1)*width+2*i] = tempval;
204 templine_green[i] = tempval;
205 /* right pixel (blue) */
206 diff = delta_table[delta_right];
208 tempval = templine_blue[0] + diff;
210 tempval = (templine_blue[i]
211 + uncomp[(2 * m + 1) * width
212 + 2 * i - 1]) / 2 + diff;
213 tempval = MIN(tempval, 0xff);
214 tempval = MAX(tempval, 0);
215 uncomp[(2*m+1)*width+2*i+1] = tempval;
216 templine_blue[i] = tempval;
219 free(templine_green);
226 digi_decompress (unsigned char *out_data, unsigned char *data,
230 unsigned char *temp_data;
232 temp_data = malloc(size);
234 return GP_ERROR_NO_MEMORY;
235 digi_first_decompress (temp_data, data, size);
236 GP_DEBUG("Stage one done\n");
237 digi_second_decompress (out_data, temp_data, w, h);
238 GP_DEBUG("Stage two done\n");
243 /* Brightness correction routine adapted from
244 * camlibs/polaroid/jd350e.c, copyright © 2001 Michael Trawny
245 * <trawny99@users.sourceforge.net>
249 #define RED(p,x,y,w) *((p)+3*((y)*(w)+(x)) )
250 #define GREEN(p,x,y,w) *((p)+3*((y)*(w)+(x))+1)
251 #define BLUE(p,x,y,w) *((p)+3*((y)*(w)+(x))+2)
254 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
257 # define MAX(a, b) ((a) > (b) ? (a) : (b))
260 # define MIN(a, b) ((a) < (b) ? (a) : (b))
263 #define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
267 digi_postprocess(int width, int height,
272 red_min=255, red_max=0,
273 blue_min=255, blue_max=0,
274 green_min=255, green_max=0;
278 /* determine min and max per color... */
280 for( y=0; y<height; y++){
281 for( x=0; x<width; x++ ){
282 MINMAX( RED(rgb,x,y,width), red_min, red_max );
283 MINMAX( GREEN(rgb,x,y,width), green_min, green_max);
284 MINMAX( BLUE(rgb,x,y,width), blue_min, blue_max );
288 /* determine min and max per color... */
290 for( y=0; y<height; y++){
291 for( x=0; x<width; x++ ){
292 MINMAX( RED(rgb,x,y,width), red_min, red_max );
293 MINMAX( GREEN(rgb,x,y,width), green_min, green_max);
294 MINMAX( BLUE(rgb,x,y,width), blue_min, blue_max );
298 /* Normalize brightness ... */
300 max = MAX( MAX( red_max, green_max ), blue_max);
301 min = MIN( MIN( red_min, green_min ), blue_min);
302 amplify = 255.0/(max-min);
304 for( y=0; y<height; y++){
305 for( x=0; x<width; x++ ){
306 RED(rgb, x, y, width)= MIN(amplify *
307 (double)(RED(rgb, x, y, width) - min), 255);
308 GREEN(rgb, x, y, width)= MIN(amplify *
309 (double)(GREEN(rgb, x, y, width) - min), 255);
310 BLUE(rgb, x, y, width)= MIN(amplify *
311 (double)(BLUE(rgb, x, y, width) -min), 255);
317 /* ===== White Balance / Color Enhance / Gamma adjust (experimental) =====
319 Get histogram for each color plane
320 Expand to reach 0.5% of white dots in image
322 Get new histogram for each color plane
323 Expand to reach 0.5% of black dots in image
326 Calculate and apply gamma correction
329 For each dot, increases color separation
331 ===================================================================== */
334 histogram (unsigned char *data, unsigned int size, int *htable_r,
335 int *htable_g, int *htable_b)
338 /* Initializations */
339 for (x = 0; x < 0x100; x++) {
344 /* Building the histograms */
345 for (x = 0; x < (size * 3); x += 3)
347 htable_r[data[x+0]]++; /* red histogram */
348 htable_g[data[x+1]]++; /* green histogram */
349 htable_b[data[x+2]]++; /* blue histogram */
355 white_balance (unsigned char *data, unsigned int size, float saturation)
357 int x, r, g, b, max, d;
358 double r_factor, g_factor, b_factor, max_factor;
359 int htable_r[0x100], htable_g[0x100], htable_b[0x100];
360 unsigned char gtable[0x100];
361 double new_gamma, gamma=1.0;
363 /* ------------------- GAMMA CORRECTION ------------------- */
365 histogram(data, size, htable_r, htable_g, htable_b);
367 for (r = 64; r < 192; r++)
373 new_gamma = sqrt((double) (x * 1.5) / (double) (size * 3));
374 GP_DEBUG("Provisional gamma correction = %1.2f\n", new_gamma);
375 /* Recalculate saturation factor for later use. */
376 saturation=saturation*new_gamma*new_gamma;
377 GP_DEBUG("saturation = %1.2f\n", saturation);
379 if (new_gamma < .70) gamma = 0.70;
380 if (new_gamma > 1.2) gamma = 1.2;
381 GP_DEBUG("Gamma correction = %1.2f\n", gamma);
382 gp_gamma_fill_table(gtable, gamma);
383 gp_gamma_correct_single(gtable,data,size);
384 if (saturation < .5 ) /* If so, exit now. */
387 /* ---------------- BRIGHT DOTS ------------------- */
389 histogram(data, size, htable_r, htable_g, htable_b);
391 for (r=0xfe, x=0; (r > 32) && (x < max); r--)
393 for (g=0xfe, x=0; (g > 32) && (x < max); g--)
395 for (b=0xfe, x=0; (b > 32) && (x < max); b--)
397 r_factor = (double) 0xfd / r;
398 g_factor = (double) 0xfd / g;
399 b_factor = (double) 0xfd / b;
401 max_factor = r_factor;
402 if (g_factor > max_factor) max_factor = g_factor;
403 if (b_factor > max_factor) max_factor = b_factor;
404 if (max_factor >= 4.0) {
405 /* We need a little bit of control, here. If max_factor > 4 the photo
406 * was very dark, after all.
408 if (2.0*b_factor < max_factor)
409 b_factor = max_factor/2.;
410 if (2.0*r_factor < max_factor)
411 r_factor = max_factor/2.;
412 if (2.0*g_factor < max_factor)
413 g_factor = max_factor/2.;
414 r_factor = (r_factor / max_factor) * 4.0;
415 g_factor = (g_factor / max_factor) * 4.0;
416 b_factor = (b_factor / max_factor) * 4.0;
419 if (max_factor > 1.5)
421 GP_DEBUG("White balance (bright): r=%1d, g=%1d, b=%1d, \
422 r_factor=%1.3f, g_factor=%1.3f, b_factor=%1.3f\n",
423 r, g, b, r_factor, g_factor, b_factor);
424 if (max_factor <= 1.4) {
425 for (x = 0; x < (size * 3); x += 3)
427 d = (data[x+0]<<8) * r_factor+8;
432 d = (data[x+1]<<8) * g_factor+8;
434 if (d > 0xff) { d = 0xff; }
436 d = (data[x+2]<<8) * b_factor+8;
443 /* ---------------- DARK DOTS ------------------- */
444 max = size / 200; /* 1/200 = 0.5% */
445 histogram(data, size, htable_r, htable_g, htable_b);
447 for (r = 0, x = 0; r < 96 && x < max; r++)
449 for (g = 0, x = 0; g < 96 && x < max; g++)
451 for (b = 0, x = 0; b < 96 && x < max; b++)
454 r_factor = (double) 0xfe / (0xff-r);
455 g_factor = (double) 0xfe / (0xff-g);
456 b_factor = (double) 0xfe / (0xff-b);
459 "White balance (dark): r=%1d, g=%1d, b=%1d, \
460 r_factor=%1.3f, g_factor=%1.3f, b_factor=%1.3f\n",
461 r, g, b, r_factor, g_factor, b_factor);
463 for (x = 0; x < (size * 3); x += 3)
465 d = (int) 0xff08-(((0xff-data[x+0])<<8) * r_factor);
470 d = (int) 0xff08-(((0xff-data[x+1])<<8) * g_factor);
475 d = (int) 0xff08-(((0xff-data[x+2])<<8) * b_factor);
482 /* ------------------ COLOR ENHANCE ------------------ */
484 if(saturation > 0.0) {
485 for (x = 0; x < (size * 3); x += 3)
487 r = data[x+0]; g = data[x+1]; b = data[x+2];
488 d = (int) (r + g + b) / 3.;
490 r = r + (int) ((r - d) * (0xff - r)
491 /(0x100 - d) * saturation);
493 r = r + (int) ((r - d) * (0xff - d)
494 / (0x100 - r) * saturation);
496 g = g + (int) ((g - d) * (0xff - g)
497 / (0x100 - d) * saturation);
499 g = g + (int) ((g - d) * (0xff - d)
500 / (0x100 - g) * saturation);
502 b = b + (int) ((b - d) * (0xff - b)
503 /(0x100 - d) * saturation);
505 b = b + (int) ((b - d) * (0xff - d)
506 /(0x100 - b) * saturation);
507 data[x+0] = CLAMP(r);
508 data[x+1] = CLAMP(g);
509 data[x+2] = CLAMP(b);