Coverage Report

Created: 2025-06-13 07:02

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