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