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., 51 Franklin Street, Fifth Floor,
21  * Boston, MA  02110-1301  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 
jd350e_postprocessing(int width,int height,unsigned char * rgb)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 
jd350e_postprocessing_and_flip(int width,int height,unsigned char * rgb)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 
trust350fs_postprocessing(int width,int height,unsigned char * rgb)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 }
215