Source code upload
[framework/connectivity/libgphoto2.git] / camlibs / polaroid / jd350e.c
1 /* jd350e.c
2  *
3  * White balancing and brightness correction for the Jenoptik 
4  * JD350 entrance camera
5  *
6  * Copyright © 2001 Michael Trawny <trawny99@users.sourceforge.net>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, 
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details. 
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <gphoto2/gphoto2-library.h>
29 #include <gphoto2/gphoto2-port-log.h>
30
31 #include "jd350e.h"
32 #include "jd350e_red.h"
33 /*#include "jd350e_blue.h"*/
34
35 #define GP_MODULE "jd350e"
36
37 #define THRESHOLD 0xf8
38
39 #define RED(p,x,y,w) *((p)+3*((y)*(w)+(x))  )
40 #define GREEN(p,x,y,w) *((p)+3*((y)*(w)+(x))+1)
41 #define BLUE(p,x,y,w) *((p)+3*((y)*(w)+(x))+2)
42
43 #define SWAP(a,b) {unsigned char t=(a); (a)=(b); (b)=t;}
44
45 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
46
47 #ifndef MAX
48 # define MAX(a, b) ((a) > (b) ? (a) : (b))
49 #endif
50 #ifndef MIN
51 # define MIN(a, b) ((a) < (b) ? (a) : (b))
52 #endif
53
54
55 int jd350e_postprocessing(int width, int height, unsigned char* rgb){
56         int
57                 x,y,
58                 red_min=255, red_max=0, 
59                 blue_min=255, blue_max=0, 
60                 green_min=255, green_max=0;
61         double
62                 min, max, amplify;
63
64         /* reverse image row by row... */
65
66         for( y=0; y<height; y++){
67                 for( x=0; x<width/2; x++ ){
68                         SWAP( RED(rgb,x,y,width), RED(rgb,width-x-1,y,width));
69                         SWAP( GREEN(rgb,x,y,width), GREEN(rgb,width-x-1,y,width));
70                         SWAP( BLUE(rgb,x,y,width), BLUE(rgb,width-x-1,y,width));
71                 }
72         }
73
74         /* determine min and max per color... */
75
76         for( y=0; y<height; y++){
77                 for( x=0; x<width; x++ ){
78                         MINMAX( RED(rgb,x,y,width), red_min,   red_max  );
79                         MINMAX( GREEN(rgb,x,y,width), green_min, green_max);
80                         MINMAX( BLUE(rgb,x,y,width), blue_min,  blue_max );
81                 }
82         }
83
84         /* white balancing ...                               */
85         /* here is still some work to do: either blue or red */
86         /* pixles need to be emphasized.                     */
87         /* but how can the driver decide?                    */
88
89 #if 0
90         if( (green_max+blue_max)/2 > red_max ){
91 #endif
92                 /* outdoor daylight : red color correction curve*/
93                 GP_DEBUG( "daylight mode");
94                 for( y=0; y<height; y++){
95                         for( x=0; x<width; x++ ){
96                                 RED(rgb,x,y,width) = jd350e_red_curve[ RED(rgb,x,y,width) ];
97                         /* RED(rgb,x,y,width) = MIN(2*(unsigned)RED(rgb,x,y,width),255); */
98                         }
99                 }
100                 red_min = jd350e_red_curve[ red_min ];
101                 red_max = jd350e_red_curve[ red_max ];
102                 /* red_min = MIN(2*(unsigned)red_min,255); */
103                 /* red_max = MIN(2*(unsigned)red_max,255); */
104 #if 0
105         }
106         else if( (green_max+red_max)/2 > blue_max ){
107                 /* indoor electric light */
108                 GP_DEBUG( "electric light mode");
109                 for( y=0; y<height; y++){
110                         for( x=0; x<width; x++ ){
111                                 BLUE(rgb,x,y,width) = MIN(2*(unsigned)BLUE(rgb,x,y,width),255);
112                         }
113                 }
114                 blue_min = MIN(2*(unsigned)blue_min,255);
115                 blue_max = MIN(2*(unsigned)blue_max,255);
116         }
117 #endif
118
119         /* Normalize brightness ... */
120
121         max = MAX( MAX( red_max, green_max ), blue_max);
122         min = MIN( MIN( red_min, green_min ), blue_min);
123         amplify = 255.0/(max-min);
124
125         for( y=0; y<height; y++){
126                 for( x=0; x<width; x++ ){
127                         RED(rgb,x,y,width)= MIN(amplify*(double)(RED(rgb,x,y,width)-min),255);
128                         GREEN(rgb,x,y,width)= MIN(amplify*(double)(GREEN(rgb,x,y,width)-min),255);
129                         BLUE(rgb,x,y,width)= MIN(amplify*(double)(BLUE(rgb,x,y,width)-min),255);
130                 }
131         }
132
133         return GP_OK;
134 }
135
136 int jd350e_postprocessing_and_flip(int width, int height, unsigned char* rgb){
137         char *tmpline;
138         int y, ret;
139
140         ret = jd350e_postprocessing (width,height,rgb);
141         if (ret < GP_OK)
142                 return ret;
143         tmpline = malloc(width*3);
144         if (!tmpline)
145                 return GP_ERROR_NO_MEMORY;
146         for( y=0; y<height/2; y++){
147                 memcpy (tmpline, rgb+y*width*3, width*3);
148                 memcpy (rgb+y*width*3, rgb+(height-y-1)*width*3, width*3);
149                 memcpy (rgb+(height-y-1)*width*3, tmpline, width*3);
150         }
151         free(tmpline);
152         return GP_OK;
153 }
154
155 int trust350fs_postprocessing(int width, int height, unsigned char* rgb) {
156         int             i,x,y,min=255,max=0;
157         double          amplify;
158         unsigned char   *buf;
159         const int       brightness_adjust = 16;
160         
161         /* flip horizontal */
162 #define RED(p,x,y,w) *((p)+3*((y)*(w)+(x))  )
163 #define GREEN(p,x,y,w) *((p)+3*((y)*(w)+(x))+1)
164 #define BLUE(p,x,y,w) *((p)+3*((y)*(w)+(x))+2)
165
166 #define SWAP(a,b) {unsigned char t=(a); (a)=(b); (b)=t;}
167
168         for( y=0; y<height; y++){
169                 for( x=0; x<width/2; x++ ){
170                         SWAP( RED(rgb,x,y,width), RED(rgb,width-x-1,y,width));
171                         SWAP( GREEN(rgb,x,y,width), GREEN(rgb,width-x-1,y,width));
172                         SWAP( BLUE(rgb,x,y,width), BLUE(rgb,width-x-1,y,width));
173                 }
174         }
175         
176         /* flip vertical */
177         buf = malloc(width*3);
178         if (!buf) return GP_ERROR_NO_MEMORY;
179         for (i=0;i<height/2;i++) {
180                 memcpy(buf,rgb+i*width*3,width*3);
181                 memcpy(rgb+i*width*3,rgb+(height-i-1)*width*3,width*3);
182                 memcpy(rgb+(height-i-1)*width*3,buf,width*3);
183         }
184         free(buf);
185         
186         /* Normalize & adjust brightness ... */
187 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
188
189 #ifndef MAX
190 # define MAX(a, b) ((a) > (b) ? (a) : (b))
191 #endif
192 #ifndef MIN
193 # define MIN(a, b) ((a) < (b) ? (a) : (b))
194 #endif
195
196         for(i=0; i<(width*height*3); i++)
197                         MINMAX( rgb[i], min, max  );
198
199         amplify = 255.0/(max-min);
200
201         for(i=0; i<(width*height*3); i++)
202         {
203                 int val = amplify * (rgb[i] - min);
204                 
205                 if(val < brightness_adjust)
206                    rgb[i] = val * 2;
207                 else if (val > (255 - brightness_adjust))
208                    rgb[i] = 255;
209                 else
210                    rgb[i] = val + brightness_adjust;
211         }
212         
213         return GP_OK;
214 }