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

  1. /*
  2.  *
  3.  * get "viewfinder" images from the wincam
  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/view.c 1.1 1997/03/01 03:44:14 Derek Exp Derek $
  24.  */
  25. #define NDEBUG 1
  26.  
  27. #define BINARY_SEARCH 1
  28.  
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <stdio.h>
  32. #include <errno.h>
  33. #include <termios.h>
  34. #include <assert.h>
  35. #include "private.h"
  36. #include "trace.h"
  37.  
  38. /* the row and column values at which to start the zoom, to keep the
  39.  * image centered:
  40.  *  zoom 0 gives a 512x246 image.
  41.  *  zoom 1 gives a 256x147 image.
  42.  *  zoom 2 gives a 192x98  image.
  43.  *  zoom 3 gives a  64x49. image.
  44.  */
  45. int centered_col[4] = { 0, (512-256)/2, (512-192)/2, (512-64)/2 };
  46. int centered_row[4] = { 0, (246-147)/2, (246-98)/2, (246-49)/2 };
  47.  
  48. result
  49. winc_viewfinder_snap( cam_t cam,
  50.         int zoom,        /* 1, 2, 4, or 8 */
  51.         int row,        /* when zoomed: starting row: 0 to 197 */
  52.         int col,        /* when zoomed: starting col: 0 to 448 */
  53.         byte *image,    /* room for resulting 1536 bytes, 0 to suppress */
  54.         int exposeiters, /* should we iterate to find correct exposure? */
  55.         int *exposurep, /* pointer to exposure guess (or null) 
  56.             (in microseconds -- real granularity is 50,000ths) */
  57.         int *avgp,        /* place to put average pixel value */
  58.         int goal,        /* desired brightness, 1 to 100 */
  59.         int *ok_p)        /* boolean: did we achieve that brightness? */
  60. {
  61.     unsigned long sum;
  62.     byte csum;
  63.     int avg;
  64.     unsigned int u_exp;
  65.     unsigned int exp;
  66.     unsigned int new_exp;
  67.  
  68.     assert(cam);
  69.  
  70.     if (exposurep && *exposurep)  /* don't allow first guess of zero */
  71.     u_exp = (unsigned)*exposurep;
  72.     else
  73.     u_exp = DEFAULT_EXPOSURE;
  74.  
  75.     /* provide default goal */
  76.     if (!goal) {
  77.     static configured_goal = 0;
  78.     if (!configured_goal) {  /* don't read from config every time */
  79.         configured_goal =
  80.             cfg_number(winc_configvar("WinCamBrightness", "50"));
  81.     }
  82.     goal = configured_goal;
  83.     if (goal > 100 || goal < 1)
  84.         goal = 42;
  85.     }
  86.     goal = (goal * 16 ) / 10;   /* we want numbers out of 160, not 100 */
  87.  
  88.     if (avgp)
  89.     avg = *avgp;
  90.     else
  91.     avg = 0;
  92.  
  93.     switch(zoom) {
  94.     case 8: zoom = 3;   break;
  95.     case 4: zoom = 2;   break;
  96.     case 2: zoom = 1;   break;
  97.     case 1: zoom = 0;   break;
  98.     default: zoom = 0; row = col = -1; break;
  99.     }
  100.     if (row == -1)
  101.     row = centered_row[zoom];
  102.     if (col == -1)
  103.     col = centered_col[zoom];
  104.  
  105.     while (1) {
  106.  
  107.     TRACE("AE", __FILE__ ": exposing %d usec, avg was %d, goal is %d\n",
  108.         u_exp, avg, goal);
  109.  
  110.     exp = u_exp / 20;    /* microseconds to 50,000ths */
  111.     /* the minimum exposure (0) is actually 1/100,000 */
  112.     if (exp > 65535) exp = 65535;    /* 1.3 seconds max */
  113.  
  114.     if (winc_send_cmd(cam, Cmd_snap_view, 
  115.             zoom, row, col/2, exp%256, exp/256, 
  116.             ((image ? -1 : -4) & 0xff), -1) != OK)
  117.         return NotOK;
  118.  
  119.     /* get 1536 bytes plus a checksum byte */
  120.     if (winc_get_resp_wait(cam, 1536, image, 500 + u_exp/1000,
  121.                 &sum) != OK)
  122.         return NotOK;
  123.     if (winc_get_resp_wait(cam, 1, &csum, 200, 0) != OK)
  124.         return NotOK;
  125.  
  126.     if ((sum & 0xff) != csum)
  127.         errormsg( __FILE__ ": warning viewfinder checksum incorrect\n");
  128.  
  129.     /* get viewfinder average from packet checksum,
  130.      *  taking into account that half the nibbles are weighted by
  131.      *  16, since we summed as bytes.  weight by 10, so we can look
  132.      *  at fractions */
  133.     avg = 10 * sum / (1536 * 17);
  134.  
  135. #define RANGE 4
  136.  
  137.     if ((goal-RANGE <= avg && avg <= goal+RANGE) || exposeiters-- <= 0)
  138.         break;
  139.  
  140.     if (avg == 0 || u_exp == 0) {
  141.         u_exp = DEFAULT_EXPOSURE;    /* safety */
  142.         /* it might be 0 for legitimate reasons, like not enough light */
  143.         if (avg == 0)
  144.         u_exp *= 10;
  145.     } else {
  146.         new_exp = (u_exp * goal) / avg;
  147.  
  148.         /* if we're far away, just guess linearly, otherwise, if we're already
  149.         close, average our new guess with the current value */
  150.         if ( (avg < goal - RANGE*2) || (avg > goal + RANGE*2) )
  151.         u_exp = new_exp;
  152.         else
  153.         u_exp = (new_exp + u_exp) / 2;
  154.     }
  155.     }
  156.  
  157.     /* stretch the results from nibbles to bytes */
  158.     {
  159.         byte *ip, *ep;
  160.         ip = &image[1536];
  161.         ep = &image[3072];
  162.         while (ip-- > image) {
  163.         *--ep = *ip & 0xf;
  164.         *--ep = *ip >> 4;
  165.         }
  166.     }
  167.  
  168.     TRACE("a", __FILE__ ": final viewfinder avg is %d\n", avg );
  169.     TRACE("e", __FILE__ ": exposure is %d\n", u_exp);
  170.  
  171.     if (exposurep)
  172.     *exposurep = u_exp;
  173.  
  174.     if (avgp)
  175.     *avgp = avg;
  176.  
  177.     if (ok_p)
  178.     *ok_p = (avg >= goal-RANGE && avg <= goal+RANGE);
  179.  
  180.     return OK;
  181.  
  182. }
  183.  
  184.