Leptonica  1.82.0
Image processing and image analysis suite
scale2.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 
98 #ifdef HAVE_CONFIG_H
99 #include <config_auto.h>
100 #endif /* HAVE_CONFIG_H */
101 
102 #include <string.h>
103 #include "allheaders.h"
104 
105 static void scaleToGray2Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
106  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
107  l_uint32 *sumtab, l_uint8 *valtab);
108 static l_uint32 *makeSumTabSG2(void);
109 static l_uint8 *makeValTabSG2(void);
110 static void scaleToGray3Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
111  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
112  l_uint32 *sumtab, l_uint8 *valtab);
113 static l_uint32 *makeSumTabSG3(void);
114 static l_uint8 *makeValTabSG3(void);
115 static void scaleToGray4Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
116  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
117  l_uint32 *sumtab, l_uint8 *valtab);
118 static l_uint32 *makeSumTabSG4(void);
119 static l_uint8 *makeValTabSG4(void);
120 static void scaleToGray6Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
121  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
122  l_int32 *tab8, l_uint8 *valtab);
123 static l_uint8 *makeValTabSG6(void);
124 static void scaleToGray8Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
125  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
126  l_int32 *tab8, l_uint8 *valtab);
127 static l_uint8 *makeValTabSG8(void);
128 static void scaleToGray16Low(l_uint32 *datad, l_int32 wd, l_int32 hd,
129  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
130  l_int32 *tab8);
131 static l_int32 scaleMipmapLow(l_uint32 *datad, l_int32 wd, l_int32 hd,
132  l_int32 wpld, l_uint32 *datas1, l_int32 wpls1,
133  l_uint32 *datas2, l_int32 wpls2, l_float32 red);
134 
135 extern l_float32 AlphaMaskBorderVals[2];
136 
137 
138 /*------------------------------------------------------------------*
139  * Scale-to-gray (1 bpp --> 8 bpp; arbitrary downscaling) *
140  *------------------------------------------------------------------*/
207 PIX *
209  l_float32 scalefactor)
210 {
211 l_int32 w, h, minsrc, mindest;
212 l_float32 mag, red;
213 PIX *pixt, *pixd;
214 
215  PROCNAME("pixScaleToGray");
216 
217  if (!pixs)
218  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
219  if (pixGetDepth(pixs) != 1)
220  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
221  if (scalefactor <= 0.0)
222  return (PIX *)ERROR_PTR("scalefactor <= 0.0", procName, NULL);
223  if (scalefactor >= 1.0)
224  return (PIX *)ERROR_PTR("scalefactor >= 1.0", procName, NULL);
225  pixGetDimensions(pixs, &w, &h, NULL);
226  minsrc = L_MIN(w, h);
227  mindest = (l_int32)((l_float32)minsrc * scalefactor);
228  if (mindest < 2)
229  return (PIX *)ERROR_PTR("scalefactor too small", procName, NULL);
230 
231  if (scalefactor > 0.5) { /* see note (5) */
232  mag = 2.0 * scalefactor; /* will be < 2.0 */
233 /* lept_stderr("2x with mag %7.3f\n", mag); */
234  if ((pixt = pixScaleBinary(pixs, mag, mag)) == NULL)
235  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
236  pixd = pixScaleToGray2(pixt);
237  } else if (scalefactor == 0.5) {
238  return pixd = pixScaleToGray2(pixs);
239  } else if (scalefactor > 0.33333) { /* see note (5) */
240  mag = 3.0 * scalefactor; /* will be < 1.5 */
241 /* lept_stderr("3x with mag %7.3f\n", mag); */
242  if ((pixt = pixScaleBinary(pixs, mag, mag)) == NULL)
243  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
244  pixd = pixScaleToGray3(pixt);
245  } else if (scalefactor > 0.25) { /* see note (5) */
246  mag = 4.0 * scalefactor; /* will be < 1.3333 */
247 /* lept_stderr("4x with mag %7.3f\n", mag); */
248  if ((pixt = pixScaleBinary(pixs, mag, mag)) == NULL)
249  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
250  pixd = pixScaleToGray4(pixt);
251  } else if (scalefactor == 0.25) {
252  return pixd = pixScaleToGray4(pixs);
253  } else if (scalefactor > 0.16667) { /* see note (5) */
254  mag = 6.0 * scalefactor; /* will be < 1.5 */
255 /* lept_stderr("6x with mag %7.3f\n", mag); */
256  if ((pixt = pixScaleBinary(pixs, mag, mag)) == NULL)
257  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
258  pixd = pixScaleToGray6(pixt);
259  } else if (scalefactor == 0.16667) {
260  return pixd = pixScaleToGray6(pixs);
261  } else if (scalefactor > 0.125) { /* see note (5) */
262  mag = 8.0 * scalefactor; /* will be < 1.3333 */
263 /* lept_stderr("8x with mag %7.3f\n", mag); */
264  if ((pixt = pixScaleBinary(pixs, mag, mag)) == NULL)
265  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
266  pixd = pixScaleToGray8(pixt);
267  } else if (scalefactor == 0.125) {
268  return pixd = pixScaleToGray8(pixs);
269  } else if (scalefactor > 0.0625) { /* see note (6) */
270  red = 8.0 * scalefactor; /* will be > 0.5 */
271 /* lept_stderr("8x with red %7.3f\n", red); */
272  if ((pixt = pixScaleBinary(pixs, red, red)) == NULL)
273  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
274  pixd = pixScaleToGray8(pixt);
275  } else if (scalefactor == 0.0625) {
276  return pixd = pixScaleToGray16(pixs);
277  } else { /* see note (7) */
278  red = 16.0 * scalefactor; /* will be <= 1.0 */
279 /* lept_stderr("16x with red %7.3f\n", red); */
280  if ((pixt = pixScaleToGray16(pixs)) == NULL)
281  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
282  if (red < 0.7)
283  pixd = pixScaleSmooth(pixt, red, red); /* see note (3) */
284  else
285  pixd = pixScaleGrayLI(pixt, red, red); /* see note (2) */
286  }
287 
288  pixDestroy(&pixt);
289  if (!pixd)
290  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
291  pixCopyInputFormat(pixd, pixs);
292  return pixd;
293 }
294 
295 
318 PIX *
320  l_float32 scalefactor)
321 {
322 l_int32 w, h, minsrc, mindest;
323 l_float32 eps, factor;
324 PIX *pixt, *pixd;
325 
326  PROCNAME("pixScaleToGrayFast");
327 
328  if (!pixs)
329  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
330  if (pixGetDepth(pixs) != 1)
331  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
332  if (scalefactor <= 0.0)
333  return (PIX *)ERROR_PTR("scalefactor <= 0.0", procName, NULL);
334  if (scalefactor >= 1.0)
335  return (PIX *)ERROR_PTR("scalefactor >= 1.0", procName, NULL);
336  pixGetDimensions(pixs, &w, &h, NULL);
337  minsrc = L_MIN(w, h);
338  mindest = (l_int32)((l_float32)minsrc * scalefactor);
339  if (mindest < 2)
340  return (PIX *)ERROR_PTR("scalefactor too small", procName, NULL);
341  eps = 0.0001;
342 
343  /* Handle the special cases */
344  if (scalefactor > 0.5 - eps && scalefactor < 0.5 + eps)
345  return pixScaleToGray2(pixs);
346  else if (scalefactor > 0.33333 - eps && scalefactor < 0.33333 + eps)
347  return pixScaleToGray3(pixs);
348  else if (scalefactor > 0.25 - eps && scalefactor < 0.25 + eps)
349  return pixScaleToGray4(pixs);
350  else if (scalefactor > 0.16666 - eps && scalefactor < 0.16666 + eps)
351  return pixScaleToGray6(pixs);
352  else if (scalefactor > 0.125 - eps && scalefactor < 0.125 + eps)
353  return pixScaleToGray8(pixs);
354  else if (scalefactor > 0.0625 - eps && scalefactor < 0.0625 + eps)
355  return pixScaleToGray16(pixs);
356 
357  if (scalefactor > 0.0625) { /* scale binary first */
358  factor = 2.0 * scalefactor;
359  if ((pixt = pixScaleBinary(pixs, factor, factor)) == NULL)
360  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
361  pixd = pixScaleToGray2(pixt);
362  } else { /* scalefactor < 0.0625; scale-to-gray first */
363  factor = 16.0 * scalefactor; /* will be < 1.0 */
364  if ((pixt = pixScaleToGray16(pixs)) == NULL)
365  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
366  if (factor < 0.7)
367  pixd = pixScaleSmooth(pixt, factor, factor);
368  else
369  pixd = pixScaleGrayLI(pixt, factor, factor);
370  }
371  pixDestroy(&pixt);
372  if (!pixd)
373  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
374  pixCopyInputFormat(pixd, pixs);
375  return pixd;
376 }
377 
378 
379 /*-----------------------------------------------------------------------*
380  * Scale-to-gray (1 bpp --> 8 bpp; integer downscaling) *
381  *-----------------------------------------------------------------------*/
389 PIX *
391 {
392 l_uint8 *valtab;
393 l_int32 ws, hs, wd, hd;
394 l_int32 wpld, wpls;
395 l_uint32 *sumtab;
396 l_uint32 *datas, *datad;
397 PIX *pixd;
398 
399  PROCNAME("pixScaleToGray2");
400 
401  if (!pixs)
402  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
403  if (pixGetDepth(pixs) != 1)
404  return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, NULL);
405 
406  pixGetDimensions(pixs, &ws, &hs, NULL);
407  wd = ws / 2;
408  hd = hs / 2;
409  if (wd == 0 || hd == 0)
410  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
411 
412  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
413  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
414  pixSetPadBits(pixs, 0);
415  pixCopyInputFormat(pixd, pixs);
416  pixCopyResolution(pixd, pixs);
417  pixScaleResolution(pixd, 0.5, 0.5);
418  datas = pixGetData(pixs);
419  datad = pixGetData(pixd);
420  wpls = pixGetWpl(pixs);
421  wpld = pixGetWpl(pixd);
422 
423  sumtab = makeSumTabSG2();
424  valtab = makeValTabSG2();
425  scaleToGray2Low(datad, wd, hd, wpld, datas, wpls, sumtab, valtab);
426  LEPT_FREE(sumtab);
427  LEPT_FREE(valtab);
428  return pixd;
429 }
430 
431 
447 PIX *
449 {
450 l_uint8 *valtab;
451 l_int32 ws, hs, wd, hd;
452 l_int32 wpld, wpls;
453 l_uint32 *sumtab;
454 l_uint32 *datas, *datad;
455 PIX *pixd;
456 
457  PROCNAME("pixScaleToGray3");
458 
459  if (!pixs)
460  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
461  if (pixGetDepth(pixs) != 1)
462  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
463 
464  pixGetDimensions(pixs, &ws, &hs, NULL);
465  wd = (ws / 3) & 0xfffffff8; /* truncate to factor of 8 */
466  hd = hs / 3;
467  if (wd == 0 || hd == 0)
468  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
469 
470  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
471  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
472  pixCopyInputFormat(pixd, pixs);
473  pixCopyResolution(pixd, pixs);
474  pixScaleResolution(pixd, 0.33333, 0.33333);
475  datas = pixGetData(pixs);
476  datad = pixGetData(pixd);
477  wpls = pixGetWpl(pixs);
478  wpld = pixGetWpl(pixd);
479 
480  sumtab = makeSumTabSG3();
481  valtab = makeValTabSG3();
482  scaleToGray3Low(datad, wd, hd, wpld, datas, wpls, sumtab, valtab);
483  LEPT_FREE(sumtab);
484  LEPT_FREE(valtab);
485  return pixd;
486 }
487 
488 
501 PIX *
503 {
504 l_uint8 *valtab;
505 l_int32 ws, hs, wd, hd;
506 l_int32 wpld, wpls;
507 l_uint32 *sumtab;
508 l_uint32 *datas, *datad;
509 PIX *pixd;
510 
511  PROCNAME("pixScaleToGray4");
512 
513  if (!pixs)
514  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
515  if (pixGetDepth(pixs) != 1)
516  return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, NULL);
517 
518  pixGetDimensions(pixs, &ws, &hs, NULL);
519  wd = (ws / 4) & 0xfffffffe; /* truncate to factor of 2 */
520  hd = hs / 4;
521  if (wd == 0 || hd == 0)
522  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
523 
524  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
525  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
526  pixCopyInputFormat(pixd, pixs);
527  pixCopyResolution(pixd, pixs);
528  pixScaleResolution(pixd, 0.25, 0.25);
529  datas = pixGetData(pixs);
530  datad = pixGetData(pixd);
531  wpls = pixGetWpl(pixs);
532  wpld = pixGetWpl(pixd);
533 
534  sumtab = makeSumTabSG4();
535  valtab = makeValTabSG4();
536  scaleToGray4Low(datad, wd, hd, wpld, datas, wpls, sumtab, valtab);
537  LEPT_FREE(sumtab);
538  LEPT_FREE(valtab);
539  return pixd;
540 }
541 
542 
543 
556 PIX *
558 {
559 l_uint8 *valtab;
560 l_int32 ws, hs, wd, hd, wpld, wpls;
561 l_int32 *tab8;
562 l_uint32 *datas, *datad;
563 PIX *pixd;
564 
565  PROCNAME("pixScaleToGray6");
566 
567  if (!pixs)
568  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
569  if (pixGetDepth(pixs) != 1)
570  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
571 
572  pixGetDimensions(pixs, &ws, &hs, NULL);
573  wd = (ws / 6) & 0xfffffff8; /* truncate to factor of 8 */
574  hd = hs / 6;
575  if (wd == 0 || hd == 0)
576  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
577 
578  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
579  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
580  pixCopyInputFormat(pixd, pixs);
581  pixCopyResolution(pixd, pixs);
582  pixScaleResolution(pixd, 0.16667, 0.16667);
583  datas = pixGetData(pixs);
584  datad = pixGetData(pixd);
585  wpls = pixGetWpl(pixs);
586  wpld = pixGetWpl(pixd);
587 
588  tab8 = makePixelSumTab8();
589  valtab = makeValTabSG6();
590  scaleToGray6Low(datad, wd, hd, wpld, datas, wpls, tab8, valtab);
591  LEPT_FREE(tab8);
592  LEPT_FREE(valtab);
593  return pixd;
594 }
595 
596 
604 PIX *
606 {
607 l_uint8 *valtab;
608 l_int32 ws, hs, wd, hd;
609 l_int32 wpld, wpls;
610 l_int32 *tab8;
611 l_uint32 *datas, *datad;
612 PIX *pixd;
613 
614  PROCNAME("pixScaleToGray8");
615 
616  if (!pixs)
617  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
618  if (pixGetDepth(pixs) != 1)
619  return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, NULL);
620 
621  pixGetDimensions(pixs, &ws, &hs, NULL);
622  wd = ws / 8; /* truncate to nearest dest byte */
623  hd = hs / 8;
624  if (wd == 0 || hd == 0)
625  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
626 
627  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
628  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
629  pixCopyInputFormat(pixd, pixs);
630  pixCopyResolution(pixd, pixs);
631  pixScaleResolution(pixd, 0.125, 0.125);
632  datas = pixGetData(pixs);
633  datad = pixGetData(pixd);
634  wpls = pixGetWpl(pixs);
635  wpld = pixGetWpl(pixd);
636 
637  tab8 = makePixelSumTab8();
638  valtab = makeValTabSG8();
639  scaleToGray8Low(datad, wd, hd, wpld, datas, wpls, tab8, valtab);
640  LEPT_FREE(tab8);
641  LEPT_FREE(valtab);
642  return pixd;
643 }
644 
645 
653 PIX *
655 {
656 l_int32 ws, hs, wd, hd;
657 l_int32 wpld, wpls;
658 l_int32 *tab8;
659 l_uint32 *datas, *datad;
660 PIX *pixd;
661 
662  PROCNAME("pixScaleToGray16");
663 
664  if (!pixs)
665  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
666  if (pixGetDepth(pixs) != 1)
667  return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, NULL);
668 
669  pixGetDimensions(pixs, &ws, &hs, NULL);
670  wd = ws / 16;
671  hd = hs / 16;
672  if (wd == 0 || hd == 0)
673  return (PIX *)ERROR_PTR("pixs too small", procName, NULL);
674 
675  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
676  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
677  pixCopyInputFormat(pixd, pixs);
678  pixCopyResolution(pixd, pixs);
679  pixScaleResolution(pixd, 0.0625, 0.0625);
680  datas = pixGetData(pixs);
681  datad = pixGetData(pixd);
682  wpls = pixGetWpl(pixs);
683  wpld = pixGetWpl(pixd);
684 
685  tab8 = makePixelSumTab8();
686  scaleToGray16Low(datad, wd, hd, wpld, datas, wpls, tab8);
687  LEPT_FREE(tab8);
688  return pixd;
689 }
690 
691 
692 /*------------------------------------------------------------------*
693  * Scale-to-gray mipmap(1 bpp --> 8 bpp, arbitrary reduction) *
694  *------------------------------------------------------------------*/
726 PIX *
728  l_float32 scalefactor)
729 {
730 l_int32 w, h, minsrc, mindest;
731 l_float32 red;
732 PIX *pixs1, *pixs2, *pixt, *pixd;
733 
734  PROCNAME("pixScaleToGrayMipmap");
735 
736  if (!pixs)
737  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
738  if (pixGetDepth(pixs) != 1)
739  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
740  if (scalefactor <= 0.0)
741  return (PIX *)ERROR_PTR("scalefactor <= 0.0", procName, NULL);
742  if (scalefactor >= 1.0)
743  return (PIX *)ERROR_PTR("scalefactor >= 1.0", procName, NULL);
744  pixGetDimensions(pixs, &w, &h, NULL);
745  minsrc = L_MIN(w, h);
746  mindest = (l_int32)((l_float32)minsrc * scalefactor);
747  if (mindest < 2)
748  return (PIX *)ERROR_PTR("scalefactor too small", procName, NULL);
749 
750  if (scalefactor > 0.5) {
751  pixs1 = pixConvert1To8(NULL, pixs, 255, 0);
752  pixs2 = pixScaleToGray2(pixs);
753  red = scalefactor;
754  } else if (scalefactor == 0.5) {
755  return pixScaleToGray2(pixs);
756  } else if (scalefactor > 0.25) {
757  pixs1 = pixScaleToGray2(pixs);
758  pixs2 = pixScaleToGray4(pixs);
759  red = 2. * scalefactor;
760  } else if (scalefactor == 0.25) {
761  return pixScaleToGray4(pixs);
762  } else if (scalefactor > 0.125) {
763  pixs1 = pixScaleToGray4(pixs);
764  pixs2 = pixScaleToGray8(pixs);
765  red = 4. * scalefactor;
766  } else if (scalefactor == 0.125) {
767  return pixScaleToGray8(pixs);
768  } else if (scalefactor > 0.0625) {
769  pixs1 = pixScaleToGray8(pixs);
770  pixs2 = pixScaleToGray16(pixs);
771  red = 8. * scalefactor;
772  } else if (scalefactor == 0.0625) {
773  return pixScaleToGray16(pixs);
774  } else { /* end of the pyramid; just do it */
775  red = 16.0 * scalefactor; /* will be <= 1.0 */
776  if ((pixt = pixScaleToGray16(pixs)) == NULL)
777  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
778  if (red < 0.7)
779  pixd = pixScaleSmooth(pixt, red, red);
780  else
781  pixd = pixScaleGrayLI(pixt, red, red);
782  pixDestroy(&pixt);
783  return pixd;
784  }
785 
786  pixd = pixScaleMipmap(pixs1, pixs2, red);
787  pixCopyInputFormat(pixd, pixs);
788 
789  pixDestroy(&pixs1);
790  pixDestroy(&pixs2);
791  return pixd;
792 }
793 
794 
795 /*------------------------------------------------------------------*
796  * Grayscale scaling using mipmap *
797  *------------------------------------------------------------------*/
814 PIX *
816  PIX *pixs2,
817  l_float32 scale)
818 {
819 l_int32 ws1, hs1, ws2, hs2, wd, hd, wpls1, wpls2, wpld;
820 l_uint32 *datas1, *datas2, *datad;
821 PIX *pixd;
822 
823  PROCNAME("pixScaleMipmap");
824 
825  if (!pixs1 || pixGetDepth(pixs1) != 8 || pixGetColormap(pixs1))
826  return (PIX *)ERROR_PTR("pixs1 underdefined, not 8 bpp, or cmapped",
827  procName, NULL);
828  if (!pixs2 || pixGetDepth(pixs2) != 8 || pixGetColormap(pixs2))
829  return (PIX *)ERROR_PTR("pixs2 underdefined, not 8 bpp, or cmapped",
830  procName, NULL);
831  pixGetDimensions(pixs1, &ws1, &hs1, NULL);
832  pixGetDimensions(pixs2, &ws2, &hs2, NULL);
833  if (scale > 1.0 || scale < 0.5)
834  return (PIX *)ERROR_PTR("scale not in [0.5, 1.0]", procName, NULL);
835  if (ws1 < 2 * ws2)
836  return (PIX *)ERROR_PTR("invalid width ratio", procName, NULL);
837  if (hs1 < 2 * hs2)
838  return (PIX *)ERROR_PTR("invalid height ratio", procName, NULL);
839 
840  /* Generate wd and hd from the lower resolution dimensions,
841  * to guarantee staying within both src images */
842  datas1 = pixGetData(pixs1);
843  wpls1 = pixGetWpl(pixs1);
844  datas2 = pixGetData(pixs2);
845  wpls2 = pixGetWpl(pixs2);
846  wd = (l_int32)(2. * scale * pixGetWidth(pixs2));
847  hd = (l_int32)(2. * scale * pixGetHeight(pixs2));
848  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
849  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
850  pixCopyInputFormat(pixd, pixs1);
851  pixCopyResolution(pixd, pixs1);
852  pixScaleResolution(pixd, scale, scale);
853  datad = pixGetData(pixd);
854  wpld = pixGetWpl(pixd);
855 
856  scaleMipmapLow(datad, wd, hd, wpld, datas1, wpls1, datas2, wpls2, scale);
857  return pixd;
858 }
859 
860 
861 /*------------------------------------------------------------------*
862  * Replicated (integer) expansion *
863  *------------------------------------------------------------------*/
871 PIX *
873  l_int32 factor)
874 {
875 l_int32 w, h, d, wd, hd, wpls, wpld, start, i, j, k;
876 l_uint8 sval;
877 l_uint16 sval16;
878 l_uint32 sval32;
879 l_uint32 *lines, *datas, *lined, *datad;
880 PIX *pixd;
881 
882  PROCNAME("pixExpandReplicate");
883 
884  if (!pixs)
885  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
886  pixGetDimensions(pixs, &w, &h, &d);
887  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
888  return (PIX *)ERROR_PTR("depth not in {1,2,4,8,16,32}", procName, NULL);
889  if (factor <= 0)
890  return (PIX *)ERROR_PTR("factor <= 0; invalid", procName, NULL);
891  if (factor == 1)
892  return pixCopy(NULL, pixs);
893 
894  if (d == 1)
895  return pixExpandBinaryReplicate(pixs, factor, factor);
896 
897  wd = factor * w;
898  hd = factor * h;
899  if ((pixd = pixCreate(wd, hd, d)) == NULL)
900  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
901  pixCopyColormap(pixd, pixs);
902  pixCopyInputFormat(pixd, pixs);
903  pixCopyResolution(pixd, pixs);
904  pixScaleResolution(pixd, (l_float32)factor, (l_float32)factor);
905  datas = pixGetData(pixs);
906  wpls = pixGetWpl(pixs);
907  datad = pixGetData(pixd);
908  wpld = pixGetWpl(pixd);
909 
910  switch (d) {
911  case 2:
912  for (i = 0; i < h; i++) {
913  lines = datas + i * wpls;
914  lined = datad + factor * i * wpld;
915  for (j = 0; j < w; j++) {
916  sval = GET_DATA_DIBIT(lines, j);
917  start = factor * j;
918  for (k = 0; k < factor; k++)
919  SET_DATA_DIBIT(lined, start + k, sval);
920  }
921  for (k = 1; k < factor; k++)
922  memcpy(lined + k * wpld, lined, 4 * wpld);
923  }
924  break;
925  case 4:
926  for (i = 0; i < h; i++) {
927  lines = datas + i * wpls;
928  lined = datad + factor * i * wpld;
929  for (j = 0; j < w; j++) {
930  sval = GET_DATA_QBIT(lines, j);
931  start = factor * j;
932  for (k = 0; k < factor; k++)
933  SET_DATA_QBIT(lined, start + k, sval);
934  }
935  for (k = 1; k < factor; k++)
936  memcpy(lined + k * wpld, lined, 4 * wpld);
937  }
938  break;
939  case 8:
940  for (i = 0; i < h; i++) {
941  lines = datas + i * wpls;
942  lined = datad + factor * i * wpld;
943  for (j = 0; j < w; j++) {
944  sval = GET_DATA_BYTE(lines, j);
945  start = factor * j;
946  for (k = 0; k < factor; k++)
947  SET_DATA_BYTE(lined, start + k, sval);
948  }
949  for (k = 1; k < factor; k++)
950  memcpy(lined + k * wpld, lined, 4 * wpld);
951  }
952  break;
953  case 16:
954  for (i = 0; i < h; i++) {
955  lines = datas + i * wpls;
956  lined = datad + factor * i * wpld;
957  for (j = 0; j < w; j++) {
958  sval16 = GET_DATA_TWO_BYTES(lines, j);
959  start = factor * j;
960  for (k = 0; k < factor; k++)
961  SET_DATA_TWO_BYTES(lined, start + k, sval16);
962  }
963  for (k = 1; k < factor; k++)
964  memcpy(lined + k * wpld, lined, 4 * wpld);
965  }
966  break;
967  case 32:
968  for (i = 0; i < h; i++) {
969  lines = datas + i * wpls;
970  lined = datad + factor * i * wpld;
971  for (j = 0; j < w; j++) {
972  sval32 = *(lines + j);
973  start = factor * j;
974  for (k = 0; k < factor; k++)
975  *(lined + start + k) = sval32;
976  }
977  for (k = 1; k < factor; k++)
978  memcpy(lined + k * wpld, lined, 4 * wpld);
979  }
980  break;
981  default:
982  lept_stderr("invalid depth\n");
983  }
984 
985  if (d == 32 && pixGetSpp(pixs) == 4)
986  pixScaleAndTransferAlpha(pixd, pixs, (l_float32)factor,
987  (l_float32)factor);
988  return pixd;
989 }
990 
991 
992 /*-----------------------------------------------------------------------*
993  * Downscaling using min or max *
994  *-----------------------------------------------------------------------*/
1018 PIX *
1020  l_int32 xfact,
1021  l_int32 yfact,
1022  l_int32 type)
1023 {
1024 l_int32 ws, hs, wd, hd, wpls, wpld, i, j, k, m;
1025 l_int32 minval, maxval, val;
1026 l_uint32 *datas, *datad, *lines, *lined;
1027 PIX *pixd;
1028 
1029  PROCNAME("pixScaleGrayMinMax");
1030 
1031  if (!pixs || pixGetDepth(pixs) != 8 || pixGetColormap(pixs))
1032  return (PIX *)ERROR_PTR("pixs undefined, not 8 bpp, or cmapped",
1033  procName, NULL);
1034  pixGetDimensions(pixs, &ws, &hs, NULL);
1035  if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX &&
1036  type != L_CHOOSE_MAXDIFF)
1037  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1038  if (xfact < 1 || yfact < 1)
1039  return (PIX *)ERROR_PTR("xfact and yfact must be >= 1", procName, NULL);
1040 
1041  if (xfact == 2 && yfact == 2)
1042  return pixScaleGrayMinMax2(pixs, type);
1043 
1044  wd = ws / xfact;
1045  if (wd == 0) { /* single tile */
1046  wd = 1;
1047  xfact = ws;
1048  }
1049  hd = hs / yfact;
1050  if (hd == 0) { /* single tile */
1051  hd = 1;
1052  yfact = hs;
1053  }
1054  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
1055  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1056  pixCopyInputFormat(pixd, pixs);
1057  datas = pixGetData(pixs);
1058  datad = pixGetData(pixd);
1059  wpls = pixGetWpl(pixs);
1060  wpld = pixGetWpl(pixd);
1061  for (i = 0; i < hd; i++) {
1062  lined = datad + i * wpld;
1063  for (j = 0; j < wd; j++) {
1064  if (type == L_CHOOSE_MIN || type == L_CHOOSE_MAXDIFF) {
1065  minval = 255;
1066  for (k = 0; k < yfact; k++) {
1067  lines = datas + (yfact * i + k) * wpls;
1068  for (m = 0; m < xfact; m++) {
1069  val = GET_DATA_BYTE(lines, xfact * j + m);
1070  if (val < minval)
1071  minval = val;
1072  }
1073  }
1074  }
1075  if (type == L_CHOOSE_MAX || type == L_CHOOSE_MAXDIFF) {
1076  maxval = 0;
1077  for (k = 0; k < yfact; k++) {
1078  lines = datas + (yfact * i + k) * wpls;
1079  for (m = 0; m < xfact; m++) {
1080  val = GET_DATA_BYTE(lines, xfact * j + m);
1081  if (val > maxval)
1082  maxval = val;
1083  }
1084  }
1085  }
1086  if (type == L_CHOOSE_MIN)
1087  SET_DATA_BYTE(lined, j, minval);
1088  else if (type == L_CHOOSE_MAX)
1089  SET_DATA_BYTE(lined, j, maxval);
1090  else /* type == L_CHOOSE_MAXDIFF */
1091  SET_DATA_BYTE(lined, j, maxval - minval);
1092  }
1093  }
1094 
1095  return pixd;
1096 }
1097 
1098 
1125 PIX *
1127  l_int32 type)
1128 {
1129 l_int32 ws, hs, wd, hd, wpls, wpld, i, j, k;
1130 l_int32 minval, maxval;
1131 l_int32 val[4];
1132 l_uint32 *datas, *datad, *lines, *lined;
1133 PIX *pixd;
1134 
1135  PROCNAME("pixScaleGrayMinMax2");
1136 
1137  if (!pixs || pixGetDepth(pixs) != 8 || pixGetColormap(pixs))
1138  return (PIX *)ERROR_PTR("pixs undefined, not 8 bpp, or cmapped",
1139  procName, NULL);
1140  pixGetDimensions(pixs, &ws, &hs, NULL);
1141  if (ws < 2 || hs < 2)
1142  return (PIX *)ERROR_PTR("too small: ws < 2 or hs < 2", procName, NULL);
1143  if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX &&
1144  type != L_CHOOSE_MAXDIFF)
1145  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1146 
1147  wd = ws / 2;
1148  hd = hs / 2;
1149  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
1150  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1151  pixCopyInputFormat(pixd, pixs);
1152  datas = pixGetData(pixs);
1153  datad = pixGetData(pixd);
1154  wpls = pixGetWpl(pixs);
1155  wpld = pixGetWpl(pixd);
1156  for (i = 0; i < hd; i++) {
1157  lines = datas + 2 * i * wpls;
1158  lined = datad + i * wpld;
1159  for (j = 0; j < wd; j++) {
1160  val[0] = GET_DATA_BYTE(lines, 2 * j);
1161  val[1] = GET_DATA_BYTE(lines, 2 * j + 1);
1162  val[2] = GET_DATA_BYTE(lines + wpls, 2 * j);
1163  val[3] = GET_DATA_BYTE(lines + wpls, 2 * j + 1);
1164  if (type == L_CHOOSE_MIN || type == L_CHOOSE_MAXDIFF) {
1165  minval = 255;
1166  for (k = 0; k < 4; k++) {
1167  if (val[k] < minval)
1168  minval = val[k];
1169  }
1170  }
1171  if (type == L_CHOOSE_MAX || type == L_CHOOSE_MAXDIFF) {
1172  maxval = 0;
1173  for (k = 0; k < 4; k++) {
1174  if (val[k] > maxval)
1175  maxval = val[k];
1176  }
1177  }
1178  if (type == L_CHOOSE_MIN)
1179  SET_DATA_BYTE(lined, j, minval);
1180  else if (type == L_CHOOSE_MAX)
1181  SET_DATA_BYTE(lined, j, maxval);
1182  else /* type == L_CHOOSE_MAXDIFF */
1183  SET_DATA_BYTE(lined, j, maxval - minval);
1184  }
1185  }
1186 
1187  return pixd;
1188 }
1189 
1190 
1191 /*-----------------------------------------------------------------------*
1192  * Grayscale downscaling using rank value *
1193  *-----------------------------------------------------------------------*/
1208 PIX *
1210  l_int32 level1,
1211  l_int32 level2,
1212  l_int32 level3,
1213  l_int32 level4)
1214 {
1215 PIX *pixt1, *pixt2, *pixt3, *pixt4;
1216 
1217  PROCNAME("pixScaleGrayRankCascade");
1218 
1219  if (!pixs || pixGetDepth(pixs) != 8 || pixGetColormap(pixs))
1220  return (PIX *)ERROR_PTR("pixs undefined, not 8 bpp, or cmapped",
1221  procName, NULL);
1222  if (level1 > 4 || level2 > 4 || level3 > 4 || level4 > 4)
1223  return (PIX *)ERROR_PTR("levels must not exceed 4", procName, NULL);
1224 
1225  if (level1 <= 0) {
1226  L_WARNING("no reduction because level1 not > 0\n", procName);
1227  return pixCopy(NULL, pixs);
1228  }
1229 
1230  pixt1 = pixScaleGrayRank2(pixs, level1);
1231  if (level2 <= 0)
1232  return pixt1;
1233 
1234  pixt2 = pixScaleGrayRank2(pixt1, level2);
1235  pixDestroy(&pixt1);
1236  if (level3 <= 0)
1237  return pixt2;
1238 
1239  pixt3 = pixScaleGrayRank2(pixt2, level3);
1240  pixDestroy(&pixt2);
1241  if (level4 <= 0)
1242  return pixt3;
1243 
1244  pixt4 = pixScaleGrayRank2(pixt3, level4);
1245  pixDestroy(&pixt3);
1246  return pixt4;
1247 }
1248 
1249 
1272 PIX *
1274  l_int32 rank)
1275 {
1276 l_int32 ws, hs, wd, hd, wpls, wpld, i, j, k, m;
1277 l_int32 minval, maxval, rankval, minindex, maxindex;
1278 l_int32 val[4];
1279 l_int32 midval[4]; /* should only use 2 of these */
1280 l_uint32 *datas, *datad, *lines, *lined;
1281 PIX *pixd;
1282 
1283  PROCNAME("pixScaleGrayRank2");
1284 
1285  if (!pixs || pixGetDepth(pixs) != 8 || pixGetColormap(pixs))
1286  return (PIX *)ERROR_PTR("pixs undefined, not 8 bpp, or cmapped",
1287  procName, NULL);
1288  if (rank < 1 || rank > 4)
1289  return (PIX *)ERROR_PTR("invalid rank", procName, NULL);
1290 
1291  if (rank == 1)
1292  return pixScaleGrayMinMax2(pixs, L_CHOOSE_MIN);
1293  if (rank == 4)
1294  return pixScaleGrayMinMax2(pixs, L_CHOOSE_MAX);
1295 
1296  pixGetDimensions(pixs, &ws, &hs, NULL);
1297  wd = ws / 2;
1298  hd = hs / 2;
1299  if ((pixd = pixCreate(wd, hd, 8)) == NULL)
1300  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1301  pixCopyInputFormat(pixd, pixs);
1302  datas = pixGetData(pixs);
1303  datad = pixGetData(pixd);
1304  wpls = pixGetWpl(pixs);
1305  wpld = pixGetWpl(pixd);
1306  for (i = 0; i < hd; i++) {
1307  lines = datas + 2 * i * wpls;
1308  lined = datad + i * wpld;
1309  for (j = 0; j < wd; j++) {
1310  val[0] = GET_DATA_BYTE(lines, 2 * j);
1311  val[1] = GET_DATA_BYTE(lines, 2 * j + 1);
1312  val[2] = GET_DATA_BYTE(lines + wpls, 2 * j);
1313  val[3] = GET_DATA_BYTE(lines + wpls, 2 * j + 1);
1314  minval = maxval = val[0];
1315  minindex = maxindex = 0;
1316  for (k = 1; k < 4; k++) {
1317  if (val[k] < minval) {
1318  minval = val[k];
1319  minindex = k;
1320  continue;
1321  }
1322  if (val[k] > maxval) {
1323  maxval = val[k];
1324  maxindex = k;
1325  }
1326  }
1327  for (k = 0, m = 0; k < 4; k++) {
1328  if (k == minindex || k == maxindex)
1329  continue;
1330  midval[m++] = val[k];
1331  }
1332  if (m > 2) /* minval == maxval; all val[k] are the same */
1333  rankval = minval;
1334  else if (rank == 2)
1335  rankval = L_MIN(midval[0], midval[1]);
1336  else /* rank == 3 */
1337  rankval = L_MAX(midval[0], midval[1]);
1338  SET_DATA_BYTE(lined, j, rankval);
1339  }
1340  }
1341 
1342  return pixd;
1343 }
1344 
1345 
1346 /*------------------------------------------------------------------------*
1347  * Helper function for transferring alpha with scaling *
1348  *------------------------------------------------------------------------*/
1363 l_ok
1365  PIX *pixs,
1366  l_float32 scalex,
1367  l_float32 scaley)
1368 {
1369 PIX *pix1, *pix2;
1370 
1371  PROCNAME("pixScaleAndTransferAlpha");
1372 
1373  if (!pixs || !pixd)
1374  return ERROR_INT("pixs and pixd not both defined", procName, 1);
1375  if (pixGetDepth(pixs) != 32 || pixGetSpp(pixs) != 4)
1376  return ERROR_INT("pixs not 32 bpp and 4 spp", procName, 1);
1377  if (pixGetDepth(pixd) != 32)
1378  return ERROR_INT("pixd not 32 bpp", procName, 1);
1379 
1380  if (scalex == 1.0 && scaley == 1.0) {
1381  pixCopyRGBComponent(pixd, pixs, L_ALPHA_CHANNEL);
1382  return 0;
1383  }
1384 
1385  pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
1386  pix2 = pixScale(pix1, scalex, scaley);
1387  pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
1388  pixDestroy(&pix1);
1389  pixDestroy(&pix2);
1390  return 0;
1391 }
1392 
1393 
1394 /*------------------------------------------------------------------------*
1395  * RGB scaling including alpha (blend) component and gamma transform *
1396  *------------------------------------------------------------------------*/
1442 PIX *
1444  l_float32 scalex,
1445  l_float32 scaley,
1446  PIX *pixg,
1447  l_float32 fract)
1448 {
1449 l_int32 ws, hs, d, spp;
1450 PIX *pixd, *pix32, *pixg2, *pixgs;
1451 
1452  PROCNAME("pixScaleWithAlpha");
1453 
1454  if (!pixs)
1455  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1456  pixGetDimensions(pixs, &ws, &hs, &d);
1457  if (d != 32 && !pixGetColormap(pixs))
1458  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
1459  if (scalex <= 0.0 || scaley <= 0.0)
1460  return (PIX *)ERROR_PTR("scale factor <= 0.0", procName, NULL);
1461  if (pixg && pixGetDepth(pixg) != 8) {
1462  L_WARNING("pixg not 8 bpp; using 'fract' transparent alpha\n",
1463  procName);
1464  pixg = NULL;
1465  }
1466  if (!pixg && (fract < 0.0 || fract > 1.0)) {
1467  L_WARNING("invalid fract; using fully opaque\n", procName);
1468  fract = 1.0;
1469  }
1470  if (!pixg && fract == 0.0)
1471  L_WARNING("transparent alpha; image will not be blended\n", procName);
1472 
1473  /* Make sure input to scaling is 32 bpp rgb, and scale it */
1474  if (d != 32)
1475  pix32 = pixConvertTo32(pixs);
1476  else
1477  pix32 = pixClone(pixs);
1478  spp = pixGetSpp(pix32);
1479  pixSetSpp(pix32, 3); /* ignore the alpha channel for scaling */
1480  pixd = pixScale(pix32, scalex, scaley);
1481  pixSetSpp(pix32, spp); /* restore initial value in case it's a clone */
1482  pixDestroy(&pix32);
1483 
1484  /* Set up alpha layer with a fading border and scale it */
1485  if (!pixg) {
1486  pixg2 = pixCreate(ws, hs, 8);
1487  if (fract == 1.0)
1488  pixSetAll(pixg2);
1489  else if (fract > 0.0)
1490  pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
1491  } else {
1492  pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
1493  }
1494  if (ws > 10 && hs > 10) { /* see note 4 */
1495  pixSetBorderRingVal(pixg2, 1,
1496  (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
1497  pixSetBorderRingVal(pixg2, 2,
1498  (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));
1499  }
1500  pixgs = pixScaleGeneral(pixg2, scalex, scaley, 0.0, 0);
1501 
1502  /* Combine into a 4 spp result */
1503  pixSetRGBComponent(pixd, pixgs, L_ALPHA_CHANNEL);
1504  pixCopyInputFormat(pixd, pixs);
1505 
1506  pixDestroy(&pixg2);
1507  pixDestroy(&pixgs);
1508  return pixd;
1509 }
1510 
1511 
1512 /* ================================================================ *
1513  * Low level static functions *
1514  * ================================================================ */
1515 
1516 /*------------------------------------------------------------------*
1517  * Scale-to-gray 2x *
1518  *------------------------------------------------------------------*/
1544 static void
1545 scaleToGray2Low(l_uint32 *datad,
1546  l_int32 wd,
1547  l_int32 hd,
1548  l_int32 wpld,
1549  l_uint32 *datas,
1550  l_int32 wpls,
1551  l_uint32 *sumtab,
1552  l_uint8 *valtab)
1553 {
1554 l_int32 i, j, l, k, m, wd4, extra;
1555 l_uint32 sbyte1, sbyte2, sum;
1556 l_uint32 *lines, *lined;
1557 
1558  /* i indexes the dest lines
1559  * l indexes the source lines
1560  * j indexes the dest bytes
1561  * k indexes the source bytes
1562  * We take two bytes from the source (in 2 lines of 8 pixels
1563  * each) and convert them into four 8 bpp bytes of the dest. */
1564  wd4 = wd & 0xfffffffc;
1565  extra = wd - wd4;
1566  for (i = 0, l = 0; i < hd; i++, l += 2) {
1567  lines = datas + l * wpls;
1568  lined = datad + i * wpld;
1569  for (j = 0, k = 0; j < wd4; j += 4, k++) {
1570  sbyte1 = GET_DATA_BYTE(lines, k);
1571  sbyte2 = GET_DATA_BYTE(lines + wpls, k);
1572  sum = sumtab[sbyte1] + sumtab[sbyte2];
1573  SET_DATA_BYTE(lined, j, valtab[sum >> 24]);
1574  SET_DATA_BYTE(lined, j + 1, valtab[(sum >> 16) & 0xff]);
1575  SET_DATA_BYTE(lined, j + 2, valtab[(sum >> 8) & 0xff]);
1576  SET_DATA_BYTE(lined, j + 3, valtab[sum & 0xff]);
1577  }
1578  if (extra > 0) {
1579  sbyte1 = GET_DATA_BYTE(lines, k);
1580  sbyte2 = GET_DATA_BYTE(lines + wpls, k);
1581  sum = sumtab[sbyte1] + sumtab[sbyte2];
1582  for (m = 0; m < extra; m++) {
1583  SET_DATA_BYTE(lined, j + m,
1584  valtab[((sum >> (24 - 8 * m)) & 0xff)]);
1585  }
1586  }
1587 
1588  }
1589 }
1590 
1591 
1604 static l_uint32 *
1606 {
1607 l_int32 i;
1608 l_int32 sum[] = {0, 1, 1, 2};
1609 l_uint32 *tab;
1610 
1611  PROCNAME("makeSumTabSG2");
1612 
1613  /* Pack the four sums separately in four bytes */
1614  tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
1615  for (i = 0; i < 256; i++) {
1616  tab[i] = (sum[i & 0x3] | sum[(i >> 2) & 0x3] << 8 |
1617  sum[(i >> 4) & 0x3] << 16 | sum[(i >> 6) & 0x3] << 24);
1618  }
1619  return tab;
1620 }
1621 
1622 
1634 static l_uint8 *
1636 {
1637 l_int32 i;
1638 l_uint8 *tab;
1639 
1640  PROCNAME("makeValTabSG2");
1641 
1642  tab = (l_uint8 *)LEPT_CALLOC(5, sizeof(l_uint8));
1643  for (i = 0; i < 5; i++)
1644  tab[i] = 255 - (i * 255) / 4;
1645  return tab;
1646 }
1647 
1648 
1649 /*------------------------------------------------------------------*
1650  * Scale-to-gray 3x *
1651  *------------------------------------------------------------------*/
1686 static void
1687 scaleToGray3Low(l_uint32 *datad,
1688  l_int32 wd,
1689  l_int32 hd,
1690  l_int32 wpld,
1691  l_uint32 *datas,
1692  l_int32 wpls,
1693  l_uint32 *sumtab,
1694  l_uint8 *valtab)
1695 {
1696 l_int32 i, j, l, k;
1697 l_uint32 threebytes1, threebytes2, threebytes3, sum;
1698 l_uint32 *lines, *lined;
1699 
1700  /* i indexes the dest lines
1701  * l indexes the source lines
1702  * j indexes the dest bytes
1703  * k indexes the source bytes
1704  * We take 9 bytes from the source (72 binary pixels
1705  * in three lines of 24 pixels each) and convert it
1706  * into 8 bytes of the dest (8 8bpp pixels in one line) */
1707  for (i = 0, l = 0; i < hd; i++, l += 3) {
1708  lines = datas + l * wpls;
1709  lined = datad + i * wpld;
1710  for (j = 0, k = 0; j < wd; j += 8, k += 3) {
1711  threebytes1 = (GET_DATA_BYTE(lines, k) << 16) |
1712  (GET_DATA_BYTE(lines, k + 1) << 8) |
1713  GET_DATA_BYTE(lines, k + 2);
1714  threebytes2 = (GET_DATA_BYTE(lines + wpls, k) << 16) |
1715  (GET_DATA_BYTE(lines + wpls, k + 1) << 8) |
1716  GET_DATA_BYTE(lines + wpls, k + 2);
1717  threebytes3 = (GET_DATA_BYTE(lines + 2 * wpls, k) << 16) |
1718  (GET_DATA_BYTE(lines + 2 * wpls, k + 1) << 8) |
1719  GET_DATA_BYTE(lines + 2 * wpls, k + 2);
1720 
1721  sum = sumtab[(threebytes1 >> 18)] +
1722  sumtab[(threebytes2 >> 18)] +
1723  sumtab[(threebytes3 >> 18)];
1724  SET_DATA_BYTE(lined, j, valtab[GET_DATA_BYTE(&sum, 2)]);
1725  SET_DATA_BYTE(lined, j + 1, valtab[GET_DATA_BYTE(&sum, 3)]);
1726 
1727  sum = sumtab[((threebytes1 >> 12) & 0x3f)] +
1728  sumtab[((threebytes2 >> 12) & 0x3f)] +
1729  sumtab[((threebytes3 >> 12) & 0x3f)];
1730  SET_DATA_BYTE(lined, j + 2, valtab[GET_DATA_BYTE(&sum, 2)]);
1731  SET_DATA_BYTE(lined, j + 3, valtab[GET_DATA_BYTE(&sum, 3)]);
1732 
1733  sum = sumtab[((threebytes1 >> 6) & 0x3f)] +
1734  sumtab[((threebytes2 >> 6) & 0x3f)] +
1735  sumtab[((threebytes3 >> 6) & 0x3f)];
1736  SET_DATA_BYTE(lined, j + 4, valtab[GET_DATA_BYTE(&sum, 2)]);
1737  SET_DATA_BYTE(lined, j + 5, valtab[GET_DATA_BYTE(&sum, 3)]);
1738 
1739  sum = sumtab[(threebytes1 & 0x3f)] +
1740  sumtab[(threebytes2 & 0x3f)] +
1741  sumtab[(threebytes3 & 0x3f)];
1742  SET_DATA_BYTE(lined, j + 6, valtab[GET_DATA_BYTE(&sum, 2)]);
1743  SET_DATA_BYTE(lined, j + 7, valtab[GET_DATA_BYTE(&sum, 3)]);
1744  }
1745  }
1746 }
1747 
1748 
1749 
1763 static l_uint32 *
1765 {
1766 l_int32 i;
1767 l_int32 sum[] = {0, 1, 1, 2, 1, 2, 2, 3};
1768 l_uint32 *tab;
1769 
1770  PROCNAME("makeSumTabSG3");
1771 
1772  /* Pack the two sums separately in two bytes */
1773  tab = (l_uint32 *)LEPT_CALLOC(64, sizeof(l_uint32));
1774  for (i = 0; i < 64; i++) {
1775  tab[i] = (sum[i & 0x07]) | (sum[(i >> 3) & 0x07] << 8);
1776  }
1777  return tab;
1778 }
1779 
1780 
1792 static l_uint8 *
1794 {
1795 l_int32 i;
1796 l_uint8 *tab;
1797 
1798  PROCNAME("makeValTabSG3");
1799 
1800  tab = (l_uint8 *)LEPT_CALLOC(10, sizeof(l_uint8));
1801  for (i = 0; i < 10; i++)
1802  tab[i] = 0xff - (i * 255) / 9;
1803  return tab;
1804 }
1805 
1806 
1807 /*------------------------------------------------------------------*
1808  * Scale-to-gray 4x *
1809  *------------------------------------------------------------------*/
1835 static void
1836 scaleToGray4Low(l_uint32 *datad,
1837  l_int32 wd,
1838  l_int32 hd,
1839  l_int32 wpld,
1840  l_uint32 *datas,
1841  l_int32 wpls,
1842  l_uint32 *sumtab,
1843  l_uint8 *valtab)
1844 {
1845 l_int32 i, j, l, k;
1846 l_uint32 sbyte1, sbyte2, sbyte3, sbyte4, sum;
1847 l_uint32 *lines, *lined;
1848 
1849  /* i indexes the dest lines
1850  * l indexes the source lines
1851  * j indexes the dest bytes
1852  * k indexes the source bytes
1853  * We take four bytes from the source (in 4 lines of 8 pixels
1854  * each) and convert it into two 8 bpp bytes of the dest. */
1855  for (i = 0, l = 0; i < hd; i++, l += 4) {
1856  lines = datas + l * wpls;
1857  lined = datad + i * wpld;
1858  for (j = 0, k = 0; j < wd; j += 2, k++) {
1859  sbyte1 = GET_DATA_BYTE(lines, k);
1860  sbyte2 = GET_DATA_BYTE(lines + wpls, k);
1861  sbyte3 = GET_DATA_BYTE(lines + 2 * wpls, k);
1862  sbyte4 = GET_DATA_BYTE(lines + 3 * wpls, k);
1863  sum = sumtab[sbyte1] + sumtab[sbyte2] +
1864  sumtab[sbyte3] + sumtab[sbyte4];
1865  SET_DATA_BYTE(lined, j, valtab[GET_DATA_BYTE(&sum, 2)]);
1866  SET_DATA_BYTE(lined, j + 1, valtab[GET_DATA_BYTE(&sum, 3)]);
1867  }
1868  }
1869 }
1870 
1871 
1884 static l_uint32 *
1886 {
1887 l_int32 i;
1888 l_int32 sum[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1889 l_uint32 *tab;
1890 
1891  PROCNAME("makeSumTabSG4");
1892 
1893  /* Pack the two sums separately in two bytes */
1894  tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
1895  for (i = 0; i < 256; i++) {
1896  tab[i] = (sum[i & 0xf]) | (sum[(i >> 4) & 0xf] << 8);
1897  }
1898  return tab;
1899 }
1900 
1901 
1913 static l_uint8 *
1915 {
1916 l_int32 i;
1917 l_uint8 *tab;
1918 
1919  PROCNAME("makeValTabSG4");
1920 
1921  tab = (l_uint8 *)LEPT_CALLOC(17, sizeof(l_uint8));
1922  for (i = 0; i < 17; i++)
1923  tab[i] = 0xff - (i * 255) / 16;
1924  return tab;
1925 }
1926 
1927 
1928 /*------------------------------------------------------------------*
1929  * Scale-to-gray 6x *
1930  *------------------------------------------------------------------*/
1964 static void
1965 scaleToGray6Low(l_uint32 *datad,
1966  l_int32 wd,
1967  l_int32 hd,
1968  l_int32 wpld,
1969  l_uint32 *datas,
1970  l_int32 wpls,
1971  l_int32 *tab8,
1972  l_uint8 *valtab)
1973 {
1974 l_int32 i, j, l, k;
1975 l_uint32 threebytes1, threebytes2, threebytes3;
1976 l_uint32 threebytes4, threebytes5, threebytes6, sum;
1977 l_uint32 *lines, *lined;
1978 
1979  /* i indexes the dest lines
1980  * l indexes the source lines
1981  * j indexes the dest bytes
1982  * k indexes the source bytes
1983  * We take 18 bytes from the source (144 binary pixels
1984  * in six lines of 24 pixels each) and convert it
1985  * into 4 bytes of the dest (four 8 bpp pixels in one line) */
1986  for (i = 0, l = 0; i < hd; i++, l += 6) {
1987  lines = datas + l * wpls;
1988  lined = datad + i * wpld;
1989  for (j = 0, k = 0; j < wd; j += 4, k += 3) {
1990  /* First grab the 18 bytes, 3 at a time, and put each set
1991  * of 3 bytes into the LS bytes of a 32-bit word. */
1992  threebytes1 = (GET_DATA_BYTE(lines, k) << 16) |
1993  (GET_DATA_BYTE(lines, k + 1) << 8) |
1994  GET_DATA_BYTE(lines, k + 2);
1995  threebytes2 = (GET_DATA_BYTE(lines + wpls, k) << 16) |
1996  (GET_DATA_BYTE(lines + wpls, k + 1) << 8) |
1997  GET_DATA_BYTE(lines + wpls, k + 2);
1998  threebytes3 = (GET_DATA_BYTE(lines + 2 * wpls, k) << 16) |
1999  (GET_DATA_BYTE(lines + 2 * wpls, k + 1) << 8) |
2000  GET_DATA_BYTE(lines + 2 * wpls, k + 2);
2001  threebytes4 = (GET_DATA_BYTE(lines + 3 * wpls, k) << 16) |
2002  (GET_DATA_BYTE(lines + 3 * wpls, k + 1) << 8) |
2003  GET_DATA_BYTE(lines + 3 * wpls, k + 2);
2004  threebytes5 = (GET_DATA_BYTE(lines + 4 * wpls, k) << 16) |
2005  (GET_DATA_BYTE(lines + 4 * wpls, k + 1) << 8) |
2006  GET_DATA_BYTE(lines + 4 * wpls, k + 2);
2007  threebytes6 = (GET_DATA_BYTE(lines + 5 * wpls, k) << 16) |
2008  (GET_DATA_BYTE(lines + 5 * wpls, k + 1) << 8) |
2009  GET_DATA_BYTE(lines + 5 * wpls, k + 2);
2010 
2011  /* Sum first set of 36 bits and convert to 0-255 */
2012  sum = tab8[(threebytes1 >> 18)] +
2013  tab8[(threebytes2 >> 18)] +
2014  tab8[(threebytes3 >> 18)] +
2015  tab8[(threebytes4 >> 18)] +
2016  tab8[(threebytes5 >> 18)] +
2017  tab8[(threebytes6 >> 18)];
2018  SET_DATA_BYTE(lined, j, valtab[GET_DATA_BYTE(&sum, 3)]);
2019 
2020  /* Ditto for second set */
2021  sum = tab8[((threebytes1 >> 12) & 0x3f)] +
2022  tab8[((threebytes2 >> 12) & 0x3f)] +
2023  tab8[((threebytes3 >> 12) & 0x3f)] +
2024  tab8[((threebytes4 >> 12) & 0x3f)] +
2025  tab8[((threebytes5 >> 12) & 0x3f)] +
2026  tab8[((threebytes6 >> 12) & 0x3f)];
2027  SET_DATA_BYTE(lined, j + 1, valtab[GET_DATA_BYTE(&sum, 3)]);
2028 
2029  sum = tab8[((threebytes1 >> 6) & 0x3f)] +
2030  tab8[((threebytes2 >> 6) & 0x3f)] +
2031  tab8[((threebytes3 >> 6) & 0x3f)] +
2032  tab8[((threebytes4 >> 6) & 0x3f)] +
2033  tab8[((threebytes5 >> 6) & 0x3f)] +
2034  tab8[((threebytes6 >> 6) & 0x3f)];
2035  SET_DATA_BYTE(lined, j + 2, valtab[GET_DATA_BYTE(&sum, 3)]);
2036 
2037  sum = tab8[(threebytes1 & 0x3f)] +
2038  tab8[(threebytes2 & 0x3f)] +
2039  tab8[(threebytes3 & 0x3f)] +
2040  tab8[(threebytes4 & 0x3f)] +
2041  tab8[(threebytes5 & 0x3f)] +
2042  tab8[(threebytes6 & 0x3f)];
2043  SET_DATA_BYTE(lined, j + 3, valtab[GET_DATA_BYTE(&sum, 3)]);
2044  }
2045  }
2046 }
2047 
2048 
2060 static l_uint8 *
2062 {
2063 l_int32 i;
2064 l_uint8 *tab;
2065 
2066  PROCNAME("makeValTabSG6");
2067 
2068  tab = (l_uint8 *)LEPT_CALLOC(37, sizeof(l_uint8));
2069  for (i = 0; i < 37; i++)
2070  tab[i] = 0xff - (i * 255) / 36;
2071  return tab;
2072 }
2073 
2074 
2075 /*------------------------------------------------------------------*
2076  * Scale-to-gray 8x *
2077  *------------------------------------------------------------------*/
2102 static void
2103 scaleToGray8Low(l_uint32 *datad,
2104  l_int32 wd,
2105  l_int32 hd,
2106  l_int32 wpld,
2107  l_uint32 *datas,
2108  l_int32 wpls,
2109  l_int32 *tab8,
2110  l_uint8 *valtab)
2111 {
2112 l_int32 i, j, k;
2113 l_int32 sbyte0, sbyte1, sbyte2, sbyte3, sbyte4, sbyte5, sbyte6, sbyte7, sum;
2114 l_uint32 *lines, *lined;
2115 
2116  /* i indexes the dest lines
2117  * k indexes the source lines
2118  * j indexes the src and dest bytes
2119  * We take 8 bytes from the source (in 8 lines of 8 pixels
2120  * each) and convert it into one 8 bpp byte of the dest. */
2121  for (i = 0, k = 0; i < hd; i++, k += 8) {
2122  lines = datas + k * wpls;
2123  lined = datad + i * wpld;
2124  for (j = 0; j < wd; j++) {
2125  sbyte0 = GET_DATA_BYTE(lines, j);
2126  sbyte1 = GET_DATA_BYTE(lines + wpls, j);
2127  sbyte2 = GET_DATA_BYTE(lines + 2 * wpls, j);
2128  sbyte3 = GET_DATA_BYTE(lines + 3 * wpls, j);
2129  sbyte4 = GET_DATA_BYTE(lines + 4 * wpls, j);
2130  sbyte5 = GET_DATA_BYTE(lines + 5 * wpls, j);
2131  sbyte6 = GET_DATA_BYTE(lines + 6 * wpls, j);
2132  sbyte7 = GET_DATA_BYTE(lines + 7 * wpls, j);
2133  sum = tab8[sbyte0] + tab8[sbyte1] +
2134  tab8[sbyte2] + tab8[sbyte3] +
2135  tab8[sbyte4] + tab8[sbyte5] +
2136  tab8[sbyte6] + tab8[sbyte7];
2137  SET_DATA_BYTE(lined, j, valtab[sum]);
2138  }
2139  }
2140 }
2141 
2142 
2154 static l_uint8 *
2156 {
2157 l_int32 i;
2158 l_uint8 *tab;
2159 
2160  PROCNAME("makeValTabSG8");
2161 
2162  tab = (l_uint8 *)LEPT_CALLOC(65, sizeof(l_uint8));
2163  for (i = 0; i < 65; i++)
2164  tab[i] = 0xff - (i * 255) / 64;
2165  return tab;
2166 }
2167 
2168 
2169 /*------------------------------------------------------------------*
2170  * Scale-to-gray 16x *
2171  *------------------------------------------------------------------*/
2194 static void
2195 scaleToGray16Low(l_uint32 *datad,
2196  l_int32 wd,
2197  l_int32 hd,
2198  l_int32 wpld,
2199  l_uint32 *datas,
2200  l_int32 wpls,
2201  l_int32 *tab8)
2202 {
2203 l_int32 i, j, k, m;
2204 l_int32 sum;
2205 l_uint32 *lines, *lined;
2206 
2207  /* i indexes the dest lines
2208  * k indexes the source lines
2209  * j indexes the dest bytes
2210  * m indexes the src bytes
2211  * We take 32 bytes from the source (in 16 lines of 16 pixels
2212  * each) and convert it into one 8 bpp byte of the dest. */
2213  for (i = 0, k = 0; i < hd; i++, k += 16) {
2214  lines = datas + k * wpls;
2215  lined = datad + i * wpld;
2216  for (j = 0; j < wd; j++) {
2217  m = 2 * j;
2218  sum = tab8[GET_DATA_BYTE(lines, m)];
2219  sum += tab8[GET_DATA_BYTE(lines, m + 1)];
2220  sum += tab8[GET_DATA_BYTE(lines + wpls, m)];
2221  sum += tab8[GET_DATA_BYTE(lines + wpls, m + 1)];
2222  sum += tab8[GET_DATA_BYTE(lines + 2 * wpls, m)];
2223  sum += tab8[GET_DATA_BYTE(lines + 2 * wpls, m + 1)];
2224  sum += tab8[GET_DATA_BYTE(lines + 3 * wpls, m)];
2225  sum += tab8[GET_DATA_BYTE(lines + 3 * wpls, m + 1)];
2226  sum += tab8[GET_DATA_BYTE(lines + 4 * wpls, m)];
2227  sum += tab8[GET_DATA_BYTE(lines + 4 * wpls, m + 1)];
2228  sum += tab8[GET_DATA_BYTE(lines + 5 * wpls, m)];
2229  sum += tab8[GET_DATA_BYTE(lines + 5 * wpls, m + 1)];
2230  sum += tab8[GET_DATA_BYTE(lines + 6 * wpls, m)];
2231  sum += tab8[GET_DATA_BYTE(lines + 6 * wpls, m + 1)];
2232  sum += tab8[GET_DATA_BYTE(lines + 7 * wpls, m)];
2233  sum += tab8[GET_DATA_BYTE(lines + 7 * wpls, m + 1)];
2234  sum += tab8[GET_DATA_BYTE(lines + 8 * wpls, m)];
2235  sum += tab8[GET_DATA_BYTE(lines + 8 * wpls, m + 1)];
2236  sum += tab8[GET_DATA_BYTE(lines + 9 * wpls, m)];
2237  sum += tab8[GET_DATA_BYTE(lines + 9 * wpls, m + 1)];
2238  sum += tab8[GET_DATA_BYTE(lines + 10 * wpls, m)];
2239  sum += tab8[GET_DATA_BYTE(lines + 10 * wpls, m + 1)];
2240  sum += tab8[GET_DATA_BYTE(lines + 11 * wpls, m)];
2241  sum += tab8[GET_DATA_BYTE(lines + 11 * wpls, m + 1)];
2242  sum += tab8[GET_DATA_BYTE(lines + 12 * wpls, m)];
2243  sum += tab8[GET_DATA_BYTE(lines + 12 * wpls, m + 1)];
2244  sum += tab8[GET_DATA_BYTE(lines + 13 * wpls, m)];
2245  sum += tab8[GET_DATA_BYTE(lines + 13 * wpls, m + 1)];
2246  sum += tab8[GET_DATA_BYTE(lines + 14 * wpls, m)];
2247  sum += tab8[GET_DATA_BYTE(lines + 14 * wpls, m + 1)];
2248  sum += tab8[GET_DATA_BYTE(lines + 15 * wpls, m)];
2249  sum += tab8[GET_DATA_BYTE(lines + 15 * wpls, m + 1)];
2250  sum = L_MIN(sum, 255);
2251  SET_DATA_BYTE(lined, j, 255 - sum);
2252  }
2253  }
2254 }
2255 
2256 
2257 
2258 /*------------------------------------------------------------------*
2259  * Grayscale mipmap *
2260  *------------------------------------------------------------------*/
2271 static l_int32
2272 scaleMipmapLow(l_uint32 *datad,
2273  l_int32 wd,
2274  l_int32 hd,
2275  l_int32 wpld,
2276  l_uint32 *datas1,
2277  l_int32 wpls1,
2278  l_uint32 *datas2,
2279  l_int32 wpls2,
2280  l_float32 red)
2281 {
2282 l_int32 i, j, val1, val2, val, row2, col2;
2283 l_int32 *srow, *scol;
2284 l_uint32 *lines1, *lines2, *lined;
2285 l_float32 ratio, w1, w2;
2286 
2287  PROCNAME("scaleMipmapLow");
2288 
2289  /* Clear dest */
2290  memset(datad, 0, 4LL * wpld * hd);
2291 
2292  /* Each dest pixel at (j,i) is computed by interpolating
2293  between the two src images at the corresponding location.
2294  We store the UL corner locations of the square of
2295  src pixels in thelower-resolution image that correspond
2296  to dest pixel (j,i). The are labeled by the arrays
2297  srow[i], scol[j]. The UL corner locations of the higher
2298  resolution src pixels are obtained from these arrays
2299  by multiplying by 2. */
2300  if ((srow = (l_int32 *)LEPT_CALLOC(hd, sizeof(l_int32))) == NULL)
2301  return ERROR_INT("srow not made", procName, 1);
2302  if ((scol = (l_int32 *)LEPT_CALLOC(wd, sizeof(l_int32))) == NULL) {
2303  LEPT_FREE(srow);
2304  return ERROR_INT("scol not made", procName, 1);
2305  }
2306  ratio = 1. / (2. * red); /* 0.5 for red = 1, 1 for red = 0.5 */
2307  for (i = 0; i < hd; i++)
2308  srow[i] = (l_int32)(ratio * i);
2309  for (j = 0; j < wd; j++)
2310  scol[j] = (l_int32)(ratio * j);
2311 
2312  /* Get weights for linear interpolation: these are the
2313  * 'distances' of the dest image plane from the two
2314  * src image planes. */
2315  w1 = 2. * red - 1.; /* w1 --> 1 as red --> 1 */
2316  w2 = 1. - w1;
2317 
2318  /* For each dest pixel, compute linear interpolation */
2319  for (i = 0; i < hd; i++) {
2320  row2 = srow[i];
2321  lines1 = datas1 + 2 * row2 * wpls1;
2322  lines2 = datas2 + row2 * wpls2;
2323  lined = datad + i * wpld;
2324  for (j = 0; j < wd; j++) {
2325  col2 = scol[j];
2326  val1 = GET_DATA_BYTE(lines1, 2 * col2);
2327  val2 = GET_DATA_BYTE(lines2, col2);
2328  val = (l_int32)(w1 * val1 + w2 * val2);
2329  SET_DATA_BYTE(lined, j, val);
2330  }
2331  }
2332 
2333  LEPT_FREE(srow);
2334  LEPT_FREE(scol);
2335  return 0;
2336 }
l_ok pixCopyRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixCopyRGBComponent()
Definition: pix2.c:2690
PIX * pixScaleWithAlpha(PIX *pixs, l_float32 scalex, l_float32 scaley, PIX *pixg, l_float32 fract)
pixScaleWithAlpha()
Definition: scale2.c:1443
static l_uint8 * makeValTabSG2(void)
makeValTabSG2()
Definition: scale2.c:1635
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
PIX * pixScaleToGray(PIX *pixs, l_float32 scalefactor)
pixScaleToGray()
Definition: scale2.c:208
static l_uint32 * makeSumTabSG4(void)
makeSumTabSG4()
Definition: scale2.c:1885
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
PIX * pixScaleGrayRankCascade(PIX *pixs, l_int32 level1, l_int32 level2, l_int32 level3, l_int32 level4)
pixScaleGrayRankCascade()
Definition: scale2.c:1209
PIX * pixScaleGrayMinMax(PIX *pixs, l_int32 xfact, l_int32 yfact, l_int32 type)
pixScaleGrayMinMax()
Definition: scale2.c:1019
PIX * pixScaleGrayRank2(PIX *pixs, l_int32 rank)
pixScaleGrayRank2()
Definition: scale2.c:1273
static l_uint8 * makeValTabSG6(void)
makeValTabSG6()
Definition: scale2.c:2061
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
static l_uint32 * makeSumTabSG2(void)
makeSumTabSG2()
Definition: scale2.c:1605
PIX * pixScaleGeneral(PIX *pixs, l_float32 scalex, l_float32 scaley, l_float32 sharpfract, l_int32 sharpwidth)
pixScaleGeneral()
Definition: scale1.c:423
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
PIX * pixScaleToGray6(PIX *pixs)
pixScaleToGray6()
Definition: scale2.c:557
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixScaleToGray3(PIX *pixs)
pixScaleToGray3()
Definition: scale2.c:448
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
PIX * pixScaleToGray8(PIX *pixs)
pixScaleToGray8()
Definition: scale2.c:605
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:951
PIX * pixScaleBinary(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBinary()
Definition: scale1.c:2161
static void scaleToGray16Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 *tab8)
scaleToGray16Low()
Definition: scale2.c:2195
static void scaleToGray3Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_uint32 *sumtab, l_uint8 *valtab)
scaleToGray3Low()
Definition: scale2.c:1687
PIX * pixScaleToGrayFast(PIX *pixs, l_float32 scalefactor)
pixScaleToGrayFast()
Definition: scale2.c:319
l_ok pixSetBorderRingVal(PIX *pixs, l_int32 dist, l_uint32 val)
pixSetBorderRingVal()
Definition: pix2.c:1667
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
static l_uint32 * makeSumTabSG3(void)
makeSumTabSG3()
Definition: scale2.c:1764
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
static void scaleToGray4Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_uint32 *sumtab, l_uint8 *valtab)
scaleToGray4Low()
Definition: scale2.c:1836
static void scaleToGray6Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 *tab8, l_uint8 *valtab)
scaleToGray6Low()
Definition: scale2.c:1965
PIX * pixScaleGrayLI(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleGrayLI()
Definition: scale1.c:780
static l_uint8 * makeValTabSG3(void)
makeValTabSG3()
Definition: scale2.c:1793
PIX * pixExpandReplicate(PIX *pixs, l_int32 factor)
pixExpandReplicate()
Definition: scale2.c:872
PIX * pixScaleMipmap(PIX *pixs1, PIX *pixs2, l_float32 scale)
pixScaleMipmap()
Definition: scale2.c:815
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
static void scaleToGray2Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_uint32 *sumtab, l_uint8 *valtab)
scaleToGray2Low()
Definition: scale2.c:1545
PIX * pixScaleGrayMinMax2(PIX *pixs, l_int32 type)
pixScaleGrayMinMax2()
Definition: scale2.c:1126
PIX * pixScaleToGray4(PIX *pixs)
pixScaleToGray4()
Definition: scale2.c:502
Definition: pix.h:138
PIX * pixScaleToGray16(PIX *pixs)
pixScaleToGray16()
Definition: scale2.c:654
static void scaleToGray8Low(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 *tab8, l_uint8 *valtab)
scaleToGray8Low()
Definition: scale2.c:2103
l_ok pixCopyColormap(PIX *pixd, const PIX *pixs)
pixCopyColormap()
Definition: pix1.c:816
PIX * pixResizeToMatch(PIX *pixs, PIX *pixt, l_int32 w, l_int32 h)
pixResizeToMatch()
Definition: pix5.c:1321
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2401
static l_uint8 * makeValTabSG8(void)
makeValTabSG8()
Definition: scale2.c:2155
static l_uint8 * makeValTabSG4(void)
makeValTabSG4()
Definition: scale2.c:1914
PIX * pixScaleSmooth(PIX *pix, l_float32 scalex, l_float32 scaley)
pixScaleSmooth()
Definition: scale1.c:1709
l_ok pixScaleAndTransferAlpha(PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleAndTransferAlpha()
Definition: scale2.c:1364
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
PIX * pixExpandBinaryReplicate(PIX *pixs, l_int32 xfact, l_int32 yfact)
pixExpandBinaryReplicate()
Definition: binexpand.c:70
PIX * pixScaleToGrayMipmap(PIX *pixs, l_float32 scalefactor)
pixScaleToGrayMipmap()
Definition: scale2.c:727
PIX * pixScaleToGray2(PIX *pixs)
pixScaleToGray2()
Definition: scale2.c:390
static l_int32 scaleMipmapLow(l_uint32 *datad, l_int32 wd, l_int32 hd, l_int32 wpld, l_uint32 *datas1, l_int32 wpls1, l_uint32 *datas2, l_int32 wpls2, l_float32 red)
scaleMipmapLow()
Definition: scale2.c:2272