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

  1. /*
  2.  *
  3.  * get real images from the camera
  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/image.c 1.1 1997/03/01 03:44:14 Derek Exp Derek $
  25.  */
  26. #define NDEBUG 1
  27.  
  28. #include <stdlib.h>
  29. #include <unistd.h>
  30. #include <stdio.h>
  31. #include <errno.h>
  32. #include <termios.h>
  33. #include <assert.h>
  34. #include "private.h"
  35. #include "trace.h"
  36.  
  37. #define ROW_BY_ROW 1
  38.  
  39. static void (*snap_alert_func)(void *cookie);
  40. static void *snap_alert_cookie;
  41.  
  42. void
  43. winc_register_alerter(
  44.     void (*alert_func)(void *),
  45.     void *cookie)
  46. {
  47.     snap_alert_func = alert_func;
  48.     snap_alert_cookie = cookie;
  49. }
  50.  
  51.  
  52. result
  53. winc_image_expose( cam_t cam,
  54.         int scantype,   /* single(1), double(2), or noninterlaced(0) */
  55.         int fraction,   /* 1, 2, 4, or 8 for full, half, 1/4 and 8th size */
  56.         int u_exp, /* exposure (in microseconds) */
  57.         byte *image /* room for expected no. bytes */
  58.     )
  59. {
  60.     Cmd_byte_t cmd;
  61.     int exp;
  62.     char *s;
  63.     int goal = 0;
  64.  
  65.     assert(cam);
  66.  
  67.     /*
  68.      * negative exposure is really a brightness goal
  69.      */
  70.     if (u_exp < 0) {
  71.     goal = -u_exp;
  72.     u_exp = 0;
  73.     }
  74.  
  75.     /*
  76.      * exposure of zero means autoexpose
  77.      */
  78.     if (u_exp == 0) {
  79.     int avg  = 0;
  80.     u_exp = 0;
  81.     if (winc_viewfinder_snap(cam, 1, -1, -1, image, 15, &u_exp, 
  82.                         &avg, goal, 0) != OK) {
  83.         errormsg(__FILE__ ": failed to get autoexposure\n");
  84.         return NotOK;
  85.     }
  86.     
  87.     }
  88.  
  89.     /* 
  90.      * viewfinder exposures are brighter than real images.  the
  91.      * docs say "4 times", but changing the exposure that much seems
  92.      * like too much.
  93.      */
  94.     u_exp *= 2;
  95.  
  96.     /*
  97.      * can snap single or double-interelaced scans, but that only
  98.      * makes sense for full-sized images
  99.      *
  100.      * treat the interlaces as twice the lines */
  101.     if (fraction != 1)
  102.     scantype = 1;
  103.  
  104.     switch(scantype) {
  105.     case 1:    cmd = Cmd_snap_single;        s = "single";   break;
  106.     case 2:    cmd = Cmd_snap_interlaced;  s = "double";   break;
  107.     case 3:    /* cmd = Cmd_snap_non;        s = "non";    break; */
  108.     default:
  109.     errormsg( __FILE__ ": bad scantype attempted (%d)\n", scantype);
  110.     return NotOK;
  111.     }
  112.  
  113.  
  114.     TRACE("a", __FILE__ ": snapping \"%s\" image\n", s);
  115.  
  116.     exp = u_exp / 20;        /* microseconds to 50,000ths */
  117.     /* the minimum exposure (0) is actually 1/100,000 */
  118.     if (exp > 65535) exp = 65535;   /* 1.3 seconds max */
  119.  
  120.     if (winc_send_cmd(cam, cmd, exp%256, exp/256, -1) != OK)
  121.     return NotOK;
  122.  
  123.     /* call the function the user registered as an alert function
  124.      * i think it's better to call it just after taking the picture,
  125.      * and not before...
  126.      */
  127.     if (snap_alert_func)
  128.     (*snap_alert_func)(snap_alert_cookie);
  129.  
  130.     return OK;
  131.  
  132. }
  133.  
  134.  
  135. /*
  136.  * set up things that are determined by what fraction of an image
  137.  * we are downloading:  repeat counts needed by the row download commands,
  138.  * and row and column counts.
  139.  */
  140. result
  141. get_repeats(int fraction, 
  142.     int *startp, int *sendp, int *skipp, int *repeatp,
  143.     int *colsp, int *rowsp)
  144. {
  145.     /* these numbers are somewhat magic.  they tell the camera that
  146.      * for the requested row, it should send some subset of the available
  147.      * data.  this is done because color sensors need to be picked up
  148.      * in pairs, not singly.
  149.      * start  - the offset into the image, divided by 2
  150.      * send   - length of a chunk of bytes to send
  151.      * skip   - lenght of a chunk of bytes to skip (not send)
  152.      * repeat - repeat count for send and skip
  153.      * send*repeat pixels are actually transferred
  154.      */
  155.     switch(fraction) {
  156.     case 1: *startp=0; *sendp=1; *skipp=0;  *repeatp=512; *colsp = 512; break;
  157.     case 2: *startp=0; *sendp=2; *skipp=2;  *repeatp=128; *colsp = 256; break;
  158.     case 4: *startp=0; *sendp=2; *skipp=6;  *repeatp=64;  *colsp = 128; break;
  159.     case 8: *startp=0; *sendp=2; *skipp=14; *repeatp=32;  *colsp = 64;    break;
  160.     default:
  161.     errormsg( __FILE__ ": bad fractional image attempted (%d)\n", fraction);
  162.     return NotOK;
  163.     }
  164.     *rowsp = 492/fraction;
  165.     return OK;
  166. }
  167.  
  168.  
  169. result
  170. winc_image_fetch( cam_t cam,
  171.         int scantype,   /* single(1), double(2), or noninterlaced(0) */
  172.         int fraction,   /* 1, 2, 4, or 8 for full, half, 1/4 and 8th size */
  173.         int color,        /* image destined for color processing */
  174.         byte *image,    /* room for expected no. bytes */
  175.         int *rows_p,    /* no. of rows in resulting image */
  176.         int *cols_p)    /* no. of cols in resulting image */
  177. {
  178.     int pairflag;
  179.     int start, send, skip, repeat;
  180.     int rows, cols;
  181.     int camrow;
  182.     byte *imagep;
  183.     byte csum;
  184.     unsigned long sum;
  185.     byte star_line[512];
  186.  
  187.     if (get_repeats(fraction, 
  188.         &start, &send, &skip, &repeat, &cols, &rows) != OK)
  189.     return NotOK;
  190.  
  191.  
  192.     /* the camera actually has 492 rows available.  the docs say to trim
  193.     it to 480 by taking 10 off the top, and two off the bottom.  no
  194.     big deal either way, and all the numbers come out nice if i do so.
  195.     */
  196.  
  197.     pairflag = 0;
  198.     imagep = image;
  199.     camrow = 0;
  200.     while (camrow < 492) {
  201.     
  202.     TRACE("A", __FILE__ ": requesting camera row %d\n", camrow);
  203.  
  204.     if (winc_send_cmd(cam, Cmd_send_row, camrow>>1, (camrow & 1), 
  205.             start, send, skip, repeat/2,
  206.             -1) != OK)
  207.         return NotOK;
  208.  
  209.     /* get 512 bytes plus a checksum byte */
  210.     if (winc_get_resp_wait(cam, cols, imagep,
  211.                 2000, &sum) != OK)
  212.         return NotOK;
  213.  
  214.     if (winc_get_resp_wait(cam, 1, &csum, 200, 0) != OK)
  215.         return NotOK;
  216.  
  217.     if ((sum & 0xff) != csum)
  218.         errormsg( __FILE__ 
  219.         ": warning: camera row %d checksum incorrect\n", camrow);
  220.  
  221.     if (winc_starfield_line(star_line, cam, camrow,
  222.             start, send, skip, repeat) == OK)
  223.         winc_starfield_fix(imagep, star_line, cols);
  224.  
  225.     imagep += cols;
  226.  
  227.     /* of the 492 possible rows (in two banks) the camera can give us,
  228.      * which do we _really_ want? */
  229.     if (scantype == 2) {    /* double scan -- all of them, both banks */
  230.         camrow++;
  231.     } else if (fraction <= 2) { /* full/half height -- every row in bank */
  232.         camrow += 2;
  233.     } else if (!color) {    /* greyscale -- simple alternation */
  234.         camrow += fraction/2;
  235.     } else {
  236.         /* to satisfy color processing req'ts we want to take rows from
  237.          * the camera in pairs.  so rather than taking alternate rows, we
  238.          * take 2, skip 2, or take 2, skip 6, etc.
  239.          */
  240.         camrow += 2 * ((pairflag++ & 1) ? fraction - 1 : 1);
  241.     }
  242.     
  243.     }
  244.  
  245.     if (rows_p) {
  246.     if (scantype == 2) {
  247.         *rows_p = 492;
  248.     } else if (fraction <= 2) {
  249.         *rows_p = 246;
  250.     } else {
  251.         *rows_p = 492 / fraction;
  252.     }
  253.     }
  254.     if (cols_p)
  255.     *cols_p = cols;
  256.  
  257.  
  258.     TRACE("a", __FILE__ ": done snapping\n");
  259.  
  260.     return OK;
  261. }
  262.  
  263. /* on exit from winc_image_snap, *rows_p is the no. of rows in the pixel
  264.  * map, but _not_ necessarily the no. in the image. */
  265. result
  266. winc_image_snap(
  267.         cam_t cam,
  268.         int u_exp,        /* exposure (in microseconds), 0 to download only */
  269.         int scantype,   /* single(1), double(2), or noninterlaced(0) */
  270.         int fraction,   /* 1, 2, 4, or 8 for full, half, 1/4 and 8th size */
  271.         int color,        /* image destined for color processing */
  272.         byte *image,    /* room for expected no. bytes */
  273.         int *rows_p,    /* no. of rows in resulting image */
  274.         int *cols_p)    /* no. of cols in resulting image */
  275. {
  276.     result r;
  277.     r = winc_image_expose(cam, scantype, fraction, u_exp, image);
  278.     if (r != OK)
  279.     return r;
  280.  
  281.     return winc_image_fetch(cam, scantype, fraction, color, 
  282.             image, rows_p, cols_p);
  283. }
  284.  
  285.  
  286. result
  287. winc_black_offset(cam_t cam, int *adjp, byte *blacks)
  288. {
  289.     byte black[513];    /* room for checksum byte, which we'll ignore */
  290.     unsigned long sum;
  291.     int blackadj;
  292.     int blackrow;
  293.  
  294.     assert(cam && adjp);
  295.  
  296.     TRACE("a", __FILE__ ": getting black adjustment\n");
  297.  
  298.     blackadj = 0;
  299.     for (blackrow = 0; blackrow <= 1; blackrow++) {
  300.  
  301.     if (winc_send_cmd(cam, Cmd_send_row, blackrow + 510, 1, 
  302.                     0, 1, 0, 0, -1) != OK)
  303.         return NotOK;
  304.  
  305.     /* there are 512 bytes plus a checksum byte, or 513.
  306.      * we get them in several chunks, so we can use the pre-calculated
  307.      * sums.
  308.      * if the caller wants the values, we use their buffer.
  309.      */
  310.     /* bytes 0 through 245 */
  311.     if (winc_get_resp(cam, 246, 
  312.         blacks ? &blacks[0 + 256 * blackrow] : black,
  313.         &sum) != OK)
  314.         return NotOK;
  315.  
  316.     blackadj += sum;
  317.  
  318.     /* bytes 246 through 512 */
  319.     if (winc_get_resp(cam, 267,
  320.         blacks ? &blacks[246 + 256 * blackrow] : black,
  321.         &sum) != OK)
  322.         return NotOK;
  323.  
  324.     }
  325.  
  326.     blackadj /= (2 * 246);
  327.  
  328.     *adjp = blackadj;
  329.  
  330.     TRACE("a", __FILE__ ": black adjustment is %d\n", blackadj);
  331.  
  332.     return OK;
  333. }
  334.