20130313
[gdash.git] / src / gfx / pixbufmanip_hqx.hpp
blob36de1bb976a93656da0dcb616b5a2e877a85d633
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #ifndef _GD_pixbufmanip_hqx
17 #define _GD_pixbufmanip_hqx
19 #include "config.h"
21 #include <glib.h>
22 #include <cstdlib>
23 #include "gfx/pixbufmanip.hpp"
24 #include "gfx/pixbuf.hpp"
26 #define Ymask 0x00FF0000
27 #define Umask 0x0000FF00
28 #define Vmask 0x000000FF
29 #define trY 0x00300000
30 #define trU 0x00000700
31 #define trV 0x00000006
33 // These masks are used to mask out two bytes from an guint32
34 // out of four.
35 // When interpolating, all r g b and a values must be interpolated.
36 // These enable the interpolation functions to do two multiplications
37 // at a time.
38 #define MASK_24 0xFF00FF00
39 #define MASK_13 0x00FF00FF
42 inline guint32 RGBtoYUV(guint32 c) {
43 guint32 r, g, b, y, u, v;
44 r = (c & Pixbuf::rmask) >> Pixbuf::rshift;
45 g = (c & Pixbuf::gmask) >> Pixbuf::gshift;
46 b = (c & Pixbuf::bmask) >> Pixbuf::bshift;
47 // y = (guint32)(0.299*r + 0.587*g + 0.114*b);
48 // u = (guint32)(-0.169*r - 0.331*g + 0.5*b) + 128;
49 // v = (guint32)(0.5*r - 0.419*g - 0.081*b) + 128;
50 // changed to fixed point math
51 y = (77*r + 150*g + 29*b)>>8;
52 u = (32768 + -43*r - 85*g + 128*b)>>8;
53 v = (32768 + 128*r - 107*g - 21*b)>>8;
54 return (y << 16) + (u << 8) + v;
57 /* Test if there is difference in color */
58 inline int Diff(guint32 w1, guint32 w2)
60 guint32 YUV1 = RGBtoYUV(w1);
61 guint32 YUV2 = RGBtoYUV(w2);
62 return ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY )
63 || ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU )
64 || ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV );
67 /* Interpolate functions */
68 inline void Interp1(guint32 * pc, guint32 c1, guint32 c2)
70 //*pc = (c1*3+c2)/4;
71 if (c1 == c2) {
72 *pc = c1;
73 return;
75 *pc = ((((c1 & MASK_24)/4 * 3 + (c2 & MASK_24)/4)) & MASK_24)
76 + ((((c1 & MASK_13)/4 * 3 + (c2 & MASK_13)/4)) & MASK_13);
79 inline void Interp2(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
81 //*pc = (c1*2+c2+c3)/4;
82 *pc = ((((c1 & MASK_24)/4 * 2 + (c2 & MASK_24)/4 + (c3 & MASK_24)/4)) & MASK_24)
83 + ((((c1 & MASK_13)/4 * 2 + (c2 & MASK_13)/4 + (c3 & MASK_13)/4)) & MASK_13);
86 inline void Interp3(guint32 * pc, guint32 c1, guint32 c2)
88 //*pc = (c1*7+c2)/8;
89 if (c1 == c2) {
90 *pc = c1;
91 return;
93 *pc = ((((c1 & MASK_24)/8 * 7 + (c2 & MASK_24)/8)) & MASK_24) +
94 ((((c1 & MASK_13)/8 * 7 + (c2 & MASK_13)/8)) & MASK_13);
97 inline void Interp4(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
99 //*pc = (c1*2+(c2+c3)*7)/16;
100 *pc = ((((c1 & MASK_24)/16 * 2 + (c2 & MASK_24)/16 * 7 + (c3 & MASK_24)/16 * 7)) & MASK_24) +
101 ((((c1 & MASK_13)/16 * 2 + (c2 & MASK_13)/16 * 7 + (c3 & MASK_13)/16 * 7)) & MASK_13);
104 inline void Interp5(guint32 * pc, guint32 c1, guint32 c2)
106 //*pc = (c1+c2)/2;
107 if (c1 == c2) {
108 *pc = c1;
109 return;
111 *pc = ((((c1 & MASK_24)/2 + (c2 & MASK_24)/2)) & MASK_24) +
112 ((((c1 & MASK_13)/2 + (c2 & MASK_13)/2)) & MASK_13);
115 inline void Interp6(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
117 //*pc = (c1*5+c2*2+c3)/8;
118 *pc = ((((c1 & MASK_24)/8 * 5 + (c2 & MASK_24)/8 * 2 + (c3 & MASK_24)/8)) & MASK_24) +
119 ((((c1 & MASK_13)/8 * 5 + (c2 & MASK_13)/8 * 2 + (c3 & MASK_13)/8)) & MASK_13);
122 inline void Interp7(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
124 //*pc = (c1*6+c2+c3)/8;
125 *pc = ((((c1 & MASK_24)/8 * 6 + (c2 & MASK_24)/8 + (c3 & MASK_24)/8)) & MASK_24) +
126 ((((c1 & MASK_13)/8 * 6 + (c2 & MASK_13)/8 + (c3 & MASK_13)/8)) & MASK_13);
129 inline void Interp8(guint32 * pc, guint32 c1, guint32 c2)
131 //*pc = (c1*5+c2*3)/8;
132 if (c1 == c2) {
133 *pc = c1;
134 return;
136 *pc = ((((c1 & MASK_24)/8 * 5 + (c2 & MASK_24)/8 * 3)) & MASK_24) +
137 ((((c1 & MASK_13)/8 * 5 + (c2 & MASK_13)/8 * 3)) & MASK_13);
140 inline void Interp9(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
142 //*pc = (c1*2+(c2+c3)*3)/8;
143 *pc = ((((c1 & MASK_24)/8 * 2 + (c2 & MASK_24)/8 * 3 + (c3 & MASK_24)/8 * 3)) & MASK_24) +
144 ((((c1 & MASK_13)/8 * 2 + (c2 & MASK_13)/8 * 3 + (c3 & MASK_13)/8 * 3)) & MASK_13);
147 inline void Interp10(guint32 * pc, guint32 c1, guint32 c2, guint32 c3)
149 //*pc = (c1*14+c2+c3)/16;
150 *pc = ((((c1 & MASK_24)/16 * 14 + (c2 & MASK_24)/16 + (c3 & MASK_24)/16)) & MASK_24) +
151 ((((c1 & MASK_13)/16 * 14 + (c2 & MASK_13)/16 + (c3 & MASK_13)/16)) & MASK_13);
154 #endif