• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -  This software is distributed in the hope that it will be
4  -  useful, but with NO WARRANTY OF ANY KIND.
5  -  No author or distributor accepts responsibility to anyone for the
6  -  consequences of using this software, or for whether it serves any
7  -  particular purpose or works at all, unless he or she says so in
8  -  writing.  Everyone is granted permission to copy, modify and
9  -  redistribute this source code, for commercial or non-commercial
10  -  purposes, with the following restrictions: (1) the origin of this
11  -  source code must not be misrepresented; (2) modified versions must
12  -  be plainly marked as such; and (3) this notice may not be removed
13  -  or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 
17 /*
18  *  arithlow.c
19  *
20  *      One image grayscale arithmetic (8, 16 or 32 bpp)
21  *            void       addConstantGrayLow()
22  *            void       multConstantGrayLow()
23  *
24  *      Two image grayscale arithmetic (8, 16 or 32 bpp)
25  *            void       addGrayLow()
26  *            void       subtractGrayLow()
27  *
28  *      Grayscale threshold operation (8, 16 or 32 bpp)
29  *            void       thresholdToValueLow()
30  *
31  *      Image accumulator arithmetic operations (8, 16, 32 bpp)
32  *            void       finalAccumulateLow()
33  *            void       finalAccumulateThreshLow()
34  *            void       accumulateLow()
35  *            void       multConstAccumulateLow()
36  *
37  *      Absolute value of difference, component-wise.
38  *            void       absDifferenceLow()
39  */
40 
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <math.h>
46 #include "allheaders.h"
47 
48 
49 /*------------------------------------------------------------------*
50  *        One image grayscale arithmetic (8, 16 or 32 bpp)          *
51  *------------------------------------------------------------------*/
52 /*!
53  *  addConstantGrayLow()
54  */
55 void
addConstantGrayLow(l_uint32 * data,l_int32 w,l_int32 h,l_int32 d,l_int32 wpl,l_int32 val)56 addConstantGrayLow(l_uint32  *data,
57                    l_int32    w,
58                    l_int32    h,
59                    l_int32    d,
60                    l_int32    wpl,
61                    l_int32    val)
62 {
63 l_int32    i, j, pval;
64 l_uint32  *line;
65 
66     for (i = 0; i < h; i++) {
67         line = data + i * wpl;
68         if (d == 8) {
69             if (val < 0) {
70                 for (j = 0; j < w; j++) {
71                     pval = GET_DATA_BYTE(line, j);
72                     pval = L_MAX(0, pval + val);
73                     SET_DATA_BYTE(line, j, pval);
74                 }
75             }
76             else {  /* val >= 0 */
77                 for (j = 0; j < w; j++) {
78                     pval = GET_DATA_BYTE(line, j);
79                     pval = L_MIN(255, pval + val);
80                     SET_DATA_BYTE(line, j, pval);
81                 }
82             }
83         }
84         else if (d == 16) {
85             if (val < 0) {
86                 for (j = 0; j < w; j++) {
87                     pval = GET_DATA_TWO_BYTES(line, j);
88                     pval = L_MAX(0, pval + val);
89                     SET_DATA_TWO_BYTES(line, j, pval);
90                 }
91             }
92             else {  /* val >= 0 */
93                 for (j = 0; j < w; j++) {
94                     pval = GET_DATA_TWO_BYTES(line, j);
95                     pval = L_MIN(0xffff, pval + val);
96                     SET_DATA_TWO_BYTES(line, j, pval);
97                 }
98             }
99         }
100         else {  /* d == 32; no check for overflow (< 0 or > 0xffffffff) */
101             for (j = 0; j < w; j++)
102                 *(line + j) += val;
103         }
104     }
105     return;
106 }
107 
108 
109 /*!
110  *  multConstantGrayLow()
111  */
112 void
multConstantGrayLow(l_uint32 * data,l_int32 w,l_int32 h,l_int32 d,l_int32 wpl,l_float32 val)113 multConstantGrayLow(l_uint32  *data,
114                     l_int32    w,
115                     l_int32    h,
116                     l_int32    d,
117                     l_int32    wpl,
118                     l_float32  val)
119 {
120 l_int32    i, j, pval;
121 l_uint32   upval;
122 l_uint32  *line;
123 
124     for (i = 0; i < h; i++) {
125         line = data + i * wpl;
126         if (d == 8) {
127             for (j = 0; j < w; j++) {
128                 pval = GET_DATA_BYTE(line, j);
129                 pval = (l_int32)(val * pval);
130                 pval = L_MIN(255, pval);
131                 SET_DATA_BYTE(line, j, pval);
132             }
133         }
134         else if (d == 16) {
135             for (j = 0; j < w; j++) {
136                 pval = GET_DATA_TWO_BYTES(line, j);
137                 pval = (l_int32)(val * pval);
138                 pval = L_MIN(0xffff, pval);
139                 SET_DATA_TWO_BYTES(line, j, pval);
140             }
141         }
142         else {  /* d == 32; no clipping */
143             for (j = 0; j < w; j++) {
144                 upval = *(line + j);
145                 upval = (l_uint32)(val * upval);
146                 *(line + j) = upval;
147             }
148         }
149     }
150     return;
151 }
152 
153 
154 /*------------------------------------------------------------------*
155  *        Two image grayscale arithmetic (8, 16 or 32 bpp)          *
156  *------------------------------------------------------------------*/
157 /*!
158  *  addGrayLow()
159  */
160 void
addGrayLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 d,l_int32 wpld,l_uint32 * datas,l_int32 wpls)161 addGrayLow(l_uint32  *datad,
162            l_int32    w,
163            l_int32    h,
164            l_int32    d,
165            l_int32    wpld,
166            l_uint32  *datas,
167            l_int32    wpls)
168 {
169 l_int32    i, j, val, sum;
170 l_uint32  *lines, *lined;
171 
172 
173     for (i = 0; i < h; i++) {
174         lined = datad + i * wpld;
175         lines = datas + i * wpls;
176         if (d == 8) {
177             for (j = 0; j < w; j++) {
178                 sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j);
179                 val = L_MIN(sum, 255);
180                 SET_DATA_BYTE(lined, j, val);
181             }
182         }
183         else if (d == 16) {
184             for (j = 0; j < w; j++) {
185                 sum = GET_DATA_TWO_BYTES(lines, j)
186                       + GET_DATA_TWO_BYTES(lined, j);
187                 val = L_MIN(sum, 0xffff);
188                 SET_DATA_TWO_BYTES(lined, j, val);
189             }
190         }
191         else {   /* d == 32; no clipping */
192             for (j = 0; j < w; j++)
193                 *(lined + j) += *(lines + j);
194         }
195     }
196 
197     return;
198 }
199 
200 
201 /*!
202  *  subtractGrayLow()
203  */
204 void
subtractGrayLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 d,l_int32 wpld,l_uint32 * datas,l_int32 wpls)205 subtractGrayLow(l_uint32  *datad,
206                 l_int32    w,
207                 l_int32    h,
208                 l_int32    d,
209                 l_int32    wpld,
210                 l_uint32  *datas,
211                 l_int32    wpls)
212 {
213 l_int32    i, j, val, diff;
214 l_uint32  *lines, *lined;
215 
216     for (i = 0; i < h; i++) {
217         lined = datad + i * wpld;
218         lines = datas + i * wpls;
219         if (d == 8) {
220             for (j = 0; j < w; j++) {
221                 diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j);
222                 val = L_MAX(diff, 0);
223                 SET_DATA_BYTE(lined, j, val);
224             }
225         }
226         else if (d == 16) {
227             for (j = 0; j < w; j++) {
228                 diff = GET_DATA_TWO_BYTES(lined, j)
229                        - GET_DATA_TWO_BYTES(lines, j);
230                 val = L_MAX(diff, 0);
231                 SET_DATA_TWO_BYTES(lined, j, val);
232             }
233         }
234         else {  /* d == 32; no clipping */
235             for (j = 0; j < w; j++)
236                 *(lined + j) -= *(lines + j);
237         }
238     }
239 
240     return;
241 }
242 
243 
244 /*-------------------------------------------------------------*
245  *                  Grayscale threshold operation              *
246  *-------------------------------------------------------------*/
247 /*!
248  *  thresholdToValueLow()
249  */
250 void
thresholdToValueLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 d,l_int32 wpld,l_int32 threshval,l_int32 setval)251 thresholdToValueLow(l_uint32  *datad,
252                     l_int32    w,
253                     l_int32    h,
254                     l_int32    d,
255                     l_int32    wpld,
256                     l_int32    threshval,
257                     l_int32    setval)
258 {
259 l_int32    i, j, setabove;
260 l_uint32  *lined;
261 
262     if (setval > threshval)
263         setabove = TRUE;
264     else
265         setabove = FALSE;
266 
267     for (i = 0; i < h; i++) {
268         lined = datad + i * wpld;
269         if (setabove == TRUE) {
270             if (d == 8) {
271                 for (j = 0; j < w; j++) {
272                     if (GET_DATA_BYTE(lined, j) - threshval >= 0)
273                         SET_DATA_BYTE(lined, j, setval);
274                 }
275             }
276             else if (d == 16) {
277                 for (j = 0; j < w; j++) {
278                     if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0)
279                         SET_DATA_TWO_BYTES(lined, j, setval);
280                 }
281             }
282             else {  /* d == 32 */
283                 for (j = 0; j < w; j++) {
284                     if (*(lined + j) - threshval >= 0)
285                         *(lined + j) = setval;
286                 }
287             }
288         }
289         else  { /* set if below or at threshold */
290             if (d == 8) {
291                 for (j = 0; j < w; j++) {
292                     if (GET_DATA_BYTE(lined, j) - threshval <= 0)
293                         SET_DATA_BYTE(lined, j, setval);
294                 }
295             }
296             else if (d == 16) {
297                 for (j = 0; j < w; j++) {
298                     if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0)
299                         SET_DATA_TWO_BYTES(lined, j, setval);
300                 }
301             }
302             else {  /* d == 32 */
303                 for (j = 0; j < w; j++) {
304                     if (*(lined + j) - threshval <= 0)
305                         *(lined + j) = setval;
306                 }
307             }
308         }
309     }
310     return;
311 }
312 
313 
314 
315 /*-------------------------------------------------------------*
316  *          Image accumulator arithmetic operations            *
317  *-------------------------------------------------------------*/
318 /*!
319  *  finalAccumulateLow()
320  */
321 void
finalAccumulateLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 d,l_int32 wpld,l_uint32 * datas,l_int32 wpls,l_uint32 offset)322 finalAccumulateLow(l_uint32  *datad,
323                    l_int32    w,
324                    l_int32    h,
325                    l_int32    d,
326                    l_int32    wpld,
327                    l_uint32  *datas,
328                    l_int32    wpls,
329                    l_uint32   offset)
330 {
331 l_int32    i, j;
332 l_int32    val;
333 l_uint32  *lines, *lined;
334 
335     switch (d)
336     {
337     case 8:
338         for (i = 0; i < h; i++) {
339             lines = datas + i * wpls;
340             lined = datad + i * wpld;
341             for (j = 0; j < w; j++) {
342                 val = lines[j] - offset;
343                 val = L_MAX(0, val);
344                 val = L_MIN(255, val);
345                 SET_DATA_BYTE(lined, j, (l_uint8)val);
346             }
347         }
348         break;
349     case 16:
350         for (i = 0; i < h; i++) {
351             lines = datas + i * wpls;
352             lined = datad + i * wpld;
353             for (j = 0; j < w; j++) {
354                 val = lines[j] - offset;
355                 val = L_MAX(0, val);
356                 val = L_MIN(0xffff, val);
357                 SET_DATA_TWO_BYTES(lined, j, (l_uint16)val);
358             }
359         }
360         break;
361     case 32:
362         for (i = 0; i < h; i++) {
363             lines = datas + i * wpls;
364             lined = datad + i * wpld;
365             for (j = 0; j < w; j++)
366                 lined[j] = lines[j] - offset;
367         }
368         break;
369     }
370     return;
371 }
372 
373 
374 void
finalAccumulateThreshLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls,l_uint32 offset,l_uint32 threshold)375 finalAccumulateThreshLow(l_uint32 *datad,
376                          l_int32 w,
377                          l_int32 h,
378                          l_int32 wpld,
379                          l_uint32 *datas,
380                          l_int32 wpls,
381                          l_uint32 offset,
382                          l_uint32 threshold)
383 {
384 l_int32    i, j;
385 l_int32    val;
386 l_uint32  *lines, *lined;
387 
388     for (i = 0; i < h; i++) {
389         lines = datas + i * wpls;
390         lined = datad + i * wpld;
391 
392         for (j = 0; j < w; j++) {
393             val = lines[j] - offset;
394             if (val >= threshold) {
395                 SET_DATA_BIT(lined, j);
396             }
397         }
398     }
399 }
400 
401 
402 /*!
403  *  accumulateLow()
404  */
405 void
accumulateLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 d,l_int32 wpls,l_int32 op)406 accumulateLow(l_uint32  *datad,
407               l_int32    w,
408               l_int32    h,
409               l_int32    wpld,
410               l_uint32  *datas,
411               l_int32    d,
412               l_int32    wpls,
413               l_int32    op)
414 {
415 l_int32    i, j;
416 l_uint32  *lines, *lined;
417 
418     switch (d)
419     {
420     case 1:
421         for (i = 0; i < h; i++) {
422             lines = datas + i * wpls;
423             lined = datad + i * wpld;
424             if (op == L_ARITH_ADD) {
425                 for (j = 0; j < w; j++)
426                     lined[j] += GET_DATA_BIT(lines, j);
427             }
428             else {  /* op == L_ARITH_SUBTRACT */
429                 for (j = 0; j < w; j++)
430                     lined[j] -= GET_DATA_BIT(lines, j);
431             }
432         }
433         break;
434     case 8:
435         for (i = 0; i < h; i++) {
436             lines = datas + i * wpls;
437             lined = datad + i * wpld;
438             if (op == L_ARITH_ADD) {
439                 for (j = 0; j < w; j++)
440                     lined[j] += GET_DATA_BYTE(lines, j);
441             }
442             else {  /* op == L_ARITH_SUBTRACT */
443                 for (j = 0; j < w; j++)
444                     lined[j] -= GET_DATA_BYTE(lines, j);
445             }
446         }
447         break;
448     case 16:
449         for (i = 0; i < h; i++) {
450             lines = datas + i * wpls;
451             lined = datad + i * wpld;
452             if (op == L_ARITH_ADD) {
453                 for (j = 0; j < w; j++)
454                     lined[j] += GET_DATA_TWO_BYTES(lines, j);
455             }
456             else {  /* op == L_ARITH_SUBTRACT */
457                 for (j = 0; j < w; j++)
458                     lined[j] -= GET_DATA_TWO_BYTES(lines, j);
459             }
460         }
461         break;
462     case 32:
463         for (i = 0; i < h; i++) {
464             lines = datas + i * wpls;
465             lined = datad + i * wpld;
466             if (op == L_ARITH_ADD) {
467                 for (j = 0; j < w; j++)
468                     lined[j] += lines[j];
469             }
470             else {  /* op == L_ARITH_SUBTRACT */
471                 for (j = 0; j < w; j++)
472                     lined[j] -= lines[j];
473             }
474         }
475         break;
476     }
477     return;
478 }
479 
480 
481 /*!
482  *  multConstAccumulateLow()
483  */
484 void
multConstAccumulateLow(l_uint32 * data,l_int32 w,l_int32 h,l_int32 wpl,l_float32 factor,l_uint32 offset)485 multConstAccumulateLow(l_uint32  *data,
486                        l_int32    w,
487                        l_int32    h,
488                        l_int32    wpl,
489                        l_float32  factor,
490                        l_uint32   offset)
491 {
492 l_int32    i, j;
493 l_int32    val;
494 l_uint32  *line;
495 
496     for (i = 0; i < h; i++) {
497         line = data + i * wpl;
498         for (j = 0; j < w; j++) {
499             val = line[j] - offset;
500             val = (l_int32)(val * factor);
501             val += offset;
502             line[j] = (l_uint32)val;
503         }
504     }
505     return;
506 }
507 
508 
509 /*-----------------------------------------------------------------------*
510  *              Absolute value of difference, component-wise             *
511  *-----------------------------------------------------------------------*/
512 /*!
513  *  absDifferenceLow()
514  *
515  *  Finds the absolute value of the difference of each pixel,
516  *  for 8 and 16 bpp gray and for 32 bpp rgb.  For 32 bpp, the
517  *  differences are found for each of the RGB components
518  *  separately, and the LSB component is ignored.
519  *  The results are written into datad.
520  */
521 void
absDifferenceLow(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas1,l_uint32 * datas2,l_int32 d,l_int32 wpls)522 absDifferenceLow(l_uint32  *datad,
523                  l_int32    w,
524                  l_int32    h,
525                  l_int32    wpld,
526                  l_uint32  *datas1,
527                  l_uint32  *datas2,
528                  l_int32    d,
529                  l_int32    wpls)
530 {
531 l_int32    i, j, val1, val2, diff;
532 l_uint32   word1, word2;
533 l_uint32  *lines1, *lines2, *lined, *pdword;
534 
535     PROCNAME("absDifferenceLow");
536 
537     switch (d)
538     {
539     case 8:
540         for (i = 0; i < h; i++) {
541             lines1 = datas1 + i * wpls;
542             lines2 = datas2 + i * wpls;
543             lined = datad + i * wpld;
544             for (j = 0; j < w; j++) {
545                 val1 = GET_DATA_BYTE(lines1, j);
546                 val2 = GET_DATA_BYTE(lines2, j);
547                 diff = L_ABS(val1 - val2);
548                 SET_DATA_BYTE(lined, j, diff);
549             }
550         }
551         break;
552     case 16:
553         for (i = 0; i < h; i++) {
554             lines1 = datas1 + i * wpls;
555             lines2 = datas2 + i * wpls;
556             lined = datad + i * wpld;
557             for (j = 0; j < w; j++) {
558                 val1 = GET_DATA_TWO_BYTES(lines1, j);
559                 val2 = GET_DATA_TWO_BYTES(lines2, j);
560                 diff = L_ABS(val1 - val2);
561                 SET_DATA_TWO_BYTES(lined, j, diff);
562             }
563         }
564         break;
565     case 32:
566         for (i = 0; i < h; i++) {
567             lines1 = datas1 + i * wpls;
568             lines2 = datas2 + i * wpls;
569             lined = datad + i * wpld;
570             for (j = 0; j < w; j++) {
571                 word1 = lines1[j];
572                 word2 = lines2[j];
573                 pdword = lined + j;
574                 val1 = GET_DATA_BYTE(&word1, COLOR_RED);
575                 val2 = GET_DATA_BYTE(&word2, COLOR_RED);
576                 diff = L_ABS(val1 - val2);
577                 SET_DATA_BYTE(pdword, COLOR_RED, diff);
578                 val1 = GET_DATA_BYTE(&word1, COLOR_GREEN);
579                 val2 = GET_DATA_BYTE(&word2, COLOR_GREEN);
580                 diff = L_ABS(val1 - val2);
581                 SET_DATA_BYTE(pdword, COLOR_GREEN, diff);
582                 val1 = GET_DATA_BYTE(&word1, COLOR_BLUE);
583                 val2 = GET_DATA_BYTE(&word2, COLOR_BLUE);
584                 diff = L_ABS(val1 - val2);
585                 SET_DATA_BYTE(pdword, COLOR_BLUE, diff);
586             }
587         }
588         break;
589     default:
590         ERROR_VOID("source depth must be 8, 16 or 32 bpp", procName);
591         break;
592     }
593 
594     return;
595 }
596 
597