Coverage Report

Created: 2026-03-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openjpeg/src/lib/openjp2/sparse_array.c
Line
Count
Source
1
/*
2
 * The copyright in this software is being made available under the 2-clauses
3
 * BSD License, included below. This software may be subject to other third
4
 * party and contributor rights, including patent rights, and no such rights
5
 * are granted under this license.
6
 *
7
 * Copyright (c) 2017, IntoPix SA <contact@intopix.com>
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#include "opj_includes.h"
33
34
35
struct opj_sparse_array_int32 {
36
    OPJ_UINT32 width;
37
    OPJ_UINT32 height;
38
    OPJ_UINT32 block_width;
39
    OPJ_UINT32 block_height;
40
    OPJ_UINT32 block_count_hor;
41
    OPJ_UINT32 block_count_ver;
42
    OPJ_INT32** data_blocks;
43
};
44
45
opj_sparse_array_int32_t* opj_sparse_array_int32_create(OPJ_UINT32 width,
46
        OPJ_UINT32 height,
47
        OPJ_UINT32 block_width,
48
        OPJ_UINT32 block_height)
49
85.5k
{
50
85.5k
    opj_sparse_array_int32_t* sa;
51
52
85.5k
    if (width == 0 || height == 0 || block_width == 0 || block_height == 0) {
53
0
        return NULL;
54
0
    }
55
85.5k
    if (block_width > ((OPJ_UINT32)~0U) / block_height / sizeof(OPJ_INT32)) {
56
0
        return NULL;
57
0
    }
58
59
85.5k
    sa = (opj_sparse_array_int32_t*) opj_calloc(1,
60
85.5k
            sizeof(opj_sparse_array_int32_t));
61
85.5k
    sa->width = width;
62
85.5k
    sa->height = height;
63
85.5k
    sa->block_width = block_width;
64
85.5k
    sa->block_height = block_height;
65
85.5k
    sa->block_count_hor = opj_uint_ceildiv(width, block_width);
66
85.5k
    sa->block_count_ver = opj_uint_ceildiv(height, block_height);
67
85.5k
    if (sa->block_count_hor > ((OPJ_UINT32)~0U) / sa->block_count_ver) {
68
0
        opj_free(sa);
69
0
        return NULL;
70
0
    }
71
85.5k
    sa->data_blocks = (OPJ_INT32**) opj_calloc(sizeof(OPJ_INT32*),
72
85.5k
                      (size_t) sa->block_count_hor * sa->block_count_ver);
73
85.5k
    if (sa->data_blocks == NULL) {
74
0
        opj_free(sa);
75
0
        return NULL;
76
0
    }
77
78
85.5k
    return sa;
79
85.5k
}
80
81
void opj_sparse_array_int32_free(opj_sparse_array_int32_t* sa)
82
85.5k
{
83
85.5k
    if (sa) {
84
85.5k
        OPJ_UINT32 i;
85
1.91M
        for (i = 0; i < sa->block_count_hor * sa->block_count_ver; i++) {
86
1.83M
            if (sa->data_blocks[i]) {
87
1.52M
                opj_free(sa->data_blocks[i]);
88
1.52M
            }
89
1.83M
        }
90
85.5k
        opj_free(sa->data_blocks);
91
85.5k
        opj_free(sa);
92
85.5k
    }
93
85.5k
}
94
95
OPJ_BOOL opj_sparse_array_is_region_valid(const opj_sparse_array_int32_t* sa,
96
        OPJ_UINT32 x0,
97
        OPJ_UINT32 y0,
98
        OPJ_UINT32 x1,
99
        OPJ_UINT32 y1)
100
43.3M
{
101
43.3M
    return !(x0 >= sa->width || x1 <= x0 || x1 > sa->width ||
102
41.5M
             y0 >= sa->height || y1 <= y0 || y1 > sa->height);
103
43.3M
}
104
105
static OPJ_BOOL opj_sparse_array_int32_read_or_write(
106
    const opj_sparse_array_int32_t* sa,
107
    OPJ_UINT32 x0,
108
    OPJ_UINT32 y0,
109
    OPJ_UINT32 x1,
110
    OPJ_UINT32 y1,
111
    OPJ_INT32* buf,
112
    OPJ_UINT32 buf_col_stride,
113
    OPJ_UINT32 buf_line_stride,
114
    OPJ_BOOL forgiving,
115
    OPJ_BOOL is_read_op)
116
43.3M
{
117
43.3M
    OPJ_UINT32 y, block_y;
118
43.3M
    OPJ_UINT32 y_incr = 0;
119
43.3M
    const OPJ_UINT32 block_width = sa->block_width;
120
121
43.3M
    if (!opj_sparse_array_is_region_valid(sa, x0, y0, x1, y1)) {
122
2.24M
        return forgiving;
123
2.24M
    }
124
125
41.1M
    block_y = y0 / sa->block_height;
126
93.2M
    for (y = y0; y < y1; block_y ++, y += y_incr) {
127
52.1M
        OPJ_UINT32 x, block_x;
128
52.1M
        OPJ_UINT32 x_incr = 0;
129
52.1M
        OPJ_UINT32 block_y_offset;
130
52.1M
        y_incr = (y == y0) ? sa->block_height - (y0 % sa->block_height) :
131
52.1M
                 sa->block_height;
132
52.1M
        block_y_offset = sa->block_height - y_incr;
133
52.1M
        y_incr = opj_uint_min(y_incr, y1 - y);
134
52.1M
        block_x = x0 / block_width;
135
138M
        for (x = x0; x < x1; block_x ++, x += x_incr) {
136
85.9M
            OPJ_UINT32 j;
137
85.9M
            OPJ_UINT32 block_x_offset;
138
85.9M
            OPJ_INT32* src_block;
139
85.9M
            x_incr = (x == x0) ? block_width - (x0 % block_width) : block_width;
140
85.9M
            block_x_offset = block_width - x_incr;
141
85.9M
            x_incr = opj_uint_min(x_incr, x1 - x);
142
85.9M
            src_block = sa->data_blocks[block_y * sa->block_count_hor + block_x];
143
85.9M
            if (is_read_op) {
144
37.5M
                if (src_block == NULL) {
145
7.10k
                    if (buf_col_stride == 1) {
146
0
                        OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride +
147
0
                                              (x - x0) * buf_col_stride;
148
0
                        for (j = 0; j < y_incr; j++) {
149
0
                            memset(dest_ptr, 0, sizeof(OPJ_INT32) * x_incr);
150
0
                            dest_ptr += buf_line_stride;
151
0
                        }
152
7.10k
                    } else {
153
7.10k
                        OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride +
154
7.10k
                                              (x - x0) * buf_col_stride;
155
14.2k
                        for (j = 0; j < y_incr; j++) {
156
7.10k
                            OPJ_UINT32 k;
157
258k
                            for (k = 0; k < x_incr; k++) {
158
251k
                                dest_ptr[k * buf_col_stride] = 0;
159
251k
                            }
160
7.10k
                            dest_ptr += buf_line_stride;
161
7.10k
                        }
162
7.10k
                    }
163
37.4M
                } else {
164
37.4M
                    const OPJ_INT32* OPJ_RESTRICT src_ptr = src_block + block_y_offset *
165
37.4M
                                                            (OPJ_SIZE_T)block_width + block_x_offset;
166
37.4M
                    if (buf_col_stride == 1) {
167
7.34M
                        OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride
168
7.34M
                                                           +
169
7.34M
                                                           (x - x0) * buf_col_stride;
170
7.34M
                        if (x_incr == 4) {
171
                            /* Same code as general branch, but the compiler */
