camlibs/mars: mars_white_balance function added

git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@10989 67ed7778-7388-44ab-90cf-0a291f65f57c
This commit is contained in:
Theodore Kilgore
2008-03-15 21:11:43 +00:00
parent fcf25de0e0
commit f50fb2ec5e
5 changed files with 216 additions and 10 deletions

View File

@@ -1,3 +1,10 @@
2008-03-15 Theodore Kilgore <kilgota@auburn.edu>
* mars.[c,h]: mars_white_balance() postprocessing function, based
upon work with Amauri Magagna done for an Aox camera.
* library.c: Added line to use mars_white_balance()
* README.mars: Description of what mars_white_balance() does.
2007-11-15 Theodore Kilgore <kilgota@auburn.edu>
* library.c: Added Sakar no. 1638x Cyberpix
* README.mars: Description of new camera added.

View File

@@ -1,6 +1,6 @@
MARS MR97310 STILLCAM DRIVER
Copyright Theodore Kilgore <kilgota@auburn.edu> April, 2004. Latest revision
of this README November 15, 2007.
of this README March 15, 2008.
(Everything in libgphoto2/camlibs/mars is LGPL-licensed, including this README;
see any of the source files for a more complete statement of the license.)
@@ -228,6 +228,16 @@ you would like to see this file and it is not included for some reason in a
"released" version of libgphoto2, then it can be found in the SVN source
repository.
THE mars_white_balance() FUNCTION
This function first of all does what its name implies. It also re-computes a
better gamma factor for the individual image, based upon internal
characteristics detected in the image, and does color enhancement. If you do
not like what it is doing, then you can turn it off by commenting out the line
in library.c where it is called, but I expect that the user will not want to
do that, because it seems to me that the image quality is much, much better.
WARRANTY?
Absolutely none. Remember, I did not sell you this software. I have written

View File

@@ -23,7 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <bayer.h>
#include <gamma.h>
@@ -298,8 +298,10 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
if (compressed) {
mars_decompress (data + 12, p_data, w, h);
}
else memcpy (p_data, data + 12, w*h);
gamma_factor = (float)data[7]/128.;
else memcpy (p_data, data + 12, w*h);
gamma_factor = sqrt((float)data[7]/100.);
if (gamma_factor <= .60)
gamma_factor = .60;
free(data);
/* Now put the data into a PPM image file. */
@@ -315,14 +317,10 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
ptr = ppm + strlen ((char *)ppm);
size = strlen ((char *)ppm) + (w * h * 3);
GP_DEBUG ("size = %i\n", size);
gp_bayer_decode (p_data, w , h , ptr, BAYER_TILE_RGGB);
if (gamma_factor < .4) gamma_factor = .4;
if (gamma_factor > .6) gamma_factor = .6;
gp_gamma_fill_table (gtable, gamma_factor );
gp_gamma_correct_single (gtable, ptr, w * h);
mars_white_balance (ptr, w*h, 1.4, gamma_factor);
gp_file_set_mime_type (file, GP_MIME_PPM);
gp_file_set_name (file, filename);
gp_file_set_data_and_size (file, (char *)ppm, size);

View File

