Add resizer letterbox2
[jpcrr.git] / streamtools / quantize.hh
blobc27dc4c55d2b591ea57512b2907b4d301ae50e3d
1 /*
2 Ordered dithering methods provided for:
3 8x8 (Quantize8x8)
4 4x4 (Quantize4x4)
5 3x3 (Quantize3x3)
6 4x2 (Quantize4x2)
7 3x2 (Quantize3x2)
8 2x2 (Quantize2x2)
9 The functions are:
11 template<int m, int in_max>
12 int QuantizeFunc(size_t quant_pos, double value)
14 - Quantizes value, assumed to be in range 0..in_max, to range 0..m
15 - quant_pos tells the coordinate into the dithering matrix
17 template<int m, int in_max>
18 int QuantizeFunc(size_t quant_pos, unsigned value)
20 - Quantizes value, assumed to be in range 0..in_max, to range 0..m
21 - quant_pos tells the coordinate into the dithering matrix
23 Copyright (C) 1992,2008 Joel Yliluoma (http://iki.fi/bisqwit/)
26 #define OrderedDitherDecl(n) \
27 static const double flts[n]; \
28 static const int ints[n]; \
29 enum { mul = n+1, \
30 maxin = in_max, \
31 even = !(maxin % mul), \
32 intmul = even ? 1 : mul };
34 /* macroes for initializing dither tables */
35 #define d(n) (n)/double(mul) - 0.5
36 #define i(n) even ? (n*in_max/mul - (int)in_max/2) \
37 : (n*in_max - (int)mul*in_max/2)
39 template<int m, int in_max = 255>
40 struct QuantizeNoDither
42 int res;
43 template<typename IntType>
44 QuantizeNoDither(IntType v) : res(v * m / in_max) { }
45 operator int() const { return res; }
48 template<int m, typename Base>
49 struct QuantizeFuncBase: private Base
51 int res;
53 QuantizeFuncBase(size_t quant_pos, double v) : res(0)
55 if(v > 0.0)
57 const double dither_threshold = Base::flts[quant_pos];
58 res = (int)(v * (m / double(Base::maxin)) + dither_threshold);
59 if(res > m) res = m;
63 QuantizeFuncBase(size_t quant_pos, unsigned char v) : res(v)
65 if(m == Base::maxin) return;
66 if(m < Base::maxin)
68 // With dithering
69 const int dither_threshold = Base::ints[quant_pos];
70 const int intmul = Base::intmul;
71 res = (res * (m * intmul) + dither_threshold) / (Base::maxin * intmul);
73 else
75 // Without dithering
76 res = QuantizeNoDither<m, Base::maxin> (res);
81 #define QuantizeFuncDecl(name, base) \
82 template<int m, int in_max=255> \
83 struct name: private QuantizeFuncBase<m, base<in_max> > \
84 { \
85 typedef QuantizeFuncBase<m, base<in_max> > Base; \
86 template<typename A, typename B> name(A a, B b) : Base(a, b) { } \
87 operator int() const { return Base::res; } \
90 /******* Quantizing with 8x8 ordered dithering ********/
91 template<int in_max> struct OrderedDither_8x8 { OrderedDitherDecl(8*8) };
92 template<int in_max>
93 const double OrderedDither_8x8<in_max>::flts[] /* A table for 8x8 ordered dithering */
94 = { d(1 ), d(49), d(13), d(61), d( 4), d(52), d(16), d(64),
95 d(33), d(17), d(45), d(29), d(36), d(20), d(48), d(32),
96 d(9 ), d(57), d( 5), d(53), d(12), d(60), d( 8), d(56),
97 d(41), d(25), d(37), d(21), d(44), d(28), d(40), d(24),
98 d(3 ), d(51), d(15), d(63), d( 2), d(50), d(14), d(62),
99 d(35), d(19), d(47), d(31), d(34), d(18), d(46), d(30),
100 d(11), d(59), d( 7), d(55), d(10), d(58), d( 6), d(54),
101 d(43), d(27), d(39), d(23), d(42), d(26), d(38), d(22) };
102 template<int in_max>
103 const int OrderedDither_8x8<in_max>::ints[]
104 = { i(1 ), i(49), i(13), i(61), i( 4), i(52), i(16), i(64),
105 i(33), i(17), i(45), i(29), i(36), i(20), i(48), i(32),
106 i(9 ), i(57), i( 5), i(53), i(12), i(60), i( 8), i(56),
107 i(41), i(25), i(37), i(21), i(44), i(28), i(40), i(24),
108 i(3 ), i(51), i(15), i(63), i( 2), i(50), i(14), i(62),
109 i(35), i(19), i(47), i(31), i(34), i(18), i(46), i(30),
110 i(11), i(59), i( 7), i(55), i(10), i(58), i( 6), i(54),
111 i(43), i(27), i(39), i(23), i(42), i(26), i(38), i(22) };
112 QuantizeFuncDecl(Quantize8x8, OrderedDither_8x8);
115 /******* Quantizing with 4x4 ordered dithering ********/
116 template<int in_max> struct OrderedDither_4x4 { OrderedDitherDecl(4*4) };
117 template<int in_max>
118 const double OrderedDither_4x4<in_max>::flts[] /* A table for 4x4 ordered dithering */
119 = { d( 1), d( 9), d( 3), d(11),
120 d(13), d( 5), d(15), d( 7),
121 d( 4), d(12), d( 2), d(10),
122 d(16), d( 8), d(14), d( 6) };
123 template<int in_max>
124 const int OrderedDither_4x4<in_max>::ints[]
125 = { i( 1), i( 9), i( 3), i(11),
126 i(13), i( 5), i(15), i( 7),
127 i( 4), i(12), i( 2), i(10),
128 i(16), i( 8), i(14), i( 6) };
129 QuantizeFuncDecl(Quantize4x4, OrderedDither_4x4);
131 /******* Quantizing with 3x3 ordered dithering ********/
132 template<int in_max> struct OrderedDither_3x3 { OrderedDitherDecl(3*3) };
133 template<int in_max>
134 const double OrderedDither_3x3<in_max>::flts[] /* A table for 3x3 ordered dithering */
135 = { d(1), d(7), d(3),
136 d(6), d(4), d(9),
137 d(8), d(2), d(5) };
138 template<int in_max>
139 const int OrderedDither_3x3<in_max>::ints[]
140 = { i(1), i(7), i(3),
141 i(6), i(4), i(9),
142 i(8), i(2), i(5) };
143 QuantizeFuncDecl(Quantize3x3, OrderedDither_3x3);
145 /******* Quantizing with 4x2 ordered dithering ********/
146 template<int in_max> struct OrderedDither_4x2 { OrderedDitherDecl(4*2) };
147 template<int in_max>
148 const double OrderedDither_4x2<in_max>::flts[] /* A table for 4x2 ordered dithering */
149 = { d(1), d(5), d(2), d(6),
150 d(7), d(3), d(8), d(4) };
151 template<int in_max>
152 const int OrderedDither_4x2<in_max>::ints[]
153 = { i(1), i(5), i(2), i(6),
154 i(7), i(3), i(8), i(4) };
155 QuantizeFuncDecl(Quantize4x2, OrderedDither_4x2);
157 /******* Quantizing with 3x2 ordered dithering ********/
158 template<int in_max> struct OrderedDither_3x2 { OrderedDitherDecl(3*2) };
159 template<int in_max>
160 const double OrderedDither_3x2<in_max>::flts[] /* A table for 3x2 ordered dithering */
161 = { d(1), d(5), d(3),
162 d(4), d(2), d(6) };
163 template<int in_max>
164 const int OrderedDither_3x2<in_max>::ints[]
165 = { i(1), i(5), i(3),
166 i(4), i(2), i(6) };
167 QuantizeFuncDecl(Quantize3x2, OrderedDither_3x2);
169 /******* Quantizing with 2x2 ordered dithering ********/
170 template<int in_max> struct OrderedDither_2x2 { OrderedDitherDecl(2*2) };
171 template<int in_max>
172 const double OrderedDither_2x2<in_max>::flts[] /* A table for 2x2 ordered dithering */
173 = { d(1), d(4),
174 d(3), d(2) };
175 template<int in_max>
176 const int OrderedDither_2x2<in_max>::ints[]
177 = { i(1), i(4),
178 i(3), i(2) };
179 QuantizeFuncDecl(Quantize2x2, OrderedDither_2x2);
182 #undef OrderedDitherDecl
183 #undef QuantizeFuncDecl
184 #undef i
185 #undef d