diff options
author | Marcus Meissner <marcus@jet.franken.de> | 2002-01-23 21:57:56 +0000 |
---|---|---|
committer | Marcus Meissner <marcus@jet.franken.de> | 2002-01-23 21:57:56 +0000 |
commit | ff24c54859bb65c5e0183e4dad8c08ed463c49a8 (patch) | |
tree | 5a31cea5ec12da8f6aa11248422340c407cc3643 /camlibs/stv0680/bayer.c | |
parent | 7ae56edbcfb187f5774e467789d305b6e90e2bea (diff) | |
download | libgphoto2-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.c | 150 |
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 */ |