Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
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.001f; /* 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 if (!pixs)
181 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
182 if (pixGetDepth(pixs) == 1)
183 return (PIX *)ERROR_PTR("pixs is 1 bpp", __func__, NULL);
184
185 if (L_ABS(angle) < MinAngleToRotate)
186 return pixClone(pixs);
187
188 /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
189 pixt1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);
190 d = pixGetDepth(pixt1);
191 if (d < 8)
192 pixt2 = pixConvertTo8(pixt1, FALSE);
193 else
194 pixt2 = pixClone(pixt1);
195 d = pixGetDepth(pixt2);
196
197 /* Compute actual incoming color */
198 fillval = 0;
199 if (incolor == L_BRING_IN_WHITE) {
200 if (d == 8)
201 fillval = 255;
202 else /* d == 32 */
203 fillval = 0xffffff00;
204 }
205
206 if (d == 8)
207 pixd = pixRotateAMGray(pixt2, angle, fillval);
208 else /* d == 32 */
209 pixd = pixRotateAMColor(pixt2, angle, fillval);
210
211 pixDestroy(&pixt1);
212 pixDestroy(&pixt2);
213 return pixd;
214}
215
216
232PIX *
234 l_float32 angle,
235 l_uint32 colorval)
236{
237l_int32 w, h, wpls, wpld;
238l_uint32 *datas, *datad;
239PIX *pix1, *pix2, *pixd;
240
241 if (!pixs)
242 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
243 if (pixGetDepth(pixs) != 32)
244 return (PIX *)ERROR_PTR("pixs must be 32 bpp", __func__, NULL);
245
246 if (L_ABS(angle) < MinAngleToRotate)
247 return pixClone(pixs);
248
249 pixGetDimensions(pixs, &w, &h, NULL);
250 datas = pixGetData(pixs);
251 wpls = pixGetWpl(pixs);
252 pixd = pixCreateTemplate(pixs);
253 datad = pixGetData(pixd);
254 wpld = pixGetWpl(pixd);
255
256 rotateAMColorLow(datad, w, h, wpld, datas, wpls, angle, colorval);
257 if (pixGetSpp(pixs) == 4) {
258 pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
259 pix2 = pixRotateAMGray(pix1, angle, 255); /* bring in opaque */
260 pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
261 pixDestroy(&pix1);
262 pixDestroy(&pix2);
263 }
264
265 return pixd;
266}
267
268
284PIX *
286 l_float32 angle,
287 l_uint8 grayval)
288{
289l_int32 w, h, wpls, wpld;
290l_uint32 *datas, *datad;
291PIX *pixd;
292
293 if (!pixs)
294 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
295 if (pixGetDepth(pixs) != 8)
296 return (PIX *)ERROR_PTR("pixs must be 8 bpp", __func__, NULL);
297
298 if (L_ABS(angle) < MinAngleToRotate)
299 return pixClone(pixs);
300
301 pixGetDimensions(pixs, &w, &h, NULL);
302 datas = pixGetData(pixs);
303 wpls = pixGetWpl(pixs);
304 pixd = pixCreateTemplate(pixs);
305 datad = pixGetData(pixd);
306 wpld = pixGetWpl(pixd);
307
308 rotateAMGrayLow(datad, w, h, wpld, datas, wpls, angle, grayval);
309
310 return pixd;
311}
312
313
314static void
315rotateAMColorLow(l_uint32 *datad,
316 l_int32 w,
317 l_int32 h,
318 l_int32 wpld,
319 l_uint32 *datas,
320 l_int32 wpls,
321 l_float32 angle,
322 l_uint32 colorval)
323{
324l_int32 i, j, xcen, ycen, wm2, hm2;
325l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
326l_int32 rval, gval, bval;
327l_uint32 word00, word01, word10, word11;
328l_uint32 *lines, *lined;
329l_float32 sina, cosa;
330
331 xcen = w / 2;
332 wm2 = w - 2;
333 ycen = h / 2;
334 hm2 = h - 2;
335 sina = 16.f * sin(angle);
336 cosa = 16.f * cos(angle);
337
338 for (i = 0; i < h; i++) {
339 ydif = ycen - i;
340 lined = datad + i * wpld;
341 for (j = 0; j < w; j++) {
342 xdif = xcen - j;
343 xpm = (l_int32)(-xdif * cosa - ydif * sina);
344 ypm = (l_int32)(-ydif * cosa + xdif * sina);
345 xp = xcen + (xpm >> 4);
346 yp = ycen + (ypm >> 4);
347 xf = xpm & 0x0f;
348 yf = ypm & 0x0f;
349
350 /* if off the edge, write input colorval */
351 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
352 *(lined + j) = colorval;
353 continue;
354 }
355
356 lines = datas + yp * wpls;
357
358 /* do area weighting. Without this, we would
359 * simply do:
360 * *(lined + j) = *(lines + xp);
361 * which is faster but gives lousy results!
362 */
363 word00 = *(lines + xp);
364 word10 = *(lines + xp + 1);
365 word01 = *(lines + wpls + xp);
366 word11 = *(lines + wpls + xp + 1);
367 rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
368 xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
369 (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
370 xf * yf * ((word11 >> L_RED_SHIFT) & 0xff) + 128) / 256;
371 gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
372 xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
373 (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
374 xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff) + 128) / 256;
375 bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
376 xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
377 (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
378 xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff) + 128) / 256;
379 composeRGBPixel(rval, gval, bval, lined + j);
380 }
381 }
382}
383
384
385static void
386rotateAMGrayLow(l_uint32 *datad,
387 l_int32 w,
388 l_int32 h,
389 l_int32 wpld,
390 l_uint32 *datas,
391 l_int32 wpls,
392 l_float32 angle,
393 l_uint8 grayval)
394{
395l_int32 i, j, xcen, ycen, wm2, hm2;
396l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
397l_int32 v00, v01, v10, v11;
398l_uint8 val;
399l_uint32 *lines, *lined;
400l_float32 sina, cosa;
401
402 xcen = w / 2;
403 wm2 = w - 2;
404 ycen = h / 2;
405 hm2 = h - 2;
406 sina = 16.f * sin(angle);
407 cosa = 16.f * cos(angle);
408
409 for (i = 0; i < h; i++) {
410 ydif = ycen - i;
411 lined = datad + i * wpld;
412 for (j = 0; j < w; j++) {
413 xdif = xcen - j;
414 xpm = (l_int32)(-xdif * cosa - ydif * sina);
415 ypm = (l_int32)(-ydif * cosa + xdif * sina);
416 xp = xcen + (xpm >> 4);
417 yp = ycen + (ypm >> 4);
418 xf = xpm & 0x0f;
419 yf = ypm & 0x0f;
420
421 /* if off the edge, write input grayval */
422 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
423 SET_DATA_BYTE(lined, j, grayval);
424 continue;
425 }
426
427 lines = datas + yp * wpls;
428
429 /* do area weighting. Without this, we would
430 * simply do:
431 * SET_DATA_BYTE(lined, j, GET_DATA_BYTE(lines, xp));
432 * which is faster but gives lousy results!
433 */
434 v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
435 v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp + 1);
436 v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
437 v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp + 1);
438 val = (l_uint8)((v00 + v01 + v10 + v11 + 128) / 256);
439 SET_DATA_BYTE(lined, j, val);
440 }
441 }
442}
443
444
445/*------------------------------------------------------------------*
446 * Rotation about the UL corner *
447 *------------------------------------------------------------------*/
463PIX *
465 l_float32 angle,
466 l_int32 incolor)
467{
468l_int32 d;
469l_uint32 fillval;
470PIX *pixt1, *pixt2, *pixd;
471
472 if (!pixs)
473 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
474
475 if (L_ABS(angle) < MinAngleToRotate)
476 return pixClone(pixs);
477
478 /* Remove cmap if it exists, and unpack to 8 bpp if necessary */
479 pixt1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);
480 d = pixGetDepth(pixt1);
481 if (d < 8)
482 pixt2 = pixConvertTo8(pixt1, FALSE);
483 else
484 pixt2 = pixClone(pixt1);
485 d = pixGetDepth(pixt2);
486
487 /* Compute actual incoming color */
488 fillval = 0;
489 if (incolor == L_BRING_IN_WHITE) {
490 if (d == 8)
491 fillval = 255;
492 else /* d == 32 */
493 fillval = 0xffffff00;
494 }
495
496 if (d == 8)
497 pixd = pixRotateAMGrayCorner(pixt2, angle, fillval);
498 else /* d == 32 */
499 pixd = pixRotateAMColorCorner(pixt2, angle, fillval);
500
501 pixDestroy(&pixt1);
502 pixDestroy(&pixt2);
503 return pixd;
504}
505
506
522PIX *
524 l_float32 angle,
525 l_uint32 fillval)
526{
527l_int32 w, h, wpls, wpld;
528l_uint32 *datas, *datad;
529PIX *pix1, *pix2, *pixd;
530
531 if (!pixs)
532 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
533 if (pixGetDepth(pixs) != 32)
534 return (PIX *)ERROR_PTR("pixs must be 32 bpp", __func__, NULL);
535
536 if (L_ABS(angle) < MinAngleToRotate)
537 return pixClone(pixs);
538
539 pixGetDimensions(pixs, &w, &h, NULL);
540 datas = pixGetData(pixs);
541 wpls = pixGetWpl(pixs);
542 pixd = pixCreateTemplate(pixs);
543 datad = pixGetData(pixd);
544 wpld = pixGetWpl(pixd);
545
546 rotateAMColorCornerLow(datad, w, h, wpld, datas, wpls, angle, fillval);
547 if (pixGetSpp(pixs) == 4) {
548 pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
549 pix2 = pixRotateAMGrayCorner(pix1, angle, 255); /* bring in opaque */
550 pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
551 pixDestroy(&pix1);
552 pixDestroy(&pix2);
553 }
554
555 return pixd;
556}
557
558
574PIX *
576 l_float32 angle,
577 l_uint8 grayval)
578{
579l_int32 w, h, wpls, wpld;
580l_uint32 *datas, *datad;
581PIX *pixd;
582
583 if (!pixs)
584 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
585 if (pixGetDepth(pixs) != 8)
586 return (PIX *)ERROR_PTR("pixs must be 8 bpp", __func__, NULL);
587
588 if (L_ABS(angle) < MinAngleToRotate)
589 return pixClone(pixs);
590
591 pixGetDimensions(pixs, &w, &h, NULL);
592 datas = pixGetData(pixs);
593 wpls = pixGetWpl(pixs);
594 pixd = pixCreateTemplate(pixs);
595 datad = pixGetData(pixd);
596 wpld = pixGetWpl(pixd);
597
598 rotateAMGrayCornerLow(datad, w, h, wpld, datas, wpls, angle, grayval);
599
600 return pixd;
601}
602
603
604static void
605rotateAMColorCornerLow(l_uint32 *datad,
606 l_int32 w,
607 l_int32 h,
608 l_int32 wpld,
609 l_uint32 *datas,
610 l_int32 wpls,
611 l_float32 angle,
612 l_uint32 colorval)
613{
614l_int32 i, j, wm2, hm2;
615l_int32 xpm, ypm, xp, yp, xf, yf;
616l_int32 rval, gval, bval;
617l_uint32 word00, word01, word10, word11;
618l_uint32 *lines, *lined;
619l_float32 sina, cosa;
620
621 wm2 = w - 2;
622 hm2 = h - 2;
623 sina = 16.f * sin(angle);
624 cosa = 16.f * cos(angle);
625
626 for (i = 0; i < h; i++) {
627 lined = datad + i * wpld;
628 for (j = 0; j < w; j++) {
629 xpm = (l_int32)(j * cosa + i * sina);
630 ypm = (l_int32)(i * cosa - j * sina);
631 xp = xpm >> 4;
632 yp = ypm >> 4;
633 xf = xpm & 0x0f;
634 yf = ypm & 0x0f;
635
636 /* if off the edge, write input colorval */
637 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
638 *(lined + j) = colorval;
639 continue;
640 }
641
642 lines = datas + yp * wpls;
643
644 /* do area weighting. Without this, we would
645 * simply do:
646 * *(lined + j) = *(lines + xp);
647 * which is faster but gives lousy results!
648 */
649 word00 = *(lines + xp);
650 word10 = *(lines + xp + 1);
651 word01 = *(lines + wpls + xp);
652 word11 = *(lines + wpls + xp + 1);
653 rval = ((16 - xf) * (16 - yf) * ((word00 >> L_RED_SHIFT) & 0xff) +
654 xf * (16 - yf) * ((word10 >> L_RED_SHIFT) & 0xff) +
655 (16 - xf) * yf * ((word01 >> L_RED_SHIFT) & 0xff) +
656 xf * yf * ((word11 >> L_RED_SHIFT) & 0xff) + 128) / 256;
657 gval = ((16 - xf) * (16 - yf) * ((word00 >> L_GREEN_SHIFT) & 0xff) +
658 xf * (16 - yf) * ((word10 >> L_GREEN_SHIFT) & 0xff) +
659 (16 - xf) * yf * ((word01 >> L_GREEN_SHIFT) & 0xff) +
660 xf * yf * ((word11 >> L_GREEN_SHIFT) & 0xff) + 128) / 256;
661 bval = ((16 - xf) * (16 - yf) * ((word00 >> L_BLUE_SHIFT) & 0xff) +
662 xf * (16 - yf) * ((word10 >> L_BLUE_SHIFT) & 0xff) +
663 (16 - xf) * yf * ((word01 >> L_BLUE_SHIFT) & 0xff) +
664 xf * yf * ((word11 >> L_BLUE_SHIFT) & 0xff) + 128) / 256;
665 composeRGBPixel(rval, gval, bval, lined + j);
666 }
667 }
668}
669
670
671static void
672rotateAMGrayCornerLow(l_uint32 *datad,
673 l_int32 w,
674 l_int32 h,
675 l_int32 wpld,
676 l_uint32 *datas,
677 l_int32 wpls,
678 l_float32 angle,
679 l_uint8 grayval)
680{
681l_int32 i, j, wm2, hm2;
682l_int32 xpm, ypm, xp, yp, xf, yf;
683l_int32 v00, v01, v10, v11;
684l_uint8 val;
685l_uint32 *lines, *lined;
686l_float32 sina, cosa;
687
688 wm2 = w - 2;
689 hm2 = h - 2;
690 sina = 16.f * sin(angle);
691 cosa = 16.f * cos(angle);
692
693 for (i = 0; i < h; i++) {
694 lined = datad + i * wpld;
695 for (j = 0; j < w; j++) {
696 xpm = (l_int32)(j * cosa + i * sina);
697 ypm = (l_int32)(i * cosa - j * sina);
698 xp = xpm >> 4;
699 yp = ypm >> 4;
700 xf = xpm & 0x0f;
701 yf = ypm & 0x0f;
702
703 /* if off the edge, write input grayval */
704 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
705 SET_DATA_BYTE(lined, j, grayval);
706 continue;
707 }
708
709 lines = datas + yp * wpls;
710
711 /* do area weighting. Without this, we would
712 * simply do:
713 * SET_DATA_BYTE(lined, j, GET_DATA_BYTE(lines, xp));
714 * which is faster but gives lousy results!
715 */
716 v00 = (16 - xf) * (16 - yf) * GET_DATA_BYTE(lines, xp);
717 v10 = xf * (16 - yf) * GET_DATA_BYTE(lines, xp + 1);
718 v01 = (16 - xf) * yf * GET_DATA_BYTE(lines + wpls, xp);
719 v11 = xf * yf * GET_DATA_BYTE(lines + wpls, xp + 1);
720 val = (l_uint8)((v00 + v01 + v10 + v11 + 128) / 256);
721 SET_DATA_BYTE(lined, j, val);
722 }
723 }
724}
725
726
727/*------------------------------------------------------------------*
728 * Fast RGB color rotation about center *
729 *------------------------------------------------------------------*/
751PIX *
753 l_float32 angle,
754 l_uint32 colorval)
755{
756l_int32 w, h, wpls, wpld;
757l_uint32 *datas, *datad;
758PIX *pixd;
759
760 if (!pixs)
761 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
762 if (pixGetDepth(pixs) != 32)
763 return (PIX *)ERROR_PTR("pixs must be 32 bpp", __func__, NULL);
764
765 if (L_ABS(angle) < MinAngleToRotate)
766 return pixClone(pixs);
767
768 pixGetDimensions(pixs, &w, &h, NULL);
769 datas = pixGetData(pixs);
770 wpls = pixGetWpl(pixs);
771 pixd = pixCreateTemplate(pixs);
772 datad = pixGetData(pixd);
773 wpld = pixGetWpl(pixd);
774
775 rotateAMColorFastLow(datad, w, h, wpld, datas, wpls, angle, colorval);
776 return pixd;
777}
778
779
848static void
849rotateAMColorFastLow(l_uint32 *datad,
850 l_int32 w,
851 l_int32 h,
852 l_int32 wpld,
853 l_uint32 *datas,
854 l_int32 wpls,
855 l_float32 angle,
856 l_uint32 colorval)
857{
858l_int32 i, j, xcen, ycen, wm2, hm2;
859l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
860l_uint32 word1, word2, word3, word4, red, blue, green;
861l_uint32 *pword, *lines, *lined;
862l_float32 sina, cosa;
863
864 xcen = w / 2;
865 wm2 = w - 2;
866 ycen = h / 2;
867 hm2 = h - 2;
868 sina = 4.f * sin(angle);
869 cosa = 4.f * cos(angle);
870
871 for (i = 0; i < h; i++) {
872 ydif = ycen - i;
873 lined = datad + i * wpld;
874 for (j = 0; j < w; j++) {
875 xdif = xcen - j;
876 xpm = (l_int32)(-xdif * cosa - ydif * sina);
877 ypm = (l_int32)(-ydif * cosa + xdif * sina);
878 xp = xcen + (xpm >> 2);
879 yp = ycen + (ypm >> 2);
880 xf = xpm & 0x03;
881 yf = ypm & 0x03;
882
883 /* if off the edge, write input grayval */
884 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
885 *(lined + j) = colorval;
886 continue;
887 }
888
889 lines = datas + yp * wpls;
890 pword = lines + xp;
891
892 switch (xf + 4 * yf)
893 {
894 case 0:
895 *(lined + j) = *pword;
896 break;
897 case 1:
898 word1 = *pword;
899 word2 = *(pword + 1);
900 red = 3 * (word1 >> 24) + (word2 >> 24);
901 green = 3 * ((word1 >> 16) & 0xff) +
902 ((word2 >> 16) & 0xff);
903 blue = 3 * ((word1 >> 8) & 0xff) +
904 ((word2 >> 8) & 0xff);
905 *(lined + j) = ((red << 22) & 0xff000000) |
906 ((green << 14) & 0x00ff0000) |
907 ((blue << 6) & 0x0000ff00);
908 break;
909 case 2:
910 word1 = *pword;
911 word2 = *(pword + 1);
912 red = (word1 >> 24) + (word2 >> 24);
913 green = ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff);
914 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff);
915 *(lined + j) = ((red << 23) & 0xff000000) |
916 ((green << 15) & 0x00ff0000) |
917 ((blue << 7) & 0x0000ff00);
918 break;
919 case 3:
920 word1 = *pword;
921 word2 = *(pword + 1);
922 red = (word1 >> 24) + 3 * (word2 >> 24);
923 green = ((word1 >> 16) & 0xff) +
924 3 * ((word2 >> 16) & 0xff);
925 blue = ((word1 >> 8) & 0xff) +
926 3 * ((word2 >> 8) & 0xff);
927 *(lined + j) = ((red << 22) & 0xff000000) |
928 ((green << 14) & 0x00ff0000) |
929 ((blue << 6) & 0x0000ff00);
930 break;
931 case 4:
932 word1 = *pword;
933 word3 = *(pword + wpls);
934 red = 3 * (word1 >> 24) + (word3 >> 24);
935 green = 3 * ((word1 >> 16) & 0xff) +
936 ((word3 >> 16) & 0xff);
937 blue = 3 * ((word1 >> 8) & 0xff) +
938 ((word3 >> 8) & 0xff);
939 *(lined + j) = ((red << 22) & 0xff000000) |
940 ((green << 14) & 0x00ff0000) |
941 ((blue << 6) & 0x0000ff00);
942 break;
943 case 5:
944 word1 = *pword;
945 word2 = *(pword + 1);
946 word3 = *(pword + wpls);
947 word4 = *(pword + wpls + 1);
948 red = 9 * (word1 >> 24) + 3 * (word2 >> 24) +
949 3 * (word3 >> 24) + (word4 >> 24);
950 green = 9 * ((word1 >> 16) & 0xff) +
951 3 * ((word2 >> 16) & 0xff) +
952 3 * ((word3 >> 16) & 0xff) +
953 ((word4 >> 16) & 0xff);
954 blue = 9 * ((word1 >> 8) & 0xff) +
955 3 * ((word2 >> 8) & 0xff) +
956 3 * ((word3 >> 8) & 0xff) +
957 ((word4 >> 8) & 0xff);
958 *(lined + j) = ((red << 20) & 0xff000000) |
959 ((green << 12) & 0x00ff0000) |
960 ((blue << 4) & 0x0000ff00);
961 break;
962 case 6:
963 word1 = *pword;
964 word2 = *(pword + 1);
965 word3 = *(pword + wpls);
966 word4 = *(pword + wpls + 1);
967 red = 3 * (word1 >> 24) + 3 * (word2 >> 24) +
968 (word3 >> 24) + (word4 >> 24);
969 green = 3 * ((word1 >> 16) & 0xff) +
970 3 * ((word2 >> 16) & 0xff) +
971 ((word3 >> 16) & 0xff) +
972 ((word4 >> 16) & 0xff);
973 blue = 3 * ((word1 >> 8) & 0xff) +
974 3 * ((word2 >> 8) & 0xff) +
975 ((word3 >> 8) & 0xff) +
976 ((word4 >> 8) & 0xff);
977 *(lined + j) = ((red << 21) & 0xff000000) |
978 ((green << 13) & 0x00ff0000) |
979 ((blue << 5) & 0x0000ff00);
980 break;
981 case 7:
982 word1 = *pword;
983 word2 = *(pword + 1);
984 word3 = *(pword + wpls);
985 word4 = *(pword + wpls + 1);
986 red = 3 * (word1 >> 24) + 9 * (word2 >> 24) +
987 (word3 >> 24) + 3 * (word4 >> 24);
988 green = 3 * ((word1 >> 16) & 0xff) +
989 9 * ((word2 >> 16) & 0xff) +
990 ((word3 >> 16) & 0xff) +
991 3 * ((word4 >> 16) & 0xff);
992 blue = 3 * ((word1 >> 8) & 0xff) +
993 9 * ((word2 >> 8) & 0xff) +
994 ((word3 >> 8) & 0xff) +
995 3 * ((word4 >> 8) & 0xff);
996 *(lined + j) = ((red << 20) & 0xff000000) |
997 ((green << 12) & 0x00ff0000) |
998 ((blue << 4) & 0x0000ff00);
999 break;
1000 case 8:
1001 word1 = *pword;
1002 word3 = *(pword + wpls);
1003 red = (word1 >> 24) + (word3 >> 24);
1004 green = ((word1 >> 16) & 0xff) + ((word3 >> 16) & 0xff);
1005 blue = ((word1 >> 8) & 0xff) + ((word3 >> 8) & 0xff);
1006 *(lined + j) = ((red << 23) & 0xff000000) |
1007 ((green << 15) & 0x00ff0000) |
1008 ((blue << 7) & 0x0000ff00);
1009 break;
1010 case 9:
1011 word1 = *pword;
1012 word2 = *(pword + 1);
1013 word3 = *(pword + wpls);
1014 word4 = *(pword + wpls + 1);
1015 red = 3 * (word1 >> 24) + (word2 >> 24) +
1016 3 * (word3 >> 24) + (word4 >> 24);
1017 green = 3 * ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1018 3 * ((word3 >> 16) & 0xff) + ((word4 >> 16) & 0xff);
1019 blue = 3 * ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1020 3 * ((word3 >> 8) & 0xff) + ((word4 >> 8) & 0xff);
1021 *(lined + j) = ((red << 21) & 0xff000000) |
1022 ((green << 13) & 0x00ff0000) |
1023 ((blue << 5) & 0x0000ff00);
1024 break;
1025 case 10:
1026 word1 = *pword;
1027 word2 = *(pword + 1);
1028 word3 = *(pword + wpls);
1029 word4 = *(pword + wpls + 1);
1030 red = (word1 >> 24) + (word2 >> 24) +
1031 (word3 >> 24) + (word4 >> 24);
1032 green = ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1033 ((word3 >> 16) & 0xff) + ((word4 >> 16) & 0xff);
1034 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1035 ((word3 >> 8) & 0xff) + ((word4 >> 8) & 0xff);
1036 *(lined + j) = ((red << 22) & 0xff000000) |
1037 ((green << 14) & 0x00ff0000) |
1038 ((blue << 6) & 0x0000ff00);
1039 break;
1040 case 11:
1041 word1 = *pword;
1042 word2 = *(pword + 1);
1043 word3 = *(pword + wpls);
1044 word4 = *(pword + wpls + 1);
1045 red = (word1 >> 24) + 3 * (word2 >> 24) +
1046 (word3 >> 24) + 3 * (word4 >> 24);
1047 green = ((word1 >> 16) & 0xff) + 3 * ((word2 >> 16) & 0xff) +
1048 ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1049 blue = ((word1 >> 8) & 0xff) + 3 * ((word2 >> 8) & 0xff) +
1050 ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1051 *(lined + j) = ((red << 21) & 0xff000000) |
1052 ((green << 13) & 0x00ff0000) |
1053 ((blue << 5) & 0x0000ff00);
1054 break;
1055 case 12:
1056 word1 = *pword;
1057 word3 = *(pword + wpls);
1058 red = (word1 >> 24) + 3 * (word3 >> 24);
1059 green = ((word1 >> 16) & 0xff) +
1060 3 * ((word3 >> 16) & 0xff);
1061 blue = ((word1 >> 8) & 0xff) +
1062 3 * ((word3 >> 8) & 0xff);
1063 *(lined + j) = ((red << 22) & 0xff000000) |
1064 ((green << 14) & 0x00ff0000) |
1065 ((blue << 6) & 0x0000ff00);
1066 break;
1067 case 13:
1068 word1 = *pword;
1069 word2 = *(pword + 1);
1070 word3 = *(pword + wpls);
1071 word4 = *(pword + wpls + 1);
1072 red = 3 * (word1 >> 24) + (word2 >> 24) +
1073 9 * (word3 >> 24) + 3 * (word4 >> 24);
1074 green = 3 * ((word1 >> 16) & 0xff) + ((word2 >> 16) & 0xff) +
1075 9 * ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1076 blue = 3 *((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1077 9 * ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1078 *(lined + j) = ((red << 20) & 0xff000000) |
1079 ((green << 12) & 0x00ff0000) |
1080 ((blue << 4) & 0x0000ff00);
1081 break;
1082 case 14:
1083 word1 = *pword;
1084 word2 = *(pword + 1);
1085 word3 = *(pword + wpls);
1086 word4 = *(pword + wpls + 1);
1087 red = (word1 >> 24) + (word2 >> 24) +
1088 3 * (word3 >> 24) + 3 * (word4 >> 24);
1089 green = ((word1 >> 16) & 0xff) +((word2 >> 16) & 0xff) +
1090 3 * ((word3 >> 16) & 0xff) + 3 * ((word4 >> 16) & 0xff);
1091 blue = ((word1 >> 8) & 0xff) + ((word2 >> 8) & 0xff) +
1092 3 * ((word3 >> 8) & 0xff) + 3 * ((word4 >> 8) & 0xff);
1093 *(lined + j) = ((red << 21) & 0xff000000) |
1094 ((green << 13) & 0x00ff0000) |
1095 ((blue << 5) & 0x0000ff00);
1096 break;
1097 case 15:
1098 word1 = *pword;
1099 word2 = *(pword + 1);
1100 word3 = *(pword + wpls);
1101 word4 = *(pword + wpls + 1);
1102 red = (word1 >> 24) + 3 * (word2 >> 24) +
1103 3 * (word3 >> 24) + 9 * (word4 >> 24);
1104 green = ((word1 >> 16) & 0xff) + 3 * ((word2 >> 16) & 0xff) +
1105 3 * ((word3 >> 16) & 0xff) + 9 * ((word4 >> 16) & 0xff);
1106 blue = ((word1 >> 8) & 0xff) + 3 * ((word2 >> 8) & 0xff) +
1107 3 * ((word3 >> 8) & 0xff) + 9 * ((word4 >> 8) & 0xff);
1108 *(lined + j) = ((red << 20) & 0xff000000) |
1109 ((green << 12) & 0x00ff0000) |
1110 ((blue << 4) & 0x0000ff00);
1111 break;
1112 default:
1113 lept_stderr("shouldn't get here\n");
1114 break;
1115 }
1116 }
1117 }
1118}
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
@ L_ALPHA_CHANNEL
Definition pix.h:331
@ REMOVE_CMAP_BASED_ON_SRC
Definition pix.h:384
@ L_BRING_IN_WHITE
Definition pix.h:662
PIX * pixRotateAMColorCorner(PIX *pixs, l_float32 angle, l_uint32 fillval)
pixRotateAMColorCorner()
Definition rotateam.c:523
PIX * pixRotateAMCorner(PIX *pixs, l_float32 angle, l_int32 incolor)
pixRotateAMCorner()
Definition rotateam.c:464
PIX * pixRotateAMGray(PIX *pixs, l_float32 angle, l_uint8 grayval)
pixRotateAMGray()
Definition rotateam.c:285
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:849
PIX * pixRotateAMColorFast(PIX *pixs, l_float32 angle, l_uint32 colorval)
pixRotateAMColorFast()
Definition rotateam.c:752
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:575
PIX * pixRotateAMColor(PIX *pixs, l_float32 angle, l_uint32 colorval)
pixRotateAMColor()
Definition rotateam.c:233