Leptonica  1.83.1
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  if (!pixs)
126  return ERROR_INT("pixs not defined", __func__, 1);
127  pixGetDimensions(pixs, &w, &h, &d);
128  if (d != 8 && d != 16 && d != 32)
129  return ERROR_INT("pixs not 8, 16 or 32 bpp", __func__, 1);
130 
131  data = pixGetData(pixs);
132  wpl = pixGetWpl(pixs);
133  for (i = 0; i < h; i++) {
134  line = data + i * wpl;
135  if (d == 8) {
136  if (val < 0) {
137  for (j = 0; j < w; j++) {
138  pval = GET_DATA_BYTE(line, j);
139  pval = L_MAX(0, pval + val);
140  SET_DATA_BYTE(line, j, pval);
141  }
142  } else { /* val >= 0 */
143  for (j = 0; j < w; j++) {
144  pval = GET_DATA_BYTE(line, j);
145  pval = L_MIN(255, pval + val);
146  SET_DATA_BYTE(line, j, pval);
147  }
148  }
149  } else if (d == 16) {
150  if (val < 0) {
151  for (j = 0; j < w; j++) {
152  pval = GET_DATA_TWO_BYTES(line, j);
153  pval = L_MAX(0, pval + val);
154  SET_DATA_TWO_BYTES(line, j, pval);
155  }
156  } else { /* val >= 0 */
157  for (j = 0; j < w; j++) {
158  pval = GET_DATA_TWO_BYTES(line, j);
159  pval = L_MIN(0xffff, pval + val);
160  SET_DATA_TWO_BYTES(line, j, pval);
161  }
162  }
163  } else { /* d == 32; no check for overflow (< 0 or > 0xffffffff) */
164  for (j = 0; j < w; j++)
165  *(line + j) += val;
166  }
167  }
168 
169  return 0;
170 }
171 
172 
187 l_ok
189  l_float32 val)
190 {
191 l_int32 i, j, w, h, d, wpl, pval;
192 l_uint32 upval;
193 l_uint32 *data, *line;
194 
195  if (!pixs)
196  return ERROR_INT("pixs not defined", __func__, 1);
197  pixGetDimensions(pixs, &w, &h, &d);
198  if (d != 8 && d != 16 && d != 32)
199  return ERROR_INT("pixs not 8, 16 or 32 bpp", __func__, 1);
200  if (val < 0.0)
201  return ERROR_INT("val < 0.0", __func__, 1);
202 
203  data = pixGetData(pixs);
204  wpl = pixGetWpl(pixs);
205  for (i = 0; i < h; i++) {
206  line = data + i * wpl;
207  if (d == 8) {
208  for (j = 0; j < w; j++) {
209  pval = GET_DATA_BYTE(line, j);
210  pval = (l_int32)(val * pval);
211  pval = L_MIN(255, pval);
212  SET_DATA_BYTE(line, j, pval);
213  }
214  } else if (d == 16) {
215  for (j = 0; j < w; j++) {
216  pval = GET_DATA_TWO_BYTES(line, j);
217  pval = (l_int32)(val * pval);
218  pval = L_MIN(0xffff, pval);
219  SET_DATA_TWO_BYTES(line, j, pval);
220  }
221  } else { /* d == 32; no clipping */
222  for (j = 0; j < w; j++) {
223  upval = *(line + j);
224  upval = (l_uint32)(val * upval);
225  *(line + j) = upval;
226  }
227  }
228  }
229 
230  return 0;
231 }
232 
233 
234 /*-------------------------------------------------------------*
235  * Two-image grayscale arithmetic ops *
236  *-------------------------------------------------------------*/
260 PIX *
262  PIX *pixs1,
263  PIX *pixs2)
264 {
265 l_int32 i, j, d, ws, hs, w, h, wpls, wpld, val, sum;
266 l_uint32 *datas, *datad, *lines, *lined;
267 
268  if (!pixs1)
269  return (PIX *)ERROR_PTR("pixs1 not defined", __func__, pixd);
270  if (!pixs2)
271  return (PIX *)ERROR_PTR("pixs2 not defined", __func__, pixd);
272  if (pixs2 == pixs1)
273  return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", __func__, pixd);
274  if (pixs2 == pixd)
275  return (PIX *)ERROR_PTR("pixs2 and pixd must differ", __func__, pixd);
276  d = pixGetDepth(pixs1);
277  if (d != 8 && d != 16 && d != 32)
278  return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", __func__, pixd);
279  if (pixGetDepth(pixs2) != d)
280  return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", __func__, pixd);
281  if (pixd && (pixGetDepth(pixd) != d))
282  return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", __func__, pixd);
283 
284  if (!pixSizesEqual(pixs1, pixs2))
285  L_WARNING("pixs1 and pixs2 not equal in size\n", __func__);
286  if (pixd && !pixSizesEqual(pixs1, pixd))
287  L_WARNING("pixs1 and pixd not equal in size\n", __func__);
288 
289  if (pixs1 != pixd)
290  pixd = pixCopy(pixd, pixs1);
291 
292  /* pixd + pixs2 ==> pixd */
293  datas = pixGetData(pixs2);
294  datad = pixGetData(pixd);
295  wpls = pixGetWpl(pixs2);
296  wpld = pixGetWpl(pixd);
297  pixGetDimensions(pixs2, &ws, &hs, NULL);
298  pixGetDimensions(pixd, &w, &h, NULL);
299  w = L_MIN(ws, w);
300  h = L_MIN(hs, h);
301  for (i = 0; i < h; i++) {
302  lined = datad + i * wpld;
303  lines = datas + i * wpls;
304  if (d == 8) {
305  for (j = 0; j < w; j++) {
306  sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j);
307  val = L_MIN(sum, 255);
308  SET_DATA_BYTE(lined, j, val);
309  }
310  } else if (d == 16) {
311  for (j = 0; j < w; j++) {
312  sum = GET_DATA_TWO_BYTES(lines, j)
313  + GET_DATA_TWO_BYTES(lined, j);
314  val = L_MIN(sum, 0xffff);
315  SET_DATA_TWO_BYTES(lined, j, val);
316  }
317  } else { /* d == 32; no clipping */
318  for (j = 0; j < w; j++)
319  *(lined + j) += *(lines + j);
320  }
321  }
322 
323  return pixd;
324 }
325 
326 
350 PIX *
352  PIX *pixs1,
353  PIX *pixs2)
354 {
355 l_int32 i, j, w, h, ws, hs, d, wpls, wpld, val, diff;
356 l_uint32 *datas, *datad, *lines, *lined;
357 
358  if (!pixs1)
359  return (PIX *)ERROR_PTR("pixs1 not defined", __func__, pixd);
360  if (!pixs2)
361  return (PIX *)ERROR_PTR("pixs2 not defined", __func__, pixd);
362  if (pixs2 == pixs1)
363  return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", __func__, pixd);
364  if (pixs2 == pixd)
365  return (PIX *)ERROR_PTR("pixs2 and pixd must differ", __func__, pixd);
366  d = pixGetDepth(pixs1);
367  if (d != 8 && d != 16 && d != 32)
368  return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", __func__, pixd);
369  if (pixGetDepth(pixs2) != d)
370  return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", __func__, pixd);
371  if (pixd && (pixGetDepth(pixd) != d))
372  return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", __func__, pixd);
373 
374  if (!pixSizesEqual(pixs1, pixs2))
375  L_WARNING("pixs1 and pixs2 not equal in size\n", __func__);
376  if (pixd && !pixSizesEqual(pixs1, pixd))
377  L_WARNING("pixs1 and pixd not equal in size\n", __func__);
378 
379  if (pixs1 != pixd)
380  pixd = pixCopy(pixd, pixs1);
381 
382  /* pixd - pixs2 ==> pixd */
383  datas = pixGetData(pixs2);
384  datad = pixGetData(pixd);
385  wpls = pixGetWpl(pixs2);
386  wpld = pixGetWpl(pixd);
387  pixGetDimensions(pixs2, &ws, &hs, NULL);
388  pixGetDimensions(pixd, &w, &h, NULL);
389  w = L_MIN(ws, w);
390  h = L_MIN(hs, h);
391  for (i = 0; i < h; i++) {
392  lined = datad + i * wpld;
393  lines = datas + i * wpls;
394  if (d == 8) {
395  for (j = 0; j < w; j++) {
396  diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j);
397  val = L_MAX(diff, 0);
398  SET_DATA_BYTE(lined, j, val);
399  }
400  } else if (d == 16) {
401  for (j = 0; j < w; j++) {
402  diff = GET_DATA_TWO_BYTES(lined, j)
403  - GET_DATA_TWO_BYTES(lines, j);
404  val = L_MAX(diff, 0);
405  SET_DATA_TWO_BYTES(lined, j, val);
406  }
407  } else { /* d == 32; no clipping */
408  for (j = 0; j < w; j++)
409  *(lined + j) -= *(lines + j);
410  }
411  }
412 
413  return pixd;
414 }
415 
416 
440 PIX *
442  PIX *pixg,
443  l_float32 norm)
444 {
445 l_int32 i, j, w, h, d, ws, hs, ds, wpls, wplg, wpld;
446 l_int32 rval, gval, bval, rval2, gval2, bval2, vals, valg, val, maxgray;
447 l_uint32 val32;
448 l_uint32 *datas, *datag, *datad, *lines, *lineg, *lined;
449 PIX *pixd;
450 
451  if (!pixs)
452  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
453  pixGetDimensions(pixs, &ws, &hs, &ds);
454  if (ds != 8 && ds != 32)
455  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", __func__, NULL);
456  if (!pixg)
457  return (PIX *)ERROR_PTR("pixg not defined", __func__, NULL);
458  pixGetDimensions(pixg, &w, &h, &d);
459  if (d != 8)
460  return (PIX *)ERROR_PTR("pixg not 8 bpp", __func__, NULL);
461 
462  if (norm <= 0.0) {
463  pixGetExtremeValue(pixg, 1, L_SELECT_MAX, NULL, NULL, NULL, &maxgray);
464  norm = (maxgray > 0) ? 1.0 / (l_float32)maxgray : 1.0;
465  }
466 
467  if ((pixd = pixCreateTemplate(pixs)) == NULL)
468  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
469  datas = pixGetData(pixs);
470  datag = pixGetData(pixg);
471  datad = pixGetData(pixd);
472  wpls = pixGetWpl(pixs);
473  wplg = pixGetWpl(pixg);
474  wpld = pixGetWpl(pixd);
475  w = L_MIN(ws, w);
476  h = L_MIN(hs, h);
477  for (i = 0; i < h; i++) {
478  lines = datas + i * wpls;
479  lineg = datag + i * wplg;
480  lined = datad + i * wpld;
481  if (ds == 8) {
482  for (j = 0; j < w; j++) {
483  vals = GET_DATA_BYTE(lines, j);
484  valg = GET_DATA_BYTE(lineg, j);
485  val = (l_int32)(vals * valg * norm + 0.5);
486  val = L_MIN(255, val);
487  SET_DATA_BYTE(lined, j, val);
488  }
489  } else { /* ds == 32 */
490  for (j = 0; j < w; j++) {
491  val32 = *(lines + j);
492  extractRGBValues(val32, &rval, &gval, &bval);
493  valg = GET_DATA_BYTE(lineg, j);
494  rval2 = (l_int32)(rval * valg * norm + 0.5);
495  rval2 = L_MIN(255, rval2);
496  gval2 = (l_int32)(gval * valg * norm + 0.5);
497  gval2 = L_MIN(255, gval2);
498  bval2 = (l_int32)(bval * valg * norm + 0.5);
499  bval2 = L_MIN(255, bval2);
500  composeRGBPixel(rval2, gval2, bval2, lined + j);
501  }
502  }
503  }
504 
505  return pixd;
506 }
507 
508 
509 /*-------------------------------------------------------------*
510  * Grayscale threshold operation *
511  *-------------------------------------------------------------*/
529 PIX *
531  PIX *pixs,
532  l_int32 threshval,
533  l_int32 setval)
534 {
535 l_int32 i, j, w, h, d, wpld, setabove;
536 l_uint32 *datad, *lined;
537 
538  if (!pixs)
539  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
540  d = pixGetDepth(pixs);
541  if (d != 8 && d != 16 && d != 32)
542  return (PIX *)ERROR_PTR("pixs not 8, 16 or 32 bpp", __func__, pixd);
543  if (pixd && (pixs != pixd))
544  return (PIX *)ERROR_PTR("pixd exists and is not pixs", __func__, pixd);
545  if (threshval < 0 || setval < 0)
546  return (PIX *)ERROR_PTR("threshval & setval not < 0", __func__, pixd);
547  if (d == 8 && setval > 255)
548  return (PIX *)ERROR_PTR("setval > 255 for 8 bpp", __func__, pixd);
549  if (d == 16 && setval > 0xffff)
550  return (PIX *)ERROR_PTR("setval > 0xffff for 16 bpp", __func__, pixd);
551 
552  if (!pixd)
553  pixd = pixCopy(NULL, pixs);
554  if (setval == threshval) {
555  L_WARNING("setval == threshval; no operation\n", __func__);
556  return pixd;
557  }
558 
559  datad = pixGetData(pixd);
560  pixGetDimensions(pixd, &w, &h, NULL);
561  wpld = pixGetWpl(pixd);
562  if (setval > threshval)
563  setabove = TRUE;
564  else
565  setabove = FALSE;
566 
567  for (i = 0; i < h; i++) {
568  lined = datad + i * wpld;
569  if (setabove == TRUE) {
570  if (d == 8) {
571  for (j = 0; j < w; j++) {
572  if (GET_DATA_BYTE(lined, j) - threshval >= 0)
573  SET_DATA_BYTE(lined, j, setval);
574  }
575  } else if (d == 16) {
576  for (j = 0; j < w; j++) {
577  if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0)
578  SET_DATA_TWO_BYTES(lined, j, setval);
579  }
580  } else { /* d == 32 */
581  for (j = 0; j < w; j++) {
582  if (*(lined + j) >= threshval)
583  *(lined + j) = setval;
584  }
585  }
586  } else { /* set if below or at threshold */
587  if (d == 8) {
588  for (j = 0; j < w; j++) {
589  if (GET_DATA_BYTE(lined, j) - threshval <= 0)
590  SET_DATA_BYTE(lined, j, setval);
591  }
592  } else if (d == 16) {
593  for (j = 0; j < w; j++) {
594  if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0)
595  SET_DATA_TWO_BYTES(lined, j, setval);
596  }
597  } else { /* d == 32 */
598  for (j = 0; j < w; j++) {
599  if (*(lined + j) <= threshval)
600  *(lined + j) = setval;
601  }
602  }
603  }
604  }
605 
606  return pixd;
607 }
608 
609 
610 /*-------------------------------------------------------------*
611  * Image accumulator arithmetic operations *
612  *-------------------------------------------------------------*/
636 PIX *
638  l_int32 h,
639  l_uint32 offset)
640 {
641 PIX *pixd;
642 
643  if ((pixd = pixCreate(w, h, 32)) == NULL)
644  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
645  if (offset > 0x40000000)
646  offset = 0x40000000;
647  pixSetAllArbitrary(pixd, offset);
648  return pixd;
649 }
650 
651 
668 PIX *
670  l_uint32 offset,
671  l_int32 depth)
672 {
673 l_int32 i, j, w, h, wpls, wpld, val;
674 l_uint32 *datas, *datad, *lines, *lined;
675 PIX *pixd;
676 
677  if (!pixs)
678  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
679  if (pixGetDepth(pixs) != 32)
680  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
681  if (depth != 8 && depth != 16 && depth != 32)
682  return (PIX *)ERROR_PTR("dest depth not 8, 16, 32 bpp", __func__, NULL);
683  if (offset > 0x40000000)
684  offset = 0x40000000;
685 
686  pixGetDimensions(pixs, &w, &h, NULL);
687  if ((pixd = pixCreate(w, h, depth)) == NULL)
688  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
689  pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */
690  datas = pixGetData(pixs);
691  datad = pixGetData(pixd);
692  wpls = pixGetWpl(pixs);
693  wpld = pixGetWpl(pixd);
694  if (depth == 8) {
695  for (i = 0; i < h; i++) {
696  lines = datas + i * wpls;
697  lined = datad + i * wpld;
698  for (j = 0; j < w; j++) {
699  val = lines[j] - offset;
700  val = L_MAX(0, val);
701  val = L_MIN(255, val);
702  SET_DATA_BYTE(lined, j, (l_uint8)val);
703  }
704  }
705  } else if (depth == 16) {
706  for (i = 0; i < h; i++) {
707  lines = datas + i * wpls;
708  lined = datad + i * wpld;
709  for (j = 0; j < w; j++) {
710  val = lines[j] - offset;
711  val = L_MAX(0, val);
712  val = L_MIN(0xffff, val);
713  SET_DATA_TWO_BYTES(lined, j, (l_uint16)val);
714  }
715  }
716  } else { /* depth == 32 */
717  for (i = 0; i < h; i++) {
718  lines = datas + i * wpls;
719  lined = datad + i * wpld;
720  for (j = 0; j < w; j++)
721  lined[j] = lines[j] - offset;
722  }
723  }
724 
725  return pixd;
726 }
727 
728 
743 PIX *
745  l_uint32 offset,
746  l_uint32 threshold)
747 {
748 l_int32 i, j, w, h, wpls, wpld, val;
749 l_uint32 *datas, *datad, *lines, *lined;
750 PIX *pixd;
751 
752  if (!pixs)
753  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
754  if (pixGetDepth(pixs) != 32)
755  return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
756  if (offset > 0x40000000)
757  offset = 0x40000000;
758 
759  pixGetDimensions(pixs, &w, &h, NULL);
760  if ((pixd = pixCreate(w, h, 1)) == NULL)
761  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
762  pixCopyResolution(pixd, pixs); /* but how did pixs get it initially? */
763  datas = pixGetData(pixs);
764  datad = pixGetData(pixd);
765  wpls = pixGetWpl(pixs);
766  wpld = pixGetWpl(pixd);
767  for (i = 0; i < h; i++) {
768  lines = datas + i * wpls;
769  lined = datad + i * wpld;
770  for (j = 0; j < w; j++) {
771  val = lines[j] - offset;
772  if (val >= threshold) {
773  SET_DATA_BIT(lined, j);
774  }
775  }
776  }
777 
778  return pixd;
779 }
780 
781 
798 l_ok
800  PIX *pixs,
801  l_int32 op)
802 {
803 l_int32 i, j, w, h, d, wd, hd, wpls, wpld;
804 l_uint32 *datas, *datad, *lines, *lined;
805 
806 
807  if (!pixd || (pixGetDepth(pixd) != 32))
808  return ERROR_INT("pixd not defined or not 32 bpp", __func__, 1);
809  if (!pixs)
810  return ERROR_INT("pixs not defined", __func__, 1);
811  d = pixGetDepth(pixs);
812  if (d != 1 && d != 8 && d != 16 && d != 32)
813  return ERROR_INT("pixs not 1, 8, 16 or 32 bpp", __func__, 1);
814  if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT)
815  return ERROR_INT("op must be in {L_ARITH_ADD, L_ARITH_SUBTRACT}",
816  __func__, 1);
817 
818  datas = pixGetData(pixs);
819  datad = pixGetData(pixd);
820  wpls = pixGetWpl(pixs);
821  wpld = pixGetWpl(pixd);
822  pixGetDimensions(pixs, &w, &h, NULL);
823  pixGetDimensions(pixd, &wd, &hd, NULL);
824  w = L_MIN(w, wd);
825  h = L_MIN(h, hd);
826  if (d == 1) {
827  for (i = 0; i < h; i++) {
828  lines = datas + i * wpls;
829  lined = datad + i * wpld;
830  if (op == L_ARITH_ADD) {
831  for (j = 0; j < w; j++)
832  lined[j] += GET_DATA_BIT(lines, j);
833  } else { /* op == L_ARITH_SUBTRACT */
834  for (j = 0; j < w; j++)
835  lined[j] -= GET_DATA_BIT(lines, j);
836  }
837  }
838  } else if (d == 8) {
839  for (i = 0; i < h; i++) {
840  lines = datas + i * wpls;
841  lined = datad + i * wpld;
842  if (op == L_ARITH_ADD) {
843  for (j = 0; j < w; j++)
844  lined[j] += GET_DATA_BYTE(lines, j);
845  } else { /* op == L_ARITH_SUBTRACT */
846  for (j = 0; j < w; j++)
847  lined[j] -= GET_DATA_BYTE(lines, j);
848  }
849  }
850  } else if (d == 16) {
851  for (i = 0; i < h; i++) {
852  lines = datas + i * wpls;
853  lined = datad + i * wpld;
854  if (op == L_ARITH_ADD) {
855  for (j = 0; j < w; j++)
856  lined[j] += GET_DATA_TWO_BYTES(lines, j);
857  } else { /* op == L_ARITH_SUBTRACT */
858  for (j = 0; j < w; j++)
859  lined[j] -= GET_DATA_TWO_BYTES(lines, j);
860  }
861  }
862  } else { /* d == 32 */
863  for (i = 0; i < h; i++) {
864  lines = datas + i * wpls;
865  lined = datad + i * wpld;
866  if (op == L_ARITH_ADD) {
867  for (j = 0; j < w; j++)
868  lined[j] += lines[j];
869  } else { /* op == L_ARITH_SUBTRACT */
870  for (j = 0; j < w; j++)
871  lined[j] -= lines[j];
872  }
873  }
874  }
875 
876  return 0;
877 }
878 
879 
895 l_ok
897  l_float32 factor,
898  l_uint32 offset)
899 {
900 l_int32 i, j, w, h, wpl, val;
901 l_uint32 *data, *line;
902 
903  if (!pixs)
904  return ERROR_INT("pixs not defined", __func__, 1);
905  if (pixGetDepth(pixs) != 32)
906  return ERROR_INT("pixs not 32 bpp", __func__, 1);
907  if (offset > 0x40000000)
908  offset = 0x40000000;
909 
910  pixGetDimensions(pixs, &w, &h, NULL);
911  data = pixGetData(pixs);
912  wpl = pixGetWpl(pixs);
913  for (i = 0; i < h; i++) {
914  line = data + i * wpl;
915  for (j = 0; j < w; j++) {
916  val = line[j] - offset;
917  val = (l_int32)(val * factor);
918  val += offset;
919  line[j] = (l_uint32)val;
920  }
921  }
922 
923  return 0;
924 }
925 
926 
927 /*-----------------------------------------------------------------------*
928  * Absolute value of difference *
929  *-----------------------------------------------------------------------*/
947 PIX *
949  PIX *pixs2)
950 {
951 l_int32 i, j, w, h, w2, h2, d, wpls1, wpls2, wpld, val1, val2, diff;
952 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rdiff, gdiff, bdiff;
953 l_uint32 *datas1, *datas2, *datad, *lines1, *lines2, *lined;
954 PIX *pixd;
955 
956  if (!pixs1)
957  return (PIX *)ERROR_PTR("pixs1 not defined", __func__, NULL);
958  if (!pixs2)
959  return (PIX *)ERROR_PTR("pixs2 not defined", __func__, NULL);
960  d = pixGetDepth(pixs1);
961  if (d != pixGetDepth(pixs2))
962  return (PIX *)ERROR_PTR("src1 and src2 depths unequal", __func__, NULL);
963  if (d != 8 && d != 16 && d != 32)
964  return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", __func__, NULL);
965 
966  pixGetDimensions(pixs1, &w, &h, NULL);
967  pixGetDimensions(pixs2, &w2, &h2, NULL);
968  w = L_MIN(w, w2);
969  h = L_MIN(h, h2);
970  if ((pixd = pixCreate(w, h, d)) == NULL)
971  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
972  pixCopyResolution(pixd, pixs1);
973  datas1 = pixGetData(pixs1);
974  datas2 = pixGetData(pixs2);
975  datad = pixGetData(pixd);
976  wpls1 = pixGetWpl(pixs1);
977  wpls2 = pixGetWpl(pixs2);
978  wpld = pixGetWpl(pixd);
979  if (d == 8) {
980  for (i = 0; i < h; i++) {
981  lines1 = datas1 + i * wpls1;
982  lines2 = datas2 + i * wpls2;
983  lined = datad + i * wpld;
984  for (j = 0; j < w; j++) {
985  val1 = GET_DATA_BYTE(lines1, j);
986  val2 = GET_DATA_BYTE(lines2, j);
987  diff = L_ABS(val1 - val2);
988  SET_DATA_BYTE(lined, j, diff);
989  }
990  }
991  } else if (d == 16) {
992  for (i = 0; i < h; i++) {
993  lines1 = datas1 + i * wpls1;
994  lines2 = datas2 + i * wpls2;
995  lined = datad + i * wpld;
996  for (j = 0; j < w; j++) {
997  val1 = GET_DATA_TWO_BYTES(lines1, j);
998  val2 = GET_DATA_TWO_BYTES(lines2, j);
999  diff = L_ABS(val1 - val2);
1000  SET_DATA_TWO_BYTES(lined, j, diff);
1001  }
1002  }
1003  } else { /* d == 32 */
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  extractRGBValues(lines1[j], &rval1, &gval1, &bval1);
1010  extractRGBValues(lines2[j], &rval2, &gval2, &bval2);
1011  rdiff = L_ABS(rval1 - rval2);
1012  gdiff = L_ABS(gval1 - gval2);
1013  bdiff = L_ABS(bval1 - bval2);
1014  composeRGBPixel(rdiff, gdiff, bdiff, lined + j);
1015  }
1016  }
1017  }
1018 
1019  return pixd;
1020 }
1021 
1022 
1023 /*-----------------------------------------------------------------------*
1024  * Sum of color images *
1025  *-----------------------------------------------------------------------*/
1042 PIX *
1044  PIX *pixs2)
1045 {
1046 l_int32 i, j, w, h, d, w2, h2, d2, wplc1, wplc2, wpld;
1047 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
1048 l_uint32 *datac1, *datac2, *datad, *linec1, *linec2, *lined;
1049 PIX *pixc1, *pixc2, *pixd;
1050 
1051  if (!pixs1)
1052  return (PIX *)ERROR_PTR("pixs1 not defined", __func__, NULL);
1053  if (!pixs2)
1054  return (PIX *)ERROR_PTR("pixs2 not defined", __func__, NULL);
1055  pixGetDimensions(pixs1, &w, &h, &d);
1056  pixGetDimensions(pixs2, &w2, &h2, &d2);
1057  if (!pixGetColormap(pixs1) && d != 32)
1058  return (PIX *)ERROR_PTR("pixs1 not cmapped or rgb", __func__, NULL);
1059  if (!pixGetColormap(pixs2) && d2 != 32)
1060  return (PIX *)ERROR_PTR("pixs2 not cmapped or rgb", __func__, NULL);
1061  if (pixGetColormap(pixs1))
1063  else
1064  pixc1 = pixClone(pixs1);
1065  if (pixGetColormap(pixs2))
1067  else
1068  pixc2 = pixClone(pixs2);
1069 
1070  w = L_MIN(w, w2);
1071  h = L_MIN(h, h2);
1072  pixd = pixCreate(w, h, 32);
1073  pixCopyResolution(pixd, pixs1);
1074  datac1 = pixGetData(pixc1);
1075  datac2 = pixGetData(pixc2);
1076  datad = pixGetData(pixd);
1077  wplc1 = pixGetWpl(pixc1);
1078  wplc2 = pixGetWpl(pixc2);
1079  wpld = pixGetWpl(pixd);
1080  for (i = 0; i < h; i++) {
1081  linec1 = datac1 + i * wplc1;
1082  linec2 = datac2 + i * wplc2;
1083  lined = datad + i * wpld;
1084  for (j = 0; j < w; j++) {
1085  extractRGBValues(linec1[j], &rval1, &gval1, &bval1);
1086  extractRGBValues(linec2[j], &rval2, &gval2, &bval2);
1087  rval = L_MIN(255, rval1 + rval2);
1088  gval = L_MIN(255, gval1 + gval2);
1089  bval = L_MIN(255, bval1 + bval2);
1090  composeRGBPixel(rval, gval, bval, lined + j);
1091  }
1092  }
1093 
1094  pixDestroy(&pixc1);
1095  pixDestroy(&pixc2);
1096  return pixd;
1097 }
1098 
1099 
1100 /*-----------------------------------------------------------------------*
1101  * Two-image min and max operations (8 and 16 bpp) *
1102  *-----------------------------------------------------------------------*/
1125 PIX *
1127  PIX *pixs1,
1128  PIX *pixs2,
1129  l_int32 type)
1130 {
1131 l_int32 d, ws, hs, w, h, wpls, wpld, i, j, vals, vald, val;
1132 l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
1133 l_uint32 *datas, *datad, *lines, *lined;
1134 
1135  if (!pixs1)
1136  return (PIX *)ERROR_PTR("pixs1 not defined", __func__, pixd);
1137  if (!pixs2)
1138  return (PIX *)ERROR_PTR("pixs2 not defined", __func__, pixd);
1139  if (pixs1 == pixs2)
1140  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", __func__, pixd);
1141  if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX)
1142  return (PIX *)ERROR_PTR("invalid type", __func__, pixd);
1143  d = pixGetDepth(pixs1);
1144  if (pixGetDepth(pixs2) != d)
1145  return (PIX *)ERROR_PTR("depths unequal", __func__, pixd);
1146  if (d != 8 && d != 16 && d != 32)
1147  return (PIX *)ERROR_PTR("depth not 8, 16 or 32 bpp", __func__, pixd);
1148 
1149  if (pixs1 != pixd)
1150  pixd = pixCopy(pixd, pixs1);
1151 
1152  pixGetDimensions(pixs2, &ws, &hs, NULL);
1153  pixGetDimensions(pixd, &w, &h, NULL);
1154  w = L_MIN(w, ws);
1155  h = L_MIN(h, hs);
1156  datas = pixGetData(pixs2);
1157  datad = pixGetData(pixd);
1158  wpls = pixGetWpl(pixs2);
1159  wpld = pixGetWpl(pixd);
1160  for (i = 0; i < h; i++) {
1161  lines = datas + i * wpls;
1162  lined = datad + i * wpld;
1163  if (d == 8) {
1164  for (j = 0; j < w; j++) {
1165  vals = GET_DATA_BYTE(lines, j);
1166  vald = GET_DATA_BYTE(lined, j);
1167  if (type == L_CHOOSE_MIN)
1168  val = L_MIN(vals, vald);
1169  else /* type == L_CHOOSE_MAX */
1170  val = L_MAX(vals, vald);
1171  SET_DATA_BYTE(lined, j, val);
1172  }
1173  } else if (d == 16) {
1174  for (j = 0; j < w; j++) {
1175  vals = GET_DATA_TWO_BYTES(lines, j);
1176  vald = GET_DATA_TWO_BYTES(lined, j);
1177  if (type == L_CHOOSE_MIN)
1178  val = L_MIN(vals, vald);
1179  else /* type == L_CHOOSE_MAX */
1180  val = L_MAX(vals, vald);
1181  SET_DATA_TWO_BYTES(lined, j, val);
1182  }
1183  } else { /* d == 32 */
1184  for (j = 0; j < w; j++) {
1185  extractRGBValues(lines[j], &rval1, &gval1, &bval1);
1186  extractRGBValues(lined[j], &rval2, &gval2, &bval2);
1187  if (type == L_CHOOSE_MIN) {
1188  rval = L_MIN(rval1, rval2);
1189  gval = L_MIN(gval1, gval2);
1190  bval = L_MIN(bval1, bval2);
1191  } else { /* type == L_CHOOSE_MAX */
1192  rval = L_MAX(rval1, rval2);
1193  gval = L_MAX(gval1, gval2);
1194  bval = L_MAX(bval1, bval2);
1195  }
1196  composeRGBPixel(rval, gval, bval, lined + j);
1197  }
1198  }
1199  }
1200 
1201  return pixd;
1202 }
1203 
1204 
1205 /*-----------------------------------------------------------------------*
1206  * Scale for maximum dynamic range *
1207  *-----------------------------------------------------------------------*/
1224 PIX *
1226  l_int32 type)
1227 {
1228 l_uint8 dval;
1229 l_int32 i, j, w, h, d, wpls, wpld, max;
1230 l_uint32 *datas, *datad;
1231 l_uint32 word, sval;
1232 l_uint32 *lines, *lined;
1233 l_float32 factor;
1234 l_float32 *tab;
1235 PIX *pixd;
1236 
1237  if (!pixs)
1238  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1239  pixGetDimensions(pixs, &w, &h, &d);
1240  if (d != 4 && d != 8 && d != 16 && d != 32)
1241  return (PIX *)ERROR_PTR("pixs not in {4,8,16,32} bpp", __func__, NULL);
1242  if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
1243  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
1244 
1245  if ((pixd = pixCreate(w, h, 8)) == NULL)
1246  return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1247  pixCopyResolution(pixd, pixs);
1248  datas = pixGetData(pixs);
1249  datad = pixGetData(pixd);
1250  wpls = pixGetWpl(pixs);
1251  wpld = pixGetWpl(pixd);
1252 
1253  /* Get max */
1254  max = 0;
1255  for (i = 0; i < h; i++) {
1256  lines = datas + i * wpls;
1257  for (j = 0; j < wpls; j++) {
1258  word = *(lines + j);
1259  if (d == 4) {
1260  max = L_MAX(max, word >> 28);
1261  max = L_MAX(max, (word >> 24) & 0xf);
1262  max = L_MAX(max, (word >> 20) & 0xf);
1263  max = L_MAX(max, (word >> 16) & 0xf);
1264  max = L_MAX(max, (word >> 12) & 0xf);
1265  max = L_MAX(max, (word >> 8) & 0xf);
1266  max = L_MAX(max, (word >> 4) & 0xf);
1267  max = L_MAX(max, word & 0xf);
1268  } else if (d == 8) {
1269  max = L_MAX(max, word >> 24);
1270  max = L_MAX(max, (word >> 16) & 0xff);
1271  max = L_MAX(max, (word >> 8) & 0xff);
1272  max = L_MAX(max, word & 0xff);
1273  } else if (d == 16) {
1274  max = L_MAX(max, word >> 16);
1275  max = L_MAX(max, word & 0xffff);
1276  } else { /* d == 32 (rgb) */
1277  max = L_MAX(max, word);
1278  }
1279  }
1280  }
1281 
1282  /* Map to the full dynamic range */
1283  if (d == 4) {
1284  if (type == L_LINEAR_SCALE) {
1285  factor = 255. / (l_float32)max;
1286  for (i = 0; i < h; i++) {
1287  lines = datas + i * wpls;
1288  lined = datad + i * wpld;
1289  for (j = 0; j < w; j++) {
1290  sval = GET_DATA_QBIT(lines, j);
1291  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1292  SET_DATA_QBIT(lined, j, dval);
1293  }
1294  }
1295  } else { /* type == L_LOG_SCALE) */
1296  tab = makeLogBase2Tab();
1297  factor = 255. / getLogBase2(max, tab);
1298  for (i = 0; i < h; i++) {
1299  lines = datas + i * wpls;
1300  lined = datad + i * wpld;
1301  for (j = 0; j < w; j++) {
1302  sval = GET_DATA_QBIT(lines, j);
1303  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1304  SET_DATA_BYTE(lined, j, dval);
1305  }
1306  }
1307  LEPT_FREE(tab);
1308  }
1309  } else if (d == 8) {
1310  if (type == L_LINEAR_SCALE) {
1311  factor = 255. / (l_float32)max;
1312  for (i = 0; i < h; i++) {
1313  lines = datas + i * wpls;
1314  lined = datad + i * wpld;
1315  for (j = 0; j < w; j++) {
1316  sval = GET_DATA_BYTE(lines, j);
1317  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1318  SET_DATA_BYTE(lined, j, dval);
1319  }
1320  }
1321  } else { /* type == L_LOG_SCALE) */
1322  tab = makeLogBase2Tab();
1323  factor = 255. / getLogBase2(max, tab);
1324  for (i = 0; i < h; i++) {
1325  lines = datas + i * wpls;
1326  lined = datad + i * wpld;
1327  for (j = 0; j < w; j++) {
1328  sval = GET_DATA_BYTE(lines, j);
1329  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1330  SET_DATA_BYTE(lined, j, dval);
1331  }
1332  }
1333  LEPT_FREE(tab);
1334  }
1335  } else if (d == 16) {
1336  if (type == L_LINEAR_SCALE) {
1337  factor = 255. / (l_float32)max;
1338  for (i = 0; i < h; i++) {
1339  lines = datas + i * wpls;
1340  lined = datad + i * wpld;
1341  for (j = 0; j < w; j++) {
1342  sval = GET_DATA_TWO_BYTES(lines, j);
1343  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1344  SET_DATA_BYTE(lined, j, dval);
1345  }
1346  }
1347  } else { /* type == L_LOG_SCALE) */
1348  tab = makeLogBase2Tab();
1349  factor = 255. / getLogBase2(max, tab);
1350  for (i = 0; i < h; i++) {
1351  lines = datas + i * wpls;
1352  lined = datad + i * wpld;
1353  for (j = 0; j < w; j++) {
1354  sval = GET_DATA_TWO_BYTES(lines, j);
1355  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1356  SET_DATA_BYTE(lined, j, dval);
1357  }
1358  }
1359  LEPT_FREE(tab);
1360  }
1361  } else { /* d == 32 */
1362  if (type == L_LINEAR_SCALE) {
1363  factor = 255. / (l_float32)max;
1364  for (i = 0; i < h; i++) {
1365  lines = datas + i * wpls;
1366  lined = datad + i * wpld;
1367  for (j = 0; j < w; j++) {
1368  sval = lines[j];
1369  dval = (l_uint8)(factor * (l_float32)sval + 0.5);
1370  SET_DATA_BYTE(lined, j, dval);
1371  }
1372  }
1373  } else { /* type == L_LOG_SCALE) */
1374  tab = makeLogBase2Tab();
1375  factor = 255. / getLogBase2(max, tab);
1376  for (i = 0; i < h; i++) {
1377  lines = datas + i * wpls;
1378  lined = datad + i * wpld;
1379  for (j = 0; j < w; j++) {
1380  sval = lines[j];
1381  dval = (l_uint8)(factor * getLogBase2(sval, tab) + 0.5);
1382  SET_DATA_BYTE(lined, j, dval);
1383  }
1384  }
1385  LEPT_FREE(tab);
1386  }
1387  }
1388 
1389  return pixd;
1390 }
1391 
1392 
1410 PIX *
1412  l_int32 type)
1413 {
1414 l_int32 i, j, w, h, wpls, wpld, max;
1415 l_uint32 sval, dval, word;
1416 l_uint32 *datas, *datad;
1417 l_uint32 *lines, *lined;
1418 l_float32 factor;
1419 l_float32 *tab;
1420 PIX *pixd;
1421 
1422  if (!pixs || pixGetDepth(pixs) != 32)
1423  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
1424  if (type != L_LINEAR_SCALE && type != L_LOG_SCALE)
1425  return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
1426 
1427  /* Get max */
1428  pixd = pixCreateTemplate(pixs);
1429  datas = pixGetData(pixs);
1430  datad = pixGetData(pixd);
1431  wpls = pixGetWpl(pixs);
1432  wpld = pixGetWpl(pixd);
1433  pixGetDimensions(pixs, &w, &h, NULL);
1434  max = 0;
1435  for (i = 0; i < h; i++) {
1436  lines = datas + i * wpls;
1437  for (j = 0; j < wpls; j++) {
1438  word = lines[j];
1439  max = L_MAX(max, word >> 24);
1440  max = L_MAX(max, (word >> 16) & 0xff);
1441  max = L_MAX(max, (word >> 8) & 0xff);
1442  }
1443  }
1444  if (max == 0) {
1445  L_WARNING("max = 0; setting to 1\n", __func__);
1446  max = 1;
1447  }
1448 
1449  /* Map to the full dynamic range */
1450  if (type == L_LINEAR_SCALE) {
1451  factor = 255. / (l_float32)max;
1452  for (i = 0; i < h; i++) {
1453  lines = datas + i * wpls;
1454  lined = datad + i * wpld;
1455  for (j = 0; j < w; j++) {
1456  sval = lines[j];
1457  dval = linearScaleRGBVal(sval, factor);
1458  lined[j] = dval;
1459  }
1460  }
1461  } else { /* type == L_LOG_SCALE) */
1462  tab = makeLogBase2Tab();
1463  factor = 255. / getLogBase2(max, tab);
1464  for (i = 0; i < h; i++) {
1465  lines = datas + i * wpls;
1466  lined = datad + i * wpld;
1467  for (j = 0; j < w; j++) {
1468  sval = lines[j];
1469  dval = logScaleRGBVal(sval, tab, factor);
1470  lined[j] = dval;
1471  }
1472  }
1473  LEPT_FREE(tab);
1474  }
1475 
1476  return pixd;
1477 }
1478 
1479 
1480 /*-----------------------------------------------------------------------*
1481  * RGB pixel value scaling *
1482  *-----------------------------------------------------------------------*/
1499 l_uint32
1500 linearScaleRGBVal(l_uint32 sval,
1501  l_float32 factor)
1502 {
1503 l_uint32 dval;
1504 
1505  dval = ((l_uint8)(factor * (sval >> 24) + 0.5) << 24) |
1506  ((l_uint8)(factor * ((sval >> 16) & 0xff) + 0.5) << 16) |
1507  ((l_uint8)(factor * ((sval >> 8) & 0xff) + 0.5) << 8) |
1508  (sval & 0xff);
1509  return dval;
1510 }
1511 
1512 
1532 l_uint32
1533 logScaleRGBVal(l_uint32 sval,
1534  l_float32 *tab,
1535  l_float32 factor)
1536 {
1537 l_uint32 dval;
1538 
1539  dval = ((l_uint8)(factor * getLogBase2(sval >> 24, tab) + 0.5) << 24) |
1540  ((l_uint8)(factor * getLogBase2(((sval >> 16) & 0xff), tab) + 0.5)
1541  << 16) |
1542  ((l_uint8)(factor * getLogBase2(((sval >> 8) & 0xff), tab) + 0.5)
1543  << 8) |
1544  (sval & 0xff);
1545  return dval;
1546 }
1547 
1548 
1549 /*-----------------------------------------------------------------------*
1550  * Log base2 lookup *
1551  *-----------------------------------------------------------------------*/
1552 /*
1553  * \brief makeLogBase2Tab()
1554  *
1555  * \return tab table giving the log[base2] of values from 1 to 255
1556  */
1557 l_float32 *
1558 makeLogBase2Tab(void)
1559 {
1560 l_int32 i;
1561 l_float32 log2;
1562 l_float32 *tab;
1563 
1564  if ((tab = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32))) == NULL)
1565  return (l_float32 *)ERROR_PTR("tab not made", __func__, NULL);
1566 
1567  log2 = (l_float32)log((l_float32)2);
1568  for (i = 0; i < 256; i++)
1569  tab[i] = (l_float32)log((l_float32)i) / log2;
1570 
1571  return tab;
1572 }
1573 
1574 
1575 /*
1576  * \brief getLogBase2()
1577  *
1578  * \param[in] val in range [0 ... 255]
1579  * \param[in] logtab 256-entry table of logs
1580  * \return logval log[base2] of %val, or 0 on error
1581  */
1582 l_float32
1583 getLogBase2(l_int32 val,
1584  l_float32 *logtab)
1585 {
1586  if (!logtab)
1587  return ERROR_INT("logtab not defined", __func__, 0);
1588 
1589  if (val < 0x100)
1590  return logtab[val];
1591  else if (val < 0x10000)
1592  return 8.0 + logtab[val >> 8];
1593  else if (val < 0x1000000)
1594  return 16.0 + logtab[val >> 16];
1595  else
1596  return 24.0 + logtab[val >> 24];
1597 }
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1878
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:929
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:2165
@ L_SELECT_MAX
Definition: pix.h:619
@ REMOVE_CMAP_TO_FULL_COLOR
Definition: pix.h:382
PIX * pixMaxDynamicRange(PIX *pixs, l_int32 type)
pixMaxDynamicRange()
Definition: pixarith.c:1225
l_ok pixMultConstAccumulate(PIX *pixs, l_float32 factor, l_uint32 offset)
pixMultConstAccumulate()
Definition: pixarith.c:896
PIX * pixInitAccumulate(l_int32 w, l_int32 h, l_uint32 offset)
pixInitAccumulate()
Definition: pixarith.c:637
l_ok pixAddConstantGray(PIX *pixs, l_int32 val)
pixAddConstantGray()
Definition: pixarith.c:119
l_uint32 logScaleRGBVal(l_uint32 sval, l_float32 *tab, l_float32 factor)
logScaleRGBVal()
Definition: pixarith.c:1533
PIX * pixAddRGB(PIX *pixs1, PIX *pixs2)
pixAddRGB()
Definition: pixarith.c:1043
l_ok pixMultConstantGray(PIX *pixs, l_float32 val)
pixMultConstantGray()
Definition: pixarith.c:188
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:351
PIX * pixThresholdToValue(PIX *pixd, PIX *pixs, l_int32 threshval, l_int32 setval)
pixThresholdToValue()
Definition: pixarith.c:530
l_uint32 linearScaleRGBVal(l_uint32 sval, l_float32 factor)
linearScaleRGBVal()
Definition: pixarith.c:1500
PIX * pixFinalAccumulate(PIX *pixs, l_uint32 offset, l_int32 depth)
pixFinalAccumulate()
Definition: pixarith.c:669
PIX * pixAddGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAddGray()
Definition: pixarith.c:261
PIX * pixFinalAccumulateThreshold(PIX *pixs, l_uint32 offset, l_uint32 threshold)
pixFinalAccumulateThreshold()
Definition: pixarith.c:744
PIX * pixMaxDynamicRangeRGB(PIX *pixs, l_int32 type)
pixMaxDynamicRangeRGB()
Definition: pixarith.c:1411
PIX * pixMultiplyGray(PIX *pixs, PIX *pixg, l_float32 norm)
pixMultiplyGray()
Definition: pixarith.c:441
l_ok pixAccumulate(PIX *pixd, PIX *pixs, l_int32 op)
pixAccumulate()
Definition: pixarith.c:799
PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type)
pixMinOrMax()
Definition: pixarith.c:1126
PIX * pixAbsDifference(PIX *pixs1, PIX *pixs2)
pixAbsDifference()
Definition: pixarith.c:948
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324