summaryrefslogtreecommitdiff
path: root/camlibs/stv0680/bayer.c
diff options
context:
space:
mode:
authorMarcus Meissner <marcus@jet.franken.de>2002-01-23 21:57:56 +0000
committerMarcus Meissner <marcus@jet.franken.de>2002-01-23 21:57:56 +0000
commitff24c54859bb65c5e0183e4dad8c08ed463c49a8 (patch)
tree5a31cea5ec12da8f6aa11248422340c407cc3643 /camlibs/stv0680/bayer.c
parent7ae56edbcfb187f5774e467789d305b6e90e2bea (diff)
downloadlibgphoto2-ff24c54859bb65c5e0183e4dad8c08ed463c49a8.tar.gz
2001-01-23 Kurt Garloff <garloff@suse.de>
* library.c, bayer.c: Enhanced the light processing even more. git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@3995 67ed7778-7388-44ab-90cf-0a291f65f57c
Diffstat (limited to 'camlibs/stv0680/bayer.c')
-rw-r--r--camlibs/stv0680/bayer.c150
1 files changed, 107 insertions, 43 deletions
diff --git a/camlibs/stv0680/bayer.c b/camlibs/stv0680/bayer.c
index 6ab07d1e7..2c98e4e17 100644
--- a/camlibs/stv0680/bayer.c
+++ b/camlibs/stv0680/bayer.c
@@ -49,40 +49,96 @@ void bayer_unshuffle_preview(int w, int h, int scale, unsigned char *raw, unsign
/****** gamma correction from trans[], plus hardcoded white balance */
/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
- Gamma correction (trans[] values generated by (pow((i-17)/256, GAMMA)*255)
- where GAMMA=0.5, 1<i<255. */
+ Gamma correction (trans[] values generated by (pow((i-17)/239, GAMMA)*254)
+ where GAMMA=0.5x, 1<i<255. */
+/* KG: Looking at very dark parts of images, the sensor seems to produce
+ * only very few points below 0x11 and almost none below 14. Therefore we map everything
+ * below 14 to 0 and ev'thing below 17 to 1; then the power function reigns.
+ */
+
+#define ZERO0 14 // 0--13 mapped to 0
+#define ZERO1 17 // 14--16 mapped to 1
+
+typedef struct _rgbgamma {
+ float ampl, gamma;
+} rgbgamma;
-#define GAMMA 0.540
-#define ZERO 16.0
-void light_enhance(int vw, int vh, int coarse, int fine, unsigned char *output)
+/* KG: Some notes on these:
+ * - Try to avoid strong deviations from 1.00 for the amplification,
+ * because this potentially results in not using the full range
+ * of colours (<1) or in clipping (>1) multiple colours to max,
+ * which would be a loss of information.
+ * - The gamma mainly determines how fast values increase after ZERO1.
+ * Influence on the highlights is small; therefore the description
+ * with amplifiaction and gamma seems not very appropriate; a better
+ * correction function would allow to influence the slope for small
+ * and for large values indepentently without incurring loss of
+ * accuracy/information. It should not be hard to construct such a
+ * thing. (Splines or Bézier or Triginometric/Hyperbolic functions
+ * could be used, e.g.)
+ * - The below parameters have been found by lots of experiments with
+ * pictures taken at different light levels. They're optimized for
+ * my PenCam (and my screens), of course. No theory behind this;
+ * I don't have insight into the physics of the imaging sensor.
+ * CCDs are linear, basically; but higher order effects may play
+ * a role as well as the electronics that controls the shutter
+ * and the one doing the readout.
+ */
+rgbgamma gampar[6][3] = {
+ { { 1.02, 0.56 }, { 1.00, 0.61 }, { 0.99, 0.65 } }, // cold
+ { { 1.01, 0.56 }, { 1.00, 0.58 }, { 1.00, 0.61 } }, // coldish
+ { { 1.00, 0.55 }, { 1.00, 0.57 }, { 1.00, 0.59 } }, // mid
+ { { 1.00, 0.55 }, { 1.00, 0.56 }, { 1.01, 0.55 } }, // warmish
+ { { 1.01, 0.56 }, { 0.99, 0.57 }, { 1.03, 0.50 } }, // warm
+ { { 1.03, 0.52 }, { 0.97, 0.57 }, { 1.04, 0.49 } } // warm bright
+};
+
+void light_enhance(int vw, int vh, int coarse, int fine,
+ unsigned char avg_pix, unsigned char *output)
{
unsigned long int i;
int lt=3; /* 3 is auto */
- float wb[3][3];
- double x, y;
- unsigned int trans[258], v;
- int tmp1, tmp2, tmp3, whitex=20, whitey=20, j, k;
+ //float wb[3][3];
+ unsigned char trans[3][256];
+ unsigned char col;
+ //int tmp1, tmp2, tmp3, whitex=20, whitey=20, j, k;
- double brightness = 1.0; /* FIXME: configurable? */
-
- /*fprintf(stderr, "(FineExp=%i CoarseExp=%i => filter=", fine, coarse); */
+ double brightness = 1.00; /* FIXME: configurable? */
+
+ //fprintf(stderr, "(FineExp=%i CoarseExp=%i => filter=", fine, coarse);
+#if 0
if (fine >= (coarse<<1)) {
lt = 0;
- /*fprintf(stderr, "natural)\n");*/
+ //fprintf(stderr, "natural)\n");
} else if (((fine<<1) < coarse) && (coarse < 400)) {
lt = 2;
- /*fprintf(stderr, "incandescent)\n");*/
+ //fprintf(stderr, "incandescent)\n");
} else {
lt = 1;
- /*fprintf(stderr, "fluorescent)\n");*/
+ //fprintf(stderr, "fluorescent)\n");
}
- x = brightness;
- wb[0][0] = 1.08 * x; wb[0][1] = 1.00 * x; wb[0][2] = 0.95 * x;
- wb[1][0] = 1.05 * x; wb[1][1] = 1.00 * x; wb[1][2] = 1.00 * x;
- wb[2][0] = 0.90 * x; wb[2][1] = 1.00 * x; wb[2][2] = 1.10 * x;
+ wb[0][0] = 1.08 * x; wb[0][1] = 1.00 * x; wb[0][2] = 0.95 * x; // natural
+ wb[1][0] = 1.00 * x; wb[1][1] = 1.00 * x; wb[1][2] = 1.00 * x; // flourescent
+ wb[2][0] = 0.90 * x; wb[2][1] = 1.00 * x; wb[2][2] = 1.11 * x; // incandescent
+#else
+ if (fine > coarse) {
+ lt = 0; //fprintf (stderr, "cold)\n");
+ } else if (coarse < 100) {
+ lt = 1; //fprintf (stderr, "coldish)\n");
+ } else if (coarse < 200) {
+ lt = 2; //fprintf (stderr, "mid)\n");
+ } else if (coarse < 400) {
+ lt = 3; //fprintf (stderr, "warmish)\n");
+ } else if (avg_pix < 94) {
+ lt = 4; //fprintf (stderr, "warm)\n");
+ } else {
+ lt = 5; //fprintf (stderr, "warm, bright)\n");
+ }
+#endif
+#if 0
/* find white pixel */
for (j=0;j<vh;j++)
{
@@ -92,41 +148,49 @@ void light_enhance(int vw, int vh, int coarse, int fine, unsigned char *output)
tmp1 = abs(*(output+i) - *(output+i+1));
tmp2 = abs(*(output+i) - *(output+i+2));
tmp3 = abs(*(output+i+1) - *(output+i+2));
- if ((tmp1<20) && (tmp2<20) && (tmp3<20) && (*(output+i)>100)) {
+ if ((tmp1<16) && (tmp2<16) && (tmp3<16) && (*(output+i)>=160)) {
whitex = k; whitey = j;
break;
}
}
}
-
- for(i=1; i<256; ++i)
- {
- x=i; x -= ZERO;
- if (x<1.0)
- x = 1.0;
- y = pow((x/256.0),GAMMA)*255.0;
- trans[i] = (unsigned int) y;
+#endif
+
+ for (col = 0; col < 3; col++) {
+ double y;
+ rgbgamma *gp = gampar[lt] + col;
+ for(i=0; i<256; ++i) {
+ if (i < ZERO0)
+ y = 0;
+ else if (i < ZERO1)
+ y = 1;
+ else
+ y = brightness * gp->ampl * (2 + pow((i-ZERO1)/((double)254-ZERO1),gp->gamma) * 253.5);
+ if (y > 255.0)
+ y = 255.0;
+ trans[col][i] = (unsigned char) y;
+ }
}
- trans[0] = 0;
for (i=0;i<(vw*vh*3);i+=3)
- { /* this (adjusting white) isn't quite right yet, so I turned it off */
- if ( (abs(*(output+i)-*(output+i+1))<1) &&
- (abs(*(output+i)-*(output+i+2))<1) &&
- (abs(*(output+i+1)-*(output+i+2))<1)) {
- y = trans[*(output+i)]*wb[lt][1]; v = (unsigned int)y;
- v = (v > 255) ? 255 : v;
- *(output+i) = (unsigned char) (v);
+ {
+ int r,g,b;
+ r = *(output+i);
+ g = *(output+i+1);
+ b = *(output+i+2);
+ /* this (adjusting white) isn't quite right yet, so I turned it off */
+ if ( 0 && (abs(r-g) < 8) &&
+ (abs(r-b) < 8) &&
+ (abs(b-g) < 8)) {
+ int v = trans[1][(r+b+g+1)/3];
+ *(output+i) = (unsigned char) (v);
*(output+i+1) = (unsigned char) (v);
*(output+i+2) = (unsigned char) (v);
-// fprintf(stdout,"Adjusting white\n");
+ fprintf(stderr,"Adjusting white\n");
} else { /* this is OK */
- y = trans[*(output+i)]*wb[lt][0]; v = (unsigned int)y;
- *(output+i) = (unsigned char) (v > 255) ? 255 : v;
- y = trans[*(output+i+1)]*wb[lt][1]; v = (unsigned int)y;
- *(output+i+1) = (unsigned char) (v > 255) ? 255 : v;
- y = trans[*(output+i+2)]*wb[lt][2]; v = (unsigned int)y;
- *(output+i+2) = (unsigned char) (v > 255) ? 255 : v;
+ *(output+i) = trans[0][r];
+ *(output+i+1) = trans[1][g];
+ *(output+i+2) = trans[2][b];
}
} /* for */