aboutsummaryrefslogtreecommitdiffstats
path: root/todo
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-04-01 09:24:40 (GMT)
committerGerd Hoffmann <kraxel@redhat.com>2010-04-01 09:24:40 (GMT)
commit82fbaff22e3e4b1bbdd1e2192cfeff061ce7285c (patch)
tree308704093028c293b650fcefab4a14ef6f6ca42b /todo
parente99e58b6d385a8ae806a97b88ec4dbb26c898619 (diff)
v3.83
Diffstat (limited to 'todo')
-rw-r--r--todo/tmohan/webcam.c1650
1 files changed, 1650 insertions, 0 deletions
diff --git a/todo/tmohan/webcam.c b/todo/tmohan/webcam.c
new file mode 100644
index 0000000..0d1e35e
--- /dev/null
+++ b/todo/tmohan/webcam.c
@@ -0,0 +1,1650 @@
+/*
+ * (c) 1998-2002 Gerd Knorr
+ *
+ * capture a image, compress as jpeg and upload to the webserver
+ * using the ftp utility or ssh
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <math.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include "grab-ng.h"
+#include "jpeglib.h"
+#include "ftp.h"
+#include "parseconfig.h"
+#include "list.h"
+
+const char *HTMLSTART = {
+"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
+"<HTML>\n\n"
+"<HEAD>\n"
+"<TITLE>Webcam</TITLE>\n"
+"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"60\">\n"
+"<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">\n"
+"<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">\n"
+"<META HTTP-EQUIV=\"Cache-Control\" content=\"no-cache\">\n"
+"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">\n"
+"</HEAD>\n\n" "<BODY BGCOLOR=\"#ffffff\">\n\n"
+};
+const char *HTMLEND = {
+ "\n</BODY>\n\n" "</HTML>\n"
+};
+const char *HTMLIMAGE = {
+ "<IMG VSPACE=5 SRC=\"%%webcam.jpg%%\">\n"
+};
+
+/* ---------------------------------------------------------------------- */
+/* configuration */
+
+int daemonize = 0;
+char *archive = NULL;
+char *tmpdir;
+struct list_head connections;
+struct list_head plugin_list;
+struct plugin_s
+{
+ struct ng_filter *filter;
+ struct list_head list;
+};
+
+char *grab_text = "webcam %Y-%m-%d %H:%M:%S"; /* strftime */
+char *grab_infofile = NULL;
+int grab_width = 320;
+int grab_height = 240;
+int grab_delay = 3;
+int grab_wait = 0;
+int grab_rotate = 0;
+int grab_top = 0;
+int grab_left = 0;
+int grab_bottom = -1;
+int grab_right = -1;
+int grab_quality = 75;
+int grab_trigger = 0;
+char *grab_trigger_area = "0%,0%,100%,100%";
+int grab_trigger_average = 0;
+int grab_trigger_delay = 0;
+int grab_times = -1;
+int grab_fg_r = 255;
+int grab_fg_g = 255;
+int grab_fg_b = 255;
+int grab_bg_r = -1;
+int grab_bg_g = -1;
+int grab_bg_b = -1;
+char *grab_input = NULL;
+char *grab_norm = NULL;
+
+/* ---------------------------------------------------------------------- */
+/* jpeg stuff */
+
+static int
+write_file (int fd, char *data, int width, int height)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ FILE *fp;
+ int i;
+ unsigned char *line;
+
+ fp = fdopen (fd, "w");
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_compress (&cinfo);
+ jpeg_stdio_dest (&cinfo, fp);
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults (&cinfo);
+ jpeg_set_quality (&cinfo, grab_quality, TRUE);
+ jpeg_start_compress (&cinfo, TRUE);
+
+ for (i = 0, line = data; i < height; i++, line += width * 3)
+ jpeg_write_scanlines (&cinfo, &line, 1);
+
+ jpeg_finish_compress (&(cinfo));
+ jpeg_destroy_compress (&(cinfo));
+ fclose (fp);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* image transfer */
+
+struct xfer_ops;
+
+struct xfer_state
+{
+ char *name;
+ struct list_head list;
+
+ /* xfer options */
+ char *host;
+ char *user;
+ char *pass;
+ char *dir;
+ char *file;
+ char *tmpfile;
+ int debug;
+ int keepjpegs;
+ int currentCount;
+ char *htmlfile;
+ char *custom_htmlfile;
+
+ /* ftp options */
+ int passive, autologin;
+
+ /* function pointers + private date */
+ struct xfer_ops *ops;
+ void *data;
+};
+
+struct xfer_ops
+{
+ int (*open) (struct xfer_state *);
+ void (*info) (struct xfer_state *);
+ int (*xfer) (struct xfer_state *, char *image, int width, int height);
+ void (*close) (struct xfer_state *);
+};
+
+static int
+ftp_open (struct xfer_state *s)
+{
+ s->data = ftp_init (s->name, s->autologin, s->passive, s->debug);
+ ftp_connect (s->data, s->host, s->user, s->pass, s->dir);
+ return 0;
+}
+
+static void
+ftp_info (struct xfer_state *s)
+{
+ fprintf (stderr, "ftp config [%s]:\n %s@%s:%s\n %s => %s\n",
+ s->name, s->user, s->host, s->dir, s->tmpfile, s->file);
+}
+
+static int
+ftp_xfer (struct xfer_state *s, char *image, int width, int height)
+{
+ char filename[1024];
+ int fh;
+
+ sprintf (filename, "%s/webcamXXXXXX", tmpdir);
+ if (-1 == (fh = mkstemp (filename)))
+ {
+ perror ("mkstemp");
+ exit (1);
+ }
+ write_file (fh, image, width, height);
+
+ if (!ftp_stillconnected (s->data))
+ ftp_connect (s->data, s->host, s->user, s->pass, s->dir);
+
+ char ftpfilename[1024];
+ strcpy (ftpfilename, s->file);
+
+ if (s->keepjpegs > 1)
+ {
+ //tack a number to the file. ..before the extension
+ char *extpos, *ext = NULL;
+ if ((extpos = strrchr (ftpfilename, '.')))
+ {
+ ext = strdup (extpos);
+ *(extpos) = '\0';
+ }
+
+ sprintf (ftpfilename, "%s%02i", ftpfilename, s->currentCount);
+ if (ext)
+ {
+ strcat (ftpfilename, ext);
+ free (ext);
+ }
+
+ }
+
+ ftp_upload (s->data, filename, ftpfilename, s->tmpfile);
+
+ unlink (filename);
+
+ return 0;
+}
+
+static void
+ftp_close (struct xfer_state *s)
+{
+ ftp_fini (s->data);
+}
+
+static struct xfer_ops ftp_ops = {
+ open:ftp_open,
+ info:ftp_info,
+ xfer:ftp_xfer,
+ close:ftp_close,
+};
+
+static int
+ssh_open (struct xfer_state *s)
+{
+ s->data =
+ malloc (strlen (s->user) + strlen (s->host) + strlen (s->tmpfile) * 2 +
+ strlen (s->dir) + strlen (s->file) + 32);
+ sprintf (s->data, "ssh %s@%s \"cat >%s && mv %s %s/%s\"", s->user, s->host,
+ s->tmpfile, s->tmpfile, s->dir, s->file);
+ return 0;
+}
+
+static void
+ssh_info (struct xfer_state *s)
+{
+ fprintf (stderr, "ssh config [%s]:\n %s@%s:%s\n %s => %s\n",
+ s->name, s->user, s->host, s->dir, s->tmpfile, s->file);
+}
+
+static int
+ssh_xfer (struct xfer_state *s, char *image, int width, int height)
+{
+ char filename[1024];
+ char *cmd = s->data;
+ unsigned char buf[4096];
+ FILE *sshp, *imgdata;
+ int len, fh;
+
+ sprintf (filename, "%s/webcamXXXXXX", tmpdir);
+ if (-1 == (fh = mkstemp (filename)))
+ {
+ perror ("mkstemp");
+ exit (1);
+ }
+ write_file (fh, image, width, height);
+
+ if ((sshp = popen (cmd, "w")) == NULL)
+ {
+ perror ("popen");
+ exit (1);
+ }
+ if ((imgdata = fopen (filename, "rb")) == NULL)
+ {
+ perror ("fopen");
+ exit (1);
+ }
+ for (;;)
+ {
+ len = fread (buf, 1, sizeof (buf), imgdata);
+ if (len <= 0)
+ break;
+ fwrite (buf, 1, len, sshp);
+ }
+ fclose (imgdata);
+ pclose (sshp);
+
+ unlink (filename);
+ return 0;
+}
+
+static void
+ssh_close (struct xfer_state *s)
+{
+ char *cmd = s->data;
+ free (cmd);
+}
+
+static struct xfer_ops ssh_ops = {
+ open:ssh_open,
+ info:ssh_info,
+ xfer:ssh_xfer,
+ close:ssh_close,
+};
+
+static int
+local_open (struct xfer_state *s)
+{
+ char *t;
+
+ if (s->dir != NULL && s->dir[0] != '\0')
+ {
+ t = malloc (strlen (s->tmpfile) + strlen (s->dir) + 2);
+ sprintf (t, "%s/%s", s->dir, s->tmpfile);
+ s->tmpfile = t;
+
+ t = malloc (strlen (s->file) + strlen (s->dir) + 2);
+ sprintf (t, "%s/%s", s->dir, s->file);
+ s->file = t;
+ }
+ return 0;
+}
+
+static void
+local_info (struct xfer_state *s)
+{
+ fprintf (stderr, "write config [%s]:\n local transfer %s => %s\n",
+ s->name, s->tmpfile, s->file);
+}
+
+static int
+local_xfer (struct xfer_state *s, char *image, int width, int height)
+{
+ int fh;
+
+ if (-1 == (fh = open (s->tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0666)))
+ {
+ fprintf (stderr, "open %s: %s\n", s->tmpfile, strerror (errno));
+ exit (1);
+ }
+ write_file (fh, image, width, height);
+ if (rename (s->tmpfile, s->file))
+ {
+ fprintf (stderr, "can't move %s -> %s\n", s->tmpfile, s->file);
+ exit (1);
+ }
+ return 0;
+}
+
+static void
+local_close (struct xfer_state *s)
+{
+ /* nothing */
+}
+
+static struct xfer_ops local_ops = {
+ open:local_open,
+ info:local_info,
+ xfer:local_xfer,
+ close:local_close,
+};
+
+/* ---------------------------------------------------------------------- */
+/* capture stuff */
+
+static struct ng_video_buf *ng_buf;
+const struct ng_vid_driver *drv;
+void *h_drv;
+struct ng_video_fmt fmt, gfmt;
+struct ng_video_conv *conv;
+struct ng_filter filter;
+void *hconv;
+
+static void
+grab_init (void)
+{
+ struct ng_attribute *attr;
+ int val, i;
+
+ drv = ng_vid_open (ng_dev.video, NULL, NULL, 0, &h_drv);
+ if (NULL == drv)
+ {
+ fprintf (stderr, "no grabber device available\n");
+ exit (1);
+ }
+ if (!(drv->capabilities (h_drv) & CAN_CAPTURE))
+ {
+ fprintf (stderr, "device does'nt support capture\n");
+ exit (1);
+ }
+
+ if (grab_input)
+ {
+ attr = ng_attr_byid (drv->list_attrs (h_drv), ATTR_ID_INPUT);
+ val = ng_attr_getint (attr, grab_input);
+ if (-1 == val)
+ {
+ fprintf (stderr, "invalid input: %s\n", grab_input);
+ exit (1);
+ }
+ attr->write (attr, val);
+ }
+ if (grab_norm)
+ {
+ attr = ng_attr_byid (drv->list_attrs (h_drv), ATTR_ID_NORM);
+ val = ng_attr_getint (attr, grab_norm);
+ if (-1 == val)
+ {
+ fprintf (stderr, "invalid norm: %s\n", grab_norm);
+ exit (1);
+ }
+ attr->write (attr, val);
+ }
+
+ /* try native */
+ fmt.fmtid = VIDEO_RGB24;
+ fmt.width = grab_width;
+ fmt.height = grab_height;
+ if (0 == drv->setformat (h_drv, &fmt))
+ return;
+
+ /* check all available conversion functions */
+ fmt.bytesperline = fmt.width * ng_vfmt_to_depth[fmt.fmtid] / 8;
+ for (i = 0;;)
+ {
+ conv = ng_conv_find_to (fmt.fmtid, &i);
+ if (NULL == conv)
+ break;
+ gfmt = fmt;
+ gfmt.fmtid = conv->fmtid_in;
+ gfmt.bytesperline = 0;
+ if (0 == drv->setformat (h_drv, &gfmt))
+ {
+ fmt.width = gfmt.width;
+ fmt.height = gfmt.height;
+ hconv = conv->init (&fmt, conv->priv);
+ return;
+ }
+ }
+ fprintf (stderr, "can't get rgb24 data\n");
+ exit (1);
+}
+
+static unsigned char *
+grab_one (int *width, int *height, struct ng_video_buf **buf)
+{
+ struct ng_video_buf *ng_cap;
+
+ if (NULL != *buf)
+ ng_release_video_buf (*buf);
+ if (NULL == (ng_cap = drv->getimage (h_drv)))
+ {
+ fprintf (stderr, "capturing image failed\n");
+ exit (1);
+ }
+
+ if (NULL != conv)
+ {
+ *buf = ng_malloc_video_buf (&fmt, 3 * fmt.width * fmt.height);
+ conv->frame (hconv, *buf, ng_cap);
+ (*buf)->info = ng_cap->info;
+ ng_release_video_buf (ng_cap);
+ }
+ else
+ {
+ *buf = ng_cap;
+ }
+
+ *width = (*buf)->fmt.width;
+ *height = (*buf)->fmt.height;
+
+ return (*buf)->data;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define MSG_MAXLEN 256
+
+#define CHAR_HEIGHT 11
+#define CHAR_WIDTH 6
+#define CHAR_START 4
+#include "font-6x11.h"
+
+static char *
+get_message (void)
+{
+ static char buffer[MSG_MAXLEN + 1];
+ FILE *fp;
+ char *p;
+
+ if (NULL == grab_infofile)
+ return grab_text;
+
+ if (NULL == (fp = fopen (grab_infofile, "r")))
+ {
+ fprintf (stderr, "open %s: %s\n", grab_infofile, strerror (errno));
+ return grab_text;
+ }
+
+ fgets (buffer, MSG_MAXLEN, fp);
+ fclose (fp);
+ if (NULL != (p = strchr (buffer, '\n')))
+ *p = '\0';
+
+ return buffer;
+}
+
+static void
+add_text (char *image, int width, int height)
+{
+ time_t t;
+ struct tm *tm;
+ char line[MSG_MAXLEN + 1], *ptr;
+ int i, x, y, f, len;
+
+ time (&t);
+ tm = localtime (&t);
+ len = strftime (line, MSG_MAXLEN, get_message (), tm);
+ fprintf (stderr, "%s\n", line);
+
+ for (y = 0; y < CHAR_HEIGHT; y++)
+ {
+ ptr = image + 3 * width * (height - CHAR_HEIGHT - 2 + y) + 12;
+ for (x = 0; x < len; x++)
+ {
+ f = fontdata[line[x] * CHAR_HEIGHT + y];
+ for (i = CHAR_WIDTH - 1; i >= 0; i--)
+ {
+ if (f & (CHAR_START << i))
+ {
+ ptr[0] = grab_fg_r;
+ ptr[1] = grab_fg_g;
+ ptr[2] = grab_fg_b;
+ }
+ else if (grab_bg_r != -1)
+ {
+ ptr[0] = grab_bg_r;
+ ptr[1] = grab_bg_g;
+ ptr[2] = grab_bg_b;
+ }
+ ptr += 3;
+ }
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Frederic Helin <Frederic.Helin@inrialpes.fr> - 15/07/2002 */
+/* Correction fonction of stereographic radial distortion */
+
+int grab_dist_on = 0;
+int grab_dist_k = 700;
+int grab_dist_cx = -1;
+int grab_dist_cy = -1;
+int grab_dist_zoom = 50;
+int grab_dist_sensorw = 640;
+int grab_dist_sensorh = 480;
+
+static unsigned char *
+correct_distor (unsigned char *in, int width, int height,
+ int grab_zoom, int grap_k, int cx, int cy,
+ int grab_sensorw, int grab_sensorh)
+{
+ static unsigned char *corrimg = NULL;
+
+ int i, j, di, dj;
+ float dr, cr, ca, sensor_w, sensor_h, sx, zoom, k;
+
+ sensor_w = grab_dist_sensorw / 100.0;
+ sensor_h = grab_dist_sensorh / 100.0;
+ zoom = grab_zoom / 100.0;
+ k = grap_k / 100.0;
+
+ if (corrimg == NULL && (corrimg = malloc (width * height * 3)) == NULL)
+ {
+ fprintf (stderr, "out of memory\n");
+ exit (1);
+ }
+
+ sensor_w = 6.4;
+ sensor_h = 4.8;
+
+ // calc ratio x/y
+ sx = width * sensor_h / (height * sensor_w);
+
+ // calc new value of k in the coordonates systeme of computer
+ k = k * height / sensor_h;
+
+ // Clear image
+ for (i = 0; i < height * width * 3; i++)
+ corrimg[i] = 255;
+
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+
+ // compute radial distortion / parameters of center of image
+ cr = sqrt ((i - cx) / sx * (i - cx) / sx + (j - cy) * (j - cy));
+ ca = atan (cr / k / zoom);
+ dr = k * tan (ca / 2);
+
+ if (i == cx && j == cy)
+ {
+ di = cx;
+ dj = cy;
+ }
+ else
+ {
+ di = (i - cx) * dr / cr + cx;
+ dj = (j - cy) * dr / cr + cy;
+ }
+
+ if (dj < height && di < width && di >= 0 && dj >= 0 &&
+ j < height && i < width && i >= 0 && j >= 0)
+ {
+ corrimg[3 * (j * width + i)] = in[3 * (dj * width + di)];
+ corrimg[3 * (j * width + i) + 1] = in[3 * (dj * width + di) + 1];
+ corrimg[3 * (j * width + i) + 2] = in[3 * (dj * width + di) + 2];
+ }
+ }
+ }
+ return corrimg;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*static unsigned int
+compare_images(unsigned char *last, unsigned char *current,
+ int width, int height)
+{
+ unsigned char *p1 = last;
+ unsigned char *p2 = current;
+ int avg, diff, max, i = width*height*3;
+
+ for (max = 0, avg = 0; --i; p1++,p2++)
+ {
+ //diff = (*p1 < *p2) ? (*p2 - *p1) : (*p1 - *p2);
+ diff = abs(*p1 - *p2);
+ avg += diff;
+ if (diff > max)
+ max = diff;
+ }
+
+ avg = avg / width / height;
+ fprintf(stderr,"compare: max=%d,avg=%d\n",max,avg);
+
+ // return max
+ return max;
+}*/
+
+static unsigned int
+compare_images (unsigned char *last, unsigned char *current,
+ int offsetx, int offsety, int iwidth, int iheight,
+ int imagewidth)
+{
+ unsigned char *p1 = last;
+ unsigned char *p2 = current;
+ unsigned int p;
+ int x, y, diff, max = 0;
+ unsigned int avg = 0;
+
+ offsety *= 3;
+ offsetx *= 3;
+ iheight *= 3;
+ iwidth *= 3;
+
+ for (y = offsety; y < offsety + iheight; y += 3)
+ {
+ p = imagewidth * y;
+
+ for (x = offsetx; x < offsetx + iwidth; x++)
+ {
+ p1 = last + p + x;
+ p2 = current + p + x;
+
+ diff = abs (*p1 - *p2);
+ avg += diff;
+ if (diff > max)
+ max = diff;
+ }
+ }
+
+ avg = 3 * avg / iwidth / iheight;
+ fprintf (stderr, "compare: max=%d,avg=%d\n", max, avg);
+
+ // return max and average
+ return (max << 8) | avg;
+}
+
+/*int max2 = 0;
+static unsigned int
+compare_images(unsigned char *saved, unsigned char *last, unsigned char *current, int width, int height)
+{
+ unsigned char *p1 = last;
+ unsigned char *p2 = current;
+ unsigned char *p3 = saved;
+ int avg, diff, max, i = width*height*3;
+ int avg2, diff2;
+
+ for (max = 0, avg = 0, max2=0,avg2=0; --i; p1++,p2++,p3++)
+ {
+ diff = abs(*p1 - *p2);
+ avg += diff;
+ if (diff > max)
+ max = diff;
+
+ diff2 = abs(*p3 - *p2);
+ avg2 += diff2;
+ if (diff2 > max2)
+ max2 = diff2;
+
+ }
+
+ avg = avg / width / height;
+ avg2 = avg2 / width / height;
+ fprintf(stderr,"compare: max=%d,%d,avg=%d,%d\n",max,max2,avg,avg2);
+
+
+ return max;
+}*/
+
+static unsigned char *
+rotate_image (unsigned char *in, int *wp, int *hp, int rot,
+ int top, int left, int bottom, int right)
+{
+ static unsigned char *rotimg = NULL;
+
+ int i, j;
+
+ int w = *wp;
+ int ow = (right - left);
+ int oh = (bottom - top);
+
+ if (rotimg == NULL && (rotimg = malloc (ow * oh * 3)) == NULL)
+ {
+ fprintf (stderr, "out of memory\n");
+ exit (1);
+ }
+
+ switch (rot)
+ {
+ default:
+ case 0:
+ for (j = 0; j < oh; j++)
+ {
+ int ir = (j + top) * w + left;
+ int or = j * ow;
+ for (i = 0; i < ow; i++)
+ {
+ rotimg[3 * (or + i)] = in[3 * (ir + i)];
+ rotimg[3 * (or + i) + 1] = in[3 * (ir + i) + 1];
+ rotimg[3 * (or + i) + 2] = in[3 * (ir + i) + 2];
+ }
+ }
+ *wp = ow;
+ *hp = oh;
+ break;
+ case 1:
+ for (i = 0; i < ow; i++)
+ {
+ int rr = (ow - 1 - i) * oh;
+ int ic = i + left;
+ for (j = 0; j < oh; j++)
+ {
+ rotimg[3 * (rr + j)] = in[3 * ((j + top) * w + ic)];
+ rotimg[3 * (rr + j) + 1] = in[3 * ((j + top) * w + ic) + 1];
+ rotimg[3 * (rr + j) + 2] = in[3 * ((j + top) * w + ic) + 2];
+ }
+ }
+ *wp = oh;
+ *hp = ow;
+ break;
+ case 2:
+ for (j = 0; j < oh; j++)
+ {
+ int ir = (j + top) * w;
+ for (i = 0; i < ow; i++)
+ {
+ rotimg[3 * ((oh - 1 - j) * ow + (ow - 1 - i))] =
+ in[3 * (ir + i + left)];
+ rotimg[3 * ((oh - 1 - j) * ow + (ow - 1 - i)) + 1] =
+ in[3 * (ir + i + left) + 1];
+ rotimg[3 * ((oh - 1 - j) * ow + (ow - 1 - i)) + 2] =
+ in[3 * (ir + i + left) + 2];
+ }
+ }
+ *wp = ow;
+ *hp = oh;
+ break;
+ case 3:
+ for (i = 0; i < ow; i++)
+ {
+ int rr = i * oh;
+ int ic = i + left;
+ rr += oh - 1;
+ for (j = 0; j < oh; j++)
+ {
+ rotimg[3 * (rr - j)] = in[3 * ((j + top) * w + ic)];
+ rotimg[3 * (rr - j) + 1] = in[3 * ((j + top) * w + ic) + 1];
+ rotimg[3 * (rr - j) + 2] = in[3 * ((j + top) * w + ic) + 2];
+ }
+ }
+ *wp = oh;
+ *hp = ow;
+ break;
+ }
+
+ return rotimg;
+}
+
+//-----------------------------------------------------
+// T.Mohan - 28 July 2002
+// # strnsub() is based on source by Erik Bachmann and
+// # was released to public domain on 27 Oct 1995.
+//-----------------------------------------------------
+
+static char *
+strnsub (char *pszString, char *pszPattern, char *pszReplacement,
+ int iMaxLength, int bOnce)
+{
+ char *pszSubstring, *pszTmpSubstring, *pszlast, *pszTempReplacement;
+ int iPatternLength, iReplacementLength;
+
+ pszSubstring = pszString;
+ pszTmpSubstring = NULL;
+ iPatternLength = strlen (pszPattern);
+ pszlast = NULL;
+
+ if (!strcmp (pszPattern, pszReplacement))
+ return NULL; // Pattern == replacement: loop
+
+ while ((pszSubstring = strstr (pszSubstring, pszPattern)))
+ {
+ iReplacementLength = strlen (pszReplacement);
+ pszTempReplacement = pszReplacement;
+
+ if ((strlen (pszString) + (iReplacementLength - iPatternLength)) >
+ iMaxLength)
+ break; // Not enough space for replacement
+
+ if (pszTmpSubstring == NULL) //allocate some memory only once
+ {
+ if ((pszTmpSubstring =
+ (char *) calloc (iMaxLength, sizeof (char))) == NULL)
+ return NULL; // oops, not enough memory?
+ }
+
+ strcpy (pszTmpSubstring, pszSubstring + iPatternLength);
+
+ while (iReplacementLength--)
+ { // Copy replacement
+ *pszSubstring++ = *pszTempReplacement++;
+ }
+
+ strcpy (pszSubstring, pszTmpSubstring);
+
+ pszlast = pszSubstring - iPatternLength;
+
+ if (bOnce)
+ break; //just change one
+
+ }
+
+ if (pszTmpSubstring)
+ free (pszTmpSubstring);
+
+ return pszlast;
+
+}
+
+//-----------------------------------------------------
+// T.Mohan - 28 July 2002
+//-----------------------------------------------------
+static int
+ftp_upload_htmlfile (struct xfer_state *s)
+{
+
+#define MAXLINELEN 1024
+
+ FILE *filecustom, *filewrite;
+ int filetemp;
+ char line[MAXLINELEN];
+ char tmpfname[1024];
+ char jpegnumbered[1024], jpegfilename[1024];
+ char pattern[20], pattern_newest[20];
+ char *pszFound;
+
+ strcpy (pattern, "%%webcam.jpg%%"); //replace with numbered .jpg's
+ strcpy (pattern_newest, "%%newest.jpg%%"); //replace with newest .jpg
+ pszFound = NULL;
+ filecustom = filewrite = NULL;
+
+ //open the custom html file if requested
+ if (s->custom_htmlfile)
+ {
+ if ((filecustom = fopen (s->custom_htmlfile, "r")) == NULL)
+ {
+ perror (s->htmlfile);
+ return 1;
+ }
+ }
+
+ //create a temporary file
+ sprintf (tmpfname, "%s/webcamhtmlXXXXXX", tmpdir);
+
+ if (-1 == (filetemp = mkstemp (tmpfname)))
+ {
+ perror ("mkstemp create");
+ fclose (filecustom);
+ return 1;
+ }
+
+ if ((filewrite = fdopen (filetemp, "w")) == NULL)
+ {
+ perror ("htmlfile open for write");
+ fclose (filecustom);
+ unlink (tmpfname);
+ return 1;
+ }
+
+ if (s->keepjpegs > 1) //format the filename
+ {
+ strcpy (jpegfilename, s->file);
+ char *extpos, *ext = NULL;
+
+ if ((extpos = strrchr (jpegfilename, '.')))
+ {
+ ext = strdup (extpos);
+ *(extpos) = '\0';
+ }
+
+ //end up with something like 'webcam%02i.jpg'
+ sprintf (jpegfilename, "%s%%02i", jpegfilename);
+
+ if (ext) //tack on the extension if there is one
+ {
+ strcat (jpegfilename, ext);
+ free (ext);
+ }
+ }
+ else
+ {
+ strcpy (jpegnumbered, s->file);
+ }
+
+ //find pattern and replace with approriate filename in custom html file
+ int count = s->currentCount;
+ if (filecustom)
+ {
+ int actualcount = 0;
+
+ while (fgets (line, sizeof (line), filecustom) != NULL)
+ {
+ if (s->keepjpegs > 1)
+ sprintf (jpegnumbered, jpegfilename, count);
+
+ //replace patterns in entire line with the numbered jpeg
+ if (strnsub (line, pattern, jpegnumbered, MAXLINELEN, FALSE))
+ {
+ if (--count < 1)
+ count = s->keepjpegs;
+
+ actualcount++;
+ }
+
+ //replace tag for %%newest.jpg%%
+ if (s->keepjpegs > 1)
+ sprintf (jpegnumbered, jpegfilename, s->currentCount);
+
+ strnsub (line, pattern_newest, jpegnumbered, MAXLINELEN, FALSE);
+
+ //write line
+ fputs (line, filewrite);
+ }
+
+ if ((s->keepjpegs > 1) && (actualcount != s->keepjpegs))
+ fprintf (stderr,
+ "\n*** Warning: Found %i patterns, but keepjpegs = %i\n\n",
+ actualcount, s->keepjpegs);
+ }
+ else
+ {
+ fputs (HTMLSTART, filewrite);
+
+ int i = s->keepjpegs;
+ while (i--)
+ {
+ strcpy (line, HTMLIMAGE);
+
+ if (s->keepjpegs > 1)
+ sprintf (jpegnumbered, jpegfilename, count);
+
+ if (strnsub (line, pattern, jpegnumbered, MAXLINELEN, TRUE))
+ {
+ if (--count < 1)
+ count = s->keepjpegs;
+ }
+
+ //replace tag for %%newest.jpg%%
+ //sprintf(jpegnumbered,jpegfilename,s->currentCount);
+ //strnsub(line, pattern_newest, jpegnumbered, MAXLINELEN, FALSE);
+
+ fputs (line, filewrite);
+ }
+
+ fputs (HTMLEND, filewrite);
+ }
+
+ if (filecustom)
+ fclose (filecustom);
+ if (filewrite)
+ fclose (filewrite);
+
+ //upload the html file
+ sprintf (jpegfilename, "%s%s", s->tmpfile, ".html");
+ fprintf (stderr, "%s,%s,%s\n", tmpfname, s->htmlfile, jpegfilename);
+ ftp_upload (s->data, tmpfname, s->htmlfile, jpegfilename);
+
+ unlink (tmpfname);
+
+ return 0;
+}
+
+static void
+parse_trigger_area (char *pszTriggerArea, int *ixoffset, int *iyoffset,
+ int *width, int *height)
+{
+ if (!ixoffset || !iyoffset || !width || !height)
+ return;
+ if (!pszTriggerArea)
+ pszTriggerArea = "0%,0%,100%,100%";
+
+ char *str, *perc, *tmpStr;
+ int count = -1, ta[4], err = 0;
+
+ tmpStr = strdup (pszTriggerArea);
+ str = strtok (tmpStr, ",");
+
+ while (str && (++count < 4))
+ {
+ if ((perc = strstr (str, "%")))
+ *perc = '\0';
+
+ if (perc)
+ ta[count] = atoi (str) * ((count % 2) ? *height : *width) / 100;
+ else
+ ta[count] = atoi (str);
+
+ str = strtok (NULL, ",");
+ }
+
+ free (tmpStr);
+
+ //some foolproofing...
+ if ((ta[0] < 0) || (ta[0] > *width))
+ {
+ ta[0] = 0;
+ err = 1;
+ }
+ if ((ta[1] < 0) || (ta[1] > *height))
+ {
+ ta[1] = 0;
+ err = 1;
+ }
+ if ((ta[2] < 0) || (ta[2] > *width))
+ {
+ ta[2] = *width;
+ err = 1;
+ }
+ if ((ta[3] < 0) || (ta[3] > *height))
+ {
+ ta[3] = *height;
+ err = 1;
+ }
+ if (ta[0] >= ta[2])
+ {
+ ta[2] = *width;
+ err = 1;
+ }
+ if (ta[1] >= ta[3])
+ {
+ ta[3] = *height;
+ err = 1;
+ }
+ if (ta[2] <= ta[0])
+ {
+ ta[0] = 0;
+ err = 1;
+ }
+ if (ta[3] <= ta[1])
+ {
+ ta[1] = 0;
+ err = 1;
+ }
+
+ if (err)
+ fprintf (stderr, "\n*** Invalid trigger area was fixed.\n\n");
+
+ *ixoffset = ta[0];
+ *iyoffset = ta[1];
+ *width = ta[2] - ta[0];
+ *height = ta[3] - ta[1];
+}
+
+static void
+draw_trigger_area (unsigned char *image, int offsetx, int offsety,
+ int iTriggerwidth, int iTriggerheight, int iImageWidth)
+{
+ unsigned char *p;
+ int x, y;
+
+ offsety *= 3;
+ offsetx *= 3;
+ iTriggerheight *= 3;
+ iTriggerwidth *= 3;
+
+ for (y = offsety; y < offsety + iTriggerheight; y += 3)
+ {
+ p = image + iImageWidth * y;
+
+ for (x = offsetx; x < offsetx + iTriggerwidth; x++)
+ {
+ //trigger area is drawn inverted
+ *(p + x) = 255 - *(p + x);
+ }
+ }
+
+}
+
+static char *
+trim (char *p)
+{
+ while ((*p == ' '))
+ p++;
+ while ((p[strlen (p) - 1]) == ' ')
+ p[strlen (p) - 1] = '\0';
+
+ return p;
+}
+
+static struct ng_filter *
+get_plugin (char *name)
+{
+ int i;
+
+ for (i = 0; NULL != ng_filters[i]; i++)
+ if (!strcmp (ng_filters[i]->name, name))
+ return ng_filters[i];
+
+ return NULL;
+}
+
+static void
+parse_plugins (void)
+{
+ char *name, *attributes, *str;
+ int count = 0;
+ struct ng_filter *plugin;
+ struct plugin_s *currfilter = NULL;
+
+ INIT_LIST_HEAD (&plugin_list);
+
+ if ((str = cfg_get_str ("plugins", "names")) == NULL)
+ return;
+
+ while ((name = strtok (str, ",")))
+ {
+ str = NULL;
+
+ //remove asterix for spaces
+ strnsub (name, "*", " ", strlen (name), FALSE);
+ name = trim (name);
+
+ //plugin actually exists?
+ if ((plugin = get_plugin (name)) == NULL)
+ {
+ fprintf (stderr, "plugin: [%s] not found.\n", name);
+ continue;
+ }
+
+ currfilter = malloc (sizeof (*currfilter));
+ memset (currfilter, 0, sizeof (*currfilter));
+ currfilter->filter = plugin;
+ list_add_tail (&currfilter->list, &plugin_list);
+
+ fprintf (stderr, "plugin: [%s] found.\n", name);
+
+ count++;
+ }
+
+ //parse the attributes
+ struct list_head *item;
+ name = NULL;
+ list_for_each (item, &plugin_list)
+ {
+ struct plugin_s *currfilter = NULL;
+
+ currfilter = list_entry (item, struct plugin_s, list);
+
+ if (name)
+ free (name);
+ name = strdup (currfilter->filter->name);
+ //replace spaces in the name with asterix
+ strnsub (name, " ", "*", strlen (name), FALSE);
+ attributes = cfg_get_str ("plugins", name);
+ //remove asterix for spaces
+ strnsub (name, "*", " ", strlen (name), FALSE);
+
+ //parse the attributes
+ if (!attributes)
+ {
+ if (currfilter->filter->attrs)
+ fprintf (stderr, "plugin: [%s] Using default attributes.\n", name);
+ continue;
+ }
+
+ char *attr = attributes;
+ char attrname[64], attrvalue[192];
+ struct ng_attribute *nga = NULL;
+ while ((attributes = strtok (attr, ",")))
+ {
+ attr = NULL;
+ if (sscanf (attributes, " %63[^=] = %191[^\n]", attrname, attrvalue) !=
+ 2)
+ fprintf (stderr, "plugin: [%s] Parse error for attribute %s\n", name,
+ attrname);
+
+ trim (attrname);
+
+ if (currfilter->filter->attrs == NULL)
+ {
+ fprintf (stderr, "plugin: [%s] has no attributes to set.\n", name);
+ break;
+ }
+
+ if (!(nga = ng_attr_byname (currfilter->filter->attrs, attrname)))
+ {
+ fprintf (stderr, "plugin: [%s] Unkown attribute: %s\n", name,
+ attrname);
+ }
+ else
+ {
+ nga->write (nga, atoi (attrvalue));
+ fprintf (stderr, "plugin: [%s] Wrote attribute: %s, value: %s\n",
+ name, attrname, attrvalue);
+ }
+
+ }
+
+ }
+
+ if (name)
+ free (name);
+
+ if (count)
+ fprintf (stderr, "plugin: Using %d plugin%s.\n", count,
+ (count == 1) ? "" : "s");
+
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+int
+main (int argc, char *argv[])
+{
+ unsigned char *image, *val, *gimg, *lastimg = NULL;
+ int width, height, i, fh;
+ char filename[1024];
+ char **sections;
+ struct list_head *item;
+ struct xfer_state *s = NULL;
+ int iTrigX, iTrigY, iTrigWidth, iTrigHeight;
+ struct plugin_s *currfilter;
+
+ /* read config */
+ if (argc > 1)
+ {
+ strcpy (filename, argv[1]);
+ }
+ else
+ {
+ sprintf (filename, "%s/%s", getenv ("HOME"), ".webcamrc");
+ }
+
+ fprintf (stderr, "reading config file: %s\n", filename);
+ cfg_parse_file (filename);
+ ng_init ();
+
+ //setup the plugins
+ parse_plugins ();
+
+ if (NULL != (val = cfg_get_str ("grab", "device")))
+ ng_dev.video = val;
+ if (NULL != (val = cfg_get_str ("grab", "text")))
+ grab_text = val;
+ if (NULL != (val = cfg_get_str ("grab", "infofile")))
+ grab_infofile = val;
+ if (NULL != (val = cfg_get_str ("grab", "input")))
+ grab_input = val;
+ if (NULL != (val = cfg_get_str ("grab", "norm")))
+ grab_norm = val;
+ if (-1 != (i = cfg_get_int ("grab", "width")))
+ grab_width = i;
+ if (-1 != (i = cfg_get_int ("grab", "height")))
+ grab_height = i;
+ if (-1 != (i = cfg_get_int ("grab", "delay")))
+ grab_delay = i;
+ if (-1 != (i = cfg_get_int ("grab", "wait")))
+ grab_wait = i;
+ if (-1 != (i = cfg_get_int ("grab", "rotate")))
+ grab_rotate = i;
+ if (-1 != (i = cfg_get_int ("grab", "top")))
+ grab_top = i;
+ if (-1 != (i = cfg_get_int ("grab", "left")))
+ grab_left = i;
+ grab_bottom = cfg_get_int ("grab", "bottom");
+ grab_right = cfg_get_int ("grab", "right");
+ if (-1 != (i = cfg_get_int ("grab", "quality")))
+ grab_quality = i;
+ if (-1 != (i = cfg_get_int ("grab", "trigger")))
+ grab_trigger = i;
+ if (NULL != (val = cfg_get_str ("grab", "trigger_area")))
+ grab_trigger_area = val;
+ if (-1 != (i = cfg_get_int ("grab", "trigger_average")))
+ grab_trigger_average = i;
+ if (-1 != (i = cfg_get_int ("grab", "trigger_delay")))
+ grab_trigger_delay = i;
+ if (-1 != (i = cfg_get_int ("grab", "once")))
+ if (i)
+ grab_times = 1;
+ if (-1 != (i = cfg_get_int ("grab", "times")))
+ grab_times = i;
+ if (NULL != (val = cfg_get_str ("grab", "archive")))
+ archive = val;
+
+ if (-1 != (i = cfg_get_int ("grab", "fg_red")))
+ if (i >= 0 && i <= 255)
+ grab_fg_r = i;
+ if (-1 != (i = cfg_get_int ("grab", "fg_green")))
+ if (i >= 0 && i <= 255)
+ grab_fg_g = i;
+ if (-1 != (i = cfg_get_int ("grab", "fg_blue")))
+ if (i >= 0 && i <= 255)
+ grab_fg_b = i;
+ if (-1 != (i = cfg_get_int ("grab", "bg_red")))
+ if (i >= 0 && i <= 255)
+ grab_bg_r = i;
+ if (-1 != (i = cfg_get_int ("grab", "bg_green")))
+ if (i >= 0 && i <= 255)
+ grab_bg_g = i;
+ if (-1 != (i = cfg_get_int ("grab", "bg_blue")))
+ if (i >= 0 && i <= 255)
+ grab_bg_b = i;
+
+ if (-1 != (i = cfg_get_int ("grab", "distor")))
+ grab_dist_on = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_k")))
+ grab_dist_k = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_cx")))
+ grab_dist_cx = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_cy")))
+ grab_dist_cy = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_zoom")))
+ grab_dist_zoom = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_sensorw")))
+ grab_dist_sensorw = i;
+ if (-1 != (i = cfg_get_int ("grab", "distor_sensorh")))
+ grab_dist_sensorh = i;
+
+ if (grab_top < 0)
+ grab_top = 0;
+ if (grab_left < 0)
+ grab_left = 0;
+ if (grab_bottom > grab_height)
+ grab_bottom = grab_height;
+ if (grab_right > grab_width)
+ grab_right = grab_width;
+ if (grab_bottom < 0)
+ grab_bottom = grab_height;
+ if (grab_right < 0)
+ grab_right = grab_width;
+ if (grab_top >= grab_bottom)
+ grab_top = 0;
+ if (grab_left >= grab_right)
+ grab_left = 0;
+
+ if (grab_dist_k < 1 || grab_dist_k > 10000)
+ grab_dist_k = 700;
+ if (grab_dist_cx < 0 || grab_dist_cx > grab_width)
+ grab_dist_cx = grab_width / 2;
+ if (grab_dist_cy < 0 || grab_dist_cy > grab_height)
+ grab_dist_cy = grab_height / 2;
+ if (grab_dist_zoom < 1 || grab_dist_zoom > 1000)
+ grab_dist_zoom = 100;
+ if (grab_dist_sensorw < 1 || grab_dist_sensorw > 9999)
+ grab_dist_sensorw = 640;
+ if (grab_dist_sensorh < 1 || grab_dist_sensorh > 9999)
+ grab_dist_sensorh = 480;
+
+ INIT_LIST_HEAD (&connections);
+ for (sections = cfg_list_sections (); *sections != NULL; sections++)
+ {
+ if ((0 == strcasecmp (*sections, "grab"))
+ || (0 == strcasecmp (*sections, "plugins")))
+ continue;
+
+ /* init + set defaults */
+ s = malloc (sizeof (*s));
+ memset (s, 0, sizeof (*s));
+ s->name = *sections;
+ s->host = "www";
+ s->user = "webcam";
+ s->pass = "xxxxxx";
+ s->dir = "public_html/images";
+ s->file = "webcam.jpeg";
+ s->tmpfile = "uploading.jpeg";
+ s->passive = 1;
+ s->autologin = 0;
+ s->ops = &ftp_ops;
+ s->keepjpegs = 1; //number of jpeg files to rotate through. 0 & 1 are synonymous
+ s->htmlfile = NULL;
+ s->custom_htmlfile = NULL;
+ s->currentCount = 0;
+
+ /* from config */
+ if (NULL != (val = cfg_get_str (*sections, "host")))
+ s->host = val;
+ if (NULL != (val = cfg_get_str (*sections, "user")))
+ s->user = val;
+ if (NULL != (val = cfg_get_str (*sections, "pass")))
+ s->pass = val;
+ if (NULL != (val = cfg_get_str (*sections, "dir")))
+ s->dir = val;
+ if (NULL != (val = cfg_get_str (*sections, "file")))
+ s->file = val;
+ if (NULL != (val = cfg_get_str (*sections, "tmp")))
+ s->tmpfile = val;
+ if (-1 != (i = cfg_get_int (*sections, "passive")))
+ s->passive = i;
+ if (-1 != (i = cfg_get_int (*sections, "auto")))
+ s->autologin = i;
+ if (-1 != (i = cfg_get_int (*sections, "debug")))
+ s->debug = i;
+ if (-1 != (i = cfg_get_int (*sections, "local")))
+ if (i)
+ s->ops = &local_ops;
+ if (-1 != (i = cfg_get_int (*sections, "ssh")))
+ if (i)
+ s->ops = &ssh_ops;
+ if (-1 != (i = cfg_get_int (*sections, "keepjpegs")))
+ s->keepjpegs = (i < 1) ? 1 : i;
+ if (NULL != (val = cfg_get_str (*sections, "htmlfile")))
+ s->htmlfile = val;
+ if (NULL != (val = cfg_get_str (*sections, "custom_htmlfile")))
+ s->custom_htmlfile = val;
+
+ /* all done */
+ list_add_tail (&s->list, &connections);
+ }
+
+ /* init everything */
+ grab_init ();
+ sleep (grab_wait);
+ tmpdir = (NULL != getenv ("TMPDIR")) ? getenv ("TMPDIR") : "/tmp";
+ list_for_each (item, &connections)
+ {
+ s = list_entry (item, struct xfer_state, list);
+ s->ops->open (s);
+ }
+
+ /* print config */
+ fprintf (stderr, "video4linux webcam v1.5 - (c) 1998-2002 Gerd Knorr\n");
+ fprintf (stderr, "grabber config:\n size %dx%d [%s]\n",
+ fmt.width, fmt.height, ng_vfmt_to_desc[gfmt.fmtid]);
+ fprintf (stderr, " input %s, norm %s, jpeg quality %d\n",
+ grab_input, grab_norm, grab_quality);
+ fprintf (stderr, " rotate=%d, top=%d, left=%d, bottom=%d, right=%d\n",
+ grab_rotate, grab_top, grab_left, grab_bottom, grab_right);
+ list_for_each (item, &connections)
+ {
+ s = list_entry (item, struct xfer_state, list);
+ s->ops->info (s);
+ }
+
+ /* run as daemon - detach from terminal */
+ if (daemonize)
+ {
+ switch (fork ())
+ {
+ case -1:
+ perror ("fork");
+ exit (1);
+ case 0:
+ close (0);
+ close (1);
+ close (2);
+ setsid ();
+ break;
+ default:
+ exit (0);
+ }
+ }
+
+
+ /* main loop */
+ for (;;)
+ {
+ /* grab a new one */
+ gimg = grab_one (&width, &height, &ng_buf);
+
+ if (grab_top != 0 || grab_left != 0 ||
+ grab_right != width || grab_bottom != height)
+ { //don't call rotate_image() if nothing to do
+ gimg = rotate_image (gimg, &width, &height, grab_rotate,
+ grab_top, grab_left, grab_bottom, grab_right);
+ }
+
+ if (grab_dist_on)
+ {
+ gimg = correct_distor (gimg, width, height,
+ grab_dist_zoom, grab_dist_k,
+ grab_dist_cx, grab_dist_cy,
+ grab_dist_sensorw, grab_dist_sensorh);
+ }
+
+ image = gimg;
+
+ if (grab_trigger)
+ {
+ /* look if it has changed */
+ if (NULL != lastimg)
+ {
+ i = compare_images (lastimg, image, iTrigX, iTrigY, iTrigWidth,
+ iTrigHeight, width);
+
+ if (grab_trigger_average)
+ i = i & 0xFF;
+ else
+ i = i >> 8;
+
+ if (i < grab_trigger)
+ {
+ if (grab_trigger_delay)
+ usleep (grab_trigger_delay * 1000);
+
+ continue;
+ }
+
+ }
+ else
+ {
+ lastimg = malloc (width * height * 3);
+
+ iTrigWidth = width;
+ iTrigHeight = height;
+ fprintf (stderr, "width: %d,height:%d\n", width, height);
+ parse_trigger_area (grab_trigger_area, &iTrigX, &iTrigY, &iTrigWidth,
+ &iTrigHeight);
+ }
+
+ memcpy (lastimg, image, width * height * 3);
+
+ //draw inverted trigger area if debug > 1
+ if (s->debug > 1)
+ draw_trigger_area (image, iTrigX, iTrigY, iTrigWidth, iTrigHeight,
+ width);
+
+ }
+
+ if (!list_empty (&plugin_list))
+ {
+ //if we're using plugins ng_buf will have to be valid
+ // to pass to the filters.
+ //assign the current image to ng_buf and make sure fmt is
+ // valid due to possible size change in rotate_image()
+ if (!conv && !ng_buf)
+ ng_buf = ng_malloc_video_buf (&fmt, 3 * fmt.width * fmt.height);
+
+ ng_buf->fmt.width = width;
+ ng_buf->fmt.height = height;
+ ng_buf->fmt.bytesperline = width * (ng_vfmt_to_depth[fmt.fmtid] / 8);
+ ng_buf->size = ng_buf->fmt.bytesperline * height;
+ memcpy (ng_buf->data, image, ng_buf->size);
+
+ //call the plugins....
+ list_for_each (item, &plugin_list)
+ {
+ currfilter = list_entry (item, struct plugin_s, list);
+ ng_buf = ng_filter_single (currfilter->filter, ng_buf);
+ image = ng_buf->data;
+ }
+
+ }
+
+ /* ok, label it and upload */
+ add_text (image, width, height);
+
+ list_for_each (item, &connections)
+ {
+ s = list_entry (item, struct xfer_state, list);
+
+ if (++s->currentCount > s->keepjpegs)
+ s->currentCount = 1;
+
+ s->ops->xfer (s, image, width, height);
+
+ if (s->htmlfile) // || s->custom_htmlfile)
+ ftp_upload_htmlfile (s);
+ }
+
+ if (archive)
+ {
+ time_t t;
+ struct tm *tm;
+
+ time (&t);
+ tm = localtime (&t);
+ strftime (filename, sizeof (filename) - 1, archive, tm);
+ if (-1 == (fh = open (filename, O_CREAT | O_WRONLY | O_TRUNC, 0666)))
+ {
+ fprintf (stderr, "open %s: %s\n", filename, strerror (errno));
+ exit (1);
+ }
+ write_file (fh, image, width, height);
+ }
+
+ if (-1 != grab_times && --grab_times == 0)
+ {
+ fprintf (stderr, "grab \"times\" reached 0\n");
+ break;
+ }
+ if (grab_delay > 0)
+ {
+ fprintf (stderr, "delay for %d seconds...\n", grab_delay);
+ sleep (grab_delay);
+ }
+ }
+
+ list_for_each (item, &connections)
+ {
+ s = list_entry (item, struct xfer_state, list);
+ s->ops->close (s);
+ }
+
+ return 0;
+}

Privacy Policy