Leptonica 1.82.0
Image processing and image analysis suite
rotateam.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27
124#ifdef HAVE_CONFIG_H
125#include <config_auto.h>
126#endif /* HAVE_CONFIG_H */
127
128#include <string.h>
129#include <math.h> /* required for sin and tan */
130#include "allheaders.h"
131
132static void rotateAMColorLow(l_uint32 *datad, l_int32 w, l_int32 h,
133 l_int32 wpld, l_uint32 *datas, l_int32 wpls,
134 l_float32 angle, l_uint32 colorval);
135static void rotateAMGrayLow(l_uint32 *datad, l_int32 w, l_int32 h,
136 l_int32 wpld, l_uint32 *datas, l_int32 wpls,
137 l_float32 angle, l_uint8 grayval);
138static void rotateAMColorCornerLow(l_uint32 *datad, l_int32 w, l_int32 h,
139 l_int32 wpld, l_uint32 *datas,
140 l_int32 wpls, l_float32 angle,
141 l_uint32 colorval);
142static void rotateAMGrayCornerLow(l_uint32 *datad, l_int32 w, l_int32 h,
143 l_int32 wpld, l_uint32 *datas, l_int32 wpls,
144 l_float32 angle, l_uint8 grayval);
145
146static void rotateAMColorFastLow(l_uint32 *datad, l_int32 w, l_int32 h,
147 l_int32 wpld, l_uint32 *datas, l_int32 wpls,
148 l_float32 angle, l_uint32 colorval);
149
150static const l_float32 MinAngleToRotate = 0.001; /* radians; ~0.06 deg */
151
152
153/*------------------------------------------------------------------*
154 * Rotation about the center *
155 *------------------------------------------------------------------*/
171PIX *
173 l_float32 angle,
174 l_int32 incolor)
175{
176l_int32 d;
177l_uint32 fillval;
178PIX *pixt1, *pixt2, *pixd;
179
180 PROCNAME("pixRotateAM");
181
182 if (!pixs)
183 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
184 if (pixGetDepth(pixs) == 1)
185 return (PIX *)ERROR_PTR("pixs is 1 bpp", procName, NULL);
186
187 if (L_ABS(angle) < MinAngleToRotate)
188 return pixClone(pixs);
189
190 /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
192 d = pixGetDepth(pixt1);
193 if (d < 8)
194 pixt2 = pixConvertTo8(pixt1, FALSE);
195 else
196 pixt2 = pixClone(pixt1);
197 d = pixGetDepth(pixt2);
198
199 /* Compute actual incoming color */
200 fillval = 0;
201 if (incolor == L_BRING_IN_WHITE) {
202 if (d == 8)
203 fillval = 255;
204 else /* d == 32 */
205 fillval = 0xffffff00;
206 }
207
208 if (d == 8)
209 pixd = pixRotateAMGray(pixt2, angle, fillval);
210 else /* d == 32 */
211 pixd = pixRotateAMColor(pixt2, angle, fillval);
212
213 pixDestroy(&pixt1);
214 pixDestroy(&pixt2);
215 return pixd;
216}
217
218
234PIX *
236 l_float32 angle,
237 l_uint32 colorval)
238{
239l_int32 w, h, wpls, wpld;
240l_uint32 *datas, *datad;
241PIX *pix1, *pix2, *pixd;
242
243 PROCNAME("pixRotateAMColor");
244
245 if (!pixs)
246 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
247 if (pixGetDepth(pixs) != 32)
248 return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
249
250 if (L_ABS(angle) < MinAngleToRotate)
251 return pixClone(pixs);
252
253 pixGetDimensions(pixs, &w, &h, NULL);
254 datas = pixGetData(pixs);
255 wpls = pixGetWpl(pixs);
256 pixd = pixCreateTemplate(pixs);
257 datad = pixGetData(pixd);
258 wpld = pixGetWpl(pixd);
259
260 rotateAMColorLow(datad, w, h, wpld, datas, wpls, angle, colorval);
261 if (pixGetSpp(pixs) == 4) {
263 pix2 = pixRotateAMGray(pix1, angle, 255); /* bring in opaque */
265 pixDestroy(&pix1);
266 pixDestroy(&pix2);
267 }
268
269 return pixd;
270}
271
272
288PIX *
290 l_float32 angle,
291 l_uint8 grayval)
292{
293l_int32 w, h, wpls, wpld;
294l_uint32 *datas, *datad;
295PIX *pixd;
296
297 PROCNAME("pixRotateAMGray");
298
299 if (!pixs)
300 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
301 if (pixGetDepth(pixs) != 8)
302 return (PIX *)ERROR_PTR("pixs must be 8 bpp", procName, NULL);
303
304 if (L_ABS(angle) < MinAngleToRotate)
305 return pixClone(pixs);
306
307 pixGetDimensions(pixs, &w, &h, NULL);
308 datas = pixGetData(pixs);
309 wpls = pixGetWpl(pixs);
310 pixd = pixCreateTemplate(pixs);
311 datad = pixGetData(pixd);
312 wpld = pixGetWpl(pixd);
313
314 rotateAMGrayLow(datad, w, h, wpld, datas, wpls, angle, grayval);
315
316 return pixd;
317}
318
319
320static void
321rotateAMColorLow(l_uint32 *datad,
322 l_int32 w,
323 l_int32 h,
324 l_int32 wpld,
325 l_uint32 *datas,
326 l_int32 wpls,
327 l_float32 angle,
328 l_uint32 colorval)
329{
330l_int32 i, j, xcen, ycen, wm2, hm2;
331l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
332l_int32 rval, gval, bval;
333l_uint32 word00, word01, word10, word11;
334l_uint32 *lines, *lined;
335l_float32 sina, cosa;
336
337 xcen = w / 2;
338 wm2 = w - 2;
339 ycen = h / 2;
340 hm2 = h - 2;
341 sina = 16. * sin(angle);
342 cosa = 16. * cos(angle);
343
344 for (i = 0; i < h; i++) {
345 ydif = ycen - i;
346 lined = datad + i * wpld;
347 for (j = 0; j < w; j++) {
348 xdif = xcen - j;
349 xpm = (l_int32)(-xdif * cosa - ydif * sina);
350 ypm = (l_int32)(-ydif * cosa + xdif * sina);
351 xp = xcen + (xpm >> 4);
352 yp = ycen + (ypm >> 4);
353 xf = xpm & 0x0f;
354 yf = ypm & 0x0f;
355
356 /* if off the edge, write input colorval */
357 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
358 *(lined + j) = colorval;
359 continue;
360 }
361
362 lines = datas + yp * wpls;
363
364 /* do area weighting. Without this, we would
365 * simply do:
366 * *(lined + j) = *(lines + xp);
367 * which is faster but gives lousy results!
368 */
369 word00 = *(lines + xp);
370 word10 = *(lines + xp + 1);
371 word01 = *(lines + wpls + xp);
372 word11 = *(lines + wpls + xp + 1);
373 rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
374 xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
375 (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
376 xf * yf * ((word11 >> L_RED_SHIFT) & 0xff) + 128) / 256;
377 gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
378 xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
379 (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
380 xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff) + 128) / 256;
381 bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
382 xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
383 (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
384 xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff) + 128) / 256;
385 composeRGBPixel(rval, gval, bval, lined + j);
386 }
387 }
388}
389
390
391static void
392rotateAMGrayLow(l_uint32 *datad,
393 l_int32 w,
394 l_int32 h,
395 l_int32 wpld,
396 l_uint32 *datas,
397 l_int32 wpls,
398 l_float32 angle,
399 l_uint8 grayval)
400{
401l_int32 i, j, xcen, ycen, wm2, hm2;
402l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
403l_int32 v00, v01, v10, v11;
404l_uint8 val;
405l_uint32 *lines, *lined;
406l_float32 sina, cosa;
407
408 xcen = w / 2;
409 wm2 = w - 2;
410 ycen = h / 2;
411 hm2 = h - 2;
412 sina = 16. * sin(angle);
413 cosa = 16. * cos(angle);
414
415 for (i = 0; i < h; i++) {
416 ydif = ycen - i;
417 lined = datad + i * wpld;
418 for (j = 0; j < w; j++) {
419 xdif = xcen - j;
420 xpm = (l_int32)(-xdif * cosa - ydif * sina);
421 ypm = (l_int32)(-ydif * cosa + xdif * sina);
422 xp = xcen + (xpm >> 4);
423 yp = ycen + (ypm >> 4);
424 xf = xpm & 0x0f;
425 yf = ypm & 0x0f;
426
427 /* if off the edge, write input grayval */
428 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
429 SET_DATA_BYTE(lined, j, grayval);
430 continue;
431 }
432
433 lines = datas + yp * wpls;
434
435 /* do area weighting. Without this, we would
436 * simply do:
437 * SET_DATA_BYTE(lined, j, GET_DATA_BYTE(lines, xp));
438 * which is faster but gives lousy results!
439 */
440 v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
441 v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp + 1);
442 v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
443 v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp + 1);
444 val = (l_uint8)((v00 + v01 + v10 + v11 + 128) / 256);
445 SET_DATA_BYTE(lined, j, val);
446 }
447 }
448}
449
450
451/*------------------------------------------------------------------*
452 * Rotation about the UL corner *
453 *------------------------------------------------------------------*/
469PIX *
471 l_float32 angle,
472 l_int32 incolor)
473{
474l_int32 d;
475l_uint32 fillval;
476PIX *pixt1, *pixt2, *pixd;
477
478 PROCNAME("pixRotateAMCorner");
479
480 if (!pixs)
481 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
482
483 if (L_ABS(angle) < MinAngleToRotate)
484 return pixClone(pixs);
485
486 /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
488 d = pixGetDepth(pixt1);
489 if (d < 8)
490 pixt2 = pixConvertTo8(pixt1, FALSE);
491 else
492 pixt2 = pixClone(pixt1);
493 d = pixGetDepth(pixt2);
494
495 /* Compute actual incoming color */
496 fillval = 0;
497 if (incolor == L_BRING_IN_WHITE) {
498 if (d == 8)
499 fillval = 255;
500 else /* d == 32 */
501 fillval = 0xffffff00;
502 }
503
504 if (d == 8)
505 pixd = pixRotateAMGrayCorner(pixt2, angle, fillval);
506 else /* d == 32 */
507 pixd = pixRotateAMColorCorner(pixt2, angle, fillval);
508
509 pixDestroy(&pixt1);
510 pixDestroy(&pixt2);
511 return pixd;
512}
513
514
530PIX *
532 l_float32 angle,
533 l_uint32 fillval)
534{
535l_int32 w, h, wpls, wpld;
536l_uint32 *datas, *datad;
537PIX *pix1, *pix2, *pixd;
538
539 PROCNAME("pixRotateAMColorCorner");
540
541 if (!pixs)
542 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
543 if (pixGetDepth(pixs) != 32)
544 return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
545
546 if (L_ABS(angle) < MinAngleToRotate)
547 return pixClone(pixs);
548
549 pixGetDimensions(pixs, &w, &h, NULL);
550 datas = pixGetData(pixs);
551 wpls = pixGetWpl(pixs);
552 pixd = pixCreateTemplate(pixs);
553 datad = pixGetData(pixd);
554 wpld = pixGetWpl(pixd);
555
556 rotateAMColorCornerLow(datad, w, h, wpld, datas, wpls, angle, fillval);
557 if (pixGetSpp(pixs) == 4) {
559 pix2 = pixRotateAMGrayCorner(pix1, angle, 255); /* bring in opaque */
561 pixDestroy(&pix1);
562 pixDestroy(&pix2);
563 }
564
565 return pixd;
566}
567
568
584PIX *
586 l_float32 angle,
587 l_uint8 grayval)
588{
589l_int32 w, h, wpls, wpld;
590l_uint32 *datas, *datad;
591PIX *pixd;
592
593 PROCNAME("pixRotateAMGrayCorner");
594
595 if (!pixs)
596 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
597 if (pixGetDepth(pixs) != 8)
598 return (PIX *)ERROR_PTR("pixs must be 8 bpp", procName, NULL);
599
600 if (L_ABS(angle) < MinAngleToRotate)
601 return pixClone(pixs);
602
603 pixGetDimensions(pixs, &w, &h, NULL);
604 datas = pixGetData(pixs);
605 wpls = pixGetWpl(pixs);
606 pixd = pixCreateTemplate(pixs);
607 datad = pixGetData(pixd);
608 wpld = pixGetWpl(pixd);
609
610 rotateAMGrayCornerLow(datad, w, h, wpld, datas, wpls, angle, grayval);
611
612 return pixd;
613}
614
615
616static void
617rotateAMColorCornerLow(l_uint32 *datad,
618 l_int32 w,
619 l_int32 h,
620 l_int32 wpld,
621 l_uint32 *datas,
622 l_int32 wpls,
623 l_float32 angle,
624 l_uint32 colorval)
625{
626l_int32 i, j, wm2, hm2;
627l_int32 xpm, ypm, xp, yp, xf, yf;
628l_int32 rval, gval, bval;
629l_uint32 word00, word01, word10, word11;
630l_uint32 *lines, *lined;
631l_float32 sina, cosa;
632
633 wm2 = w - 2;
634 hm2 = h - 2;
635 sina = 16. * sin(angle);
636 cosa = 16. * cos(angle);
637
638 for (i = 0; i < h; i++) {
639 lined = datad + i * wpld;
640 for (j = 0; j < w; j++) {
641 xpm = (l_int32)(j * cosa + i * sina);
642 ypm = (l_int32)(i * cosa - j * sina);
643 xp = xpm >> 4;
644 yp = ypm >> 4;
645 xf = xpm & 0x0f;
646 yf = ypm & 0x0f;
647
648 /* if off the edge, write input colorval */
649 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
650 *(lined + j) = colorval;
651 continue;
652 }
653
654 lines = datas + yp * wpls;
655
656 /* do area weighting. Without this, we would
657 * simply do:
658 * *(lined + j) = *(lines + xp);
659 * which is faster but gives lousy results!
660 */
661 word00 = *(lines + xp);
662 word10 = *(lines + xp + 1);
663 word01 = *(lines + wpls + xp);
664 word11 = *(lines + wpls + xp + 1);
665 rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
666 xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
667 (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
668 xf * yf * ((word11 >> L_RED_SHIFT) & 0xff) + 128) / 256;
669 gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
670 xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
671 (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
672 xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff) + 128) / 256;
673 bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
674 xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
675 (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
676 xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff) + 128) / 256;
677 composeRGBPixel(rval, gval, bval, lined + j);
678 }
679 }
680}
681
682
683static void
684rotateAMGrayCornerLow(l_uint32 *datad,
685 l_int32 w,
686 l_int32 h,
687 l_int32 wpld,
688 l_uint32 *datas,
689 l_int32 wpls,
690 l_float32 angle,
691 l_uint8 grayval)
692{
693l_int32 i, j, wm2, hm2;
694l_int32 xpm, ypm, xp, yp, xf, yf;
695l_int32 v00, v01, v10, v11;
696l_uint8 val;
697l_uint32 *lines, *lined;
698l_float32 sina, cosa;
699
700 wm2 = w - 2;
701 hm2 = h - 2;
702 sina = 16. * sin(angle);
703 cosa = 16. * cos(angle);
704
705 for (i = 0; i < h; i++) {
706 lined = datad + i * wpld;
707 for (j = 0; j < w; j++) {
708 xpm = (l_int32)(j * cosa + i * sina);
709 ypm = (l_int32)(i * cosa - j * sina);
710 xp = xpm >> 4;
711 yp = ypm >> 4;
712 xf = xpm & 0x0f;
713 yf = ypm & 0x0f;
714
715 /* if off the edge, write input grayval */
716 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
717 SET_DATA_BYTE(lined, j, grayval);
718 continue;
719 }
720
721 lines = datas + yp * wpls;
722
723 /* do area weighting. Without this, we would
724 * simply do:
725 * SET_DATA_BYTE(lined, j, GET_DATA_BYTE(lines, xp));
726 * which is faster but gives lousy results!
727 */
728 v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
729 v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp + 1);
730 v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
731 v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp + 1);
732 val = (l_uint8)((v00 + v01 + v10 + v11 + 128) / 256);
733 SET_DATA_BYTE(lined, j, val);
734 }
735 }
736}
737
738
739/*------------------------------------------------------------------*
740 * Fast RGB color rotation about center *
741 *------------------------------------------------------------------*/
763PIX *
765 l_float32 angle,
766 l_uint32 colorval)
767{
768l_int32 w, h, wpls, wpld;
769l_uint32 *datas, *datad;
770PIX *pixd;
771
772 PROCNAME("pixRotateAMColorFast");
773
774 if (!pixs)
775 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
776 if (pixGetDepth(pixs) != 32)
777 return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
778
779 if (L_ABS(angle) < MinAngleToRotate)
780 return pixClone(pixs);
781
782 pixGetDimensions(pixs, &w, &h, NULL);
783 datas = pixGetData(pixs);
784 wpls = pixGetWpl(pixs);
785 pixd = pixCreateTemplate(pixs);
786 datad = pixGetData(pixd);
787 wpld = pixGetWpl(pixd);
788
789 rotateAMColorFastLow(datad, w, h, wpld, datas, wpls, angle, colorval);
790 return pixd;
791}
792
793
862static void
863rotateAMColorFastLow(l_uint32 *datad,
864 l_int32 w,
865 l_int32 h,
866 l_int32 wpld,
867 l_uint32 *datas,
868 l_int32 wpls,
869 l_float32 angle,
870 l_uint32 colorval)
871{
872l_int32 i, j, xcen, ycen, wm2, hm2;
873l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
874l_uint32 word1, word2, word3, word4, red, blue, green;
875l_uint32 *pword, *lines, *lined;
876l_float32 sina, cosa;
877
878 xcen = w / 2;
879 wm2 = w - 2;
880 ycen = h / 2;
881 hm2 = h - 2;
882 sina = 4. * sin(angle);
883 cosa = 4. * cos(angle);
884
885 for (i = 0; i < h; i++) {
886 ydif = ycen - i;
887 lined = datad + i * wpld;
888 for (j = 0; j < w; j++) {
889 xdif = xcen - j;
890 xpm = (l_int32)(-xdif * cosa - ydif * sina);
891 ypm = (l_int32)(-ydif * cosa + xdif * sina);
892 xp = xcen + (xpm >> 2);
893 yp = ycen + (ypm >> 2);
894 xf = xpm & 0x03;
895 yf = ypm & 0x03;
896
897 /* if off the edge, write input grayval */
898 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
899 *(lined + j) = colorval;
900 continue;
901 }
902
903 lines = datas + yp * wpls;
904 pword = lines + xp;
905
906 switch (xf + 4 * yf)
907 {
908 case 0:
909 *(lined + j) = *pword;
910 break;
911 case 1:
912 word1 = *pword;
913 word2 = *(pword + 1);
914 red = 3 * (word1 >> 24) + (word2 >> 24);
915 green = 3 * ((word1 >> 16) & 0xff) +
916 ((word2 >> 16) & 0xff);
917 blue = 3 * ((word1 >> 8) & 0xff) +
918 ((word2 >> 8) & 0xff);
919 *(lined + j) = ((red << 22) & 0xff000000) |
920 ((green << 14) & 0x00ff0000) |
921 ((blue << 6) & 0x0000ff00);
922 break;
923 case 2:
924 word1 = *pword;
925 word2 = *(pword + 1);
926 red = (word1 >> 24) + (word2 >> 24);
927 green = ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff);
928 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff);
929 *(lined + j) = ((red << 23) & 0xff000000) |
930 ((green << 15) & 0x00ff0000) |
931 ((blue << 7) & 0x0000ff00);
932 break;
933 case 3:
934 word1 = *pword;
935 word2 = *(pword + 1);
936 red = (word1 >> 24) + 3 * (word2 >> 24);
937 green = ((word1 >> 16) & 0xff) +
938 3 * ((word2 >> 16) & 0xff);
939 blue = ((word1 >> 8) & 0xff) +
940 3 * ((word2 >> 8) & 0xff);
941 *(lined + j) = ((red << 22) & 0xff000000) |
942 ((green << 14) & 0x00ff0000) |
943 ((blue << 6) & 0x0000ff00);
944 break;
945 case 4:
946 word1 = *pword;
947 word3 = *(pword + wpls);
948 red = 3 * (word1 >> 24) + (word3 >> 24);
949 green = 3 * ((word1 >> 16) & 0xff) +
950 ((word3 >> 16) & 0xff);
951 blue = 3 * ((word1 >> 8) & 0xff) +
952 ((word3 >> 8) & 0xff);
953 *(lined + j) = ((red << 22) & 0xff000000) |
954 ((green << 14) & 0x00ff0000) |
955 ((blue << 6) & 0x0000ff00);
956 break;
957 case 5:
958 word1 = *pword;
959 word2 = *(pword + 1);
960 word3 = *(pword + wpls);
961 word4 = *(pword + wpls + 1);
962 red = 9 * (word1 >> 24) + 3 * (word2 >> 24) +
963 3 * (word3 >> 24) + (word4 >> 24);
964 green = 9 * ((word1 >> 16) & 0xff) +
965 3 * ((word2 >> 16) & 0xff) +
966 3 * ((word3 >> 16) & 0xff) +
967 ((word4 >> 16) & 0xff);
968 blue = 9 * ((word1 >> 8) & 0xff) +
969 3 * ((word2 >> 8) & 0xff) +
970 3 * ((word3 >> 8) & 0xff) +
971 ((word4 >> 8) & 0xff);
972 *(lined + j) = ((red << 20) & 0xff000000) |
973 ((green << 12) & 0x00ff0000) |
974 ((blue << 4) & 0x0000ff00);
975 break;
976 case 6:
977 word1 = *pword;
978 word2 = *(pword + 1);
979 word3 = *(pword + wpls);
980 word4 = *(pword + wpls + 1);
981 red = 3 * (word1 >> 24) + 3 * (word2 >> 24) +
982 (word3 >> 24) + (word4 >> 24);
983 green = 3 * ((word1 >> 16) & 0xff) +
984 3 * ((word2 >> 16) & 0xff) +
985 ((word3 >> 16) & 0xff) +
986 ((word4 >> 16) & 0xff);
987 blue = 3 * ((word1 >> 8) & 0xff) +
988 3 * ((word2 >> 8) & 0xff) +
989 ((word3 >> 8) & 0xff) +
990 ((word4 >> 8) & 0xff);
991 *(lined + j) = ((red << 21) & 0xff000000) |
992 ((green << 13) & 0x00ff0000) |
993 ((blue << 5) & 0x0000ff00);
994 break;
995 case 7:
996 word1 = *pword;
997 word2 = *(pword + 1);
998 word3 = *(pword + wpls);
999 word4 = *(pword + wpls + 1);
1000 red = 3 * (word1 >> 24) + 9 * (word2 >> 24) +
1001 (word3 >> 24) + 3 * (word4 >> 24);
1002 green = 3 * ((word1 >> 16) & 0xff) +
1003 9 * ((word2 >> 16) & 0xff) +
1004 ((word3 >> 16) & 0xff) +
1005 3 * ((word4 >> 16) & 0xff);
1006 blue = 3 * ((word1 >> 8) & 0xff) +
1007 9 * ((word2 >> 8) & 0xff) +
1008 ((word3 >> 8) & 0xff) +
1009 3 * ((word4 >> 8) & 0xff);
1010 *(lined + j) = ((red << 20) & 0xff000000) |
1011 ((green << 12) & 0x00ff0000) |
1012 ((blue << 4) & 0x0000ff00);
1013 break;
1014 case 8:
1015 word1 = *pword;
1016 word3 = *(pword + wpls);
1017 red = (word1 >> 24) + (word3 >> 24);
1018 green = ((word1 >> 16) & 0xff) + ((word3 >> 16) & 0xff);
1019 blue = ((word1 >> 8) & 0xff) + ((word3 >> 8) & 0xff);
1020 *(lined + j) = ((red << 23) & 0xff000000) |
1021 ((green << 15) & 0x00ff0000) |
1022 ((blue << 7) & 0x0000ff00);
1023 break;
1024 case 9:
1025 word1 = *pword;
1026 word2 = *(pword + 1);
1027 word3 = *(pword + wpls);
1028 word4 = *(pword + wpls + 1);
1029 red = 3 * (word1 >> 24) + (word2 >> 24) +
1030 3 * (word3 >> 24) + (word4 >> 24);
1031 green = 3 * ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1032 3 * ((word3 >> 16) & 0xff) + ((word4 >> 16) & 0xff);
1033 blue = 3 * ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1034 3 * ((word3 >> 8) & 0xff) + ((word4 >> 8) & 0xff);
1035 *(lined + j) = ((red << 21) & 0xff000000) |
1036 ((green << 13) & 0x00ff0000) |
1037 ((blue << 5) & 0x0000ff00);
1038 break;
1039 case 10:
1040 word1 = *pword;
1041 word2 = *(pword + 1);
1042 word3 = *(pword + wpls);
1043 word4 = *(pword + wpls + 1);
1044 red = (word1 >> 24) + (word2 >> 24) +
1045 (word3 >> 24) + (word4 >> 24);
1046 green = ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1047 ((word3 >> 16) & 0xff) + ((word4 >> 16) & 0xff);
1048 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1049 ((word3 >> 8) & 0xff) + ((word4 >> 8) & 0xff);
1050 *(lined + j) = ((red << 22) & 0xff000000) |
1051 ((green << 14) & 0x00ff0000) |
1052 ((blue << 6) & 0x0000ff00);
1053 break;
1054 case 11:
1055 word1 = *pword;
1056 word2 = *(pword + 1);
1057 word3 = *(pword + wpls);
1058 word4 = *(pword + wpls + 1);
1059 red = (word1 >> 24) + 3 * (word2 >> 24) +
1060 (word3 >> 24) + 3 * (word4 >> 24);
1061 green = ((word1 >> 16) & 0xff) + 3 * ((word2 >> 16) & 0xff) +
1062 ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1063 blue = ((word1 >> 8) & 0xff) + 3 * ((word2 >> 8) & 0xff) +
1064 ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1065 *(lined + j) = ((red << 21) & 0xff000000) |
1066 ((green << 13) & 0x00ff0000) |
1067 ((blue << 5) & 0x0000ff00);
1068 break;
1069 case 12:
1070 word1 = *pword;
1071 word3 = *(pword + wpls);
1072 red = (word1 >> 24) + 3 * (word3 >> 24);
1073 green = ((word1 >> 16) & 0xff) +
1074 3 * ((word3 >> 16) & 0xff);
1075 blue = ((word1 >> 8) & 0xff) +
1076 3 * ((word3 >> 8) & 0xff);
1077 *(lined + j) = ((red << 22) & 0xff000000) |
1078 ((green << 14) & 0x00ff0000) |
1079 ((blue << 6) & 0x0000ff00);
1080 break;
1081 case 13:
1082 word1 = *pword;
1083 word2 = *(pword + 1);
1084 word3 = *(pword + wpls);
1085 word4 = *(pword + wpls + 1);
1086 red = 3 * (word1 >> 24) + (word2 >> 24) +
1087 9 * (word3 >> 24) + 3 * (word4 >> 24);
1088 green = 3 * ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1089 9 * ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1090 blue = 3 *((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1091 9 * ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1092 *(lined + j) = ((red << 20) & 0xff000000) |
1093 ((green << 12) & 0x00ff0000) |
1094 ((blue << 4) & 0x0000ff00);
1095 break;
1096 case 14:
1097 word1 = *pword;
1098 word2 = *(pword + 1);
1099 word3 = *(pword + wpls);
1100 word4 = *(pword + wpls + 1);
1101 red = (word1 >> 24) + (word2 >> 24) +
1102 3 * (word3 >> 24) + 3 * (word4 >> 24);
1103 green = ((word1 >> 16) & 0xff) +((word2 >> 16) & 0xff) +
1104 3 * ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1105 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1106 3 * ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1107 *(lined + j) = ((red << 21) & 0xff000000) |
1108 ((green << 13) & 0x00ff0000) |
1109 ((blue << 5) & 0x0000ff00);
1110 break;
1111 case 15:
1112 word1 = *pword;
1113 word2 = *(pword + 1);
1114 word3 = *(pword + wpls);
1115 word4 = *(pword + wpls + 1);
1116 red = (word1 >> 24) + 3 * (word2 >> 24) +
1117 3 * (word3 >> 24) + 9 * (word4 >> 24);
1118 green = ((word1 >> 16) & 0xff) + 3 * ((word2 >> 16) & 0xff) +
1119 3 * ((word3 >> 16) & 0xff) + 9 * ((word4 >> 16) & 0xff);
1120 blue = ((word1 >> 8) & 0xff) + 3 * ((word2 >> 8) & 0xff) +
1121 3 * ((word3 >> 8) & 0xff) + 9 * ((word4 >> 8) & 0xff);
1122 *(lined + j) = ((red << 20) & 0xff000000) |
1123 ((green << 12) & 0x00ff0000) |
1124 ((blue << 4) & 0x0000ff00);
1125 break;
1126 default:
1127 lept_stderr("shouldn't get here\n");
1128 break;
1129 }
1130 }
1131 }
1132}
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
@ L_BRING_IN_WHITE
Definition: pix.h:869
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixRotateAMColorCorner(PIX *pixs, l_float32 angle, l_uint32 fillval)
pixRotateAMColorCorner()
Definition: rotateam.c:531
PIX * pixRotateAMCorner(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateAMCorner()
Definition: rotateam.c:470
PIX * pixRotateAMGray(PIX *pixs, l_float32 angle, l_uint8 grayval)
pixRotateAMGray()
Definition: rotateam.c:289
static void rotateAMColorFastLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_float32 angle, l_uint32 colorval)
rotateAMColorFastLow()
Definition: rotateam.c:863
PIX * pixRotateAMColorFast(PIX *pixs, l_float32 angle, l_uint32 colorval)
pixRotateAMColorFast()
Definition: rotateam.c:764
PIX * pixRotateAM(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateAM()
Definition: rotateam.c:172
PIX * pixRotateAMGrayCorner(PIX *pixs, l_float32 angle, l_uint8 grayval)
pixRotateAMGrayCorner()
Definition: rotateam.c:585
PIX * pixRotateAMColor(PIX *pixs, l_float32 angle, l_uint32 colorval)
pixRotateAMColor()
Definition: rotateam.c:235
Definition: pix.h:139
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306