Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / digigr8 / digi_postprocess.c
1 /*
2  * postprocess.c
3  *
4  * Here are the decompression function  for the compressed photos and the 
5  * postprocessing for uncompressed photos. 
6  *
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,  
11  *
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.
15  */    
16
17 #include <config.h>
18
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <math.h>
26 #ifdef OS2
27 #include <db.h>
28 #endif
29
30 #include <gphoto2/gphoto2.h>
31 #include <gphoto2/gphoto2-port.h>
32 #include <gamma.h>
33 #include "digigr8.h"
34
35 #define GP_MODULE "digigr8" 
36
37 #ifndef MAX
38 # define MAX(a, b) ((a) > (b) ? (a) : (b))
39 #endif
40 #ifndef MIN
41 # define MIN(a, b) ((a) < (b) ? (a) : (b))
42 #endif
43
44 static int
45 digi_first_decompress (unsigned char *output, unsigned char *input,
46                                             unsigned int outputsize)
47 {
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;
53         unsigned int i = 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};
64
65         GP_DEBUG ("Running first_decompress.\n");
66         nibble_to_keep[0] = 0;
67         nibble_to_keep[1] = 0;
68
69         while (bytes_done < outputsize) {
70                 while (parity < 2 ) {
71                         while ( lookup > table[cycles]) {
72                                 if (bit_counter == 8) {
73                                         input_byte = input[bytes_used];
74                                         bytes_used ++;
75                                         temp1 = input_byte;
76                                         bit_counter = 0;
77                                 }
78                                 input_byte = temp1;
79                                 temp2 = (temp2 << 1) & 0xFF;
80                                 input_byte = input_byte >> 7;
81                                 temp2 = temp2 | input_byte;
82                                 temp1 = (temp1 <<1)&0xFF;
83                                 bit_counter ++ ;
84                                 cycles ++ ;
85                                 if (cycles > 8) {
86                                         GP_DEBUG ("Too many cycles?\n");
87                                         return GP_ERROR; 
88                                 }
89                                 lookup = temp2 & 0xff;        
90                         }
91                         temp2 = 0;
92                         for (i=0; i < 17; i++ ) {
93                                 if (i == 16) {
94                                         GP_DEBUG(
95                                         "Illegal lookup value during decomp\n");
96                                         return GP_ERROR;
97                                 }
98                                 if (lookup == lookup_table[i] ) {
99                                         nibble_to_keep[parity] = translator[i];
100                                         break;  
101                                 }
102                         }               
103                         cycles = 0;
104                         parity ++ ;
105                 } 
106                 output[bytes_done] = (nibble_to_keep[0] << 4)
107                                                 | nibble_to_keep[1];
108                 bytes_done ++ ;
109                 parity = 0; 
110         }
111         GP_DEBUG ("bytes_used = 0x%x = %i\n", bytes_used, bytes_used);        
112         return GP_OK;
113 }
114
115 static int
116 digi_second_decompress (unsigned char *uncomp, unsigned char *in, 
117                                                     int width, int height)
118 {
119         int diff = 0;
120         int tempval = 0;
121         int i, m, parity;
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);
131         if (!templine_red) {
132                 return GP_ERROR_NO_MEMORY;
133         }       
134         for(i=0; i < width; i++){
135             templine_red[i] = 0x80;
136         }
137         templine_green = malloc(width); 
138         if (!templine_green) {
139                 return GP_ERROR_NO_MEMORY;
140         }       
141         for(i=0; i < width; i++){
142                 templine_green[i] = 0x80;
143         }
144         templine_blue = malloc(width);  
145         if (!templine_blue) {
146                 return GP_ERROR_NO_MEMORY;
147         }       
148         for(i=0; i < width; i++){
149                 templine_blue[i] = 0x80;
150         }
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++) {
155                         parity = i&1;
156                         delta_right = in[input_counter] &0x0f;
157                         delta_left = (in[input_counter]>>4)&0xff;
158                         input_counter ++;
159                         /* left pixel (red) */
160                         diff = delta_table[delta_left];
161                         if (!i) 
162                                 tempval = templine_red[0] + diff;
163                         else 
164                                 tempval = (templine_red[i]
165                                     + uncomp[2 *m * width + 2 * i - 2]) / 2
166                                                                     + diff;
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];
173                         if (!i) 
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 
178                                                         + diff;
179                         else
180                                 tempval = (templine_green[i+1]
181                                                 + uncomp[2*m*width+2*i-1])/2 
182                                                         + diff;
183                         tempval = MIN(tempval, 0xff);
184                         tempval = MAX(tempval, 0);
185                         uncomp[2*m*width+2*i+1] = tempval;
186                         templine_green[i] = tempval;
187                 }
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;
192                         input_counter ++;
193                         /* left pixel (green) */
194                         diff = delta_table[delta_left];
195                         if (!i) 
196                                 tempval = templine_green[0] + diff;
197                         else 
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];
207                         if (!i) 
208                                 tempval = templine_blue[0] + diff;
209                         else 
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;
217                 }
218         }
219         free(templine_green);
220         free(templine_red);
221         free(templine_blue);
222         return GP_OK;
223 }
224
225 int
226 digi_decompress (unsigned char *out_data, unsigned char *data,
227             int w, int h)
228 {
229         int size;
230         unsigned char *temp_data;
231         size = w*h/2;
232         temp_data = malloc(size);
233         if (!temp_data) 
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");
239         free(temp_data);
240         return(GP_OK);
241 }
242
243 /* Brightness correction routine adapted from 
244  * camlibs/polaroid/jd350e.c, copyright Â© 2001 Michael Trawny 
245  * <trawny99@users.sourceforge.net>
246  */
247
248
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)
252
253
254 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
255
256 #ifndef MAX
257 # define MAX(a, b) ((a) > (b) ? (a) : (b))
258 #endif
259 #ifndef MIN
260 # define MIN(a, b) ((a) < (b) ? (a) : (b))
261 #endif
262 #ifndef CLAMP
263 #define CLAMP(x)        ((x)<0?0:((x)>255)?255:(x))
264 #endif
265
266 int 
267 digi_postprocess(int width, int height, 
268                                         unsigned char* rgb)
269 {
270         int
271                 x,y,
272                 red_min=255, red_max=0, 
273                 blue_min=255, blue_max=0, 
274                 green_min=255, green_max=0;
275         double
276                 min, max, amplify; 
277
278         /* determine min and max per color... */
279
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 );
285                 }
286         }
287
288         /* determine min and max per color... */
289
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 );
295                 }
296         }
297
298         /* Normalize brightness ... */
299
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);
303
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);
312                 }
313         }
314         return GP_OK;
315 }
316
317 /*      ===== White Balance / Color Enhance / Gamma adjust (experimental) =====
318
319         Get histogram for each color plane
320         Expand to reach 0.5% of white dots in image
321
322         Get new histogram for each color plane
323         Expand to reach 0.5% of black dots in image
324
325         Get new histogram
326         Calculate and apply gamma correction
327
328         if not a dark image:
329         For each dot, increases color separation
330
331         ===================================================================== */
332
333 static int
334 histogram (unsigned char *data, unsigned int size, int *htable_r, 
335                                             int *htable_g, int *htable_b)
336 {
337         int x;
338         /* Initializations */
339         for (x = 0; x < 0x100; x++) { 
340                 htable_r[x] = 0; 
341                 htable_g[x] = 0; 
342                 htable_b[x] = 0; 
343         }
344         /* Building the histograms */
345         for (x = 0; x < (size * 3); x += 3)
346         {
347                 htable_r[data[x+0]]++;  /* red histogram */
348                 htable_g[data[x+1]]++;  /* green histogram */
349                 htable_b[data[x+2]]++;  /* blue histogram */
350         }
351         return GP_OK;
352 }
353
354 int
355 white_balance (unsigned char *data, unsigned int size, float saturation)
356 {
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;
362
363         /* ------------------- GAMMA CORRECTION ------------------- */
364
365         histogram(data, size, htable_r, htable_g, htable_b);
366         x = 1;
367         for (r = 64; r < 192; r++)
368         {
369                 x += htable_r[r]; 
370                 x += htable_g[r];
371                 x += htable_b[r];
372         }
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);
378         gamma = new_gamma;
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. */ 
385                 return GP_OK;
386
387         /* ---------------- BRIGHT DOTS ------------------- */
388         max = size / 200; 
389         histogram(data, size, htable_r, htable_g, htable_b);
390
391         for (r=0xfe, x=0; (r > 32) && (x < max); r--)  
392                 x += htable_r[r]; 
393         for (g=0xfe, x=0; (g > 32) && (x < max); g--) 
394                 x += htable_g[g];
395         for (b=0xfe, x=0; (b > 32) && (x < max); b--) 
396                 x += htable_b[b];
397         r_factor = (double) 0xfd / r;
398         g_factor = (double) 0xfd / g;
399         b_factor = (double) 0xfd / b;
400
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. 
407          */
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;
417         }
418
419         if (max_factor > 1.5) 
420                 saturation = 0;
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)
426                 {
427                         d = (data[x+0]<<8) * r_factor+8;
428                         d >>=8;
429                         if (d > 0xff) 
430                                 d = 0xff;
431                         data[x+0] = d;
432                         d = (data[x+1]<<8) * g_factor+8;
433                         d >>=8;
434                         if (d > 0xff) { d = 0xff; }
435                         data[x+1] = d;
436                         d = (data[x+2]<<8) * b_factor+8;
437                         d >>=8;
438                         if (d > 0xff) 
439                                 d = 0xff;
440                         data[x+2] = d;
441                 }
442         }
443         /* ---------------- DARK DOTS ------------------- */
444         max = size / 200;  /*  1/200 = 0.5%  */
445         histogram(data, size, htable_r, htable_g, htable_b);
446
447         for (r = 0, x = 0; r < 96 && x < max; r++)
448                 x += htable_r[r]; 
449         for (g = 0, x = 0; g < 96 && x < max; g++)
450                 x += htable_g[g];
451         for (b = 0, x = 0; b < 96 && x < max; b++)
452                 x += htable_b[b];
453
454         r_factor = (double) 0xfe / (0xff-r);
455         g_factor = (double) 0xfe / (0xff-g);
456         b_factor = (double) 0xfe / (0xff-b);
457
458         GP_DEBUG(
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);
462
463         for (x = 0; x < (size * 3); x += 3)
464         {
465                 d = (int) 0xff08-(((0xff-data[x+0])<<8) * r_factor);
466                 d >>= 8;
467                 if (d < 0)
468                          d = 0;
469                 data[x+0] = d;
470                 d = (int) 0xff08-(((0xff-data[x+1])<<8) * g_factor);
471                 d >>= 8;
472                 if (d < 0)
473                         d = 0;
474                 data[x+1] = d;
475                 d = (int) 0xff08-(((0xff-data[x+2])<<8) * b_factor);
476                 d >>= 8;
477                 if (d < 0)
478                         d = 0;
479                 data[x+2] = d;
480         }
481
482         /* ------------------ COLOR ENHANCE ------------------ */
483
484         if(saturation > 0.0) {
485                 for (x = 0; x < (size * 3); x += 3)
486                 {
487                         r = data[x+0]; g = data[x+1]; b = data[x+2];
488                         d = (int) (r + g + b) / 3.;
489                         if ( r > d )
490                                 r = r + (int) ((r - d) * (0xff - r)
491                                                 /(0x100 - d) * saturation);
492                         else 
493                                 r = r + (int) ((r - d) * (0xff - d)
494                                                 / (0x100 - r) * saturation);
495                         if (g > d)
496                                 g = g + (int) ((g - d) * (0xff - g)
497                                                 / (0x100 - d) * saturation);
498                         else 
499                                 g = g + (int) ((g - d) * (0xff - d)
500                                                 / (0x100 - g) * saturation);
501                         if (b > d)
502                                 b = b + (int) ((b - d) * (0xff - b)
503                                                 /(0x100 - d) * saturation);
504                         else 
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);
510                 }
511         }
512         return GP_OK;
513 }