#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <errno.h>
#include "mark.h"
#include "yuv.h"
#include "dir_seperator.h"
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)
{
}
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) {
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;
}
}
+/* 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];
// 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;
}