@@ -2,6 +2,8 @@
*
* Copyright (C) 2004 Theodore Kilgore <kilgota@auburn.edu>
*
* white_balance() Copyright (C) 2008 Theodore Kilgore and Amauri Magagna.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -25,6 +27,7 @@
#include <fcntl.h>
#include <string.h>
#include <math.h>
#include <gamma.h>
#include <gphoto2/gphoto2.h>
#include <gphoto2/gphoto2-port.h>
@@ -343,3 +346,188 @@ mars_routine (Info *info, GPPort *port, char param, int n)
return(c[0]);
}
/*
* ========= White Balance / Color Enhance / Gamma adjust ===============
*
* Get histogram for each color plane
* Expand to reach 0.5% of white dots in image
*
* Get new histogram for each color plane
* Expand to reach 0.5% of black dots in image
*
* Get new histogram
* Calculate and apply gamma correction
*
* if not a dark image:
* For each dot, increases color separation
*
* ======================================================================
*/
int
histogram (unsigned char *data, unsigned int size, int *htable_r, int *htable_g, int *htable_b)
{
int x;
/* Initializations */
for (x = 0; x < 0x100; x++) {
htable_r[x] = 0;
htable_g[x] = 0;
htable_b[x] = 0;
}
/* Building the histograms */
for (x = 0; x < (size * 3); x += 3)
{
htable_r[data[x+0]]++; /* red histogram */
htable_g[data[x+1]]++; /* green histogram */
htable_b[data[x+2]]++; /* blue histogram */
}
return 0;
}
int
mars_white_balance (unsigned char *data, unsigned int size, float saturation,
float image_gamma)
{
int x, r, g, b, max, d;
double r_factor, g_factor, b_factor, max_factor;
int htable_r[0x100], htable_g[0x100], htable_b[0x100];
unsigned char gtable[0x100];
double new_gamma, gamma=1.0;
/* ------------------- GAMMA CORRECTION ------------------- */
histogram(data, size, htable_r, htable_g, htable_b);
x = 1;
for (r = 48; r < 208; r++)
{
x += htable_r[r];
x += htable_g[r];
x += htable_r[r];
}
new_gamma = sqrt((double) (x * 1.5) / (double) (size * 3));
x=0;
GP_DEBUG("Provisional gamma correction = %1.2f\n", new_gamma);
/* Recalculate saturation factor for later use. */
saturation=saturation*new_gamma*new_gamma;
GP_DEBUG("saturation = %1.2f\n", saturation);
if(new_gamma >= 1.0)
gamma = new_gamma;
else
gamma = image_gamma;
GP_DEBUG("Gamma correction = %1.2f\n", gamma);
gp_gamma_fill_table(gtable, gamma);
/* ---------------- BRIGHT DOTS ------------------- */
max = size / 200;
histogram(data, size, htable_r, htable_g, htable_b);
for (r=0xfe, x=0; (r > 32) && (x < max); r--)
x += htable_r[r];
for (g=0xfe, x=0; (g > 32) && (x < max); g--)
x += htable_g[g];
for (b=0xfe, x=0; (b > 32) && (x < max); b--)
x += htable_b[b];
r_factor = (double) 0xfd / r;
g_factor = (double) 0xfd / g;
b_factor = (double) 0xfd / b;
max_factor = r_factor;
if (g_factor > max_factor) max_factor = g_factor;
if (b_factor > max_factor) max_factor = b_factor;
if (max_factor >= 2.5) {
r_factor = (r_factor / max_factor) * 2.5;
g_factor = (g_factor / max_factor) * 2.5;
b_factor = (b_factor / max_factor) * 2.5;
}
GP_DEBUG("White balance (bright): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n", r, g, b, r_factor, g_factor, b_factor);
if (max_factor <= 2.5) {
for (x = 0; x < (size * 3); x += 3)
{
d = (data[x+0]<<8) * r_factor;
d >>=8;
if (d > 0xff) { d = 0xff; }
data[x+0] = d;
d = (data[x+1]<<8) * g_factor;
d >>=8;
if (d > 0xff) { d = 0xff; }
data[x+1] = d;
d = (data[x+2]<<8) * b_factor;
d >>=8;
if (d > 0xff) { d = 0xff; }
data[x+2] = d;
}
}
/* ---------------- DARK DOTS ------------------- */
max = size / 200; /* 1/200 = 0.5% */
histogram(data, size, htable_r, htable_g, htable_b);
for (r=0, x=0; (r < 96) && (x < max); r++)
x += htable_r[r];
for (g=0, x=0; (g < 96) && (x < max); g++)
x += htable_g[g];
for (b=0, x=0; (b < 96) && (x < max); b++)
x += htable_b[b];
r_factor = (double) 0xfe / (0xff-r);
g_factor = (double) 0xfe / (0xff-g);
b_factor = (double) 0xfe / (0xff-b);
max_factor = r_factor;
if (g_factor > max_factor) max_factor = g_factor;
if (b_factor > max_factor) max_factor = b_factor;
if (max_factor >= 1.15) {
r_factor = (r_factor / max_factor) * 1.15;
g_factor = (g_factor / max_factor) * 1.15;
b_factor = (b_factor / max_factor) * 1.15;
}
GP_DEBUG(
"White balance (dark): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n",
r, g, b, r_factor, g_factor, b_factor);
for (x = 0; x < (size * 3); x += 3)
{
d = (int) 0xff08-(((0xff-data[x+0])<<8) * r_factor);
d >>= 8;
if (d < 0) { d = 0; }
data[x+0] = d;
d = (int) 0xff08-(((0xff-data[x+1])<<8) * g_factor);
d >>= 8;
if (d < 0) { d = 0; }
data[x+1] = d;
d = (int) 0xff08-(((0xff-data[x+2])<<8) * b_factor);
d >>= 8;
if (d < 0) { d = 0; }
data[x+2] = d;
}
/* ------------------ COLOR ENHANCE ------------------ */
if(saturation > 0.0) {
for (x = 0; x < (size * 3); x += 3)
{
r = data[x+0]; g = data[x+1]; b = data[x+2];
d = (int) (r + g + b) /3.;
if ( r > d )
r = r + (int) ((r - d) * (0xff-r)/(0x100-d) * saturation);
else
r = r + (int) ((r - d) * (0xff-d)/(0x100-r) * saturation);
if (g > d)
g = g + (int) ((g - d) * (0xff-g)/(0x100-d) * saturation);
else
g = g + (int) ((g - d) * (0xff-d)/(0x100-g) * saturation);
if (b > d)
b = b + (int) ((b - d) * (0xff-b)/(0x100-d) * saturation);
else
b = b + (int) ((b - d) * (0xff-d)/(0x100-b) * saturation);
data[x+0] = CLAMP(r);
data[x+1] = CLAMP(g);
data[x+2] = CLAMP(b);
}
}
return 0;
}

View File

@@ -44,6 +44,9 @@ int mars_read_picture_data (Camera *camera, Info *info,
GPPort *port, char *data, int size, int n);
int mars_decompress (unsigned char *inp ,unsigned char *outp, int w, int h);
int histogram (unsigned char *data, unsigned int size, int *htable_r,
int *htable_g, int *htable_b);
int mars_white_balance (unsigned char *data, unsigned int size, float saturation,
float image_gamma);
#endif