diff -ru motion-20111030-051001/conf.c motion-20111030-051001_mirror/conf.c
--- motion-20111030-051001/conf.c	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/conf.c	2011-11-05 18:54:47.000000000 +0200
@@ -46,6 +46,7 @@
     width:                          DEF_WIDTH,
     height:                         DEF_HEIGHT,
     quality:                        DEF_QUALITY,
+    mirror:                         0,
     rotate_deg:                     0,
     max_changes:                    DEF_CHANGES,
     threshold_tune:                 0,
@@ -318,6 +319,16 @@
     print_int
     },
     {
+    "mirror",
+    "# Flip images in X axis. The mirroring occurs before rotation and affects all\n"
+    "# saved images as well as movies.\n"
+    "# Default: off.",
+    0,
+    CONF_OFFSET(mirror),
+    copy_bool,
+    print_bool
+    },
+    {
     "rotate",
     "# Rotate image this number of degrees. The rotation affects all saved images as\n"
     "# well as movies. Valid values: 0 (default = no rotation), 90, 180 and 270.",
diff -ru motion-20111030-051001/conf.h motion-20111030-051001_mirror/conf.h
--- motion-20111030-051001/conf.h	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/conf.h	2011-11-05 18:50:50.000000000 +0200
@@ -26,6 +26,7 @@
     int width;
     int height;
     int quality;
+    int mirror;
     int rotate_deg;
     int max_changes;
     int threshold_tune;
diff -ru motion-20111030-051001/motion-dist.conf.in motion-20111030-051001_mirror/motion-dist.conf.in
--- motion-20111030-051001/motion-dist.conf.in	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/motion-dist.conf.in	2011-11-05 18:53:36.000000000 +0200
@@ -82,6 +82,11 @@
 # The frequency to set the tuner to (kHz) (only for TV tuner cards) (default: 0)
 frequency 0
 
+# Flip images in X axis. The mirroring occurs before rotation and affects all
+# saved images as well as movies.
+# Default: off.
+mirror off
+
 # Rotate image this number of degrees. The rotation affects all saved images as
 # well as movies. Valid values: 0 (default = no rotation), 90, 180 and 270.
 rotate 0
diff -ru motion-20111030-051001/motion.h motion-20111030-051001_mirror/motion.h
--- motion-20111030-051001/motion.h	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/motion.h	2011-11-05 18:49:29.000000000 +0200
@@ -319,6 +319,13 @@
     /* Temporary buffer for 90 and 270 degrees rotation. */
     unsigned char *temp_buf;
     /* 
+     * Mirror flag; copied from conf.mirror. This is the value
+     * that is actually used. The value of conf.mirror cannot be used
+     * because it can be changed by motion-control, and changing mirroring
+     * while Motion is running just causes problems.
+     */
+    int mirror;
+    /* 
      * Degrees to rotate; copied from conf.rotate_deg. This is the value
      * that is actually used. The value of conf.rotate_deg cannot be used
      * because it can be changed by motion-control, and changing rotation
diff -ru motion-20111030-051001/netcam_jpeg.c motion-20111030-051001_mirror/netcam_jpeg.c
--- motion-20111030-051001/netcam_jpeg.c	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/netcam_jpeg.c	2011-11-05 18:29:56.000000000 +0200
@@ -405,7 +405,7 @@
     jpeg_finish_decompress(cinfo);
     jpeg_destroy_decompress(cinfo);
 
-    if (netcam->cnt->rotate_data.degrees > 0)
+    if (netcam->cnt->rotate_data.mirror || netcam->cnt->rotate_data.degrees)
         /* Rotate as specified */
         rotate_map(netcam->cnt, image);
 
diff -ru motion-20111030-051001/rotate.c motion-20111030-051001_mirror/rotate.c
--- motion-20111030-051001/rotate.c	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/rotate.c	2011-11-05 18:58:26.000000000 +0200
@@ -148,6 +148,60 @@
 }
 
 /**
+ * hflip_inplace_quad
+ *
+ *  Horizontally flip a block of memory in-place, 4 bytes at a time. This
+ *  function requires the __uint32 type, which is 32 bits wide.
+ *
+ * Parameters:
+ *
+ *   src  - the memory block to reverse
+ *   width  - the width of the memory block when seen as an image
+ *   height - the height of the memory block when seen as an image
+ *
+ * Returns: nothing
+ */
+static void hflip_inplace_quad(unsigned char *src, int width, int height)
+{
+    register int j;
+
+    for (j = 0; j < height; j++, src += width)
+        reverse_inplace_quad(src, width);
+}
+
+/**
+ * vflip_inplace_quad
+ *
+ *  Vertically flip a block of memory in-place, 4 bytes at a time. This
+ *  function requires the __uint32 type, which is 32 bits wide.
+ *
+ * Parameters:
+ *
+ *   src  - the memory block to reverse
+ *   width  - the width of the memory block when seen as an image
+ *   height - the height of the memory block when seen as an image
+ *
+ * Returns: nothing
+ */
+static void vflip_inplace_quad(unsigned char *src, int width, int height)
+{
+    __uint32 *nsrc = (__uint32 *)src;
+    __uint32 *ndst = (__uint32 *)(src + width * height - width);
+    register __uint32 tmp;
+    register int j = width / 4;
+
+    while (nsrc < ndst) {
+        tmp = *ndst;
+        *ndst++ = *nsrc;
+        *nsrc++ = tmp;
+        if (--j == 0) {
+            ndst -= width / 2;
+            j = width / 4;
+        }
+    }
+}
+
+/**
  * rot90cw
  *
  *  Performs a 90 degrees clockwise rotation of the memory block pointed to
@@ -158,20 +212,19 @@
  *
  *   src    - pointer to the memory block (image) to rotate clockwise
  *   dst    - where to put the rotated memory block
- *   size   - the size (in bytes) of the memory blocks (both src and dst)
  *   width  - the width of the memory block when seen as an image
  *   height - the height of the memory block when seen as an image
  *
  * Returns: nothing
  */
