1
2
3 #include "trop.h"
4
5 // TnzCore includes
6 #include "tpixelgr.h"
7 #include "trandom.h"
8 #include "tpixelutils.h"
9
10 //******************************************************************
11 // Conversion functions
12 //******************************************************************
13
do_convert(const TRaster64P & dst,const TRaster32P & src)14 static void do_convert(const TRaster64P &dst, const TRaster32P &src) {
15 assert(dst->getSize() == src->getSize());
16 int lx = src->getLx();
17 for (int y = 0; y < src->getLy(); y++) {
18 TPixel64 *outPix = dst->pixels(y);
19 TPixel32 *inPix = src->pixels(y);
20 TPixel32 *inEndPix = inPix + lx;
21 for (; inPix < inEndPix; ++outPix, ++inPix) {
22 outPix->r = ushortFromByte(inPix->r);
23 outPix->g = ushortFromByte(inPix->g);
24 outPix->b = ushortFromByte(inPix->b);
25 outPix->m = ushortFromByte(inPix->m);
26 }
27 }
28 }
29
30 //-----------------------------------------------------------------------------
31
do_convert(const TRasterGR8P & dst,const TRaster32P & src)32 static void do_convert(const TRasterGR8P &dst, const TRaster32P &src) {
33 assert(dst->getSize() == src->getSize());
34
35 int lx = src->getLx();
36
37 for (int y = 0; y < src->getLy(); ++y) {
38 TPixelGR8 *outPix = dst->pixels(y);
39 TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx;
40
41 for (; inPix < inEndPix; ++outPix, ++inPix)
42 *outPix = TPixelGR8::from(overPix(TPixel32::White, *inPix));
43 }
44 }
45
46 //-----------------------------------------------------------------------------
47
do_convert(const TRasterGR16P & dst,const TRaster32P & src)48 static void do_convert(const TRasterGR16P &dst, const TRaster32P &src) {
49 assert(dst->getSize() == src->getSize());
50
51 int lx = src->getLx();
52
53 for (int y = 0; y < src->getLy(); ++y) {
54 TPixelGR16 *outPix = dst->pixels(y);
55 TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx;
56
57 for (; inPix < inEndPix; ++outPix, ++inPix)
58 outPix->value =
59 257 * (TPixelGR8::from(overPix(TPixel32::White, *inPix))).value;
60 }
61 }
62
63 //-----------------------------------------------------------------------------
64
do_convert(const TRasterGR16P & dst,const TRaster64P & src)65 static void do_convert(const TRasterGR16P &dst, const TRaster64P &src) {
66 assert(dst->getSize() == src->getSize());
67 int lx = src->getLx();
68 for (int y = 0; y < src->getLy(); y++) {
69 TPixelGR16 *outPix = dst->pixels(y);
70 TPixel64 *inPix = src->pixels(y);
71 TPixel64 *inEndPix = inPix + lx;
72 while (inPix < inEndPix) {
73 outPix->value = (inPix->r + 2 * inPix->g + inPix->b) >> 2;
74 outPix++;
75 inPix++;
76 }
77 }
78 }
79
80 //-----------------------------------------------------------------------------
81
do_convert(const TRaster32P & dst,const TRasterGR8P & src)82 static void do_convert(const TRaster32P &dst, const TRasterGR8P &src) {
83 assert(dst->getSize() == src->getSize());
84 int lx = src->getLx();
85 for (int y = 0; y < src->getLy(); y++) {
86 TPixel32 *outPix = dst->pixels(y);
87 TPixelGR8 *inPix = src->pixels(y);
88 TPixelGR8 *inEndPix = inPix + lx;
89 while (inPix < inEndPix) {
90 outPix->r = inPix->value;
91 outPix->g = inPix->value;
92 outPix->b = inPix->value;
93 outPix->m = 0xff;
94 outPix++;
95 inPix++;
96 }
97 }
98 }
99
100 //-----------------------------------------------------------------------------
101
102 #define USHORT2BYTE_MAGICFAC (256U * 255U + 1U)
103
ditherUcharFromUshort(USHORT in,UINT rndNum)104 inline UCHAR ditherUcharFromUshort(USHORT in, UINT rndNum) {
105 return ((((in * USHORT2BYTE_MAGICFAC) - ((in * USHORT2BYTE_MAGICFAC) >> 24)) +
106 rndNum) >>
107 24);
108 }
109
ditherRgbmFromRgbm64(TPixel32 & out,const TPixel64 & in,TRandom & rnd)110 inline void ditherRgbmFromRgbm64(TPixel32 &out, const TPixel64 &in,
111 TRandom &rnd) {
112 UINT randomRound;
113 randomRound = rnd.getUInt() & ((1U << 24) - 1);
114
115 out.r = ditherUcharFromUshort(in.r, randomRound);
116 out.g = ditherUcharFromUshort(in.g, randomRound);
117 out.b = ditherUcharFromUshort(in.b, randomRound);
118 out.m = ditherUcharFromUshort(in.m, randomRound);
119 }
120
121 //-----------------------------------------------------------------------------
122
ditherConvert(TRaster64P inRas,TRaster32P outRas)123 inline void ditherConvert(TRaster64P inRas, TRaster32P outRas) {
124 int inWrap = inRas->getWrap();
125 int outWrap = outRas->getWrap();
126
127 TPixel64 *inPix = 0, *inRow = inRas->pixels();
128 TPixel32 *outPix, *outRow = outRas->pixels();
129 TPixel64 *endPix;
130 int inLx = inRas->getLx();
131 TPixel64 *lastPix = inRow + inWrap * (inRas->getLy() - 1) + inLx;
132
133 TRandom rnd(130266);
134
135 while (inPix < lastPix) {
136 inPix = inRow;
137 outPix = outRow;
138 endPix = inPix + inLx;
139 while (inPix < endPix) {
140 ditherRgbmFromRgbm64(*outPix, *inPix, rnd);
141 inPix++;
142 outPix++;
143 }
144 inRow += inWrap;
145 outRow += outWrap;
146 }
147 }
148
149 //******************************************************************
150 // Obsolete conversion functions
151 //******************************************************************
152
do_convert(const TRasterCM32P & dst,const TRasterGR8P & src)153 static void do_convert(const TRasterCM32P &dst, const TRasterGR8P &src) {
154 assert(dst->getSize() == src->getSize());
155 TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone());
156
157 int lx = src->getLx();
158 for (int y = 0; y < src->getLy(); y++) {
159 TPixelCM32 *outPix = dst->pixels(y);
160 TPixelGR8 *inPix = src->pixels(y);
161 TPixelGR8 *inEndPix = inPix + lx;
162 while (inPix < inEndPix) {
163 *outPix = (inPix->value == 255) ? bg : TPixelCM32(1, 0, inPix->value);
164 outPix++;
165 inPix++;
166 }
167 }
168 }
169
170 //-----------------------------------------------------------------------------
171
do_convert(const TRasterCM32P & dst,const TRaster32P & src)172 static void do_convert(const TRasterCM32P &dst, const TRaster32P &src) {
173 assert(dst->getSize() == src->getSize());
174 TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone());
175
176 int lx = src->getLx();
177
178 bool isOverlay = false;
179
180 for (int y = 0; y < src->getLy(); y++) // if it is an overlay, I use the
181 // matte value for inks, otherwise I
182 // use the brightness.
183 {
184 TPixel32 *inPix = src->pixels(y);
185 TPixel32 *inEndPix = inPix + lx;
186 while (inPix < inEndPix) {
187 if (inPix->m != 255) {
188 isOverlay = true;
189 break;
190 }
191 inPix++;
192 }
193 if (isOverlay) break;
194 }
195
196 if (isOverlay)
197 for (int y = 0; y < src->getLy(); y++) {
198 TPixelCM32 *outPix = dst->pixels(y);
199 TPixel32 *inPix = src->pixels(y);
200 TPixel32 *inEndPix = inPix + lx;
201 while (inPix < inEndPix) {
202 *outPix = (inPix->m == 0) ? bg : TPixelCM32(1, 0, 255 - inPix->m);
203 outPix++;
204 inPix++;
205 }
206 }
207 else
208 for (int y = 0; y < src->getLy(); y++) {
209 TPixelCM32 *outPix = dst->pixels(y);
210 TPixel32 *inPix = src->pixels(y);
211 TPixel32 *inEndPix = inPix + lx;
212 while (inPix < inEndPix) {
213 UCHAR val = TPixelGR8::from(*inPix).value;
214 *outPix = (val == 255) ? bg : TPixelCM32(1, 0, val);
215 outPix++;
216 inPix++;
217 }
218 }
219 }
220
221 //-----------------------------------------------------------------------------
222
do_convert(const TRasterYUV422P & dst,const TRaster32P & src)223 static void do_convert(const TRasterYUV422P &dst, const TRaster32P &src) {
224 assert(src->getLx() & 0);
225 long y1, y2, u, v, u1, u2, v1, v2;
226 TPixel32 *pix = (TPixel32 *)src->pixels();
227 TPixel32 *lastPix = &(src->pixels(src->getLy() - 1)[src->getLx() - 1]);
228
229 UCHAR *out = dst->getRawData();
230
231 while (pix < lastPix) {
232 /* first pixel gives Y and 0.5 of chroma */
233
234 y1 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b;
235 u1 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b;
236 v1 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b;
237
238 /* second pixel gives Y and 0.5 of chroma */
239 ++pix;
240
241 y2 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b;
242 u2 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b;
243 v2 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b;
244
245 /* average the chroma */
246 u = u1 + u2;
247 v = v1 + v2;
248
249 /* round the chroma */
250 u1 = (u + 0x008000) >> 16;
251 v1 = (v + 0x008000) >> 16;
252
253 /* limit the chroma */
254 if (u1 < -112) u1 = -112;
255 if (u1 > 111) u1 = 111;
256 if (v1 < -112) v1 = -112;
257 if (v1 > 111) v1 = 111;
258
259 /* limit the lum */
260 if (y1 > 0x00dbffff) y1 = 0x00dbffff;
261 if (y2 > 0x00dbffff) y2 = 0x00dbffff;
262
263 /* save the results */
264 *out++ = (UCHAR)(u1 + 128);
265 *out++ = (UCHAR)((y1 >> 16) + 16);
266 *out++ = (UCHAR)(v1 + 128);
267 *out++ = (UCHAR)((y2 >> 16) + 16);
268 ++pix;
269 }
270 }
271
272 //-----------------------------------------------------------------------------
273
do_convert(const TRaster32P & dst,const TRasterYUV422P & src)274 static void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) {
275 int long r, g, b, y1, y2, u, v;
276 TPixel32 *buf = dst->pixels();
277 const UCHAR *in = src->getRawData();
278 const UCHAR *last = in + src->getRowSize() * src->getLy() - 1;
279
280 while (in < last) {
281 u = *in;
282 u -= 128;
283 in++;
284 y1 = *in;
285 y1 -= 16;
286 in++;
287 v = *in;
288 v -= 128;
289 in++;
290 y2 = *in;
291 y2 -= 16;
292 in++;
293
294 r = 76310 * y1 + 104635 * v;
295 if (r > 0xFFFFFF) r = 0xFFFFFF;
296 if (r <= 0xFFFF) r = 0;
297
298 g = 76310 * y1 + -25690 * u + -53294 * v;
299 if (g > 0xFFFFFF) g = 0xFFFFFF;
300 if (g <= 0xFFFF) g = 0;
301
302 b = 76310 * y1 + 132278 * u;
303 if (b > 0xFFFFFF) b = 0xFFFFFF;
304 if (b <= 0xFFFF) b = 0;
305
306 buf->r = (UCHAR)(r >> 16);
307 buf->g = (UCHAR)(g >> 16);
308 buf->b = (UCHAR)(b >> 16);
309 buf->m = (UCHAR)255;
310 buf++;
311
312 r = 76310 * y2 + 104635 * v;
313 if (r > 0xFFFFFF) r = 0xFFFFFF;
314 if (r <= 0xFFFF) r = 0;
315
316 g = 76310 * y2 + -25690 * u + -53294 * v;
317 if (g > 0xFFFFFF) g = 0xFFFFFF;
318 if (g <= 0xFFFF) g = 0;
319
320 b = 76310 * y2 + 132278 * u;
321 if (b > 0xFFFFFF) b = 0xFFFFFF;
322 if (b <= 0xFFFF) b = 0;
323
324 buf->r = (UCHAR)(r >> 16);
325 buf->g = (UCHAR)(g >> 16);
326 buf->b = (UCHAR)(b >> 16);
327 buf->m = (UCHAR)255;
328 buf++;
329 }
330 }
331
332 //******************************************************************
333 // Main conversion function
334 //******************************************************************
335
convert(TRasterP dst,const TRasterP & src)336 void TRop::convert(TRasterP dst, const TRasterP &src) {
337 if (dst->getSize() != src->getSize())
338 throw TRopException("convert: size mismatch");
339
340 TRaster32P dst32 = dst;
341 TRasterGR8P dst8 = dst;
342 TRasterGR16P dst16 = dst;
343 TRaster64P dst64 = dst;
344 TRasterCM32P dstCm = dst;
345
346 TRaster32P src32 = src;
347 TRasterGR8P src8 = src;
348 TRaster64P src64 = src;
349 TRasterYUV422P srcYUV = src;
350 TRasterYUV422P dstYUV = dst;
351
352 src->lock();
353 dst->lock();
354
355 if (dst64 && src32)
356 do_convert(dst64, src32);
357 else if (dst8 && src32)
358 do_convert(dst8, src32);
359 else if (dst16 && src32)
360 do_convert(dst16, src32);
361 else if (dst32 && src64)
362 ditherConvert(src64, dst32);
363 else if (dst16 && src64)
364 do_convert(dst16, src64);
365 else if (dst32 && src8)
366 do_convert(dst32, src8);
367 else if (dstYUV && src32)
368 do_convert(dstYUV, src32); // Obsolete conversions
369 else if (dst32 && srcYUV)
370 do_convert(dst32, srcYUV); //
371 else if (dstCm && src32)
372 do_convert(dstCm, src32); //
373 else if (dstCm && src8)
374 do_convert(dstCm, src8); //
375 else {
376 dst->unlock();
377 src->unlock();
378
379 throw TRopException("unsupported pixel type");
380 }
381
382 dst->unlock();
383 src->unlock();
384 }
385