172
                            /* can have an efficient memcpy() */
173
4.21M
                            (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */
174
201M
                            for (j = 0; j < y_incr; j++) {
175
197M
                                memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr);
176
197M
                                dest_ptr += buf_line_stride;
177
197M
                                src_ptr += block_width;
178
197M
                            }
179
4.21M
                        } else {
180
146M
                            for (j = 0; j < y_incr; j++) {
181
143M
                                memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr);
182
143M
                                dest_ptr += buf_line_stride;
183
143M
                                src_ptr += block_width;
184
143M
                            }
185
3.13M
                        }
186
30.1M
                    } else {
187
30.1M
                        OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride
188
30.1M
                                                           +
189
30.1M
                                                           (x - x0) * buf_col_stride;
190
30.1M
                        if (x_incr == 1) {
191
4.43M
                            for (j = 0; j < y_incr; j++) {
192
2.21M
                                *dest_ptr = *src_ptr;
193
2.21M
                                dest_ptr += buf_line_stride;
194
2.21M
                                src_ptr += block_width;
195
2.21M
                            }
196
27.9M
                        } else if (y_incr == 1 && buf_col_stride == 2) {
197
17.2M
                            OPJ_UINT32 k;
198
212M
                            for (k = 0; k < (x_incr & ~3U); k += 4) {
199
195M
                                dest_ptr[k * buf_col_stride] = src_ptr[k];
200
195M
                                dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1];
201
195M
                                dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2];
202
195M
                                dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3];
