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