2 * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )
4 * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * This is a modified version of the hq2x engine, to support alpha
23 * channel, and to work on rgba images both on little endian and big
26 * When scaling, the pixel values are determined by the rgb levels
27 * of the input picture. The alpha channel is also scaled,
28 * but interpolation settings do not depend on it.
30 * The scaling function is also modified to be able to handle cases
31 * when image pitch (bytes per row) is != width * bytes per pixel.
33 * The RGBtoYUV lookup table is removed, as scaling is only done once
34 * in GDash for every cave loading, not continuously during the game.
36 * The interpolation functions are changed so they do not produce
37 * overflows for the most significant bytes. So when calculating, they
38 * always do divisions first, then multiplications. This makes some
39 * inaccuracies (least significant bits are sometimes dropped), but
40 * it is not really visible in the result.
45 #include "gfx/pixbufmanip.hpp"
46 #include "gfx/pixbufmanip_hqx.hpp"
48 #define PIXEL00_1M Interp1(dp, w[5], w[1]);
49 #define PIXEL00_1U Interp1(dp, w[5], w[2]);
50 #define PIXEL00_1L Interp1(dp, w[5], w[4]);
51 #define PIXEL00_2 Interp2(dp, w[5], w[4], w[2]);
52 #define PIXEL00_4 Interp4(dp, w[5], w[4], w[2]);
53 #define PIXEL00_5 Interp5(dp, w[4], w[2]);
54 #define PIXEL00_C *dp = w[5];
56 #define PIXEL01_1 Interp1(dp+1, w[5], w[2]);
57 #define PIXEL01_3 Interp3(dp+1, w[5], w[2]);
58 #define PIXEL01_6 Interp1(dp+1, w[2], w[5]);
59 #define PIXEL01_C *(dp+1) = w[5];
61 #define PIXEL02_1M Interp1(dp+2, w[5], w[3]);
62 #define PIXEL02_1U Interp1(dp+2, w[5], w[2]);
63 #define PIXEL02_1R Interp1(dp+2, w[5], w[6]);
64 #define PIXEL02_2 Interp2(dp+2, w[5], w[2], w[6]);
65 #define PIXEL02_4 Interp4(dp+2, w[5], w[2], w[6]);
66 #define PIXEL02_5 Interp5(dp+2, w[2], w[6]);
67 #define PIXEL02_C *(dp+2) = w[5];
69 #define PIXEL10_1 Interp1(dp+dpL, w[5], w[4]);
70 #define PIXEL10_3 Interp3(dp+dpL, w[5], w[4]);
71 #define PIXEL10_6 Interp1(dp+dpL, w[4], w[5]);
72 #define PIXEL10_C *(dp+dpL) = w[5];
74 #define PIXEL11 *(dp+dpL+1) = w[5];
76 #define PIXEL12_1 Interp1(dp+dpL+2, w[5], w[6]);
77 #define PIXEL12_3 Interp3(dp+dpL+2, w[5], w[6]);
78 #define PIXEL12_6 Interp1(dp+dpL+2, w[6], w[5]);
79 #define PIXEL12_C *(dp+dpL+2) = w[5];
81 #define PIXEL20_1M Interp1(dp+dpL+dpL, w[5], w[7]);
82 #define PIXEL20_1D Interp1(dp+dpL+dpL, w[5], w[8]);
83 #define PIXEL20_1L Interp1(dp+dpL+dpL, w[5], w[4]);
84 #define PIXEL20_2 Interp2(dp+dpL+dpL, w[5], w[8], w[4]);
85 #define PIXEL20_4 Interp4(dp+dpL+dpL, w[5], w[8], w[4]);
86 #define PIXEL20_5 Interp5(dp+dpL+dpL, w[8], w[4]);
87 #define PIXEL20_C *(dp+dpL+dpL) = w[5];
89 #define PIXEL21_1 Interp1(dp+dpL+dpL+1, w[5], w[8]);
90 #define PIXEL21_3 Interp3(dp+dpL+dpL+1, w[5], w[8]);
91 #define PIXEL21_6 Interp1(dp+dpL+dpL+1, w[8], w[5]);
92 #define PIXEL21_C *(dp+dpL+dpL+1) = w[5];
94 #define PIXEL22_1M Interp1(dp+dpL+dpL+2, w[5], w[9]);
95 #define PIXEL22_1D Interp1(dp+dpL+dpL+2, w[5], w[8]);
96 #define PIXEL22_1R Interp1(dp+dpL+dpL+2, w[5], w[6]);
97 #define PIXEL22_2 Interp2(dp+dpL+dpL+2, w[5], w[6], w[8]);
98 #define PIXEL22_4 Interp4(dp+dpL+dpL+2, w[5], w[6], w[8]);
99 #define PIXEL22_5 Interp5(dp+dpL+dpL+2, w[6], w[8]);
100 #define PIXEL22_C *(dp+dpL+dpL+2) = w[5];
102 void hq3x(Pixbuf
const&src
, Pixbuf
&dst
)
117 int sw
=src
.get_width();
118 int sh
=src
.get_height();
119 int dpL
=dst
.get_pitch()/4; /* 4 bytes/pixel */
121 for (int j
=0; j
<sh
; j
++)
123 const guint32
*line
=src
.get_row(j
);
124 const guint32
*prevline
, *nextline
;
125 if (j
>0) prevline
= src
.get_row(j
-1); else prevline
= src
.get_row(sh
-1);
126 if (j
<sh
-1) nextline
= src
.get_row(j
+1); else nextline
= src
.get_row(0);
128 for (int i
=0; i
<sw
; i
++) {
134 w
[1] = prevline
[i
-1];
136 w
[7] = nextline
[i
-1];
139 w
[1] = prevline
[sw
-1];
141 w
[7] = nextline
[sw
-1];
145 w
[3] = prevline
[i
+1];
147 w
[9] = nextline
[i
+1];
158 guint32 YUV1
= RGBtoYUV(w
[5]);
160 for (int k
=1; k
<=9; k
++) {
163 if ( w
[k
] != w
[5] ) {
164 guint32 YUV2
= RGBtoYUV(w
[k
]);
165 if ( ( abs((YUV1
& Ymask
) - (YUV2
& Ymask
)) > trY
) ||
166 ( abs((YUV1
& Umask
) - (YUV2
& Umask
)) > trU
) ||
167 ( abs((YUV1
& Vmask
) - (YUV2
& Vmask
)) > trV
) )
173 guint32
*dp
=dst
.get_row(j
*3)+i
*3;
401 if (Diff(w
[2], w
[6]))
429 if (Diff(w
[6], w
[8]))
451 if (Diff(w
[8], w
[4]))
469 if (Diff(w
[4], w
[2]))
579 if (Diff(w
[2], w
[6]))
607 if (Diff(w
[6], w
[8]))
629 if (Diff(w
[8], w
[4]))
647 if (Diff(w
[4], w
[2]))
670 if (Diff(w
[2], w
[6]))
694 if (Diff(w
[2], w
[6]))
718 if (Diff(w
[6], w
[8]))
742 if (Diff(w
[6], w
[8]))
766 if (Diff(w
[8], w
[4]))
790 if (Diff(w
[8], w
[4]))
814 if (Diff(w
[4], w
[2]))
838 if (Diff(w
[4], w
[2]))
966 if (Diff(w
[4], w
[2]))
977 if (Diff(w
[2], w
[6]))
997 if (Diff(w
[2], w
[6]))
1011 if (Diff(w
[6], w
[8]))
1030 if (Diff(w
[8], w
[4]))
1041 if (Diff(w
[6], w
[8]))
1056 if (Diff(w
[4], w
[2]))
1070 if (Diff(w
[8], w
[4]))
1085 if (Diff(w
[4], w
[2]))
1108 if (Diff(w
[2], w
[6]))
1135 if (Diff(w
[6], w
[8]))
1156 if (Diff(w
[8], w
[4]))
1174 if (Diff(w
[2], w
[6]))
1201 if (Diff(w
[6], w
[8]))
1222 if (Diff(w
[8], w
[4]))
1239 if (Diff(w
[4], w
[2]))
1417 if (Diff(w
[4], w
[2]))
1426 if (Diff(w
[2], w
[6]))
1446 if (Diff(w
[2], w
[6]))
1459 if (Diff(w
[6], w
[8]))
1477 if (Diff(w
[8], w
[4]))
1486 if (Diff(w
[6], w
[8]))
1498 if (Diff(w
[4], w
[2]))
1511 if (Diff(w
[8], w
[4]))
1525 if (Diff(w
[4], w
[2]))
1538 if (Diff(w
[8], w
[4]))
1552 if (Diff(w
[4], w
[2]))
1561 if (Diff(w
[2], w
[6]))
1581 if (Diff(w
[2], w
[6]))
1594 if (Diff(w
[6], w
[8]))
1612 if (Diff(w
[8], w
[4]))
1621 if (Diff(w
[6], w
[8]))
1633 if (Diff(w
[4], w
[2]))
1642 if (Diff(w
[2], w
[6]))
1653 if (Diff(w
[8], w
[4]))
1662 if (Diff(w
[6], w
[8]))
1675 if (Diff(w
[2], w
[6]))
1699 if (Diff(w
[2], w
[6]))
1723 if (Diff(w
[6], w
[8]))
1747 if (Diff(w
[6], w
[8]))
1771 if (Diff(w
[8], w
[4]))
1795 if (Diff(w
[8], w
[4]))
1819 if (Diff(w
[4], w
[2]))
1843 if (Diff(w
[4], w
[2]))
1871 if (Diff(w
[8], w
[4]))
1888 if (Diff(w
[4], w
[2]))
1911 if (Diff(w
[2], w
[6]))
1938 if (Diff(w
[6], w
[8]))
1955 if (Diff(w
[2], w
[6]))
1982 if (Diff(w
[6], w
[8]))
2003 if (Diff(w
[8], w
[4]))
2020 if (Diff(w
[4], w
[2]))
2151 if (Diff(w
[8], w
[4]))
2159 if (Diff(w
[6], w
[8]))
2175 if (Diff(w
[4], w
[2]))
2183 if (Diff(w
[2], w
[6]))
2204 if (Diff(w
[4], w
[2]))
2216 if (Diff(w
[8], w
[4]))
2235 if (Diff(w
[2], w
[6]))
2246 if (Diff(w
[6], w
[8]))
2262 if (Diff(w
[4], w
[2]))
2274 if (Diff(w
[2], w
[6]))
2296 if (Diff(w
[8], w
[4]))
2308 if (Diff(w
[6], w
[8]))
2321 if (Diff(w
[2], w
[6]))
2337 if (Diff(w
[6], w
[8]))
2349 if (Diff(w
[4], w
[2]))
2364 if (Diff(w
[8], w
[4]))
2378 if (Diff(w
[4], w
[2]))
2387 if (Diff(w
[2], w
[6]))
2397 if (Diff(w
[8], w
[4]))
2409 if (Diff(w
[6], w
[8]))
2421 if (Diff(w
[4], w
[2]))
2429 if (Diff(w
[2], w
[6]))
2443 if (Diff(w
[8], w
[4]))
2452 if (Diff(w
[6], w
[8]))
2464 if (Diff(w
[4], w
[2]))
2473 if (Diff(w
[2], w
[6]))
2483 if (Diff(w
[8], w
[4]))
2491 if (Diff(w
[6], w
[8]))
2507 if (Diff(w
[4], w
[2]))
2519 if (Diff(w
[2], w
[6]))
2529 if (Diff(w
[8], w
[4]))
2538 if (Diff(w
[6], w
[8]))
2602 if (Diff(w
[4], w
[2]))
2611 if (Diff(w
[2], w
[6]))
2631 if (Diff(w
[2], w
[6]))
2644 if (Diff(w
[6], w
[8]))
2662 if (Diff(w
[8], w
[4]))
2671 if (Diff(w
[6], w
[8]))
2683 if (Diff(w
[4], w
[2]))
2696 if (Diff(w
[8], w
[4]))
2717 if (Diff(w
[8], w
[4]))
2732 if (Diff(w
[4], w
[2]))
2755 if (Diff(w
[2], w
[6]))
2782 if (Diff(w
[6], w
[8]))
2821 if (Diff(w
[2], w
[6]))
2834 if (Diff(w
[8], w
[4]))
2851 if (Diff(w
[4], w
[2]))
2866 if (Diff(w
[6], w
[8]))
2882 if (Diff(w
[8], w
[4]))
2905 if (Diff(w
[6], w
[8]))
2928 if (Diff(w
[4], w
[2]))
2951 if (Diff(w
[8], w
[4]))
2974 if (Diff(w
[2], w
[6]))
2997 if (Diff(w
[4], w
[2]))
3020 if (Diff(w
[6], w
[8]))
3043 if (Diff(w
[2], w
[6]))
3073 if (Diff(w
[8], w
[4]))
3088 if (Diff(w
[4], w
[2]))
3111 if (Diff(w
[2], w
[6]))
3138 if (Diff(w
[6], w
[8]))
3154 if (Diff(w
[8], w
[4]))
3165 if (Diff(w
[6], w
[8]))
3179 if (Diff(w
[4], w
[2]))
3193 if (Diff(w
[8], w
[4]))
3208 if (Diff(w
[4], w
[2]))
3219 if (Diff(w
[2], w
[6]))
3238 if (Diff(w
[2], w
[6]))
3252 if (Diff(w
[6], w
[8]))
3271 if (Diff(w
[8], w
[4]))
3282 if (Diff(w
[6], w
[8]))
3299 if (Diff(w
[8], w
[4]))
3308 if (Diff(w
[6], w
[8]))
3322 if (Diff(w
[4], w
[2]))
3336 if (Diff(w
[8], w
[4]))
3350 if (Diff(w
[4], w
[2]))
3363 if (Diff(w
[8], w
[4]))
3378 if (Diff(w
[4], w
[2]))
3387 if (Diff(w
[2], w
[6]))
3406 if (Diff(w
[4], w
[2]))
3417 if (Diff(w
[2], w
[6]))
3436 if (Diff(w
[2], w
[6]))
3448 if (Diff(w
[6], w
[8]))
3463 if (Diff(w
[2], w
[6]))
3478 if (Diff(w
[6], w
[8]))
3491 if (Diff(w
[2], w
[6]))
3502 if (Diff(w
[8], w
[4]))
3512 if (Diff(w
[6], w
[8]))
3534 if (Diff(w
[8], w
[4]))
3543 if (Diff(w
[6], w
[8]))
3555 if (Diff(w
[4], w
[2]))
3567 if (Diff(w
[8], w
[4]))
3579 if (Diff(w
[6], w
[8]))
3593 if (Diff(w
[4], w
[2]))
3606 if (Diff(w
[8], w
[4]))
3620 if (Diff(w
[4], w
[2]))
3632 if (Diff(w
[2], w
[6]))
3643 if (Diff(w
[8], w
[4]))
3658 if (Diff(w
[4], w
[2]))
3667 if (Diff(w
[2], w
[6]))
3685 if (Diff(w
[4], w
[2]))
3695 if (Diff(w
[2], w
[6]))
3709 if (Diff(w
[6], w
[8]))
3725 if (Diff(w
[2], w
[6]))
3738 if (Diff(w
[6], w
[8]))
3750 if (Diff(w
[4], w
[2]))
3759 if (Diff(w
[2], w
[6]))
3770 if (Diff(w
[8], w
[4]))
3779 if (Diff(w
[6], w
[8]))