Leptonica  1.82.0
Image processing and image analysis suite
pixarith.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 
91 #ifdef HAVE_CONFIG_H
92 #include <config_auto.h>
93 #endif /* HAVE_CONFIG_H */
94 
95 #include <string.h>
96 #include <math.h>
97 #include "allheaders.h"
98 
99 /*-------------------------------------------------------------*
100  * One-image grayscale arithmetic operations *
101  *-------------------------------------------------------------*/
118 l_ok
120  l_int32 val)
121 {
122 l_int32 i, j, w, h, d, wpl, pval;
123 l_uint32 *data, *line;
124 
125  PROCNAME("pixAddConstantGray");
126 
127  if (!pixs)
128  return ERROR_INT("pixs not defined", procName, 1);
129  pixGetDimensions(pixs, &w, &h, &d);
130  if (d != 8 && d != 16 && d != 32)
131  return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1);
132 
133  data = pixGetData(pixs);
134  wpl = pixGetWpl(pixs);
135  for (i = 0; i < h; i++) {
136  line = data + i * wpl;
137  if (d == 8) {
138  if (val < 0) {
139  for (j = 0; j < w; j++) {
140  pval = GET_DATA_BYTE(line, j);
141  pval = L_MAX(0, pval + val);
142  SET_DATA_BYTE(line, j, pval);
143  }
144  } else { /* val >= 0 */
145  for (j = 0; j < w; j++) {
146  pval = GET_DATA_BYTE(line, j);
147  pval = L_MIN(255, pval + val);
148  SET_DATA_BYTE(line, j, pval);
149  }
150  }
151  } else if (d == 16) {
152  if (val < 0) {
153  for (j = 0; j < w; j++) {
154  pval = GET_DATA_TWO_BYTES(line, j);
155  pval = L_MAX(0, pval + val);
156  SET_DATA_TWO_BYTES(line, j, pval);
157  }
158  } else { /* val >= 0 */
159  for (j = 0; j < w; j++) {
160  pval = GET_DATA_TWO_BYTES(line, j);
161  pval = L_MIN(0xffff, pval + val);
162  SET_DATA_TWO_BYTES(line, j, pval);
163  }
164  }
165  } else { /* d == 32; no check for overflow (< 0 or > 0xffffffff) */
166  for (j = 0; j < w; j++)
167  *(line + j) += val;
168  }
169  }
170 
171  return 0;
172 }
173 
174 
189 l_ok
191  l_float32 val)
192 {
193 l_int32 i, j, w, h, d, wpl, pval;
194 l_uint32 upval;
195 l_uint32 *data, *line;
196 
197  PROCNAME("pixMultConstantGray");
198 
199  if (!pixs)
200  return ERROR_INT("pixs not defined", procName, 1);
201  pixGetDimensions(pixs, &w, &h, &d);
202  if (d != 8 && d != 16 && d != 32)
203  return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1);
204  if (val < 0.0)
205  return ERROR_INT("val < 0.0", procName, 1);
206 
207  data = pixGetData(pixs);
208  wpl = pixGetWpl(pixs);
209  for (i = 0; i < h; i++) {
210  line = data + i * wpl;
211  if (d == 8) {
212  for (j = 0; j < w; j++) {
213  pval = GET_DATA_BYTE(line, j);
214  pval = (l_int32)(val * pval);
215  pval = L_MIN(255, pval);
216  SET_DATA_BYTE(line, j, pval);
217  }
218  } else if (d == 16) {
219  for (j = 0; j < w; j++) {
220  pval = GET_DATA_TWO_BYTES(line, j);
221  pval = (l_int32)(val * pval);
222  pval = L_MIN(0xffff, pval);
223  SET_DATA_TWO_BYTES(line, j, pval);
224  }
225  } else { /* d == 32; no clipping */
226  for (j = 0; j < w; j++) {
227  upval = *(line + j);
228  upval = (l_uint32)(val * upval);
229  *(line + j) = upval;
230  }
231  }
232  }
233 
234  return 0;
235 }
236 
237 
238 /*-------------------------------------------------------------*
239  * Two-image grayscale arithmetic ops *
240  *-------------------------------------------------------------*/
264 PIX *
266  PIX *pixs1,
267  PIX *pixs2)
268 {
269 l_int32 i, j, d, ws, hs, w, h, wpls, wpld, val, sum;
270 l_uint32 *datas, *datad, *lines, *lined;
271 
272  PROCNAME("pixAddGray");
273 
274  if (!pixs1)
275  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
276  if (!pixs2)
277  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
278  if (pixs2 == pixs1)
279  return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd);
280  if (pixs2 == pixd)
281  return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd);
282  d = pixGetDepth(pixs1);
283  if (d != 8 && d != 16 && d != 32)
284  return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd);
285  if (pixGetDepth(pixs2) != d)
286  return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd);
287  if (pixd && (pixGetDepth(pixd) != d))
288  return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd);
289 
290  if (!pixSizesEqual(pixs1, pixs2))
291  L_WARNING("pixs1 and pixs2 not equal in size\n", procName);
292  if (pixd && !pixSizesEqual(pixs1, pixd))
293  L_WARNING("pixs1 and pixd not equal in size\n", procName);
294 
295  if (pixs1 != pixd)
296  pixd = pixCopy(pixd, pixs1);
297 
298  /* pixd + pixs2 ==> pixd */
299  datas = pixGetData(pixs2);
300  datad = pixGetData(pixd);
301  wpls = pixGetWpl(pixs2);
302  wpld = pixGetWpl(pixd);
303  pixGetDimensions(pixs2, &ws, &hs, NULL);
304  pixGetDimensions(pixd, &w, &h, NULL);
305  w = L_MIN(ws, w);
306  h = L_MIN(hs, h);
307  for (i = 0; i < h; i++) {
308  lined = datad + i * wpld;
309  lines = datas + i * wpls;
310  if (d == 8) {
311  for (j = 0; j < w; j++) {
312  sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j);
313  val = L_MIN(sum, 255);
314  SET_DATA_BYTE(lined, j, val);
315  }
316  } else if (d == 16) {
317  for (j = 0; j < w; j++) {
318  sum = GET_DATA_TWO_BYTES(lines, j)
319  + GET_DATA_TWO_BYTES(lined, j);
320  val = L_MIN(sum, 0xffff);
321  SET_DATA_TWO_BYTES(lined, j, val);
322  }
323  } else { /* d == 32; no clipping */
324  for (j = 0; j < w; j++)
325  *(lined + j) += *(lines + j);
326  }
327  }
328 
329  return pixd;
330 }
331 
332 
356 PIX *
358  PIX *pixs1,
359  PIX *pixs2)
360 {
361 l_int32 i, j, w, h, ws, hs, d, wpls, wpld, val, diff;
362 l_uint32 *datas, *datad, *lines, *lined;
363 
364  PROCNAME("pixSubtractGray");
365 
366  if (!pixs1)
367  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
368  if (!pixs2)
369  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
370  if (pixs2 == pixs1)
371  return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd);
372  if (pixs2 == pixd)
373  return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd);
374  d = pixGetDepth(pixs1);
375  if (d != 8 && d != 16 && d != 32)
376  return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd);
377  if (pixGetDepth(pixs2) != d)
378  return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd);
379  if (pixd && (pixGetDepth(pixd) != d))
380  return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd);
381 
382  if (!pixSizesEqual(pixs1, pixs2))
383  L_WARNING("pixs1 and pixs2 not equal in size\n", procName);
384  if (pixd && !pixSizesEqual(pixs1, pixd))
385  L_WARNING("pixs1 and pixd not equal in size\n", procName);
386 
387  if (pixs1 != pixd)
388  pixd = pixCopy(pixd, pixs1);
389 
390  /* pixd - pixs2 ==> pixd */
391  datas = pixGetData(pixs2);
392  datad = pixGetData(pixd);
393  wpls = pixGetWpl(pixs2);
394  wpld = pixGetWpl(pixd);
395  pixGetDimensions(pixs2, &ws, &hs, NULL);
396  pixGetDimensions(pixd, &w, &h, NULL);
397  w = L_MIN(ws, w);
398  h = L_MIN(hs, h);
399  for (i = 0; i < h; i++) {
400  lined = datad + i * wpld;
401  lines = datas + i * wpls;
402  if (d == 8) {
403  for (j = 0; j < w; j++) {
404  diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j);
405  val = L_MAX(diff, 0);
406  SET_DATA_BYTE(lined, j, val);
407  }
408  } else if (d == 16) {
409  for (j = 0; j < w; j++) {
410  diff = GET_DATA_TWO_BYTES(lined, j)
411  - GET_DATA_TWO_BYTES(lines, j);
412  val = L_MAX(diff, 0);
413  SET_DATA_TWO_BYTES(lined, j, val);
414  }
415  } else { /* d == 32; no clipping */
416  for (j = 0; j < w; j++)
417  *(lined + j) -= *(lines + j);
418  }
419  }
420 
421  return pixd;
422 }
423 
424 
448 PIX *
450  PIX *pixg,
451  l_float32 norm)
452 {
453 l_int32 i, j, w, h, d, ws, hs, ds, wpls, wplg, wpld;
454 l_int32 rval, gval, bval, rval2, gval2, bval2, vals, valg, val, maxgray;
455 l_uint32 val32;
456 l_uint32 *datas, *datag, *datad, *lines, *lineg, *lined;
457 PIX *pixd;
458 
459  PROCNAME("pixMultiplyGray");
460 
461  if (!pixs)
462  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
463  pixGetDimensions(pixs, &ws, &hs, &ds);
464  if (ds != 8 && ds != 32)
465  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
466  if (!pixg)
467  return (PIX *)ERROR_PTR("pixg not defined", procName, NULL);
468  pixGetDimensions(pixg, &w, &h, &d);
469  if (d != 8)
470  return (PIX *)ERROR_PTR("pixg not 8 bpp", procName, NULL);
471 
472  if (norm <= 0.0) {
473  pixGetExtremeValue(pixg, 1, L_SELECT_MAX, NULL, NULL, NULL, &maxgray);
474  norm = (maxgray > 0) ? 1.0 / (l_float32)maxgray : 1.0;
475  }
476 
477  if ((pixd = pixCreateTemplate(pixs)) == NULL)
478  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
479  datas = pixGetData(pixs);
480  datag = pixGetData(pixg);
481  datad = pixGetData(pixd);
482  wpls = pixGetWpl(pixs);
483  wplg = pixGetWpl(pixg);
484  wpld = pixGetWpl(pixd);
485  w = L_MIN(ws, w);
486  h = L_MIN(hs, h);
487  for (i = 0; i < h; i++) {
488  lines = datas + i * wpls;
489  lineg = datag + i * wplg;
490  lined = datad + i * wpld;
491  if (ds == 8) {
492  for (j = 0; j < w; j++) {
493  vals = GET_DATA_BYTE(lines, j);
494  valg = GET_DATA_BYTE(lineg, j);
495  val = (l_int32)(vals * valg * norm + 0.5);
496  val = L_MIN(255, val);
497  SET_DATA_BYTE(lined, j, val);
498  }
499  } else { /* ds == 32 */
500  for (j = 0; j < w; j++) {
501  val32 = *(lines + j);
502  extractRGBValues(val32, &rval, &gval, &bval);
503  valg = GET_DATA_BYTE(lineg, j);
504  rval2 = (l_int32)(rval * valg * norm + 0.5);
505  rval2 = L_MIN(255, rval2);
506  gval2 = (l_int32)(gval * valg * norm + 0.5);
507  gval2 = L_MIN(255, gval2);
508  bval2 = (l_int32)(bval * valg * norm + 0.5);
509  bval2 = L_MIN(255, bval2);
510  composeRGBPixel(rval2, gval2, bval2, lined + j);
511  }
512  }
513  }
514 
515  return pixd;
516 }
517 
518 
519 /*-------------------------------------------------------------*
520  * Grayscale threshold operation *
521  *-------------------------------------------------------------*/
539 PIX *
541  PIX *pixs,
542  l_int32 threshval,
543  l_int32 setval)
544 {
545 l_int32 i, j, w, h, d, wpld, setabove;
546 l_uint32 *datad, *lined;
547 
548  PROCNAME("pixThresholdToValue");
549 
550  if (!pixs)
551  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
552  d = pixGetDepth(pixs);
553  if (d != 8 && d != 16 && d != 32)
554  return (PIX *)ERROR_PTR("pixs not 8, 16 or 32 bpp", procName, pixd);
555  if (pixd && (pixs != pixd))
556  return (PIX *)ERROR_PTR("pixd exists and is not pixs", procName, pixd);
557  if (threshval < 0 || setval < 0)
558  return (PIX *)ERROR_PTR("threshval & setval not < 0", procName, pixd);
559  if (d == 8 && setval > 255)
560  return (PIX *)ERROR_PTR("setval > 255 for 8 bpp", procName, pixd);
561  if (d == 16 && setval > 0xffff)
562  return (PIX *)ERROR_PTR("setval > 0xffff for 16 bpp", procName, pixd);
563 
564  if (!pixd)
565  pixd = pixCopy(NULL, pixs);
566  if (setval == threshval) {
567  L_WARNING("setval == threshval; no operation\n", procName);
568  return pixd;
569  }
570 
571  datad = pixGetData(pixd);
572  pixGetDimensions(pixd, &w, &h, NULL);
573  wpld = pixGetWpl(pixd);
574  if (setval > threshval)
575  setabove = TRUE;
576  else
577  setabove = FALSE;
578 
579  for (i = 0; i < h; i++) {
580  lined = datad + i * wpld;
581  if (setabove == TRUE) {
582  if (d == 8) {
583  for (j = 0; j < w; j++) {
584  if (GET_DATA_BYTE(lined, j) - threshval >= 0)
585  SET_DATA_BYTE(lined, j, setval);
586  }
587  } else if (d == 16) {
588  for (j = 0; j < w; j++) {
589  if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0)
590  SET_DATA_TWO_BYTES(lined, j, setval);
591  }
592  } else { /* d == 32 */
593  for (j = 0; j < w; j++) {
594  if (*(lined + j) >= threshval)
595  *(lined + j) = setval;
596  }
597  }
598  } else { /* set if below or at threshold */
599  if (d == 8) {
600  for (j = 0; j < w; j++) {
601  if (GET_DATA_BYTE(lined, j) - threshval <= 0)
602  SET_DATA_BYTE(lined, j, setval);
603  }
604  } else if (d == 16) {
605  for (j = 0; j < w; j++) {
606  if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0)
607  SET_DATA_TWO_BYTES(lined, j, setval);
608  }
609  } else { /* d == 32 */
610  for (j = 0; j < w; j++) {
611  if (*(lined + j) <= threshval)
612  *(lined + j) = setval;
613  }
614  }
615  }
616  }
617 
618  return pixd;
619 }
620 
621 
622 /*-------------------------------------------------------------*
623  * Image accumulator arithmetic operations *
624  *-------------------------------------------------------------*/
648 PIX *
650  l_int32 h,
651  l_uint32 offset)
652 {
653 PIX *pixd;
654 
655  PROCNAME("pixInitAccumulate");
656 
657  if ((pixd = pixCreate(w, h, 32)) == NULL)
658  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
659  if (offset > 0x40000000)
660  offset = 0x40000000;
661  pixSetAllArbitrary(pixd, offset);
662  return pixd;
663 }
664 
665 
682 PIX *
684  l_uint32 offset,
685  l_int32 depth)
686 {
687 l_int32 i, j, w, h, wpls, wpld, val;
688 l_uint32 *datas, *datad, *lines, *lined;
689 PIX *pixd;
690 
691  PROCNAME("pixFinalAccumulate");
692 
693  if (!pixs)
694  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
695  if (pixGetDepth(pixs) != 32)
696  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
697  if (depth != 8 && depth != 16 && depth != 32)
698  return (PIX *)ERROR_PTR("dest depth not 8, 16, 32 bpp", procName, NULL);
699  if (offset > 0x40000000)
700  offset = 0x40000000;
701 
702  pixGetDimensions(pixs, &w, &h, NULL);
703  if ((pixd = pixCreate(w, h, depth)) == NULL)
704  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
705  pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */
706  datas = pixGetData(pixs);
707  datad = pixGetData(pixd);
708  wpls = pixGetWpl(pixs);
709  wpld = pixGetWpl(pixd);
710  if (depth == 8) {
711  for (i = 0; i < h; i++) {
712  lines = datas + i * wpls;
713  lined = datad + i * wpld;
714  for (j = 0; j < w; j++) {
715  val = lines[j] - offset;
716  val = L_MAX(0, val);
717  val = L_MIN(255, val);
718  SET_DATA_BYTE(lined, j, (l_uint8)val);
719  }
720  }
721  } else if (depth == 16) {
722  for (i = 0; i < h; i++) {
723  lines = datas + i * wpls;
724  lined = datad + i * wpld;
725  for (j = 0; j < w; j++) {
726  val = lines[j] - offset;
727  val = L_MAX(0, val);
728  val = L_MIN(0xffff, val);
729  SET_DATA_TWO_BYTES(lined, j, (l_uint16)val);
730  }
731  }
732  } else { /* depth == 32 */
733  for (i = 0; i < h; i++) {
734  lines = datas + i * wpls;
735  lined = datad + i * wpld;
736  for (j = 0; j < w; j++)
737  lined[j] = lines[j] - offset;
738  }
739  }
740 
741  return pixd;
742 }
743 
744 
759 PIX *
761  l_uint32 offset,
762  l_uint32 threshold)
763 {
764 l_int32 i, j, w, h, wpls, wpld, val;
765 l_uint32 *datas, *datad, *lines, *lined;
766 PIX *pixd;
767 
768  PROCNAME("pixFinalAccumulateThreshold");
769 
770  if (!pixs)
771  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
772  if (pixGetDepth(pixs) != 32)
773  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
774  if (offset > 0x40000000)
775  offset = 0x40000000;
776 
777  pixGetDimensions(pixs, &w, &h, NULL);
778  if ((pixd = pixCreate(w, h, 1)) == NULL)
779  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
780  pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */
781  datas = pixGetData(pixs);
782  datad = pixGetData(pixd);
783  wpls = pixGetWpl(pixs);
784  wpld = pixGetWpl(pixd);
785  for (i = 0; i < h; i++) {
786  lines = datas + i * wpls;
787  lined = datad + i * wpld;
788  for (j = 0; j < w; j++) {
789  val = lines[j] - offset;
790  if (val >= threshold) {
791  SET_DATA_BIT(lined, j);
792  }
793  }
794  }
795 
796  return pixd;
797 }
798 
799 
816 l_ok
818  PIX *pixs,
819  l_int32 op)
820 {
821 l_int32 i, j, w, h, d, wd, hd, wpls, wpld;
822 l_uint32 *datas, *datad, *lines, *lined;
823 
824 
825  PROCNAME("pixAccumulate");
826 
827  if (!pixd || (pixGetDepth(pixd) != 32))
828  return ERROR_INT("pixd not defined or not 32 bpp", procName, 1);
829  if (!pixs)
830  return ERROR_INT("pixs not defined", procName, 1);
831  d = pixGetDepth(pixs);
832  if (d != 1 && d != 8 && d != 16 && d != 32)
833  return ERROR_INT("pixs not 1, 8, 16 or 32 bpp", procName, 1);
834  if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT)
835  return ERROR_INT("op must be in {L_ARITH_ADD, L_ARITH_SUBTRACT}",
836  procName, 1);
837 
838  datas = pixGetData(pixs);
839  datad = pixGetData(pixd);
840  wpls = pixGetWpl(pixs);
841  wpld = pixGetWpl(pixd);
842  pixGetDimensions(pixs, &w, &h, NULL);
843  pixGetDimensions(pixd, &wd, &hd, NULL);
844  w = L_MIN(w, wd);
845  h = L_MIN(h, hd);
846  if (d == 1) {
847  for (i = 0; i < h; i++) {
848  lines = datas + i * wpls;
849  lined = datad + i * wpld;
850  if (op == L_ARITH_ADD) {
851  for (j = 0; j < w; j++)
852  lined[j] += GET_DATA_BIT(lines, j);
853  } else { /* op == L_ARITH_SUBTRACT */
854  for (j = 0; j < w; j++)
855  lined[j] -= GET_DATA_BIT(lines, j);
856  }
857  }
858  } else if (d == 8) {
859  for (i = 0; i < h; i++) {
860  lines = datas + i * wpls;
861  lined = datad + i * wpld;
862  if (op == L_ARITH_ADD) {
863  for (j = 0; j < w; j++)
864  lined[j] += GET_DATA_BYTE(lines, j);
865  } else { /* op == L_ARITH_SUBTRACT */
866  for (j = 0; j < w; j++)
867  lined[j] -= GET_DATA_BYTE(lines, j);
868  }
869  }
870  } else if (d == 16) {
871  for (i = 0; i < h; i++) {
872  lines = datas + i * wpls;
873  lined = datad + i * wpld;
874  if (op == L_ARITH_ADD) {
875  for (j = 0; j < w; j++)
876  lined[j] += GET_DATA_TWO_BYTES(lines, j);
877  } else { /* op == L_ARITH_SUBTRACT */
878  for (j = 0; j < w; j++)
879  lined[j] -= GET_DATA_TWO_BYTES(lines, j);
880  }
881  }
882  } else { /* d == 32 */
883  for (i = 0; i < h; i++) {
884  lines = datas + i * wpls;
885  lined = datad + i * wpld;
886  if (op == L_ARITH_ADD) {
887  for (j = 0; j < w; j++)
888  lined[j] += lines[j];
889  } else { /* op == L_ARITH_SUBTRACT */
890  for (j = 0; j < w; j++)
891  lined[j] -= lines[j];
892  }
893  }
894  }
895 
896  return 0;
897 }
898 
899 
915 l_ok
917  l_float32 factor,
918  l_uint32 offset)
919 {
920 l_int32 i, j, w, h, wpl, val;
921 l_uint32 *data, *line;
922 
923  PROCNAME("pixMultConstAccumulate");
924 
925  if (!pixs)
926  return ERROR_INT("pixs not defined", procName, 1);
927  if (pixGetDepth(pixs) != 32)
928  return ERROR_INT("pixs not 32 bpp", procName, 1);
929  if (offset > 0x40000000)
930  offset = 0x40000000;
931 
932  pixGetDimensions(pixs, &w, &h, NULL);
933  data = pixGetData(pixs);
934  wpl = pixGetWpl(pixs);
935  for (i = 0; i < h; i++) {
936  line = data + i * wpl;
937  for (j = 0; j < w; j++) {
938  val = line[j] - offset;
939  val = (l_int32)(val * factor);
940  val += offset;
941  line[j] = (l_uint32)val;
942  }
943  }
944 
945  return 0;
946 }
947 
948 
949 /*-----------------------------------------------------------------------*
950  * Absolute value of difference *
951  *-----------------------------------------------------------------------*/
969 PIX *
971  PIX *pixs2)
972 {
973 l_int32 i, j, w, h, w2, h2, d, wpls1, wpls2, wpld, val1, val2, diff;
974 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rdiff, gdiff, bdiff;
975 l_uint32 *datas1, *datas2, *datad, *lines1, *lines2, *lined;
976 PIX *pixd;
977 
978  PROCNAME("pixAbsDifference");
979 
980  if (!pixs1)
981  return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL);
982  if (!pixs2)
983  return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL);
984  d = pixGetDepth(pixs1);
985  if (d != pixGetDepth(pixs2))
986  return (PIX *)ERROR_PTR("src1 and src2 depths unequal", procName, NULL);
987  if (d != 8 && d != 16 && d != 32)
988  return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", procName, NULL);
989 
990  pixGetDimensions(pixs1, &w, &h, NULL);
991  pixGetDimensions(pixs2, &w2, &h2, NULL);
992  w = L_MIN(w, w2);
993  h = L_MIN(h, h2);
994  if ((pixd = pixCreate(w, h, d)) == NULL)
995  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
996  pixCopyResolution(pixd, pixs1);
997  datas1 = pixGetData(pixs1);
998  datas2 = pixGetData(pixs2);
999  datad = pixGetData(pixd);
1000  wpls1 = pixGetWpl(pixs1);
1001  wpls2 = pixGetWpl(pixs2);
1002  wpld = pixGetWpl(pixd);
1003  if (d == 8) {
1004  for (i = 0; i < h; i++) {
1005  lines1 = datas1 + i * wpls1;
1006  lines2 = datas2 + i * wpls2;
1007  lined = datad + i * wpld;
1008  for (j = 0; j < w; j++) {
1009  val1 = GET_DATA_BYTE(lines1, j);
1010  val2 = GET_DATA_BYTE(lines2, j);
1011  diff = L_ABS(val1 - val2);
1012  SET_DATA_BYTE(lined, j, diff);
1013  }
1014  }
1015  } else if (d == 16) {
1016  for (i = 0; i < h; i++) {
1017  lines1 = datas1 + i * wpls1;
1018  lines2 = datas2 + i * wpls2;
1019  lined = datad + i * wpld;
1020  for (j = 0; j < w; j++) {
1021  val1 = GET_DATA_TWO_BYTES(lines1, j);
1022  val2 = GET_DATA_TWO_BYTES(lines2, j);
1023  diff = L_ABS(val1 - val2);
1024  SET_DATA_TWO_BYTES(lined, j, diff);
1025  }
1026  }
1027  } else { /* d == 32 */
1028  for (i = 0; i < h; i++) {
1029  lines1 = datas1 + i * wpls1;
1030  lines2 = datas2 + i * wpls2;
1031  lined = datad + i * wpld;
1032  for (j = 0; j < w; j++) {
1033  extractRGBValues(lines1[j], &rval1, &gval1, &bval1);
1034  extractRGBValues(lines2[j], &rval2, &gval2, &bval2);
1035  rdiff = L_ABS(rval1 - rval2);
1036  gdiff = L_ABS(gval1 - gval2);
1037  bdiff = L_ABS(bval1 - bval2);
1038  composeRGBPixel(rdiff, gdiff, bdiff, lined + j);
1039  }
1040  }
1041  }
1042 
1043  return pixd;
1044 }
1045 
1046 
1047 /*-----------------------------------------------------------------------*
1048  * Sum of color images *
1049  *-----------------------------------------------------------------------*/
1066 PIX *
1068  PIX *pixs2)
1069 {
1070 l_int32 i, j, w, h, d, w2, h2, d2, wplc1, wplc2, wpld;
1071 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
1072 l_uint32 *datac1, *datac2, *datad, *linec1, *linec2, *lined;
1073 PIX *pixc1, *pixc2, *pixd;
1074 
1075  PROCNAME("pixAddRGB");
1076 
1077  if (!pixs1)
1078  return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL);
1079  if (!pixs2)
1080  return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL);
1081  pixGetDimensions(pixs1, &w, &h, &d);
1082  pixGetDimensions(pixs2, &w2, &h2, &d2);
1083  if (!pixGetColormap(pixs1) && d != 32)
1084  return (PIX *)ERROR_PTR("pixs1 not cmapped or rgb", procName, NULL);
1085  if (!pixGetColormap(pixs2) && d2 != 32)
1086  return (PIX *)ERROR_PTR("pixs2 not cmapped or rgb", procName, NULL);
1087  if (pixGetColormap(pixs1))
1089  else
1090  pixc1 = pixClone(pixs1);
1091  if (pixGetColormap(pixs2))
1093  else
1094  pixc2 = pixClone(pixs2);
1095 
1096  w = L_MIN(w, w2);
1097  h = L_MIN(h, h2);
1098  pixd = pixCreate(w, h, 32);
1099  pixCopyResolution(pixd, pixs1);
1100  datac1 = pixGetData(pixc1);
1101  datac2 = pixGetData(pixc2);
1102  datad = pixGetData(pixd);
1103  wplc1 = pixGetWpl(pixc1);
1104  wplc2 = pixGetWpl(pixc2);
1105  wpld = pixGetWpl(pixd);
1106  for (i = 0; i < h; i++) {
1107  linec1 = datac1 + i * wplc1;
1108  linec2 = datac2 + i * wplc2;
1109  lined = datad + i * wpld;
1110  for (j = 0; j < w; j++) {
1111  extractRGBValues(linec1[j], &rval1, &gval1, &bval1);
1112  extractRGBValues(linec2[j], &rval2, &gval2, &bval2);
1113  rval = L_MIN(255, rval1 + rval2);
1114  gval = L_MIN(255, gval1 + gval2);
1115  bval = L_MIN(255, bval1 + bval2);
1116  composeRGBPixel(rval, gval, bval, lined + j);
1117  }
1118  }
1119 
1120  pixDestroy(&pixc1);
1121  pixDestroy(&pixc2);
1122  return pixd;
1123 }
1124 
1125 
1126 /*-----------------------------------------------------------------------*
1127  * Two-image min and max operations (8 and 16 bpp) *
1128  *-----------------------------------------------------------------------*/
1151 PIX *
1153  PIX *pixs1,
1154  PIX *pixs2,
1155  l_int32 type)
1156 {
1157 l_int32 d, ws, hs, w, h, wpls, wpld, i, j, vals, vald, val;
1158 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
1159 l_uint32 *datas, *datad, *lines, *lined;
1160 
1161  PROCNAME("pixMinOrMax");
1162 
1163  if (!pixs1)
1164  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1165  if (!pixs2)
1166  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1167  if (pixs1 == pixs2)
1168  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
1169  if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX)
1170  return (PIX *)ERROR_PTR("invalid type", procName, pixd);
1171  d = pixGetDepth(pixs1);
1172  if (pixGetDepth(pixs2) != d)
1173  return (PIX *)ERROR_PTR("depths unequal", procName, pixd);
1174  if (d != 8 && d != 16 && d != 32)
1175  return (PIX *)ERROR_PTR("depth not 8, 16 or 32 bpp", procName, pixd);
1176 
1177  if (pixs1 != pixd)
1178  pixd = pixCopy(pixd, pixs1);
1179 
1180  pixGetDimensions(pixs2, &ws, &hs, NULL);
1181  pixGetDimensions(pixd, &w, &h, NULL);
1182  w = L_MIN(w, ws);
1183  h = L_MIN(h, hs);
1184  datas = pixGetData(pixs2);
1185  datad = pixGetData(pixd);
1186  wpls = pixGetWpl(pixs2);
1187  wpld = pixGetWpl(pixd);
1188  for (i = 0; i < h; i++) {
1189  lines = datas + i * wpls;
1190  lined = datad + i * wpld;
1191  if (d == 8) {
1192  for (j = 0; j < w; j++) {
1193  vals = GET_DATA_BYTE(lines, j);
1194  vald = GET_DATA_BYTE(lined, j);
1195  if (type == L_CHOOSE_MIN)
1196  val = L_MIN(vals, vald);
1197  else /* type == L_CHOOSE_MAX */
1198  val = L_MAX(vals, vald);
1199  SET_DATA_BYTE(lined, j, val);
1200  }
1201  } else if (d == 16) {
1202  for (j = 0; j < w; j++) {
1203  vals = GET_DATA_TWO_BYTES(lines, j);
1204  vald = GET_DATA_TWO_BYTES(lined, j);
1205  if (type == L_CHOOSE_MIN)
1206  val = L_MIN(vals, vald);
1207  else /* type == L_CHOOSE_MAX */
1208  val = L_MAX(vals, vald);
1209  SET_DATA_TWO_BYTES(lined, j, val);
1210  }
1211  } else { /* d == 32 */
1212  for (j = 0; j < w; j++) {
1213  extractRGBValues(lines[j], &rval1, &gval1, &bval1);
1214  extractRGBValues(lined[j], &rval2, &gval2, &bval2);
1215  if (type == L_CHOOSE_MIN) {
1216  rval = L_MIN(rval1, rval2);
1217  gval = L_MIN(gval1, gval2);
1218  bval = L_MIN(bval1, bval2);
1219  } else { /* type == L_CHOOSE_MAX */
1220  rval = L_MAX(rval1, rval2);
1221  gval = L_MAX(gval1, gval2);
1222  bval = L_MAX(bval1, bval2);
1223  }
1224  composeRGBPixel(rval, gval, bval, lined + j);
1225  }
1226  }
1227  }
1228 
1229  return pixd;
1230 }
1231 
1232 
1233 /*-----------------------------------------------------------------------*
1234  * Scale for maximum dynamic range *
1235  *-----------------------------------------------------------------------*/
1252 PIX *
1254  l_int32 type)
1255 {
1256 l_uint8 dval;
1257 l_int32 i, j, w, h, d, wpls, wpld, max;
1258 l_uint32 *datas, *datad;
1259 l_uint32 word, sval;
1260 l_uint32 *lines, *lined;
1261 l_float32 factor;
1262 l_float32 *tab;
1263 PIX *pixd;
1264 
1265  PROCNAME("pixMaxDynamicRange");
1266 
1267  if (!pixs)
1268  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1269  pixGetDimensions(pixs, &w, &h, &d);
1270  if (d != 4 && d != 8 && d != 16 && d != 32)
1271  return (PIX *)ERROR_PTR("pixs not in {4,8,16,32} bpp", procName, NULL);
1272  if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
1273  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1274 
1275  if ((pixd = pixCreate(w, h, 8)) == NULL)
1276  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1277  pixCopyResolution(pixd, pixs);
1278  datas = pixGetData(pixs);
1279  datad = pixGetData(pixd);
1280  wpls = pixGetWpl(pixs);
1281  wpld = pixGetWpl(pixd);
1282 
1283  /* Get max */
1284  max = 0;
1285  for (i = 0; i < h; i++) {
1286  lines = datas + i * wpls;
1287  for (j = 0; j < wpls; j++) {
1288  word = *(lines + j);
1289  if (d == 4) {
1290  max = L_MAX(max, word >> 28);
1291  max = L_MAX(max, (word >> 24) & 0xf);
1292  max = L_MAX(max, (word >> 20) & 0xf);
1293  max = L_MAX(max, (word >> 16) & 0xf);
1294  max = L_MAX(max, (word >> 12) & 0xf);
1295  max = L_MAX(max, (word >> 8) & 0xf);
1296  max = L_MAX(max, (word >> 4) & 0xf);
1297  max = L_MAX(max, word & 0xf);
1298  } else if (d == 8) {
1299  max = L_MAX(max, word >> 24);
1300  max = L_MAX(max, (word >> 16) & 0xff);
1301  max = L_MAX(max, (word >> 8) & 0xff);
1302  max = L_MAX(max, word & 0xff);
1303  } else if (d == 16) {
1304  max = L_MAX(max, word >> 16);
1305  max = L_MAX(max, word & 0xffff);
1306  } else { /* d == 32 (rgb) */
1307  max = L_MAX(max, word);
1308  }
1309  }
1310  }
1311 
1312  /* Map to the full dynamic range */
1313  if (d == 4) {
1314  if (type == L_LINEAR_SCALE) {
1315  factor = 255. / (l_float32)max;
1316  for (i = 0; i < h; i++) {
1317  lines = datas + i * wpls;
1318  lined = datad + i * wpld;
1319  for (j = 0; j < w; j++) {
1320  sval = GET_DATA_QBIT(lines, j);
1321  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1322  SET_DATA_QBIT(lined, j, dval);
1323  }
1324  }
1325  } else { /* type == L_LOG_SCALE) */
1326  tab = makeLogBase2Tab();
1327  factor = 255. / getLogBase2(max, tab);
1328  for (i = 0; i < h; i++) {
1329  lines = datas + i * wpls;
1330  lined = datad + i * wpld;
1331  for (j = 0; j < w; j++) {
1332  sval = GET_DATA_QBIT(lines, j);
1333  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1334  SET_DATA_BYTE(lined, j, dval);
1335  }
1336  }
1337  LEPT_FREE(tab);
1338  }
1339  } else if (d == 8) {
1340  if (type == L_LINEAR_SCALE) {
1341  factor = 255. / (l_float32)max;
1342  for (i = 0; i < h; i++) {
1343  lines = datas + i * wpls;
1344  lined = datad + i * wpld;
1345  for (j = 0; j < w; j++) {
1346  sval = GET_DATA_BYTE(lines, j);
1347  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1348  SET_DATA_BYTE(lined, j, dval);
1349  }
1350  }
1351  } else { /* type == L_LOG_SCALE) */
1352  tab = makeLogBase2Tab();
1353  factor = 255. / getLogBase2(max, tab);
1354  for (i = 0; i < h; i++) {
1355  lines = datas + i * wpls;
1356  lined = datad + i * wpld;
1357  for (j = 0; j < w; j++) {
1358  sval = GET_DATA_BYTE(lines, j);
1359  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1360  SET_DATA_BYTE(lined, j, dval);
1361  }
1362  }
1363  LEPT_FREE(tab);
1364  }
1365  } else if (d == 16) {
1366  if (type == L_LINEAR_SCALE) {
1367  factor = 255. / (l_float32)max;
1368  for (i = 0; i < h; i++) {
1369  lines = datas + i * wpls;
1370  lined = datad + i * wpld;
1371  for (j = 0; j < w; j++) {
1372  sval = GET_DATA_TWO_BYTES(lines, j);
1373  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1374  SET_DATA_BYTE(lined, j, dval);
1375  }
1376  }
1377  } else { /* type == L_LOG_SCALE) */
1378  tab = makeLogBase2Tab();
1379  factor = 255. / getLogBase2(max, tab);
1380  for (i = 0; i < h; i++) {
1381  lines = datas + i * wpls;
1382  lined = datad + i * wpld;
1383  for (j = 0; j < w; j++) {
1384  sval = GET_DATA_TWO_BYTES(lines, j);
1385  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1386  SET_DATA_BYTE(lined, j, dval);
1387  }
1388  }
1389  LEPT_FREE(tab);
1390  }
1391  } else { /* d == 32 */
1392  if (type == L_LINEAR_SCALE) {
1393  factor = 255. / (l_float32)max;
1394  for (i = 0; i < h; i++) {
1395  lines = datas + i * wpls;
1396  lined = datad + i * wpld;
1397  for (j = 0; j < w; j++) {
1398  sval = lines[j];
1399  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1400  SET_DATA_BYTE(lined, j, dval);
1401  }
1402  }
1403  } else { /* type == L_LOG_SCALE) */
1404  tab = makeLogBase2Tab();
1405  factor = 255. / getLogBase2(max, tab);
1406  for (i = 0; i < h; i++) {
1407  lines = datas + i * wpls;
1408  lined = datad + i * wpld;
1409  for (j = 0; j < w; j++) {
1410  sval = lines[j];
1411  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1412  SET_DATA_BYTE(lined, j, dval);
1413  }
1414  }
1415  LEPT_FREE(tab);
1416  }
1417  }
1418 
1419  return pixd;
1420 }
1421 
1422 
1440 PIX *
1442  l_int32 type)
1443 {
1444 l_int32 i, j, w, h, wpls, wpld, max;
1445 l_uint32 sval, dval, word;
1446 l_uint32 *datas, *datad;
1447 l_uint32 *lines, *lined;
1448 l_float32 factor;
1449 l_float32 *tab;
1450 PIX *pixd;
1451 
1452  PROCNAME("pixMaxDynamicRangeRGB");
1453 
1454  if (!pixs || pixGetDepth(pixs) != 32)
1455  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1456  if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
1457  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1458 
1459  /* Get max */
1460  pixd = pixCreateTemplate(pixs);
1461  datas = pixGetData(pixs);
1462  datad = pixGetData(pixd);
1463  wpls = pixGetWpl(pixs);
1464  wpld = pixGetWpl(pixd);
1465  pixGetDimensions(pixs, &w, &h, NULL);
1466  max = 0;
1467  for (i = 0; i < h; i++) {
1468  lines = datas + i * wpls;
1469  for (j = 0; j < wpls; j++) {
1470  word = lines[j];
1471  max = L_MAX(max, word >> 24);
1472  max = L_MAX(max, (word >> 16) & 0xff);
1473  max = L_MAX(max, (word >> 8) & 0xff);
1474  }
1475  }
1476  if (max == 0) {
1477  L_WARNING("max = 0; setting to 1\n", procName);
1478  max = 1;
1479  }
1480 
1481  /* Map to the full dynamic range */
1482  if (type == L_LINEAR_SCALE) {
1483  factor = 255. / (l_float32)max;
1484  for (i = 0; i < h; i++) {
1485  lines = datas + i * wpls;
1486  lined = datad + i * wpld;
1487  for (j = 0; j < w; j++) {
1488  sval = lines[j];
1489  dval = linearScaleRGBVal(sval, factor);
1490  lined[j] = dval;
1491  }
1492  }
1493  } else { /* type == L_LOG_SCALE) */
1494  tab = makeLogBase2Tab();
1495  factor = 255. / getLogBase2(max, tab);
1496  for (i = 0; i < h; i++) {
1497  lines = datas + i * wpls;
1498  lined = datad + i * wpld;
1499  for (j = 0; j < w; j++) {
1500  sval = lines[j];
1501  dval = logScaleRGBVal(sval, tab, factor);
1502  lined[j] = dval;
1503  }
1504  }
1505  LEPT_FREE(tab);
1506  }
1507 
1508  return pixd;
1509 }
1510 
1511 
1512 /*-----------------------------------------------------------------------*
1513  * RGB pixel value scaling *
1514  *-----------------------------------------------------------------------*/
1531 l_uint32
1532 linearScaleRGBVal(l_uint32 sval,
1533  l_float32 factor)
1534 {
1535 l_uint32 dval;
1536 
1537  dval = ((l_uint8)(factor * (sval >> 24) + 0.5) << 24) |
1538  ((l_uint8)(factor * ((sval >> 16) & 0xff) + 0.5) << 16) |
1539  ((l_uint8)(factor * ((sval >> 8) & 0xff) + 0.5) << 8) |
1540  (sval & 0xff);
1541  return dval;
1542 }
1543 
1544 
1564 l_uint32
1565 logScaleRGBVal(l_uint32 sval,
1566  l_float32 *tab,
1567  l_float32 factor)
1568 {
1569 l_uint32 dval;
1570 
1571  dval = ((l_uint8)(factor * getLogBase2(sval >> 24, tab) + 0.5) << 24) |
1572  ((l_uint8)(factor * getLogBase2(((sval >> 16) & 0xff), tab) + 0.5)
1573  << 16) |
1574  ((l_uint8)(factor * getLogBase2(((sval >> 8) & 0xff), tab) + 0.5)
1575  << 8) |
1576  (sval & 0xff);
1577  return dval;
1578 }
1579 
1580 
1581 /*-----------------------------------------------------------------------*
1582  * Log base2 lookup *
1583  *-----------------------------------------------------------------------*/
1584 /*
1585  * \brief makeLogBase2Tab()
1586  *
1587  * \return tab table giving the log[base2] of values from 1 to 255
1588  */
1589 l_float32 *
1590 makeLogBase2Tab(void)
1591 {
1592 l_int32 i;
1593 l_float32 log2;
1594 l_float32 *tab;
1595 
1596  PROCNAME("makeLogBase2Tab");
1597 
1598  if ((tab = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32))) == NULL)
1599  return (l_float32 *)ERROR_PTR("tab not made", procName, NULL);
1600 
1601  log2 = (l_float32)log((l_float32)2);
1602  for (i = 0; i < 256; i++)
1603  tab[i] = (l_float32)log((l_float32)i) / log2;
1604 
1605  return tab;
1606 }
1607 
1608 
1609 /*
1610  * \brief getLogBase2()
1611  *
1612  * \param[in] val in range [0 ... 255]
1613  * \param[in] logtab 256-entry table of logs
1614  * \return logval log[base2] of %val, or 0 on error
1615  */
1616 l_float32
1617 getLogBase2(l_int32 val,
1618  l_float32 *logtab)
1619 {
1620  PROCNAME("getLogBase2");
1621 
1622  if (!logtab)
1623  return ERROR_INT("logtab not defined", procName, 0);
1624 
1625  if (val < 0x100)
1626  return logtab[val];
1627  else if (val < 0x10000)
1628  return 8.0 + logtab[val >> 8];
1629  else if (val < 0x1000000)
1630  return 16.0 + logtab[val >> 16];
1631  else
1632  return 24.0 + logtab[val >> 24];
1633 }
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
l_ok pixMultConstAccumulate(PIX *pixs, l_float32 factor, l_uint32 offset)
pixMultConstAccumulate()
Definition: pixarith.c:916
l_uint32 linearScaleRGBVal(l_uint32 sval, l_float32 factor)
linearScaleRGBVal()
Definition: pixarith.c:1532
PIX * pixMaxDynamicRange(PIX *pixs, l_int32 type)
pixMaxDynamicRange()
Definition: pixarith.c:1253
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixFinalAccumulateThreshold(PIX *pixs, l_uint32 offset, l_uint32 threshold)
pixFinalAccumulateThreshold()
Definition: pixarith.c:760
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixAddRGB(PIX *pixs1, PIX *pixs2)
pixAddRGB()
Definition: pixarith.c:1067
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixMultiplyGray(PIX *pixs, PIX *pixg, l_float32 norm)
pixMultiplyGray()
Definition: pixarith.c:449
PIX * pixMaxDynamicRangeRGB(PIX *pixs, l_int32 type)
pixMaxDynamicRangeRGB()
Definition: pixarith.c:1441
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:951
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:357
l_ok pixGetExtremeValue(PIX *pixs, l_int32 factor, l_int32 type, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *pgrayval)
pixGetExtremeValue()
Definition: pix4.c:2215
PIX * pixAbsDifference(PIX *pixs1, PIX *pixs2)
pixAbsDifference()
Definition: pixarith.c:970
PIX * pixInitAccumulate(l_int32 w, l_int32 h, l_uint32 offset)
pixInitAccumulate()
Definition: pixarith.c:649
l_ok pixAccumulate(PIX *pixd, PIX *pixs, l_int32 op)
pixAccumulate()
Definition: pixarith.c:817
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#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
PIX * pixFinalAccumulate(PIX *pixs, l_uint32 offset, l_int32 depth)
pixFinalAccumulate()
Definition: pixarith.c:683
PIX * pixThresholdToValue(PIX *pixd, PIX *pixs, l_int32 threshval, l_int32 setval)
pixThresholdToValue()
Definition: pixarith.c:540
l_uint32 logScaleRGBVal(l_uint32 sval, l_float32 *tab, l_float32 factor)
logScaleRGBVal()
Definition: pixarith.c:1565
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 * pixAddGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAddGray()
Definition: pixarith.c:265
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
Definition: pix.h:138
l_ok pixMultConstantGray(PIX *pixs, l_float32 val)
pixMultConstantGray()
Definition: pixarith.c:190
PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type)
pixMinOrMax()
Definition: pixarith.c:1152
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1985
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
l_ok pixAddConstantGray(PIX *pixs, l_int32 val)
pixAddConstantGray()
Definition: pixarith.c:119