3 * White balancing and brightness correction for the Jenoptik
4 * JD350 entrance camera
6 * Copyright © 2001 Michael Trawny <trawny99@users.sourceforge.net>
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.
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.
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.
28 #include <gphoto2/gphoto2-library.h>
29 #include <gphoto2/gphoto2-port-log.h>
32 #include "jd350e_red.h"
33 /*#include "jd350e_blue.h"*/
35 #define GP_MODULE "jd350e"
37 #define THRESHOLD 0xf8
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)
43 #define SWAP(a,b) {unsigned char t=(a); (a)=(b); (b)=t;}
45 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
48 # define MAX(a, b) ((a) > (b) ? (a) : (b))
51 # define MIN(a, b) ((a) < (b) ? (a) : (b))
55 int jd350e_postprocessing(int width, int height, unsigned char* rgb){
58 red_min=255, red_max=0,
59 blue_min=255, blue_max=0,
60 green_min=255, green_max=0;
64 /* reverse image row by row... */
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));
74 /* determine min and max per color... */
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 );
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? */
90 if( (green_max+blue_max)/2 > red_max ){
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); */
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); */
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);
114 blue_min = MIN(2*(unsigned)blue_min,255);
115 blue_max = MIN(2*(unsigned)blue_max,255);
119 /* Normalize brightness ... */
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);
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);
136 int jd350e_postprocessing_and_flip(int width, int height, unsigned char* rgb){
140 ret = jd350e_postprocessing (width,height,rgb);
143 tmpline = malloc(width*3);
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);
155 int trust350fs_postprocessing(int width, int height, unsigned char* rgb) {
156 int i,x,y,min=255,max=0;
159 const int brightness_adjust = 16;
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)
166 #define SWAP(a,b) {unsigned char t=(a); (a)=(b); (b)=t;}
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));
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);
186 /* Normalize & adjust brightness ... */
187 #define MINMAX(a,min,max) { (min)=MIN(min,a); (max)=MAX(max,a); }
190 # define MAX(a, b) ((a) > (b) ? (a) : (b))
193 # define MIN(a, b) ((a) < (b) ? (a) : (b))
196 for(i=0; i<(width*height*3); i++)
197 MINMAX( rgb[i], min, max );
199 amplify = 255.0/(max-min);
201 for(i=0; i<(width*height*3); i++)
203 int val = amplify * (rgb[i] - min);
205 if(val < brightness_adjust)
207 else if (val > (255 - brightness_adjust))
210 rgb[i] = val + brightness_adjust;