home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: OtherApp / OtherApp.zip / wincam.zip / winc_src.zip / vignette.c < prev    next >
C/C++ Source or Header  |  1997-02-28  |  5KB  |  174 lines

  1. /*
  2.  *
  3.  * routine to correct for corner darkening that the camera does for us.
  4.  *
  5.  * Copyright (C) 1996, Paul G. Fox
  6.  * This program is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2 of the License, or (at your
  9.  * option) any later version.
  10.  * 
  11.  * This program is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * General Public License for more details.
  15.  * 
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  * This software was created with the help of proprietary information
  21.  * belonging to StarDot Technologies.
  22.  *
  23.  * $Header: E:/winc/RCS/vignette.c 1.1 1997/03/01 03:44:14 Derek Exp Derek $
  24.  */
  25.  
  26.  
  27.  
  28. #include "private.h"
  29. #include "trace.h"
  30.  
  31. #include <math.h>
  32. #include <string.h>
  33.  
  34.  
  35. /*
  36.  * the ccd sensors are wider than they are tall (that's why the 512x496
  37.  * image needs to stretch to 640 wide).  the exact ratio is 7.5uM to 9.6uM,
  38.  * or a factor of 1.28.  that is, the 4th pixel from the center in the
  39.  * horizontal direction is really 4*1.28 vertical units from the center.
  40.  */
  41.  
  42. /* 
  43.  * the wincam folks tell me that the intensity falls as the square of
  44.  * the distance from the center, and that the drop in intensity is 50% 
  45.  * at the right edge of the screen, relative to the center.
  46.  * the right edge is maxX (= 256 * 1.28) units away.  so, assuming
  47.  *        i = 1 - (d**2 * factor)
  48.  * substituting maxX and 1/2, we get:
  49.  *        1/2 = 1 - (maxX ** 2) * factor
  50.  * or
  51.  *        1/2 = maxX**2 * factor
  52.  * or
  53.  *        factor = 1 / (2 * (maxX)**2)
  54.  *
  55.  * back to the beginning, we get:
  56.  *        i = 1 - (d**2)/(2*maxX**2))
  57.  *
  58.  * to brighten a pixel, we need to multiply by the inverse of that:
  59.  *        newpix = pix * (2*maxX**2)/(2*maxX**2 - d**2)
  60.  *  
  61.  */
  62.  
  63.  
  64. /* find the absolute value of an integer */
  65. static inline int absolute(int i)
  66. {
  67.     return (i < 0) ? -i : i;
  68. }
  69.  
  70. /*
  71.  * the corners of a raw image are darker than the middle, by quite
  72.  * a bit.  this routine tries to correct for this. 
  73.  */
  74. void
  75. winc_vignette_fix(
  76.     byte *image,
  77.     int rows,
  78.     int cols,
  79.     int rgb)
  80. {
  81.     int r, c;
  82.     int x, y;
  83.     int dsq, twomaxXsq, newpix;
  84.  
  85.     /* calculate 2*maxX**2 -- 
  86.      *     it's 256, corrected for pitch, squared, and doubled */
  87.     twomaxXsq = (256 * 128) / 100;
  88.     twomaxXsq *= twomaxXsq * 2;
  89.  
  90.     for (r = 0; r < rows; r++) {
  91.     /* distance from center */
  92.     y = absolute((rows/2) - r);
  93.  
  94.     /* adjust for image size */
  95.     y *= 512;    /* should really be 492, but this seems close enough */
  96.     y /= rows;
  97.  
  98.     for (c = 0; c < cols; c++) {
  99.         /* distance from center */
  100.         x = absolute((cols/2) - c);
  101.  
  102.         /* adjust for image size */
  103.         x *= 512;
  104.         x /= cols;
  105.  
  106.         /* correct for pitch */
  107.         x *= 128;
  108.         x /= 100;
  109.  
  110.  
  111.         /* distance is sqrt(x**2 + y**2), so this is d**2 */
  112.         dsq = x * x + y * y;
  113.  
  114.         newpix = (twomaxXsq * *image) / (twomaxXsq - dsq);
  115.         *image++ = (newpix > 255) ? 255 : newpix;
  116.         if (rgb) {
  117.         newpix = (twomaxXsq * *image) / (twomaxXsq - dsq);
  118.         *image++ = (newpix > 255) ? 255 : newpix;
  119.         newpix = (twomaxXsq * *image) / (twomaxXsq - dsq);
  120.         *image++ = (newpix > 255) ? 255 : newpix;
  121.         }
  122.     }
  123.     }
  124. }
  125.  
  126. /*
  127.  * apply a gamma function to the image.  the parameter to a gamma function
  128.  * is normally a number near 1.0, where 1.0 exactly leaves the image
  129.  * unchanges.  we use 100 as the base, to avoid forcing floating point
  130.  * on the callers.
  131.  *
  132.  * thanks to John Bradley's xv program for the correct equation.
  133.  */
  134. static byte gammamap[256];    /* the current gamma function map */
  135. static int last_gam;        /* the gamma value which produced it */
  136.  
  137. void
  138. winc_gamma(
  139.     int gam,        /* gamma value, times 100 */
  140.     byte * image,
  141.     int rows,
  142.     int cols,
  143.     int rgb)
  144. {
  145.     double d, one_over_gam;
  146.     int i, j;
  147.     byte *ip;
  148.  
  149.     if (gam == 0) /* fetch default */
  150.     gam = cfg_number(winc_configvar("WinCamGamma", "110"));
  151.  
  152.     /* 100 is "normal", i.e. image is unchanges.  0 is undefined */
  153.     if (gam == 0 || gam == 100)
  154.     return;
  155.  
  156.     if (gam != last_gam) {    /* recalculate the map */
  157.     one_over_gam = 100.0 / absolute(gam);
  158.     for (i = 0; i < 256; i++) {
  159.         d = pow(((double) i / 255.0), one_over_gam) * 255.0;
  160.         j = (int) floor(d + 0.5);
  161.         if (j < 0) j = 0;
  162.         else if (j > 255) j = 255;
  163.         if (gam > 0)
  164.         gammamap[i] = j;
  165.         else
  166.         gammamap[255 - i] = j;    /* entries reversed */
  167.     }
  168.     last_gam = gam;
  169.     }
  170.  
  171.     for (ip = image + rows * cols * (rgb ? 3:1); ip >= image; ip--)
  172.     *ip = gammamap[*ip];
  173. }
  174.