summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2006-11-17 07:56:23 +0000
committerDavid Schleef <ds@schleef.org>2006-11-17 07:56:23 +0000
commit402101cd065c69e0d8e1297a0f106ea90e1750e8 (patch)
tree922be89299db9fdd199701a69fe3cff26db49fc1 /examples
parent2b96a77c184f68858cd86d6025246088ecbcb05b (diff)
* examples/jpeg/Makefile.am:
* examples/jpeg/huffman.c: * examples/jpeg/huffman.h: * examples/jpeg/jpeg.c: * examples/jpeg/jpeg_rgb_decoder.c: * examples/jpeg/test.c: * examples/jpeg/test_rgb.c: Remove glibisms from jpeg code. * configure.ac: * examples/Makefile.am: * examples/videoscale/Makefile.am: * examples/videoscale/vs_4tap.c: * examples/videoscale/vs_4tap.h: * examples/videoscale/vs_image.c: * examples/videoscale/vs_image.h: * examples/videoscale/vs_scanline.c: * examples/videoscale/vs_scanline.h: Add videoscale code from gstreamer.
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile.am2
-rw-r--r--examples/jpeg/Makefile.am16
-rw-r--r--examples/jpeg/huffman.c26
-rw-r--r--examples/jpeg/huffman.h26
-rw-r--r--examples/jpeg/jpeg.c24
-rw-r--r--examples/jpeg/jpeg_rgb_decoder.c13
-rw-r--r--examples/jpeg/test.c5
-rw-r--r--examples/jpeg/test_rgb.c13
-rw-r--r--examples/videoscale/Makefile.am15
-rw-r--r--examples/videoscale/vs_4tap.c179
-rw-r--r--examples/videoscale/vs_4tap.h44
-rw-r--r--examples/videoscale/vs_image.c853
-rw-r--r--examples/videoscale/vs_image.h78
-rw-r--r--examples/videoscale/vs_scanline.c590
-rw-r--r--examples/videoscale/vs_scanline.h70
15 files changed, 1894 insertions, 60 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am
index a590d50..b683bb4 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,5 +1,5 @@
-SUBDIRS = jpeg md5 uberopt work huffman taylor
+SUBDIRS = jpeg md5 uberopt work huffman taylor videoscale
bin_PROGRAMS = oil-bugreport
diff --git a/examples/jpeg/Makefile.am b/examples/jpeg/Makefile.am
index 4364976..c244c74 100644
--- a/examples/jpeg/Makefile.am
+++ b/examples/jpeg/Makefile.am
@@ -1,16 +1,10 @@
-if HAVE_GLIB
noinst_LTLIBRARIES = libjpeg.la
noinst_PROGRAMS = jpeg_test jpeg_rgb_test
-else
-noinst_LTLIBRARIES =
-noinst_PROGRAMS =
-endif
libjpeg_la_SOURCES = jpeg.c huffman.c jpeg_rgb_decoder.c
-libjpeg_la_CFLAGS = $(GLIB_CFLAGS) $(LIBOIL_CFLAGS)
-libjpeg_la_LIBADD = -lm $(GLIB_LIBS)
+libjpeg_la_CFLAGS = $(LIBOIL_CFLAGS)
noinst_HEADERS = bits.h huffman.h jpeg.h jpeg_debug.h \
jpeg_internal.h jpeg_rgb_decoder.h jpeg_rgb_internal.h
@@ -18,10 +12,10 @@ noinst_HEADERS = bits.h huffman.h jpeg.h jpeg_debug.h \
jpeg_test_SOURCES = test.c
-jpeg_test_CFLAGS = $(GLIB_CFLAGS) $(LIBOIL_CFLAGS)
-jpeg_test_LDADD = libjpeg.la -lm $(GLIB_LIBS) $(LIBOIL_LIBS)
+jpeg_test_CFLAGS = $(LIBOIL_CFLAGS)
+jpeg_test_LDADD = libjpeg.la $(LIBOIL_LIBS)
jpeg_rgb_test_SOURCES = test_rgb.c
-jpeg_rgb_test_CFLAGS = $(GLIB_CFLAGS) $(LIBOIL_CFLAGS)
-jpeg_rgb_test_LDADD = libjpeg.la -lm $(GLIB_LIBS) $(LIBOIL_LIBS)
+jpeg_rgb_test_CFLAGS = $(LIBOIL_CFLAGS)
+jpeg_rgb_test_LDADD = libjpeg.la $(LIBOIL_LIBS)
diff --git a/examples/jpeg/huffman.c b/examples/jpeg/huffman.c
index 9a031c2..0a81ca8 100644
--- a/examples/jpeg/huffman.c
+++ b/examples/jpeg/huffman.c
@@ -4,7 +4,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
-#include <glib.h>
#include <string.h>
#include "huffman.h"
@@ -17,6 +16,8 @@
static char *sprintbits (char *str, unsigned int bits, int n);
+#define TRUE 1
+#define FALSE 0
void
huffman_table_dump (HuffmanTable * table)
@@ -29,7 +30,7 @@ huffman_table_dump (HuffmanTable * table)
JPEG_DEBUG (4, "dumping huffman table %p\n", table);
for (i = 0; i < table->len; i++) {
- entry = &g_array_index (table, HuffmanEntry, i);
+ entry = table->entries + i;
n_bits = entry->n_bits;
code = entry->symbol >> (16 - n_bits);
sprintbits (str, code, n_bits);
@@ -42,7 +43,8 @@ huffman_table_new (void)
{
HuffmanTable *table;
- table = g_array_new (FALSE, TRUE, sizeof (HuffmanEntry));
+ table = malloc (sizeof(HuffmanTable));
+ memset (table, 0, sizeof(HuffmanTable));
return table;
}
@@ -50,20 +52,20 @@ huffman_table_new (void)
void
huffman_table_free (HuffmanTable * table)
{
- g_array_free (table, TRUE);
+ free (table);
}
void
-huffman_table_add (HuffmanTable * table, guint32 code, gint n_bits, gint value)
+huffman_table_add (HuffmanTable * table, uint32_t code, int n_bits, int value)
{
- HuffmanEntry entry;
+ HuffmanEntry *entry = table->entries + table->len;
- entry.value = value;
- entry.symbol = code << (16 - n_bits);
- entry.mask = 0xffff ^ (0xffff >> n_bits);
- entry.n_bits = n_bits;
+ entry->value = value;
+ entry->symbol = code << (16 - n_bits);
+ entry->mask = 0xffff ^ (0xffff >> n_bits);
+ entry->n_bits = n_bits;
- g_array_append_val (table, entry);
+ table->len++;
}
unsigned int
@@ -76,7 +78,7 @@ huffman_table_decode_jpeg (HuffmanTable * tab, bits_t * bits)
code = peekbits (bits, 16);
for (i = 0; i < tab->len; i++) {
- entry = &g_array_index (tab, HuffmanEntry, i);
+ entry = tab->entries + i;
if ((code & entry->mask) == entry->symbol) {
code = getbits (bits, entry->n_bits);
sprintbits (str, code, entry->n_bits);
diff --git a/examples/jpeg/huffman.h b/examples/jpeg/huffman.h
index f32dcee..e3bd94a 100644
--- a/examples/jpeg/huffman.h
+++ b/examples/jpeg/huffman.h
@@ -2,25 +2,31 @@
#ifndef _HUFFMAN_H_
#define _HUFFMAN_H_
-#include <glib.h>
+#include <liboil/liboil-stdint.h>
+
#include "bits.h"
-typedef struct huffman_entry_struct HuffmanEntry;
-typedef GArray HuffmanTable;
+typedef struct _HuffmanEntry HuffmanEntry;
+typedef struct _HuffmanTable HuffmanTable;
+
+struct _HuffmanEntry {
+ unsigned int symbol;
+ unsigned int mask;
+ int n_bits;
+ unsigned char value;
+};
-struct huffman_entry_struct {
- unsigned int symbol;
- unsigned int mask;
- int n_bits;
- unsigned char value;
+struct _HuffmanTable {
+ int len;
+ HuffmanEntry entries[256];
};
void huffman_table_dump(HuffmanTable *table);
HuffmanTable *huffman_table_new(void);
void huffman_table_free(HuffmanTable *table);
-void huffman_table_add(HuffmanTable *table, guint32 code, gint n_bits,
- gint value);
+void huffman_table_add(HuffmanTable *table, uint32_t code, int n_bits,
+ int value);
unsigned int huffman_table_decode_jpeg(HuffmanTable *tab, bits_t *bits);
int huffman_table_decode_macroblock(short *block, HuffmanTable *dc_tab,
HuffmanTable *ac_tab, bits_t *bits);
diff --git a/examples/jpeg/jpeg.c b/examples/jpeg/jpeg.c
index 83bb3bf..c70a762 100644
--- a/examples/jpeg/jpeg.c
+++ b/examples/jpeg/jpeg.c
@@ -4,14 +4,18 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
-#include <glib.h>
#include <string.h>
#include <ctype.h>
+#include <limits.h>
+#include <liboil/liboil-stdint.h>
#include <liboil/liboil.h>
+#include <stdarg.h>
#include "jpeg_internal.h"
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+
#define JPEG_MARKER_STUFFED 0x00
#define JPEG_MARKER_TEM 0x01
@@ -261,7 +265,7 @@ jpeg_decoder_sof_baseline_dct (JpegDecoder * dec, bits_t * bits)
(dec->height_blocks * 8 * max_v_oversample /
dec->components[i].v_subsample);
dec->components[i].rowstride = rowstride;
- dec->components[i].image = g_malloc (image_size);
+ dec->components[i].image = malloc (image_size);
}
if (bits->end != bits->ptr)
@@ -671,7 +675,7 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits)
/* we allocate extra space, since the getbits() code can
* potentially read past the end of the buffer */
- newptr = g_malloc (len + 2);
+ newptr = malloc (len + 2);
for (i = 0; i < len; i++) {
newptr[j] = bits->ptr[i];
j++;
@@ -691,8 +695,7 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits)
x = dec->x;
y = dec->y;
n = dec->restart_interval;
- if (n == 0)
- n = G_MAXINT;
+ if (n == 0) n = INT_MAX;
while (n-- > 0) {
for (i = 0; i < dec->scan_list_length; i++) {
int dc_table_index;
@@ -754,7 +757,7 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits)
}
dec->x = x;
dec->y = y;
- g_free (newptr);
+ free (newptr);
}
@@ -766,7 +769,8 @@ jpeg_decoder_new (void)
oil_init ();
- dec = g_new0 (JpegDecoder, 1);
+ dec = malloc (sizeof(JpegDecoder));
+ memset (dec, 0, sizeof(JpegDecoder));
huffman_table_load_std_jpeg (dec);
@@ -785,13 +789,13 @@ jpeg_decoder_free (JpegDecoder * dec)
for (i = 0; i < JPEG_N_COMPONENTS; i++) {
if (dec->components[i].image)
- g_free (dec->components[i].image);
+ free (dec->components[i].image);
}
if (dec->data)
- g_free (dec->data);
+ free (dec->data);
- g_free (dec);
+ free (dec);
}
int
diff --git a/examples/jpeg/jpeg_rgb_decoder.c b/examples/jpeg/jpeg_rgb_decoder.c
index 859ac4b..c17631a 100644
--- a/examples/jpeg/jpeg_rgb_decoder.c
+++ b/examples/jpeg/jpeg_rgb_decoder.c
@@ -1,7 +1,7 @@
-#include <glib.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "jpeg_rgb_internal.h"
#include "jpeg.h"
@@ -27,7 +27,8 @@ jpeg_rgb_decoder_new (void)
{
JpegRGBDecoder *rgbdec;
- rgbdec = g_new0 (JpegRGBDecoder, 1);
+ rgbdec = malloc (sizeof (JpegRGBDecoder));
+ memset (rgbdec, 0, sizeof (JpegRGBDecoder));
rgbdec->dec = jpeg_decoder_new ();
@@ -43,11 +44,11 @@ jpeg_rgb_decoder_free (JpegRGBDecoder * rgbdec)
for (i = 0; i < 3; i++) {
if (rgbdec->component[i].alloc) {
- g_free (rgbdec->component[i].image);
+ free (rgbdec->component[i].image);
}
}
- g_free (rgbdec);
+ free (rgbdec);
}
int
@@ -80,7 +81,7 @@ jpeg_rgb_decoder_get_image (JpegRGBDecoder * rgbdec,
rgbdec->component[i].v_subsample > 1) {
unsigned char *dest;
- dest = g_malloc (rgbdec->width * rgbdec->height);
+ dest = malloc (rgbdec->width * rgbdec->height);
if (rgbdec->component[i].v_subsample > 1) {
if (rgbdec->component[i].h_subsample > 1) {
imagescale2h2v_u8 (dest,
@@ -107,7 +108,7 @@ jpeg_rgb_decoder_get_image (JpegRGBDecoder * rgbdec,
}
}
- rgbdec->image = g_malloc (rgbdec->width * rgbdec->height * 4);
+ rgbdec->image = malloc (rgbdec->width * rgbdec->height * 4);
convert (rgbdec);
diff --git a/examples/jpeg/test.c b/examples/jpeg/test.c
index 22c3aa1..0ebdae0 100644
--- a/examples/jpeg/test.c
+++ b/examples/jpeg/test.c
@@ -4,7 +4,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
-#include <glib.h>
#include "jpeg.h"
@@ -67,7 +66,7 @@ getfile (char *path, int *n_bytes)
return NULL;
}
- ptr = g_malloc (st.st_size);
+ ptr = malloc (st.st_size);
if (!ptr) {
close (fd);
return NULL;
@@ -75,7 +74,7 @@ getfile (char *path, int *n_bytes)
ret = read (fd, ptr, st.st_size);
if (ret != st.st_size) {
- g_free (ptr);
+ free (ptr);
close (fd);
return NULL;
}
diff --git a/examples/jpeg/test_rgb.c b/examples/jpeg/test_rgb.c
index 39f2fd0..8f85f2e 100644
--- a/examples/jpeg/test_rgb.c
+++ b/examples/jpeg/test_rgb.c
@@ -4,7 +4,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
-#include <glib.h>
#include "jpeg_rgb_decoder.h"
@@ -28,14 +27,14 @@ main (int argc, char *argv[])
dec = jpeg_rgb_decoder_new ();
if (argc < 2) {
- g_print("jpeg_rgb_test <file.jpg>\n");
+ printf("jpeg_rgb_test <file.jpg>\n");
exit(1);
}
fn = argv[1];
data = getfile (fn, &len);
if (data == NULL) {
- g_print("cannot read file %s\n", fn);
+ printf("cannot read file %s\n", fn);
exit(1);
}
@@ -46,10 +45,10 @@ main (int argc, char *argv[])
dump_pnm (ptr, rowstride, width, height);
- g_free (ptr);
+ free (ptr);
jpeg_rgb_decoder_free (dec);
- g_free (data);
+ free (data);
return 0;
}
@@ -76,7 +75,7 @@ getfile (char *path, int *n_bytes)
return NULL;
}
- ptr = g_malloc (st.st_size);
+ ptr = malloc (st.st_size);
if (!ptr) {
close (fd);
return NULL;
@@ -84,7 +83,7 @@ getfile (char *path, int *n_bytes)
ret = read (fd, ptr, st.st_size);
if (ret != st.st_size) {
- g_free (ptr);
+ free (ptr);
close (fd);
return NULL;
}
diff --git a/examples/videoscale/Makefile.am b/examples/videoscale/Makefile.am
new file mode 100644
index 0000000..01dd502
--- /dev/null
+++ b/examples/videoscale/Makefile.am
@@ -0,0 +1,15 @@
+
+
+noinst_LTLIBRARIES = libvideoscale.la
+#noinst_PROGRAMS = videoscale_test
+
+libvideoscale_la_SOURCES = vs_4tap.c vs_image.c vs_scanline.c
+libvideoscale_la_CFLAGS = $(LIBOIL_CFLAGS)
+
+noinst_HEADERS = vs_4tap.h vs_image.h vs_scanline.h
+
+
+#videoscale_test_SOURCES = test.c
+#videoscale_test_CFLAGS = $(LIBOIL_CFLAGS)
+#videoscale_test_LDADD = libvideoscale.la $(LIBOIL_LIBS)
+
diff --git a/examples/videoscale/vs_4tap.c b/examples/videoscale/vs_4tap.c
new file mode 100644
index 0000000..5d9edf4
--- /dev/null
+++ b/examples/videoscale/vs_4tap.c
@@ -0,0 +1,179 @@
+/*
+ * Image Scaling Functions (4 tap)
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "vs_image.h"
+#include "vs_scanline.h"
+
+#include <liboil/liboil.h>
+#include <math.h>
+
+#define SHIFT 10
+
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define CLAMP(x,a,b) MAX(MIN((x),(b)),(a))
+
+int16_t vs_4tap_taps[256][4];
+
+double vs_4tap_func (double x)
+{
+#if 0
+ if (x<-1) return 0;
+ if (x>1) return 0;
+ if (x<0) return 1 + x;
+ return 1 - x;
+#endif
+#if 0
+ if (x==0) return 1;
+ return sin(M_PI*x)/(M_PI*x) * (1 - 0.25*x*x);
+#endif
+#if 1
+ if (x==0) return 1;
+ return sin(M_PI*x)/(M_PI*x);
+#endif
+}
+
+void
+vs_4tap_init (void)
+{
+ int i;
+ double a, b, c, d;
+ double sum;
+
+ for(i=0;i<256;i++){
+ a = vs_4tap_func(-1 - i/256.0);
+ b = vs_4tap_func(0 - i/256.0);
+ c = vs_4tap_func(1 - i/256.0);
+ d = vs_4tap_func(2 - i/256.0);
+ sum = a + b + c + d;
+
+ vs_4tap_taps[i][0] = rint((1<<SHIFT)*(a/sum));
+ vs_4tap_taps[i][1] = rint((1<<SHIFT)*(b/sum));
+ vs_4tap_taps[i][2] = rint((1<<SHIFT)*(c/sum));
+ vs_4tap_taps[i][3] = rint((1<<SHIFT)*(d/sum));
+ }
+}
+
+
+void
+vs_scanline_resample_4tap_Y (uint8_t *dest, uint8_t *src,
+ int n, int *xacc, int increment)
+{
+ int i;
+ int j;
+ int acc;
+ int x;
+ int y;
+
+ acc = *xacc;
+ for(i=0;i<n;i++){
+ j = acc>>16;
+ x = (acc&0xff00)>>8;
+ y = (vs_4tap_taps[x][0] * src[MAX(j-1,0)] +
+ vs_4tap_taps[x][1] * src[j] +
+ vs_4tap_taps[x][2] * src[j+1] +
+ vs_4tap_taps[x][3] * src[j+2] + (1<<(SHIFT-1))) >> SHIFT;
+ if (y<0) y = 0;
+ if (y>255) y = 255;
+ dest[i] = y;
+ acc += increment;
+ }
+ *xacc = acc;
+}
+
+void
+vs_scanline_merge_4tap_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+ uint8_t *src3, uint8_t *src4, int n, int acc)
+{
+ int i;
+ int y;
+
+ acc = (acc>>8) & 0xff;
+ for(i=0;i<n;i++){
+ y = (vs_4tap_taps[acc][0] * src1[i] +
+ vs_4tap_taps[acc][1] * src2[i] +
+ vs_4tap_taps[acc][2] * src3[i] +
+ vs_4tap_taps[acc][3] * src4[i] + (1<<(SHIFT-1))) >> SHIFT;
+ if (y<0) y = 0;
+ if (y>255) y = 255;
+ dest[i] = y;
+ }
+
+}
+
+
+void
+vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int yacc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int xacc;
+ int k;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ k = 0;
+ for(i=0;i<4;i++){
+ xacc = 0;
+ vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width,
+ src->pixels + i * src->stride,
+ dest->width, &xacc, x_increment);
+ }
+
+ yacc = 0;
+ for (i = 0; i < dest->height; i++) {
+ uint8_t *t0, *t1, *t2, *t3;
+
+ j = yacc >> 16;
+
+ if (j > k) {
+ k++;
+ if (k + 3 < src->height) {
+ xacc = 0;
+ vs_scanline_resample_4tap_Y (tmpbuf + ((k+3)&3) * dest->width,
+ src->pixels + (k+3) * src->stride,
+ dest->width, &xacc, x_increment);
+ }
+ }
+
+ t0 = tmpbuf + (CLAMP(j - 1, 0, src->height - 1)&3) * dest->width;
+ t1 = tmpbuf + (CLAMP(j , 0, src->height - 1)&3) * dest->width;
+ t2 = tmpbuf + (CLAMP(j + 1, 0, src->height - 1)&3) * dest->width;
+ t3 = tmpbuf + (CLAMP(j + 2, 0, src->height - 1)&3) * dest->width;
+ vs_scanline_merge_4tap_Y (dest->pixels + i*dest->stride,
+ t0, t1, t2, t3, dest->width, yacc & 0xffff);
+
+ yacc += y_increment;
+ }
+}
+
+
diff --git a/examples/videoscale/vs_4tap.h b/examples/videoscale/vs_4tap.h
new file mode 100644
index 0000000..830441a
--- /dev/null
+++ b/examples/videoscale/vs_4tap.h
@@ -0,0 +1,44 @@
+/*
+ * Image Scaling Functions (4 tap)
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _VS_4TAP_H_
+#define _VS_4TAP_H_
+
+#include "vs_image.h"
+
+#include <liboil/liboil.h>
+
+void vs_4tap_init (void);
+void vs_scanline_resample_4tap_Y (uint8_t *dest, uint8_t *src,
+ int n, int *xacc, int increment);
+void vs_scanline_merge_4tap_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2,
+ uint8_t *src3, uint8_t *src4, int n, int acc);
+void vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf);
+
+#endif
+
diff --git a/examples/videoscale/vs_image.c b/examples/videoscale/vs_image.c
new file mode 100644
index 0000000..d29fe8a
--- /dev/null
+++ b/examples/videoscale/vs_image.c
@@ -0,0 +1,853 @@
+/*
+ * Image Scaling Functions
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include "vs_scanline.h"
+#include "vs_image.h"
+
+#define ROUND_UP_2(x) (((x)+1)&~1)
+#define ROUND_UP_4(x) (((x)+3)&~3)
+#define ROUND_UP_8(x) (((x)+7)&~7)
+
+void
+vs_image_scale_nearest_RGBA (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_RGBA (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_RGBA (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = dest->width * 4;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_RGBA (tmp1, src->pixels, dest->width, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGBA (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGBA (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGBA (tmp1,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
+ tmp2, tmp1, dest->width, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGBA (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_RGBA (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_RGBA (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+
+void
+vs_image_scale_nearest_RGB (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_RGB (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = dest->width * 3;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_RGB (tmp1, src->pixels, dest->width, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB (tmp1,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
+ tmp2, tmp1, dest->width, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_RGB (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+/* YUYV */
+
+void
+vs_image_scale_nearest_YUYV (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+ int n_quads;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ n_quads = ROUND_UP_2 (dest->width) / 2;
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, n_quads, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_YUYV (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int n_quads;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = ROUND_UP_4 (dest->width * 2);
+ n_quads = ROUND_UP_2 (dest->width) / 2;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_YUYV (tmp1, src->pixels, n_quads, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
+ n_quads, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_YUYV (tmp2,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
+ tmp1, tmp2, n_quads, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_YUYV (tmp1,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
+ tmp2, tmp1, n_quads, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
+ n_quads, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_YUYV (tmp2,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
+ tmp1, tmp2, n_quads, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+/* UYVY */
+
+void
+vs_image_scale_nearest_UYVY (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+ int n_quads;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ n_quads = (dest->width + 1) / 2;
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, n_quads, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int n_quads;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = ROUND_UP_4 (dest->width * 2);
+ n_quads = ROUND_UP_2 (dest->width) / 2;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_UYVY (tmp1, src->pixels, n_quads, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
+ n_quads, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_UYVY (tmp2,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
+ tmp1, tmp2, n_quads, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_UYVY (tmp1,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
+ tmp2, tmp1, n_quads, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
+ n_quads, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_UYVY (tmp2,
+ src->pixels + (j + 1) * src->stride, n_quads, &xacc, x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
+ tmp1, tmp2, n_quads, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+/* greyscale */
+
+void
+vs_image_scale_nearest_Y (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_Y (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = dest->width;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_Y (tmp1, src->pixels, dest->width, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_Y (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_Y (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_Y (tmp1,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
+ tmp2, tmp1, dest->width, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_Y (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_Y (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_Y (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+/* RGB565 */
+
+void
+vs_image_scale_nearest_RGB565 (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_RGB565 (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = dest->width * 2;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, dest->width, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB565 (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB565 (tmp1,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
+ tmp2, tmp1, dest->width, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_RGB565 (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
+
+/* RGB555 */
+
+void
+vs_image_scale_nearest_RGB555 (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ int i;
+ int j;
+ int x;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ acc = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ xacc = 0;
+ vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride,
+ src->pixels + j * src->stride, dest->width, &xacc, x_increment);
+
+ acc += y_increment;
+ }
+}
+
+void
+vs_image_scale_linear_RGB555 (const VSImage * dest, const VSImage * src,
+ uint8_t * tmpbuf)
+{
+ int acc;
+ int y_increment;
+ int x_increment;
+ uint8_t *tmp1;
+ uint8_t *tmp2;
+ int y1;
+ int y2;
+ int i;
+ int j;
+ int x;
+ int dest_size;
+ int xacc;
+
+ y_increment = ((src->height - 1) << 16) / (dest->height - 1);
+ x_increment = ((src->width - 1) << 16) / (dest->width - 1);
+
+ dest_size = dest->width * 2;
+
+ tmp1 = tmpbuf;
+ tmp2 = tmpbuf + dest_size;
+
+ acc = 0;
+ xacc = 0;
+ y2 = -1;
+ vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, dest->width, &xacc,
+ x_increment);
+ y1 = 0;
+ for (i = 0; i < dest->height; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+
+ if (x == 0) {
+ if (j == y1) {
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ } else if (j == y2) {
+ memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
+ }
+ } else {
+ if (j == y1) {
+ if (j + 1 != y2) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB555 (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ } else if (j == y2) {
+ if (j + 1 != y1) {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB555 (tmp1,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y1 = j + 1;
+ }
+ vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
+ tmp2, tmp1, dest->width, x);
+ } else {
+ xacc = 0;
+ vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
+ dest->width, &xacc, x_increment);
+ y1 = j;
+ xacc = 0;
+ vs_scanline_resample_linear_RGB555 (tmp2,
+ src->pixels + (j + 1) * src->stride, dest->width, &xacc,
+ x_increment);
+ y2 = (j + 1);
+ vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
+ tmp1, tmp2, dest->width, x);
+ }
+ }
+
+ acc += y_increment;
+ }
+}
diff --git a/examples/videoscale/vs_image.h b/examples/videoscale/vs_image.h
new file mode 100644
index 0000000..ba912f9
--- /dev/null
+++ b/examples/videoscale/vs_image.h
@@ -0,0 +1,78 @@
+/*
+ * Image Scaling Functions
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __VS_IMAGE_H__
+#define __VS_IMAGE_H__
+
+#include <liboil/liboil-stdint.h>
+
+typedef struct _VSImage VSImage;
+
+struct _VSImage {
+ uint8_t *pixels;
+ int width;
+ int height;
+ int stride;
+};
+
+void vs_image_scale_nearest_RGBA (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_RGB (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_YUYV (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_YUYV (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_UYVY (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_UYVY (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_RGB565 (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_RGB565 (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+void vs_image_scale_nearest_RGB555 (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+void vs_image_scale_linear_RGB555 (const VSImage *dest, const VSImage *src,
+ uint8_t *tmpbuf);
+
+#endif
+
diff --git a/examples/videoscale/vs_scanline.c b/examples/videoscale/vs_scanline.c
new file mode 100644
index 0000000..8b9bbb8
--- /dev/null
+++ b/examples/videoscale/vs_scanline.c
@@ -0,0 +1,590 @@
+/*
+ * Image Scaling Functions
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "vs_scanline.h"
+
+#include <liboil/liboil.h>
+
+/* greyscale, i.e., single componenet */
+
+void
+vs_scanline_downsample_Y (uint8_t * dest, uint8_t * src, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i] = (src[i * 2] + src[i * 2 + 1]) / 2;
+ }
+}
+
+void
+vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i] = (x < 32768) ? src[j] : src[j + 1];
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ uint32_t vals[2];
+
+ vals[0] = *accumulator;
+ vals[1] = increment;
+
+ oil_resample_linear_u8 (dest, src, n, vals);
+
+ *accumulator = vals[0];
+}
+
+void
+vs_scanline_merge_linear_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+ int n, int x)
+{
+ uint32_t value = x >> 8;
+
+ oil_merge_linear_u8 (dest, src1, src2, &value, n);
+}
+
+
+/* RGBA */
+
+void
+vs_scanline_downsample_RGBA (uint8_t * dest, uint8_t * src, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 4]) / 2;
+ dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 5]) / 2;
+ dest[i * 4 + 2] = (src[i * 8 + 2] + src[i * 8 + 6]) / 2;
+ dest[i * 4 + 3] = (src[i * 8 + 3] + src[i * 8 + 7]) / 2;
+ }
+}
+
+void
+vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 0] = (x < 32768) ? src[j * 4 + 0] : src[j * 4 + 4];
+ dest[i * 4 + 1] = (x < 32768) ? src[j * 4 + 1] : src[j * 4 + 5];
+ dest[i * 4 + 2] = (x < 32768) ? src[j * 4 + 2] : src[j * 4 + 6];
+ dest[i * 4 + 3] = (x < 32768) ? src[j * 4 + 3] : src[j * 4 + 7];
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ uint32_t vals[2];
+
+ vals[0] = *accumulator;
+ vals[1] = increment;
+
+ oil_resample_linear_argb ((uint32_t *) dest, (uint32_t *) src, n, vals);
+
+ *accumulator = vals[0];
+}
+
+void
+vs_scanline_merge_linear_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+ int n, int x)
+{
+ uint32_t value = x >> 8;
+
+ oil_merge_linear_argb ((uint32_t *) dest, (uint32_t *) src1, (uint32_t *) src2,
+ &value, n);
+}
+
+
+/* RGB */
+
+void
+vs_scanline_downsample_RGB (uint8_t * dest, uint8_t * src, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i * 3 + 0] = (src[i * 6 + 0] + src[i * 6 + 3]) / 2;
+ dest[i * 3 + 1] = (src[i * 6 + 1] + src[i * 6 + 4]) / 2;
+ dest[i * 3 + 2] = (src[i * 6 + 2] + src[i * 6 + 5]) / 2;
+ }
+}
+
+void
+vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 3 + 0] = (x < 32768) ? src[j * 3 + 0] : src[j * 3 + 3];
+ dest[i * 3 + 1] = (x < 32768) ? src[j * 3 + 1] : src[j * 3 + 4];
+ dest[i * 3 + 2] = (x < 32768) ? src[j * 3 + 2] : src[j * 3 + 5];
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 3 + 0] = (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16;
+ dest[i * 3 + 1] = (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16;
+ dest[i * 3 + 2] = (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16;
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_merge_linear_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+ int n, int x)
+{
+ uint32_t value = x >> 8;
+
+ oil_merge_linear_u8 (dest, src1, src2, &value, n * 3);
+}
+
+
+/* YUYV */
+
+/* n is the number of bi-pixels */
+/* increment is per Y pixel */
+
+void
+vs_scanline_downsample_YUYV (uint8_t * dest, uint8_t * src, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 2]) / 2;
+ dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 5]) / 2;
+ dest[i * 4 + 2] = (src[i * 8 + 4] + src[i * 8 + 6]) / 2;
+ dest[i * 4 + 3] = (src[i * 8 + 3] + src[i * 8 + 7]) / 2;
+ }
+}
+
+void
+vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 0] = (x < 32768) ? src[j * 2 + 0] : src[j * 2 + 2];
+
+ j = acc >> 17;
+ x = acc & 0x1ffff;
+ dest[i * 4 + 1] = (x < 65536) ? src[j * 4 + 1] : src[j * 4 + 5];
+ dest[i * 4 + 3] = (x < 65536) ? src[j * 4 + 3] : src[j * 4 + 7];
+
+ acc += increment;
+
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 2] = (x < 32768) ? src[j * 2 + 0] : src[j * 2 + 2];
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 0] = (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
+
+ j = acc >> 17;
+ x = acc & 0x1ffff;
+ dest[i * 4 + 1] =
+ (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17;
+ dest[i * 4 + 3] =
+ (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17;
+
+ acc += increment;
+
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 2] = (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_merge_linear_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+ int n, int x)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i * 4 + 0] =
+ (src1[i * 4 + 0] * (65536 - x) + src2[i * 4 + 0] * x) >> 16;
+ dest[i * 4 + 1] =
+ (src1[i * 4 + 1] * (65536 - x) + src2[i * 4 + 1] * x) >> 16;
+ dest[i * 4 + 2] =
+ (src1[i * 4 + 2] * (65536 - x) + src2[i * 4 + 2] * x) >> 16;
+ dest[i * 4 + 3] =
+ (src1[i * 4 + 3] * (65536 - x) + src2[i * 4 + 3] * x) >> 16;
+ }
+}
+
+
+/* UYVY */
+
+/* n is the number of bi-pixels */
+/* increment is per Y pixel */
+
+void
+vs_scanline_downsample_UYVY (uint8_t * dest, uint8_t * src, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 4]) / 2;
+ dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 3]) / 2;
+ dest[i * 4 + 2] = (src[i * 8 + 2] + src[i * 8 + 6]) / 2;
+ dest[i * 4 + 3] = (src[i * 8 + 5] + src[i * 8 + 7]) / 2;
+ }
+}
+
+void
+vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 1] = (x < 32768) ? src[j * 2 + 1] : src[j * 2 + 3];
+
+ j = acc >> 17;
+ x = acc & 0x1ffff;
+ dest[i * 4 + 0] = (x < 65536) ? src[j * 4 + 0] : src[j * 4 + 4];
+ dest[i * 4 + 2] = (x < 65536) ? src[j * 4 + 2] : src[j * 4 + 6];
+
+ acc += increment;
+
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 3] = (x < 32768) ? src[j * 2 + 1] : src[j * 2 + 3];
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int n,
+ int *accumulator, int increment)
+{
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 1] = (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
+
+ j = acc >> 17;
+ x = acc & 0x1ffff;
+ dest[i * 4 + 0] =
+ (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17;
+ dest[i * 4 + 2] =
+ (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17;
+
+ acc += increment;
+
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i * 4 + 3] = (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2,
+ int n, int x)
+{
+ uint32_t value = x >> 8;
+
+ oil_merge_linear_argb ((uint32_t *) dest, (uint32_t *) src1, (uint32_t *) src2,
+ &value, n);
+}
+
+
+/* RGB565 */
+
+/* note that src and dest are uint16_t, and thus endian dependent */
+
+#define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
+#define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
+#define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
+
+#define RGB565(r,g,b) \
+ ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
+
+
+void
+vs_scanline_downsample_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i] = RGB565 (
+ (RGB565_R (src[i * 2]) + RGB565_R (src[i * 2 + 1])) / 2,
+ (RGB565_G (src[i * 2]) + RGB565_G (src[i * 2 + 1])) / 2,
+ (RGB565_B (src[i * 2]) + RGB565_B (src[i * 2 + 1])) / 2);
+ }
+}
+
+void
+vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n,
+ int *accumulator, int increment)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i] = (x < 32768) ? src[j] : src[j + 1];
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n,
+ int *accumulator, int increment)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i] = RGB565 (
+ (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16,
+ (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16,
+ (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16);
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_merge_linear_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
+ uint8_t * src2_u8, int n, int x)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src1 = (uint16_t *) src1_u8;
+ uint16_t *src2 = (uint16_t *) src2_u8;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i] = RGB565 (
+ (RGB565_R (src1[i]) * (65536 - x) + RGB565_R (src2[i]) * x) >> 16,
+ (RGB565_G (src1[i]) * (65536 - x) + RGB565_G (src2[i]) * x) >> 16,
+ (RGB565_B (src1[i]) * (65536 - x) + RGB565_B (src2[i]) * x) >> 16);
+ }
+}
+
+
+/* RGB555 */
+
+/* note that src and dest are uint16_t, and thus endian dependent */
+
+#define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
+#define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
+#define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
+
+#define RGB555(r,g,b) \
+ ((((r)<<7)&0x7c00) | (((g)<<3)&0x03e0) | (((b)>>3)&0x001f))
+
+
+void
+vs_scanline_downsample_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i] = RGB555 (
+ (RGB555_R (src[i * 2]) + RGB555_R (src[i * 2 + 1])) / 2,
+ (RGB555_G (src[i * 2]) + RGB555_G (src[i * 2 + 1])) / 2,
+ (RGB555_B (src[i * 2]) + RGB555_B (src[i * 2 + 1])) / 2);
+ }
+}
+
+void
+vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n,
+ int *accumulator, int increment)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i] = (x < 32768) ? src[j] : src[j + 1];
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n,
+ int *accumulator, int increment)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src = (uint16_t *) src_u8;
+ int acc = *accumulator;
+ int i;
+ int j;
+ int x;
+
+ for (i = 0; i < n; i++) {
+ j = acc >> 16;
+ x = acc & 0xffff;
+ dest[i] = RGB555 (
+ (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16,
+ (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16,
+ (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16);
+
+ acc += increment;
+ }
+
+ *accumulator = acc;
+}
+
+void
+vs_scanline_merge_linear_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
+ uint8_t * src2_u8, int n, int x)
+{
+ uint16_t *dest = (uint16_t *) dest_u8;
+ uint16_t *src1 = (uint16_t *) src1_u8;
+ uint16_t *src2 = (uint16_t *) src2_u8;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dest[i] = RGB555 (
+ (RGB555_R (src1[i]) * (65536 - x) + RGB555_R (src2[i]) * x) >> 16,
+ (RGB555_G (src1[i]) * (65536 - x) + RGB555_G (src2[i]) * x) >> 16,
+ (RGB555_B (src1[i]) * (65536 - x) + RGB555_B (src2[i]) * x) >> 16);
+ }
+}
diff --git a/examples/videoscale/vs_scanline.h b/examples/videoscale/vs_scanline.h
new file mode 100644
index 0000000..5317d17
--- /dev/null
+++ b/examples/videoscale/vs_scanline.h
@@ -0,0 +1,70 @@
+/*
+ * Image Scaling Functions
+ * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __VS_SCANLINE_H__
+#define __VS_SCANLINE_H__
+
+#include <liboil/liboil-stdint.h>
+
+void vs_scanline_downsample_Y (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_Y (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_Y (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_RGBA (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_RGBA (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_RGBA (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_RGBA (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_RGB (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_RGB (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_RGB (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_RGB (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_YUYV (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_YUYV (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_YUYV (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_YUYV (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_UYVY (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_UYVY (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_RGB565 (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_RGB565 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+void vs_scanline_downsample_RGB555 (uint8_t *dest, uint8_t *src, int n);
+void vs_scanline_resample_nearest_RGB555 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_resample_linear_RGB555 (uint8_t *dest, uint8_t *src, int n, int *accumulator, int increment);
+void vs_scanline_merge_linear_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
+
+
+#endif
+