summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/rle.c171
-rw-r--r--tools/rle.h49
2 files changed, 220 insertions, 0 deletions
diff --git a/tools/rle.c b/tools/rle.c
new file mode 100644
index 00000000..2e60afd1
--- /dev/null
+++ b/tools/rle.c
@@ -0,0 +1,171 @@
+/*
+ * rle.c: RLE utils
+ *
+ * See the main source file 'xineliboutput.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: rle.c,v 1.1 2008-12-05 16:34:21 phintuka Exp $
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "../xine_osd_command.h"
+
+#include "rle.h"
+
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/*
+ * rle_compress()
+ *
+ */
+int rle_compress(xine_rle_elem_t **rle_data, const uint8_t *data, int w, int h)
+{
+ xine_rle_elem_t rle, *rle_p = 0, *rle_base;
+ int x, y, num_rle = 0, rle_size = 8128;
+ const uint8_t *c;
+
+ rle_p = (xine_rle_elem_t*)malloc(4*rle_size);
+ rle_base = rle_p;
+
+ for( y = 0; y < h; y++ ) {
+ rle.len = 0;
+ rle.color = 0;
+ c = data + y * w;
+ for( x = 0; x < w; x++, c++ ) {
+ if( rle.color != *c ) {
+ if( rle.len ) {
+ if( (num_rle + h-y+1) > rle_size ) {
+ rle_size *= 2;
+ rle_base = (xine_rle_elem_t*)realloc( rle_base, 4*rle_size );
+ rle_p = rle_base + num_rle;
+ }
+ *rle_p++ = rle;
+ num_rle++;
+ }
+ rle.color = *c;
+ rle.len = 1;
+ } else {
+ rle.len++;
+ }
+ }
+ *rle_p++ = rle;
+ num_rle++;
+ }
+
+ *rle_data = rle_base;
+ return num_rle;
+}
+
+/*
+ * rle_scale_nearest()
+ *
+ * - Simple nearest-neighbour scaling for RLE-compressed image
+ * - fast scaling in compressed form without decompression
+ */
+xine_rle_elem_t *rle_scale_nearest(const xine_rle_elem_t *old_rle, int *rle_elems,
+ int w, int h, int new_w, int new_h)
+{
+ #define FACTORBASE 0x100
+ #define FACTOR2PIXEL(f) ((f)>>8)
+ #define SCALEX(x) FACTOR2PIXEL(factor_x*(x))
+ #define SCALEY(y) FACTOR2PIXEL(factor_y*(y))
+
+ int old_w = w, old_h = h;
+ int old_y = 0, new_y = 0;
+ int factor_x = FACTORBASE*new_w/old_w;
+ int factor_y = FACTORBASE*new_h/old_h;
+ int rle_size = MAX(8128, *rle_elems * new_h/h ); /* guess ... */
+ int num_rle = 0;
+ xine_rle_elem_t *new_rle = (xine_rle_elem_t*)malloc(sizeof(xine_rle_elem_t)*rle_size);
+ xine_rle_elem_t *new_rle_start = new_rle;
+
+ /* we assume rle elements are breaked at end of line */
+ while(old_y < old_h) {
+ int elems_current_line = 0;
+ int old_x = 0, new_x = 0;
+
+ while(old_x < old_w) {
+ int new_x_end = SCALEX(old_x + old_rle->len);
+
+ if(new_x_end > new_w) {
+ new_x_end = new_w;
+ }
+
+ new_rle->len = new_x_end - new_x;
+ new_rle->color = old_rle->color;
+
+ old_x += old_rle->len;
+ old_rle++; /* may be incremented to last element + 1 (element is not accessed anymore) */
+
+ if(new_rle->len > 0) {
+ new_x += new_rle->len;
+ new_rle++;
+
+ num_rle++;
+ elems_current_line++;
+
+ if( (num_rle + 1) >= rle_size ) {
+ rle_size *= 2;
+ new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size);
+ new_rle = new_rle_start + num_rle;
+ }
+ }
+ }
+ if(new_x < new_w)
+ (new_rle-1)->len += new_w - new_x;
+ old_y++;
+ new_y++;
+
+ if(factor_y > FACTORBASE) {
+ /* scale up -- duplicate current line ? */
+ int dup = SCALEY(old_y) - new_y;
+
+ /* if no lines left in (old) rle, copy all lines still missing from new */
+ if(old_y == old_h)
+ dup = new_h - new_y - 1;
+
+ while(dup-- && (new_y+1<new_h)) {
+ xine_rle_elem_t *prevline;
+ int n;
+ if( (num_rle + elems_current_line + 1) >= rle_size ) {
+ rle_size *= 2;
+ new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size);
+ new_rle = new_rle_start + num_rle;
+ }
+
+ /* duplicate previous line */
+ prevline = new_rle - elems_current_line;
+ for(n = 0; n < elems_current_line; n++) {
+ *new_rle++ = *prevline++;
+ num_rle++;
+ }
+ new_y++;
+ }
+
+ } else if(factor_y < FACTORBASE) {
+ /* scale down -- drop next line ? */
+ int skip = new_y - SCALEY(old_y);
+ if(old_y == old_h-1) {
+ /* one (old) line left ; don't skip it if new rle is not complete */
+ if(new_y < new_h)
+ skip = 0;
+ }
+ while(skip-- &&
+ old_y<old_h /* rounding error may add one line, filter it out */) {
+ for(old_x = 0; old_x < old_w;) {
+ old_x += old_rle->len;
+ old_rle++;
+ }
+ old_y++;
+ }
+ }
+ }
+
+ *rle_elems = num_rle;
+ return new_rle_start;
+}
diff --git a/tools/rle.h b/tools/rle.h
new file mode 100644
index 00000000..09405bbc
--- /dev/null
+++ b/tools/rle.h
@@ -0,0 +1,49 @@
+/*
+ * rle.h: RLE utils
+ *
+ * See the main source file 'xineliboutput.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: rle.h,v 1.1 2008-12-05 16:34:21 phintuka Exp $
+ *
+ */
+
+#ifndef XINELIBOUTPUT_RLE_H_
+#define XINELIBOUTPUT_RLE_H_
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ scale_fast = 0, /* simple pixel doubling/dropping */
+ scale_good_BW = 1, /* linear interpolation, palette re-generation */
+} scale_mode_t;
+
+struct xine_rle_elem_s;
+struct xine_clut_s;
+
+int rle_compress(struct xine_rle_elem_s **rle_data, const uint8_t *data, int w, int h);
+
+void rle_uncompress_lut8(const struct xine_rle_elem_s *rle_data,
+ uint8_t *data, int w, int h);
+void rle_uncompress_argb(const struct xine_rle_elem_s *rle_data,
+ uint8_t *data, int w, int h,
+ struct xine_clut_s *palette);
+
+/*
+ * rle_scale_nearest()
+ *
+ * - Simple nearest-neighbour scaling for RLE-compressed image
+ * - fast scaling in compressed form without decompression
+ */
+struct xine_rle_elem_s *rle_scale_nearest(const struct xine_rle_elem_s *old_rle,
+ int *rle_elems,
+ int w, int h, int new_w, int new_h);
+
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* XINELIBOUTPUT_RLE_H_ */