compress marked frames
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 11 Oct 2015 11:32:47 +0000 (13:32 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 May 2016 10:55:54 +0000 (12:55 +0200)
src/mark.c

index 687837a..3d5143f 100644 (file)
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
 #include "mark.h"
 #include "yuv.h"
 #include "dir_seperator.h"
@@ -82,6 +83,34 @@ int load_palette(const char *filename)
        return 0;
 }
 
+/* encode RLE */
+static int encode_rle(unsigned char *in, unsigned char *out, int width, int height)
+{
+       int n = width * height;
+       unsigned char v, l;
+       int i, j;
+
+       /* encode into lengh-value array of two bytes */
+       strncpy((char *)out, "RLE!", 4);
+       j = 4;
+       for (i = 0; i < n;) {
+               v = in[i++];
+               for (l = 1; l < 255; l++) {
+                       if (v != in[i])
+                               break;
+                       i++;
+               }
+               /* encoded size would exceed regular size */
+               if (j+3 >= n)
+                       return 0;
+               out[j++] = l;
+               out[j++] = v;
+       }
+       out[j++] = 0;
+
+       return j;
+}
+
 /* save marked area, if any. return 0, if no pixle is marked and erase existing file */
 int save_marked(unsigned char *img_mark_buffer, int width, int height, const char *filename)
 {
@@ -95,13 +124,22 @@ int save_marked(unsigned char *img_mark_buffer, int width, int height, const cha
        }
        sprintf(name, "%s_marked", filename);
        if (i == width * height) {
-//             printf("delete marked frame=%s\n", name);
                /* empty, so delete */
                unlink(name);
 
                return 0;
        } else {
-//             printf("save marked frame=%s\n", name);
+               int len = width*height;
+               unsigned char *out;
+               out = (unsigned char *)malloc(len);
+               if (out) {
+                       rc = encode_rle(img_mark_buffer, out, width, height);
+                       if (rc < 1) {
+                               free(out);
+                               out = NULL;
+                       } else
+                               len = rc;
+               }
                /* not empty, so save */
                fp = fopen(name, "w");
                if (!fp) {
@@ -109,8 +147,9 @@ int save_marked(unsigned char *img_mark_buffer, int width, int height, const cha
                        printf("failed to save marked frame=%s\n", name);
                        return -1;
                }
-               rc = fwrite(img_mark_buffer, width * height, 1, fp);
+               rc = fwrite(out ?: img_mark_buffer, len, 1, fp);
                fclose(fp);
+               free(out);
                if (rc != 1)
                        goto write_failed;
 
@@ -118,6 +157,41 @@ int save_marked(unsigned char *img_mark_buffer, int width, int height, const cha
        }
 }
 
+/* decode RLE */
+static int decode_rle(unsigned char *in, int len, int width, int height)
+{
+       int n = width * height;
+       unsigned char *out, v, l;
+       int i, j = 0;
+
+       /* no RLE magic */
+       if (n < 4 || !!strncmp((char *)in, "RLE!", 4))
+               return 0;
+
+       i = 4;
+       if (len-i < 1)
+               return -EINVAL;
+
+       out = (unsigned char *)malloc(n);
+       if (!out)
+               return -ENOMEM;
+
+       while ((l = in[i++])) {
+               if (len-i < 1) {
+                       /* short read */
+                       free(out);
+                       return -EIO;
+               }
+               v = in[i++];
+               memset(out+j, v, l);
+               j += l;
+       }
+
+       memcpy(in, out, n);
+       free(out);
+       return 0;
+}
+
 int load_marked(unsigned char *img_mark_buffer, int width, int height, const char *filename)
 {
        char name[256];
@@ -132,10 +206,15 @@ int load_marked(unsigned char *img_mark_buffer, int width, int height, const cha
 //             printf("failed to load marked frame=%s\n", name);
                return -1;
        }
-       rc = fread(img_mark_buffer, width * height, 1, fp);
+       rc = fread(img_mark_buffer, 1, width * height, fp);
        fclose(fp);
-       if (rc != 1)
+       if (rc < 0)
                goto read_failed;
+       rc = decode_rle(img_mark_buffer, rc, width, height);
+       if (rc < 0) {
+               printf("failed to decode RLE of marked frame=%s\n", name);
+               return -1;
+       }
 
        return 0;
 }