203
195M
                            }
204
28.3M
                            for (; k < x_incr; k++) {
205
11.0M
                                dest_ptr[k * buf_col_stride] = src_ptr[k];
206
11.0M
                            }
207
17.2M
                        } else if (x_incr >= 8 && buf_col_stride == 8) {
208
0
                            for (j = 0; j < y_incr; j++) {
209
0
                                OPJ_UINT32 k;
210
0
                                for (k = 0; k < (x_incr & ~3U); k += 4) {
211
0
                                    dest_ptr[k * buf_col_stride] = src_ptr[k];
212
0
                                    dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1];
213
0
                                    dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2];
214
0
                                    dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3];
215
0
                                }
216
0
                                for (; k < x_incr; k++) {
217
0
                                    dest_ptr[k * buf_col_stride] = src_ptr[k];
218
0
                                }
219
0
                                dest_ptr += buf_line_stride;
220
0
                                src_ptr += block_width;
221
0
                            }
222
10.6M
                        } else {
223
                            /* General case */
224
21.3M
                            for (j = 0; j < y_incr; j++) {
225
10.6M
                                OPJ_UINT32 k;
226
506M
                                for (k = 0; k < x_incr; k++) {
227
495M
                                    dest_ptr[k * buf_col_stride] = src_ptr[k];
228
495M
                                }
229
10.6M
                                dest_ptr += buf_line_stride;
230
10.6M
                                src_ptr += block_width;
231
10.6M
                            }
232
10.6M
                        }
233
30.1M
                    }
234
37.4M
                }
235
48.4M
            } else {
236
48.4M
                if (src_block == NULL) {
237
1.52M
                    src_block = (OPJ_INT32*) opj_calloc(1,
238
1.52M
                                                        (size_t) sa->block_width * sa->block_height * sizeof(OPJ_INT32));
239
1.52M
                    if (src_block == NULL) {
240
0
                        return OPJ_FALSE;
241
0
                    }
242
1.52M
                    sa->data_blocks[block_y * sa->block_count_hor + block_x] = src_block;
243
1.52M
                }
244
245
48.4M
                if (buf_col_stride == 1) {
246
47.2M
                    OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset *
247
47.2M
                                                       (OPJ_SIZE_T)block_width + block_x_offset;
248
47.2M
                    const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) *
249
47.2M
                                                            (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride;
250
47.2M
                    if (x_incr == 4) {
251
                        /* Same code as general branch, but the compiler */
252
                        /* can have an efficient memcpy() */
253
10.5M
                        (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */
254
293M
                        for (j = 0; j < y_incr; j++) {
255
283M
                            memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr);
256
283M
                            dest_ptr += block_width;
257
283M
                            src_ptr += buf_line_stride;
258
283M
                        }
259
36.6M
                    } else {
260
418M
                        for (j = 0; j < y_incr; j++) {
261
382M
                            memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr);
262
382M
                            dest_ptr += block_width;
263
382M
                            src_ptr += buf_line_stride;
264
382M
                        }
265
36.6M
                    }
266
47.2M
                } else {
267
1.22M
                    OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset *
268
1.22M
                                                       (OPJ_SIZE_T)block_width + block_x_offset;
269
1.22M
                    const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) *
