Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * filter.c
  3.  * Copyright (C) 2003 Florian Schulze <crow@icculus.org>
  4.  *
  5.  * This file is part of Jump'n'Bump.
  6.  *
  7.  * Jump'n'Bump is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * Jump'n'Bump is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  */
  21.  
  22. /*
  23.  The following scaling filter is called advancedmame2x.
  24.  The implementation found here was possible because of the great ideas of
  25.  Lucas Pope.
  26.  */
  27.  
  28. typedef unsigned char byte;
  29. static int scale2x_inited = 0;
  30. static byte lookup_map[4*16];
  31.  
  32. void init_scale2x(void)
  33. {
  34.         int i;
  35.  
  36.         if (scale2x_inited)
  37.                 return;
  38.  
  39.         //-------------------------------------------------------------------------  
  40.         // scale2x takes the following source:
  41.         // A B C
  42.         // D E F
  43.         // G H I
  44.         //
  45.         // and doubles the size of E to produce:
  46.         // E0 E1
  47.         // E2 E3
  48.         //
  49.         //  E0 = D == B && B != F && D != H ? D : E;
  50.         //  E1 = B == F && B != D && F != H ? F : E;
  51.         //  E2 = D == H && D != B && H != F ? D : E;
  52.         //  E3 = H == F && D != H && B != F ? F : E;
  53.         //
  54.         // to make this comparison regimen faster, we encode source color
  55.         // equivalency into a single byte with the getCode() macro
  56.         //
  57.         // #define getCode(b,f,h,d) ( (b == f)<<0 | (f == h)<<1 | (h == d)<<2 | (d == b)<<3 )
  58.  
  59.         // encode the scale2x conditionals into a lookup code
  60.         for (i=0; i<16; i++) {
  61.                 //  E0 = D == B && B != F && D != H ? D : E; // 10-0 => 1000 or 1010 => 8 or A
  62.                 lookup_map[0*16+i] = (i == 0x8 || i == 0xA) ? 0 : 1;
  63.                 //  E1 = B == F && B != D && F != H ? F : E; // 0-01 => 0101 or 0001 => 5 or 1
  64.                 lookup_map[1*16+i] = (i == 0x5 || i == 0x1) ? 2 : 1;
  65.                 //  E2 = D == H && D != B && H != F ? D : E; // 010- => 0101 or 0100 => 5 or 4
  66.                 lookup_map[2*16+i] = (i == 0x4 || i == 0x5) ? 0 : 1;
  67.                 //  E3 = H == F && D != H && B != F ? F : E; // -010 => 1010 or 0010 => A or 2
  68.                 lookup_map[3*16+i] = (i == 0xA || i == 0x2) ? 2 : 1;
  69.         }
  70. }
  71.  
  72. void do_scale2x(unsigned char *src,
  73.                 int src_width,
  74.                 int src_height,
  75.                 unsigned char *dst)
  76. {
  77.         int x;
  78.         int y;
  79.         int dst_width = src_width * 2;
  80.         int dst_height = src_height * 2;
  81.         int code;
  82.         byte rowColors[3];
  83.         byte *e0;
  84.         byte *e1;
  85.         byte *e2;
  86.         byte *e3;
  87.  
  88.         if (!scale2x_inited)
  89.                 init_scale2x();
  90.  
  91.         // special top case - b is always unknown
  92.         {
  93.                 byte *d;
  94.                 byte *e;
  95.                 byte *f;
  96.                 byte *h;
  97.  
  98.                 e0 = &dst[0];
  99.                 e1 = &dst[1];
  100.                 e2 = &dst[dst_width];
  101.                 e3 = &dst[dst_width + 1];
  102.                 e = &src[0];
  103.                 f = &src[1];
  104.                 h = &src[src_width];
  105.  
  106.                 // special left case - d is unknown
  107.                 rowColors[0] = *e;
  108.                 rowColors[1] = *e;
  109.                 rowColors[2] = *f;
  110.                 code = ( (*f == *h)<<1 );
  111.                 *e0 = rowColors[lookup_map[0*16+code]];
  112.                 *e1 = rowColors[lookup_map[1*16+code]];
  113.                 *e2 = rowColors[lookup_map[2*16+code]];
  114.                 *e3 = rowColors[lookup_map[3*16+code]];
  115.                 e++; f++; h++;
  116.                 d = &src[src_width]; // (src_width - 1) + 1
  117.                 e0+=2; e1+=2; e2+=2; e3+=2;
  118.  
  119.                 // normal case
  120.                 for (x=1; x<(src_width-1); x++) {
  121.                         rowColors[0] = *d;
  122.                         rowColors[1] = *e;
  123.                         rowColors[2] = *f;
  124.                         code = ( (*f == *h)<<1 | (*h == *d)<<2 );
  125.                         *e0 = rowColors[lookup_map[0*16+code]];
  126.                         *e1 = rowColors[lookup_map[1*16+code]];
  127.                         *e2 = rowColors[lookup_map[2*16+code]];
  128.                         *e3 = rowColors[lookup_map[3*16+code]];
  129.                         d++; e++; f++; h++;
  130.                         e0+=2; e1+=2; e2+=2; e3+=2;
  131.                 }
  132.  
  133.                 // special right case - f is unknown
  134.                 rowColors[0] = *d;
  135.                 rowColors[1] = *e;
  136.                 rowColors[2] = *e;
  137.                 code = ( (*h == *d)<<2 );
  138.                 *e0 = rowColors[lookup_map[0*16+code]];
  139.                 *e1 = rowColors[lookup_map[1*16+code]];
  140.                 *e2 = rowColors[lookup_map[2*16+code]];
  141.                 *e3 = rowColors[lookup_map[3*16+code]];
  142.         }
  143.  
  144.         // top and bottom always known
  145.         for (y=1; y<(src_height-1); y++) {
  146.                 byte *b;
  147.                 byte *d;
  148.                 byte *e;
  149.                 byte *f;
  150.                 byte *h;
  151.  
  152.                 e0 = &dst[y*dst_width*2];
  153.                 e1 = &dst[y*dst_width*2 + 1];
  154.                 e2 = &dst[y*dst_width*2 + dst_width];
  155.                 e3 = &dst[y*dst_width*2 + dst_width + 1];
  156.                 b = &src[y * src_width - src_width];
  157.                 e = &src[y * src_width];
  158.                 f = &src[y * src_width + 1];
  159.                 h = &src[y * src_width + src_width];
  160.  
  161.                 // special left case - d is unknown
  162.                 rowColors[0] = *e;
  163.                 rowColors[1] = *e;
  164.                 rowColors[2] = *f;
  165.                 code = ( (*b == *f)<<0 | (*f == *h)<<1 );
  166.                 *e0 = rowColors[lookup_map[0*16+code]];
  167.                 *e1 = rowColors[lookup_map[1*16+code]];
  168.                 *e2 = rowColors[lookup_map[2*16+code]];
  169.                 *e3 = rowColors[lookup_map[3*16+code]];
  170.                 b++; e++; f++; h++;
  171.                 d = &src[y * src_width]; // (y * src_width - 1) + 1
  172.                 e0+=2; e1+=2; e2+=2; e3+=2;
  173.  
  174.                 // normal case
  175.                 for (x=1; x<(src_width-1); x++) {
  176.                         rowColors[0] = *d;
  177.                         rowColors[1] = *e;
  178.                         rowColors[2] = *f;
  179.                         code = ( (*b == *f)<<0 | (*f == *h)<<1 | (*h == *d)<<2 | (*d == *b)<<3 );
  180.                         *e0 = rowColors[lookup_map[0*16+code]];
  181.                         *e1 = rowColors[lookup_map[1*16+code]];
  182.                         *e2 = rowColors[lookup_map[2*16+code]];
  183.                         *e3 = rowColors[lookup_map[3*16+code]];
  184.                         b++; d++; e++; f++; h++;
  185.                         e0+=2; e1+=2; e2+=2; e3+=2;
  186.                 }
  187.  
  188.                 // special right case - f is unknown
  189.                 rowColors[0] = *d;
  190.                 rowColors[1] = *e;
  191.                 rowColors[2] = *e;
  192.                 code = ( (*h == *d)<<2 | (*d == *b)<<3 );
  193.                 *e0 = rowColors[lookup_map[0*16+code]];
  194.                 *e1 = rowColors[lookup_map[1*16+code]];
  195.                 *e2 = rowColors[lookup_map[2*16+code]];
  196.                 *e3 = rowColors[lookup_map[3*16+code]];
  197.         }
  198.  
  199.         // special bottom case - h is always unknown
  200.         {
  201.                 byte *b;
  202.                 byte *d;
  203.                 byte *e;
  204.                 byte *f;
  205.  
  206.                 e0 = &dst[y*dst_width*2];
  207.                 e1 = &dst[y*dst_width*2 + 1];
  208.                 e2 = &dst[y*dst_width*2 + dst_width];
  209.                 e3 = &dst[y*dst_width*2 + dst_width + 1];
  210.                 b = &src[y * src_width - src_width];
  211.                 e = &src[y * src_width];
  212.                 f = &src[y * src_width + 1];
  213.  
  214.                 // special left case - d is unknown
  215.                 rowColors[0] = *e;
  216.                 rowColors[1] = *e;
  217.                 rowColors[2] = *f;
  218.                 code = ( (*b == *f)<<0 );
  219.                 *e0 = rowColors[lookup_map[0*16+code]];
  220.                 *e1 = rowColors[lookup_map[1*16+code]];
  221.                 *e2 = rowColors[lookup_map[2*16+code]];
  222.                 *e3 = rowColors[lookup_map[3*16+code]];
  223.                 b++; e++; f++;
  224.                 d = &src[y * src_width]; // (y * src_width - 1) + 1
  225.                 e0+=2; e1+=2; e2+=2; e3+=2;
  226.  
  227.                 // normal case
  228.                 for (x=1; x<(src_width-1); x++) {
  229.                         rowColors[0] = *d;
  230.                         rowColors[1] = *e;
  231.                         rowColors[2] = *f;
  232.                         code = ( (*b == *f)<<0 | (*d == *b)<<3 );
  233.                         *e0 = rowColors[lookup_map[0*16+code]];
  234.                         *e1 = rowColors[lookup_map[1*16+code]];
  235.                         *e2 = rowColors[lookup_map[2*16+code]];
  236.                         *e3 = rowColors[lookup_map[3*16+code]];
  237.                         b++; d++; e++; f++;
  238.                         e0+=2; e1+=2; e2+=2; e3+=2;
  239.                 }
  240.  
  241.                 // special right case - f is unknown
  242.                 rowColors[0] = *d;
  243.                 rowColors[1] = *e;
  244.                 rowColors[2] = *e;
  245.                 code = ( (*d == *b)<<3 );
  246.                 *e0 = rowColors[lookup_map[0*16+code]];
  247.                 *e1 = rowColors[lookup_map[1*16+code]];
  248.                 *e2 = rowColors[lookup_map[2*16+code]];
  249.                 *e3 = rowColors[lookup_map[3*16+code]];
  250.         }
  251. }
  252.