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

  1. /*
  2.  *
  3.  * correct the star-studded appearance of low-light images
  4.  *
  5.  * Copyright (C) 1996, Paul G. Fox
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify it
  8.  * under the terms of the GNU General Public License as published by the
  9.  * Free Software Foundation; either version 2 of the License, or (at your
  10.  * option) any later version.
  11.  * 
  12.  * This program is distributed in the hope that it will be useful, but
  13.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU General Public License along
  18.  * with this program; if not, write to the Free Software Foundation, Inc.,
  19.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  * This software was created with the help of proprietary information
  22.  * belonging to StarDot Technologies.
  23.  *
  24.  * $Header: E:/winc/RCS/starfield.c 1.1 1997/03/01 03:44:14 Derek Exp Derek $
  25.  */
  26. #define NDEBUG 1
  27.  
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <errno.h>
  31. #include <assert.h>
  32. #include "private.h"
  33. #include "trace.h"
  34.  
  35. /*
  36.  * the starfield image should be created by saving a double-scan full-height
  37.  * image taken with the lens cap on, in PBM (monochrome bitmap) format.
  38.  */
  39.  
  40. result
  41. winc_read_starfield(cam_t cam)
  42. {
  43.     char *fn;
  44.     FILE *f;
  45.     int pbm, cols, rows;
  46.     char newl;
  47.  
  48.     if (cam->starfield)
  49.         return OK;
  50.  
  51.     /* give the starfield snapper way to suppress this stuff */
  52.     fn = winc_configvar("NoStarfield", "");
  53.     if (fn && *fn)
  54.     return NotOK;
  55.  
  56.     /* get the name of the starfield file */
  57.     fn = winc_configvar("WinCamStarfield", "");
  58.     if (!fn || *fn  == 0)
  59.         return NotOK;
  60.  
  61.     f = fopen(fn, "r");
  62.     if (!f) {
  63.     TRACE("a", __FILE__ ": cannot open %s\n", fn);
  64.         return NotOK;
  65.     }
  66.  
  67.     TRACE("a", __FILE__ ": reading starfield from %s\n", fn);
  68.  
  69.     if (4 != fscanf(f, "P%d %d %d%c", &pbm, &cols, &rows, &newl) ||
  70.         pbm != 4 || newl != '\n' ||
  71.         cols != 512 || rows != 492) {
  72.     TRACE("a", __FILE__ ": bad stuff in starfield file\n");
  73.         return NotOK;
  74.     }
  75.  
  76.     cam->starfield = (byte *)malloc(512 * 492 / 8);
  77.     if (!cam->starfield) {
  78.     TRACE("a", __FILE__ ": couldn't malloc starfield\n");
  79.     fclose(f);
  80.     return NotOK;
  81.     }
  82.  
  83.     if (fread(cam->starfield, 512 * 492 / 8, 1, f) != 1) {
  84.     TRACE("a", __FILE__ ": didn't read starfield\n");
  85.     fclose(f);
  86.     free(cam->starfield);
  87.     cam->starfield  = 0;
  88.     return NotOK;
  89.     }
  90.     return OK;
  91. }
  92.  
  93. static 
  94. unsigned char bit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  95. /*
  96.  * return 0 or 1 depending on whether bit N is set in a bit array
  97.  * (the bit order matches the pbm monochrome bit ordering)
  98.  */
  99. #define bit2byte(bits,n) (bits[n/8] & bit[n%8]) ? 1 : 0;
  100.  
  101. result
  102. winc_starfield_line(byte *oline, cam_t cam, int row,
  103.     int start, int send, int skip, int repeat)
  104. {
  105.     int rep, i, o, snd;
  106.     byte *starf_bits;
  107.     result ret;
  108.  
  109.     ret = winc_read_starfield(cam);
  110.     if (ret != OK)
  111.         return ret;
  112.  
  113.     /*  the starfield is always 512 bits across by 492 bits high */
  114.     starf_bits = &cam->starfield[row * (512 / 8)];
  115.  
  116.     i = start;    /* first input byte */
  117.     o = 0;      /* first output byte */
  118.     for (rep = 0; rep < repeat; rep++) {
  119.     for (snd = 0; snd < send; snd++) {
  120.         oline[o++] = bit2byte(starf_bits,i);
  121.         i++;
  122.     }
  123.     i += skip;
  124.     }
  125.  
  126.     assert(o == repeat * send);
  127.  
  128.     return OK;
  129. }
  130.  
  131. /*
  132.  * correct an image row for starfield effect by averaging "bad" pixels
  133.  * with their neighbors.  the "neighbor" is two distant, since not all
  134.  * pixels are the same in a raw image (i.e. red/blue/red/blue or
  135.  * yel/grn/yel/grn).  or something like that
  136.  */
  137. void
  138. winc_starfield_fix(byte *line, byte *starf_line, int len)
  139. {
  140.     int i;
  141.  
  142.     /* make sure the first two and last two bytes have valid values */
  143.     if (starf_line[0]) {
  144.     for (i = 2; i < len && starf_line[i]; i += 2) /* loop */ ;
  145.     if (i >= len)
  146.         return;  /* whole bad row */
  147.     line[0] = line[i];
  148.     }
  149.     if (starf_line[1]) {
  150.     for (i = 3; i < len && starf_line[i]; i += 2) /* loop */ ;
  151.     if (i >= len)
  152.         return;  /* whole bad row */
  153.     line[1] = line[i];
  154.     }
  155.     if (starf_line[len-1]) {
  156.     for (i = len-3; i >= 0 && starf_line[i]; i -= 2) /* loop */ ;
  157.     if (i < 0)
  158.         return;  /* whole bad row */
  159.     line[len-1] = line[i];
  160.     }
  161.     if (starf_line[len-2]) {
  162.     for (i = len-4; i >= 0 && starf_line[i]; i -= 2) /* loop */ ;
  163.     if (i < 0)
  164.         return;  /* whole bad row */
  165.     line[len-2] = line[i];
  166.     }
  167.         
  168.     /* now average the rest */
  169.     for (i = 2; i < len - 2; i++) {
  170.     if (starf_line[i]) {
  171.         int val;
  172.         /* use the rearward neighbor */
  173.         val = line[i-2];  /* we know this will work */
  174.         /* look forward, use the forward neighbor if it's okay */
  175.         if (!starf_line[i+2]) {
  176.         val += line[i+2];
  177.         val /= 2;
  178.         }
  179.         line[i] = val;
  180.     }
  181.     }
  182. }
  183.  
  184.