270
1.22M
                                                            (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride;
271
1.22M
                    if (x_incr == 1) {
272
355k
                        for (j = 0; j < y_incr; j++) {
273
292k
                            *dest_ptr = *src_ptr;
274
292k
                            src_ptr += buf_line_stride;
275
292k
                            dest_ptr += block_width;
276
292k
                        }
277
1.15M
                    } else if (x_incr >= 8 && buf_col_stride == 8) {
278
9.62M
                        for (j = 0; j < y_incr; j++) {
279
8.53M
                            OPJ_UINT32 k;
280
131M
                            for (k = 0; k < (x_incr & ~3U); k += 4) {
281
123M
                                dest_ptr[k] = src_ptr[k * buf_col_stride];
282
123M
                                dest_ptr[k + 1] = src_ptr[(k + 1) * buf_col_stride];
283
123M
                                dest_ptr[k + 2] = src_ptr[(k + 2) * buf_col_stride];
284
123M
                                dest_ptr[k + 3] = src_ptr[(k + 3) * buf_col_stride];
285
123M
                            }
286
10.7M
                            for (; k < x_incr; k++) {
287
2.21M
                                dest_ptr[k] = src_ptr[k * buf_col_stride];
288
2.21M
                            }
289
8.53M
                            src_ptr += buf_line_stride;
290
8.53M
                            dest_ptr += block_width;
291
8.53M
                        }
292
1.08M
                    } else {
293
                        /* General case */
294
533k
                        for (j = 0; j < y_incr; j++) {
295
464k
                            OPJ_UINT32 k;
296
2.23M
                            for (k = 0; k < x_incr; k++) {
297
1.77M
                                dest_ptr[k] = src_ptr[k * buf_col_stride];
298
1.77M
                            }
299
464k
                            src_ptr += buf_line_stride;
300
464k
                            dest_ptr += block_width;
301
464k
                        }
302
69.0k
                    }
303
1.22M
                }
304
48.4M
            }
305
85.9M
        }
306
52.1M
    }
307
308
41.1M
    return OPJ_TRUE;
309
41.1M
}
310
311
OPJ_BOOL opj_sparse_array_int32_read(const opj_sparse_array_int32_t* sa,
312
                                     OPJ_UINT32 x0,
313
                                     OPJ_UINT32 y0,
314
                                     OPJ_UINT32 x1,
315
                                     OPJ_UINT32 y1,
316
                                     OPJ_INT32* dest,
317
                                     OPJ_UINT32 dest_col_stride,
318
                                     OPJ_UINT32 dest_line_stride,
319
                                     OPJ_BOOL forgiving)
320
16.7M
{
321
16.7M
    return opj_sparse_array_int32_read_or_write(
322
16.7M
               (opj_sparse_array_int32_t*)sa, x0, y0, x1, y1,
323
16.7M
               dest,
324
16.7M
               dest_col_stride,
325
16.7M
               dest_line_stride,
326
16.7M
               forgiving,
327
16.7M
               OPJ_TRUE);
328
16.7M
}
329
330
OPJ_BOOL opj_sparse_array_int32_write(opj_sparse_array_int32_t* sa,
331
                                      OPJ_UINT32 x0,
332
                                      OPJ_UINT32 y0,
333
                                      OPJ_UINT32 x1,
334
                                      OPJ_UINT32 y1,
335
                                      const OPJ_INT32* src,
336
                                      OPJ_UINT32 src_col_stride,
337
                                      OPJ_UINT32 src_line_stride,
338
                                      OPJ_BOOL forgiving)
339
26.6M
{
340
26.6M
    return opj_sparse_array_int32_read_or_write(sa, x0, y0, x1, y1,
341
26.6M
            (OPJ_INT32*)src,
342
26.6M
            src_col_stride,
343
26.6M
            src_line_stride,
344
26.6M
            forgiving,
345
26.6M
            OPJ_FALSE);
346
26.6M
}