diff options
author | David Schleef <ds@schleef.org> | 2006-11-17 07:56:23 +0000 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2006-11-17 07:56:23 +0000 |
commit | 402101cd065c69e0d8e1297a0f106ea90e1750e8 (patch) | |
tree | 922be89299db9fdd199701a69fe3cff26db49fc1 /examples | |
parent | 2b96a77c184f68858cd86d6025246088ecbcb05b (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.am | 2 | ||||
-rw-r--r-- | examples/jpeg/Makefile.am | 16 | ||||
-rw-r--r-- | examples/jpeg/huffman.c | 26 | ||||
-rw-r--r-- | examples/jpeg/huffman.h | 26 | ||||
-rw-r--r-- | examples/jpeg/jpeg.c | 24 | ||||
-rw-r--r-- | examples/jpeg/jpeg_rgb_decoder.c | 13 | ||||
-rw-r--r-- | examples/jpeg/test.c | 5 | ||||
-rw-r--r-- | examples/jpeg/test_rgb.c | 13 | ||||
-rw-r--r-- | examples/videoscale/Makefile.am | 15 | ||||
-rw-r--r-- | examples/videoscale/vs_4tap.c | 179 | ||||
-rw-r--r-- | examples/videoscale/vs_4tap.h | 44 | ||||
-rw-r--r-- | examples/videoscale/vs_image.c | 853 | ||||
-rw-r--r-- | examples/videoscale/vs_image.h | 78 | ||||
-rw-r--r-- | examples/videoscale/vs_scanline.c | 590 | ||||
-rw-r--r-- | examples/videoscale/vs_scanline.h | 70 |
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 + |