New scaling filter.
authorFlorian Schulze <crow@icculus.org>
Fri, 21 Mar 2003 14:40:56 +0000 (14:40 +0000)
committerFlorian Schulze <crow@icculus.org>
Fri, 21 Mar 2003 14:40:56 +0000 (14:40 +0000)
filter.c [new file with mode: 0644]
filter.h [new file with mode: 0644]

diff --git a/filter.c b/filter.c
new file mode 100644 (file)
index 0000000..988788c
--- /dev/null
+++ b/filter.c
@@ -0,0 +1,251 @@
+/*
+ * filter.c
+ * Copyright (C) 2003 Florian Schulze <crow@icculus.org>
+ *
+ * This file is part of Jump'n'Bump.
+ *
+ * Jump'n'Bump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Jump'n'Bump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ The following scaling filter is called advancedmame2x.
+ The implementation found here was possible because of the great ideas of
+ Lucas Pope.
+ */
+
+typedef unsigned char byte;
+static int scale2x_inited = 0;
+static byte lookup_map[4*16];
+
+void init_scale2x(void)
+{
+       int i;
+
+       if (scale2x_inited)
+               return;
+
+       //-------------------------------------------------------------------------  
+       // scale2x takes the following source:
+       // A B C
+       // D E F
+       // G H I
+       //
+       // and doubles the size of E to produce:
+       // E0 E1
+       // E2 E3
+       //
+       //  E0 = D == B && B != F && D != H ? D : E;
+       //  E1 = B == F && B != D && F != H ? F : E;
+       //  E2 = D == H && D != B && H != F ? D : E;
+       //  E3 = H == F && D != H && B != F ? F : E;
+       //
+       // to make this comparison regimen faster, we encode source color
+       // equivalency into a single byte with the getCode() macro
+       //
+       // #define getCode(b,f,h,d) ( (b == f)<<0 | (f == h)<<1 | (h == d)<<2 | (d == b)<<3 )
+  
+       // encode the scale2x conditionals into a lookup code
+       for (i=0; i<16; i++) {
+               //  E0 = D == B && B != F && D != H ? D : E; // 10-0 => 1000 or 1010 => 8 or A
+               lookup_map[0*16+i] = (i == 0x8 || i == 0xA) ? 0 : 1;
+               //  E1 = B == F && B != D && F != H ? F : E; // 0-01 => 0101 or 0001 => 5 or 1
+               lookup_map[1*16+i] = (i == 0x5 || i == 0x1) ? 2 : 1;
+               //  E2 = D == H && D != B && H != F ? D : E; // 010- => 0101 or 0100 => 5 or 4
+               lookup_map[2*16+i] = (i == 0x4 || i == 0x5) ? 0 : 1;
+               //  E3 = H == F && D != H && B != F ? F : E; // -010 => 1010 or 0010 => A or 2
+               lookup_map[3*16+i] = (i == 0xA || i == 0x2) ? 2 : 1;
+       }
+}
+
+void do_scale2x(unsigned char *src,
+               int src_width,
+               int src_height,
+               unsigned char *dst)
+{
+       int x;
+       int y;
+       int dst_width = src_width * 2;
+       int dst_height = src_height * 2;
+       int code;
+       byte rowColors[3];
+       byte *e0;
+       byte *e1;
+       byte *e2;
+       byte *e3;
+
+       if (!scale2x_inited)
+               init_scale2x();
+
+       // special top case - b is always unknown
+       {
+               byte *d;
+               byte *e;
+               byte *f;
+               byte *h;
+
+               e0 = &dst[0];
+               e1 = &dst[1];
+               e2 = &dst[dst_width];
+               e3 = &dst[dst_width + 1];
+               e = &src[0];
+               f = &src[1];
+               h = &src[src_width];
+
+               // special left case - d is unknown
+               rowColors[0] = *e;
+               rowColors[1] = *e;
+               rowColors[2] = *f;
+               code = ( (*f == *h)<<1 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+               e++; f++; h++;
+               d = &src[src_width]; // (src_width - 1) + 1
+               e0+=2; e1+=2; e2+=2; e3+=2;
+
+               // normal case
+               for (x=1; x<(src_width-1); x++) {
+                       rowColors[0] = *d;
+                       rowColors[1] = *e;
+                       rowColors[2] = *f;
+                       code = ( (*f == *h)<<1 | (*h == *d)<<2 );
+                       *e0 = rowColors[lookup_map[0*16+code]];
+                       *e1 = rowColors[lookup_map[1*16+code]];
+                       *e2 = rowColors[lookup_map[2*16+code]];
+                       *e3 = rowColors[lookup_map[3*16+code]];
+                       d++; e++; f++; h++;
+                       e0+=2; e1+=2; e2+=2; e3+=2;
+               }
+
+               // special right case - f is unknown
+               rowColors[0] = *d;
+               rowColors[1] = *e;
+               rowColors[2] = *e;
+               code = ( (*h == *d)<<2 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+       }
+
+       // top and bottom always known
+       for (y=1; y<(src_height-1); y++) {
+               byte *b;
+               byte *d;
+               byte *e;
+               byte *f;
+               byte *h;
+
+               e0 = &dst[y*dst_width*2];
+               e1 = &dst[y*dst_width*2 + 1];
+               e2 = &dst[y*dst_width*2 + dst_width];
+               e3 = &dst[y*dst_width*2 + dst_width + 1];
+               b = &src[y * src_width - src_width];
+               e = &src[y * src_width];
+               f = &src[y * src_width + 1];
+               h = &src[y * src_width + src_width];
+
+               // special left case - d is unknown
+               rowColors[0] = *e;
+               rowColors[1] = *e;
+               rowColors[2] = *f;
+               code = ( (*b == *f)<<0 | (*f == *h)<<1 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+               b++; e++; f++; h++;
+               d = &src[y * src_width]; // (y * src_width - 1) + 1
+               e0+=2; e1+=2; e2+=2; e3+=2;
+
+               // normal case
+               for (x=1; x<(src_width-1); x++) {
+                       rowColors[0] = *d;
+                       rowColors[1] = *e;
+                       rowColors[2] = *f;
+                       code = ( (*b == *f)<<0 | (*f == *h)<<1 | (*h == *d)<<2 | (*d == *b)<<3 );
+                       *e0 = rowColors[lookup_map[0*16+code]];
+                       *e1 = rowColors[lookup_map[1*16+code]];
+                       *e2 = rowColors[lookup_map[2*16+code]];
+                       *e3 = rowColors[lookup_map[3*16+code]];
+                       b++; d++; e++; f++; h++;
+                       e0+=2; e1+=2; e2+=2; e3+=2;
+               }
+
+               // special right case - f is unknown
+               rowColors[0] = *d;
+               rowColors[1] = *e;
+               rowColors[2] = *e;
+               code = ( (*h == *d)<<2 | (*d == *b)<<3 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+       }
+
+       // special bottom case - h is always unknown
+       {
+               byte *b;
+               byte *d;
+               byte *e;
+               byte *f;
+
+               e0 = &dst[y*dst_width*2];
+               e1 = &dst[y*dst_width*2 + 1];
+               e2 = &dst[y*dst_width*2 + dst_width];
+               e3 = &dst[y*dst_width*2 + dst_width + 1];
+               b = &src[y * src_width - src_width];
+               e = &src[y * src_width];
+               f = &src[y * src_width + 1];
+
+               // special left case - d is unknown
+               rowColors[0] = *e;
+               rowColors[1] = *e;
+               rowColors[2] = *f;
+               code = ( (*b == *f)<<0 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+               b++; e++; f++;
+               d = &src[y * src_width]; // (y * src_width - 1) + 1
+               e0+=2; e1+=2; e2+=2; e3+=2;
+
+               // normal case
+               for (x=1; x<(src_width-1); x++) {
+                       rowColors[0] = *d;
+                       rowColors[1] = *e;
+                       rowColors[2] = *f;
+                       code = ( (*b == *f)<<0 | (*d == *b)<<3 );
+                       *e0 = rowColors[lookup_map[0*16+code]];
+                       *e1 = rowColors[lookup_map[1*16+code]];
+                       *e2 = rowColors[lookup_map[2*16+code]];
+                       *e3 = rowColors[lookup_map[3*16+code]];
+                       b++; d++; e++; f++;
+                       e0+=2; e1+=2; e2+=2; e3+=2;
+               }
+
+               // special right case - f is unknown
+               rowColors[0] = *d;
+               rowColors[1] = *e;
+               rowColors[2] = *e;
+               code = ( (*d == *b)<<3 );
+               *e0 = rowColors[lookup_map[0*16+code]];
+               *e1 = rowColors[lookup_map[1*16+code]];
+               *e2 = rowColors[lookup_map[2*16+code]];
+               *e3 = rowColors[lookup_map[3*16+code]];
+       }
+}
diff --git a/filter.h b/filter.h
new file mode 100644 (file)
index 0000000..42d87d3
--- /dev/null
+++ b/filter.h
@@ -0,0 +1,34 @@
+/*
+ * config.h
+ * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
+ * 
+ * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
+ *
+ * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
+ *
+ * This file is part of Jump'n'Bump.
+ *
+ * Jump'n'Bump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Jump'n'Bump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __FILTER_H__
+#define __FILTER_H__
+
+void do_scale2x(unsigned char *src,
+               int src_width,
+               int src_height,
+               unsigned char *dst);
+
+#endif // __FILTER_H__