-static void rot90cw(unsigned char *src, register unsigned char *dst, int size,
+static void rot90cw(unsigned char *src, register unsigned char *dst,
                     int width, int height)
 {
     unsigned char *endp;
     register unsigned char *base;
     int j;
 
-    endp = src + size;
+    endp = src + width * height;
     for (base = endp - width; base < endp; base++) {
         src = base;
         for (j = 0; j < height; j++, src -= width)
@@ -181,6 +234,39 @@
 }
 
 /**
+ * mirrot90cw
+ *
+ *  Performs horizontal flip and 90 degrees clockwise rotation of the
+ *  memory block pointed to by src. The rotation is NOT performed in-place;
+ *  dst must point to a receiving memory block the same size as src.
+ *
+ * Parameters:
+ *
+ *   src    - pointer to the memory block (image) to rotate clockwise
+ *   dst    - where to put the rotated memory block
+ *   width  - the width of the memory block when seen as an image
+ *   height - the height of the memory block when seen as an image
+ *
+ * Returns: nothing
+ */
+static void mirrot90cw(unsigned char *src, register unsigned char *dst,
+                       int width, int height)
+{
+    unsigned char *endp;
+    register unsigned char *base;
+    int j;
+
+    endp = src + width;
+    dst = dst + width * height - 1;
+    for (base = src; base < endp; base++) {
+        src = base;
+        for (j = 0; j < height; j++, src += width)
+            *dst-- = *src;
+
+    }
+}
+
+/**
  * rot90ccw
  *
  *  Performs a 90 degrees counterclockwise rotation of the memory block pointed
@@ -191,21 +277,20 @@
  *
  *   src    - pointer to the memory block (image) to rotate counterclockwise
  *   dst    - where to put the rotated memory block
- *   size   - the size (in bytes) of the memory blocks (both src and dst)
  *   width  - the width of the memory block when seen as an image
  *   height - the height of the memory block when seen as an image
  *
  * Returns: nothing
  */
 static inline void rot90ccw(unsigned char *src, register unsigned char *dst,
-                            int size, int width, int height)
+                            int width, int height)
 {
     unsigned char *endp;
     register unsigned char *base;
     int j;
 
-    endp = src + size;
-    dst = dst + size - 1;
+    endp = src + width * height;
+    dst = dst + width * height - 1;
     for (base = endp - width; base < endp; base++) {
         src = base;
         for (j = 0; j < height; j++, src -= width)
@@ -215,6 +300,38 @@
 }
 
 /**
+ * mirrot90ccw
+ *
+ *  Performs horizontal flip and 90 degrees counterclockwise rotation of the
+ *  memory block pointed to by src. The rotation is NOT performed in-place;
+ *  dst must point to a receiving memory block the same size as src.
+ *
+ * Parameters:
+ *
+ *   src    - pointer to the memory block (image) to rotate clockwise
+ *   dst    - where to put the rotated memory block
+ *   width  - the width of the memory block when seen as an image
+ *   height - the height of the memory block when seen as an image
+ *
+ * Returns: nothing
+ */
+static inline void mirrot90ccw(unsigned char *src, register unsigned char *dst,
+                               int width, int height)
+{
+    unsigned char *endp;
+    register unsigned char *base;
+    int j;
+
+    endp = src + width;
+    for (base = src; base < endp; base++) {
+        src = base;
+        for (j = 0; j < height; j++, src += width)
+            *dst++ = *src;
+
+    }
+}
+
+/**
  * rotate_init
  *
  *  Initializes rotation data - allocates memory and determines which function
@@ -234,6 +351,12 @@
     cnt->rotate_data.temp_buf = NULL;
 
     /*
+     * Assign the value in conf.mirror to rotate_data.mirror. This way,
+     * we have a value that is safe from changes caused by motion-control.
+     */
+    cnt->rotate_data.mirror = cnt->conf.mirror;
+
+    /*
      * Assign the value in conf.rotate_deg to rotate_data.degrees. This way,
      * we have a value that is safe from changes caused by motion-control.
      */
@@ -271,16 +394,16 @@
      * If we're not rotating, let's exit once we have setup the capture dimensions
      * and output dimensions properly.
      */
-    if (cnt->rotate_data.degrees == 0)
+    if (cnt->rotate_data.mirror == 0 && cnt->rotate_data.degrees == 0)
         return;
 
     switch (cnt->imgs.type) {
     case VIDEO_PALETTE_YUV420P:
         /*
          * For YUV 4:2:0 planar, the memory block used for 90/270 degrees
-         * rotation needs to be width x height x 1.5 bytes large.
+         * rotation needs to be width x height bytes large.
          */
-        size = cnt->imgs.width * cnt->imgs.height * 3 / 2;
+        size = cnt->imgs.width * cnt->imgs.height;
         break;
     case VIDEO_PALETTE_GREY:
         /*
@@ -290,6 +413,7 @@
         size = cnt->imgs.width * cnt->imgs.height;
         break;
     default:
+        cnt->rotate_data.mirror = 0;
         cnt->rotate_data.degrees = 0;
         MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "%s: Unsupported palette (%d), rotation is disabled",
                     cnt->imgs.type);
@@ -349,9 +473,10 @@
      * of width x height bytes.
      */
     int wh, wh4 = 0, w2 = 0, h2 = 0;  /* width * height, width * height / 4 etc. */
-    int size, deg;
+    int mirror, deg;
     int width, height;
 
+    mirror = cnt->rotate_data.mirror;
     deg = cnt->rotate_data.degrees;
     width = cnt->rotate_data.cap_width;
     height = cnt->rotate_data.cap_height;
@@ -359,61 +484,95 @@
     /*
      * Pre-calculate some stuff:
      *  wh   - size of the Y plane, or the entire greyscale image
-     *  size - size of the entire memory block
      *  wh4  - size of the U plane, and the V plane
      *  w2   - width of the U plane, and the V plane
      *  h2   - as w2, but height instead
      */
     wh = width * height;
-    if (cnt->imgs.type == VIDEO_PALETTE_YUV420P) {
-        size = wh * 3 / 2;
-        wh4 = wh / 4;
-        w2 = width / 2;
-        h2 = height / 2;
-    } else { /* VIDEO_PALETTE_GREY */
-        size = wh;
-    }
+    wh4 = wh / 4;
+    w2 = width / 2;
+    h2 = height / 2;
 
     switch (deg) {
+    case 0:
+        /* Only mirror the data within Y, U and V */
+        if (mirror)
+            hflip_inplace_quad(map, width, height);
+        if (cnt->imgs.type == VIDEO_PALETTE_YUV420P) {
+            if (mirror) {
+                hflip_inplace_quad(map + wh, w2, h2);
+                hflip_inplace_quad(map + wh + wh4, w2, h2);
+            }
+        }
+        break;
+
     case 90:
         /* First do the Y part */
-        rot90cw(map, cnt->rotate_data.temp_buf, wh, width, height);
+        if (mirror)
+            mirrot90cw(map, cnt->rotate_data.temp_buf, width, height);
+        else
+            rot90cw(map, cnt->rotate_data.temp_buf, width, height);
+        /* Then copy back from the temp buffer to map. */
+        memcpy(map, cnt->rotate_data.temp_buf, wh);
         if (cnt->imgs.type == VIDEO_PALETTE_YUV420P) {
             /* Then do U and V */
-            rot90cw(map + wh, cnt->rotate_data.temp_buf + wh, wh4, w2, h2);
-            rot90cw(map + wh + wh4, cnt->rotate_data.temp_buf + wh + wh4,
-                    wh4, w2, h2);
+            if (mirror) {
+                mirrot90cw(map + wh, cnt->rotate_data.temp_buf, w2, h2);
+                mirrot90cw(map + wh + wh4, cnt->rotate_data.temp_buf + wh4,
+                           w2, h2);
+            } else {
+                rot90cw(map + wh, cnt->rotate_data.temp_buf, w2, h2);
+                rot90cw(map + wh + wh4, cnt->rotate_data.temp_buf + wh4,
+                        w2, h2);
+            }
+            /* Then copy back from the temp buffer to map. */
+            memcpy(map + wh, cnt->rotate_data.temp_buf, wh/2);
         }
-
-        /* Then copy back from the temp buffer to map. */
-        memcpy(map, cnt->rotate_data.temp_buf, size);
         break;
 
     case 180:
         /*
-         * 180 degrees is easy - just reverse the data within
-         * Y, U and V.
+         * 180 degrees just reverse the data within Y, U and V.
+         * 180 degrees + mirror = flip upside down data within Y, U and V.
          */
-        reverse_inplace_quad(map, wh);
+        if (mirror)
+            vflip_inplace_quad(map, width, height);
+        else
+            reverse_inplace_quad(map, wh);
         if (cnt->imgs.type == VIDEO_PALETTE_YUV420P) {
-            reverse_inplace_quad(map + wh, wh4);
-            reverse_inplace_quad(map + wh + wh4, wh4);
+            if (mirror) {
+                vflip_inplace_quad(map + wh, w2, h2);
+                vflip_inplace_quad(map + wh + wh4, w2, h2);
+            } else {
+                reverse_inplace_quad(map + wh, wh4);
+                reverse_inplace_quad(map + wh + wh4, wh4);
+            }
         }
         break;
 
     case 270:
 
         /* First do the Y part */
-        rot90ccw(map, cnt->rotate_data.temp_buf, wh, width, height);
+        if (mirror)
+            mirrot90ccw(map, cnt->rotate_data.temp_buf, width, height);
+        else
+            rot90ccw(map, cnt->rotate_data.temp_buf, width, height);
+        /* Then copy back from the temp buffer to map. */
+        memcpy(map, cnt->rotate_data.temp_buf, wh);
         if (cnt->imgs.type == VIDEO_PALETTE_YUV420P) {
             /* Then do U and V */
-            rot90ccw(map + wh, cnt->rotate_data.temp_buf + wh, wh4, w2, h2);
-            rot90ccw(map + wh + wh4, cnt->rotate_data.temp_buf + wh + wh4,
-                     wh4, w2, h2);
+            if (mirror) {
+                mirrot90ccw(map + wh, cnt->rotate_data.temp_buf, w2, h2);
+                mirrot90ccw(map + wh + wh4, cnt->rotate_data.temp_buf + wh4,
+                            w2, h2);
+            } else {
+                rot90ccw(map + wh, cnt->rotate_data.temp_buf, w2, h2);
+                rot90ccw(map + wh + wh4, cnt->rotate_data.temp_buf + wh4,
+                         w2, h2);
+            }
+            /* Then copy back from the temp buffer to map. */
+            memcpy(map + wh, cnt->rotate_data.temp_buf, wh/2);
         }
-
-        /* Then copy back from the temp buffer to map. */
-        memcpy(map, cnt->rotate_data.temp_buf, size);
         break;
 
     default:
diff -ru motion-20111030-051001/video_common.c motion-20111030-051001_mirror/video_common.c
--- motion-20111030-051001/video_common.c	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/video_common.c	2011-11-05 18:31:40.000000000 +0200
@@ -957,7 +957,7 @@
         }
 
         /* Rotate the image as specified. */
-        if (cnt->rotate_data.degrees > 0)
+        if (cnt->rotate_data.mirror || cnt->rotate_data.degrees)
             rotate_map(cnt, map);
 
     }
diff -ru motion-20111030-051001/video_freebsd.c motion-20111030-051001_mirror/video_freebsd.c
--- motion-20111030-051001/video_freebsd.c	2011-10-30 06:10:01.000000000 +0200
+++ motion-20111030-051001_mirror/video_freebsd.c	2011-11-05 18:30:15.000000000 +0200
@@ -1326,7 +1326,7 @@
     }
 
     /* Rotate the image as specified */
-    if (cnt->rotate_data.degrees > 0)
+    if (cnt->rotate_data.mirror || cnt->rotate_data.degrees)
         rotate_map(cnt, map);
 
 
