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  *   pixacc.c
19  *
20  *      Pixacc creation, destruction
21  *           PIXACC   *pixaccCreate()
22  *           PIXACC   *pixaccCreateWithPix()
23  *           void      pixaccDestroy()
24  *
25  *      Pixacc finalization
26  *           PIX      *pixaccFinal()
27  *
28  *      Pixacc accessors
29  *           PIX      *pixaccGetPix()
30  *           l_int32   pixaccGetOffset()
31  *
32  *      Pixacc accumulators
33  *           l_int32   pixaccAdd()
34  *           l_int32   pixaccSubtract()
35  *           l_int32   pixaccMultConst()
36  *           l_int32   pixaccMultConstAccumulate()
37  *
38  *  This is a simple interface for some of the pixel arithmetic operations
39  *  in pixarith.c.  These are easy to code up, but not as fast as
40  *  hand-coded functions that do arithmetic on corresponding pixels.
41  *
42  *  Suppose you want to make a linear combination of pix1 and pix2:
43  *     pixd = 0.4 * pix1 + 0.6 * pix2
44  *  where pix1 and pix2 are the same size and have depth 'd'.  Then:
45  *     Pixacc *pacc = pixaccCreateWithPix(pix1, 0);  // first; addition only
46  *     pixaccMultConst(pacc, 0.4);
47  *     pixaccMultConstAccumulate(pacc, pix2, 0.6);  // Add in 0.6 of the second
48  *     pixd = pixaccFinal(pacc, d);  // Get the result
49  *     pixaccDestroy(&pacc);
50  */
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include "allheaders.h"
55 
56 
57 /*---------------------------------------------------------------------*
58  *                     Pixacc creation, destruction                    *
59  *---------------------------------------------------------------------*/
60 /*!
61  *  pixaccCreate()
62  *
63  *      Input:  w, h (of 32 bpp internal Pix)
64  *              negflag (0 if only positive numbers are involved;
65  *                       1 if there will be negative numbers)
66  *      Return: pixacc, or null on error
67  *
68  *  Notes:
69  *      (1) Use @negflag = 1 for safety if any negative numbers are going
70  *          to be used in the chain of operations.  Negative numbers
71  *          arise, e.g., by subtracting a pix, or by adding a pix
72  *          that has been pre-multiplied by a negative number.
73  *      (2) Initializes the internal 32 bpp pix, similarly to the
74  *          initialization in pixInitAccumulate().
75  */
76 PIXACC *
pixaccCreate(l_int32 w,l_int32 h,l_int32 negflag)77 pixaccCreate(l_int32  w,
78              l_int32  h,
79              l_int32  negflag)
80 {
81 PIXACC  *pixacc;
82 
83     PROCNAME("pixaccCreate");
84 
85     if ((pixacc = (PIXACC *)CALLOC(1, sizeof(PIXACC))) == NULL)
86         return (PIXACC *)ERROR_PTR("pixacc not made", procName, NULL);
87     pixacc->w = w;
88     pixacc->h = h;
89 
90     if ((pixacc->pix = pixCreate(w, h, 32)) == NULL)
91         return (PIXACC *)ERROR_PTR("pix not made", procName, NULL);
92 
93     if (negflag) {
94         pixacc->offset = 0x40000000;
95         pixSetAllArbitrary(pixacc->pix, pixacc->offset);
96     }
97 
98     return pixacc;
99 }
100 
101 
102 /*!
103  *  pixaccCreateWithPix()
104  *
105  *      Input:  pix
106  *              negflag (0 if only positive numbers are involved;
107  *                       1 if there will be negative numbers)
108  *      Return: pixacc, or null on error
109  *
110  *  Notes:
111  *      (1) See pixaccCreate()
112  */
113 PIXACC *
pixaccCreateWithPix(PIX * pix,l_int32 negflag)114 pixaccCreateWithPix(PIX     *pix,
115                     l_int32  negflag)
116 {
117 l_int32  w, h;
118 PIXACC  *pixacc;
119 
120     PROCNAME("pixaccCreateWithPix");
121 
122     if (!pix)
123         return (PIXACC *)ERROR_PTR("pix not defined", procName, NULL);
124 
125     pixGetDimensions(pix, &w, &h, NULL);
126     pixacc = pixaccCreate(w, h, negflag);
127     pixaccAdd(pixacc, pix);
128     return pixacc;
129 }
130 
131 
132 /*!
133  *  pixaccDestroy()
134  *
135  *      Input:  &pixacc (<can be null>)
136  *      Return: void
137  *
138  *  Notes:
139  *      (1) Always nulls the input ptr.
140  */
141 void
pixaccDestroy(PIXACC ** ppixacc)142 pixaccDestroy(PIXACC  **ppixacc)
143 {
144 PIXACC  *pixacc;
145 
146     PROCNAME("pixaccDestroy");
147 
148     if (ppixacc == NULL) {
149         L_WARNING("ptr address is NULL!", procName);
150         return;
151     }
152 
153     if ((pixacc = *ppixacc) == NULL)
154         return;
155 
156     pixDestroy(&pixacc->pix);
157     FREE(pixacc);
158     *ppixacc = NULL;
159     return;
160 }
161 
162 
163 /*---------------------------------------------------------------------*
164  *                            Pixacc finalization                      *
165  *---------------------------------------------------------------------*/
166 /*!
167  *  pixaccFinal()
168  *
169  *      Input:  pixacc
170  *              outdepth (8, 16 or 32 bpp)
171  *      Return: pixd (8 , 16 or 32 bpp), or null on error
172  */
173 PIX *
pixaccFinal(PIXACC * pixacc,l_int32 outdepth)174 pixaccFinal(PIXACC  *pixacc,
175             l_int32  outdepth)
176 {
177     PROCNAME("pixaccFinal");
178 
179     if (!pixacc)
180         return (PIX *)ERROR_PTR("pixacc not defined", procName, NULL);
181 
182     return pixFinalAccumulate(pixaccGetPix(pixacc), pixaccGetOffset(pixacc),
183                               outdepth);
184 }
185 
186 
187 /*---------------------------------------------------------------------*
188  *                            Pixacc accessors                         *
189  *---------------------------------------------------------------------*/
190 /*!
191  *  pixaccGetPix()
192  *
193  *      Input:  pixacc
194  *      Return: pix, or null on error
195  */
196 PIX *
pixaccGetPix(PIXACC * pixacc)197 pixaccGetPix(PIXACC  *pixacc)
198 {
199     PROCNAME("pixaccGetPix");
200 
201     if (!pixacc)
202         return (PIX *)ERROR_PTR("pixacc not defined", procName, NULL);
203     return pixacc->pix;
204 }
205 
206 
207 /*!
208  *  pixaccGetOffset()
209  *
210  *      Input:  pixacc
211  *      Return: offset, or -1 on error
212  */
213 l_int32
pixaccGetOffset(PIXACC * pixacc)214 pixaccGetOffset(PIXACC  *pixacc)
215 {
216     PROCNAME("pixaccGetOffset");
217 
218     if (!pixacc)
219         return ERROR_INT("pixacc not defined", procName, -1);
220     return pixacc->offset;
221 }
222 
223 
224 /*---------------------------------------------------------------------*
225  *                          Pixacc accumulators                        *
226  *---------------------------------------------------------------------*/
227 /*!
228  *  pixaccAdd()
229  *
230  *      Input:  pixacc
231  *              pix (to be added)
232  *      Return: 0 if OK, 1 on error
233  */
234 l_int32
pixaccAdd(PIXACC * pixacc,PIX * pix)235 pixaccAdd(PIXACC  *pixacc,
236           PIX     *pix)
237 {
238     PROCNAME("pixaccAdd");
239 
240     if (!pixacc)
241         return ERROR_INT("pixacc not defined", procName, 1);
242     if (!pix)
243         return ERROR_INT("pix not defined", procName, 1);
244     pixAccumulate(pixaccGetPix(pixacc), pix, L_ARITH_ADD);
245     return 0;
246 }
247 
248 
249 /*!
250  *  pixaccSubtract()
251  *
252  *      Input:  pixacc
253  *              pix (to be subtracted)
254  *      Return: 0 if OK, 1 on error
255  */
256 l_int32
pixaccSubtract(PIXACC * pixacc,PIX * pix)257 pixaccSubtract(PIXACC  *pixacc,
258                PIX     *pix)
259 {
260     PROCNAME("pixaccSubtract");
261 
262     if (!pixacc)
263         return ERROR_INT("pixacc not defined", procName, 1);
264     if (!pix)
265         return ERROR_INT("pix not defined", procName, 1);
266     pixAccumulate(pixaccGetPix(pixacc), pix, L_ARITH_SUBTRACT);
267     return 0;
268 }
269 
270 
271 /*!
272  *  pixaccMultConst()
273  *
274  *      Input:  pixacc
275  *              factor
276  *      Return: 0 if OK, 1 on error
277  */
278 l_int32
pixaccMultConst(PIXACC * pixacc,l_float32 factor)279 pixaccMultConst(PIXACC    *pixacc,
280                 l_float32  factor)
281 {
282     PROCNAME("pixaccMultConst");
283 
284     if (!pixacc)
285         return ERROR_INT("pixacc not defined", procName, 1);
286     pixMultConstAccumulate(pixaccGetPix(pixacc), factor,
287                            pixaccGetOffset(pixacc));
288     return 0;
289 }
290 
291 
292 /*!
293  *  pixaccMultConstAccumulate()
294  *
295  *      Input:  pixacc
296  *              pix
297  *              factor
298  *      Return: 0 if OK, 1 on error
299  *
300  *  Notes:
301  *      (1) This creates a temp pix that is @pix multiplied by the
302  *          constant @factor.  It then adds that into @pixacc.
303  */
304 l_int32
pixaccMultConstAccumulate(PIXACC * pixacc,PIX * pix,l_float32 factor)305 pixaccMultConstAccumulate(PIXACC    *pixacc,
306                           PIX       *pix,
307                           l_float32  factor)
308 {
309 l_int32  w, h, d, negflag;
310 PIX     *pixt;
311 PIXACC  *pacct;
312 
313     PROCNAME("pixaccMultConstAccumulate");
314 
315     if (!pixacc)
316         return ERROR_INT("pixacc not defined", procName, 1);
317     if (!pix)
318         return ERROR_INT("pix not defined", procName, 1);
319 
320     if (factor == 0.0) return 0;
321 
322     pixGetDimensions(pix, &w, &h, &d);
323     negflag = (factor > 0.0) ? 0 : 1;
324     pacct = pixaccCreate(w, h, negflag);
325     pixaccAdd(pacct, pix);
326     pixaccMultConst(pacct, factor);
327     pixt = pixaccFinal(pacct, d);
328     pixaccAdd(pixacc, pixt);
329 
330     pixaccDestroy(&pacct);
331     pixDestroy(&pixt);
332     return 0;
333 }
334 
335 
336