comparison mupdf-source/thirdparty/openjpeg/src/lib/openjp2/bench_dwt.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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 #ifdef _WIN32
35 #include <windows.h>
36 #else
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/times.h>
40 #endif /* _WIN32 */
41
42 OPJ_INT32 getValue(OPJ_UINT32 i)
43 {
44 return ((OPJ_INT32)i % 511) - 256;
45 }
46
47 void init_tilec(opj_tcd_tilecomp_t * l_tilec,
48 OPJ_INT32 x0,
49 OPJ_INT32 y0,
50 OPJ_INT32 x1,
51 OPJ_INT32 y1,
52 OPJ_UINT32 numresolutions,
53 OPJ_BOOL irreversible)
54 {
55 opj_tcd_resolution_t* l_res;
56 OPJ_UINT32 resno, l_level_no;
57 size_t i, nValues;
58
59 memset(l_tilec, 0, sizeof(*l_tilec));
60 l_tilec->x0 = x0;
61 l_tilec->y0 = y0;
62 l_tilec->x1 = x1;
63 l_tilec->y1 = y1;
64 nValues = (size_t)(l_tilec->x1 - l_tilec->x0) *
65 (size_t)(l_tilec->y1 - l_tilec->y0);
66 l_tilec->data = (OPJ_INT32*) opj_malloc(sizeof(OPJ_INT32) * nValues);
67 assert(l_tilec->data != NULL);
68 for (i = 0; i < nValues; i++) {
69 OPJ_INT32 val = getValue((OPJ_UINT32)i);
70 if (irreversible) {
71 OPJ_FLOAT32 fVal = (OPJ_FLOAT32)val;
72 memcpy(&l_tilec->data[i], &fVal, sizeof(OPJ_FLOAT32));
73 } else {
74 l_tilec->data[i] = val;
75 }
76 }
77 l_tilec->numresolutions = numresolutions;
78 l_tilec->minimum_num_resolutions = numresolutions;
79 l_tilec->resolutions = (opj_tcd_resolution_t*) opj_calloc(
80 l_tilec->numresolutions,
81 sizeof(opj_tcd_resolution_t));
82
83 l_level_no = l_tilec->numresolutions;
84 l_res = l_tilec->resolutions;
85
86 /* Adapted from opj_tcd_init_tile() */
87 for (resno = 0; resno < l_tilec->numresolutions; ++resno) {
88
89 --l_level_no;
90
91 /* border for each resolution level (global) */
92 l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no);
93 l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no);
94 l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no);
95 l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no);
96
97 ++l_res;
98 }
99 }
100
101 void free_tilec(opj_tcd_tilecomp_t * l_tilec)
102 {
103 opj_free(l_tilec->data);
104 opj_free(l_tilec->resolutions);
105 }
106
107 void usage(void)
108 {
109 printf(
110 "bench_dwt [-decode|encode] [-I] [-size value] [-check] [-display]\n");
111 printf(
112 " [-num_resolutions val] [-offset x y] [-num_threads val]\n");
113 exit(1);
114 }
115
116
117 OPJ_FLOAT64 opj_clock(void)
118 {
119 #ifdef _WIN32
120 /* _WIN32: use QueryPerformance (very accurate) */
121 LARGE_INTEGER freq, t ;
122 /* freq is the clock speed of the CPU */
123 QueryPerformanceFrequency(&freq) ;
124 /* cout << "freq = " << ((double) freq.QuadPart) << endl; */
125 /* t is the high resolution performance counter (see MSDN) */
126 QueryPerformanceCounter(& t) ;
127 return freq.QuadPart ? (t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) : 0 ;
128 #else
129 /* Unix or Linux: use resource usage */
130 struct rusage t;
131 OPJ_FLOAT64 procTime;
132 /* (1) Get the rusage data structure at this moment (man getrusage) */
133 getrusage(0, &t);
134 /* (2) What is the elapsed time ? - CPU time = User time + System time */
135 /* (2a) Get the seconds */
136 procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec);
137 /* (2b) More precisely! Get the microseconds part ! */
138 return (procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) *
139 1e-6) ;
140 #endif
141 }
142
143 static OPJ_FLOAT64 opj_wallclock(void)
144 {
145 #ifdef _WIN32
146 return opj_clock();
147 #else
148 struct timeval tv;
149 gettimeofday(&tv, NULL);
150 return (OPJ_FLOAT64)tv.tv_sec + 1e-6 * (OPJ_FLOAT64)tv.tv_usec;
151 #endif
152 }
153
154 int main(int argc, char** argv)
155 {
156 int num_threads = 0;
157 opj_tcd_t tcd;
158 opj_tcd_image_t tcd_image;
159 opj_tcd_tile_t tcd_tile;
160 opj_tcd_tilecomp_t tilec;
161 opj_image_t image;
162 opj_image_comp_t image_comp;
163 opj_thread_pool_t* tp;
164 OPJ_INT32 i, j, k;
165 OPJ_BOOL display = OPJ_FALSE;
166 OPJ_BOOL check = OPJ_FALSE;
167 OPJ_INT32 size = 16384 - 1;
168 OPJ_FLOAT64 start, stop;
169 OPJ_FLOAT64 start_wc, stop_wc;
170 OPJ_UINT32 offset_x = ((OPJ_UINT32)size + 1) / 2 - 1;
171 OPJ_UINT32 offset_y = ((OPJ_UINT32)size + 1) / 2 - 1;
172 OPJ_UINT32 num_resolutions = 6;
173 OPJ_BOOL bench_decode = OPJ_TRUE;
174 OPJ_BOOL irreversible = OPJ_FALSE;
175
176 for (i = 1; i < argc; i++) {
177 if (strcmp(argv[i], "-encode") == 0) {
178 bench_decode = OPJ_FALSE;
179 } else if (strcmp(argv[i], "-decode") == 0) {
180 bench_decode = OPJ_TRUE;
181 } else if (strcmp(argv[i], "-display") == 0) {
182 display = OPJ_TRUE;
183 } else if (strcmp(argv[i], "-check") == 0) {
184 check = OPJ_TRUE;
185 } else if (strcmp(argv[i], "-I") == 0) {
186 irreversible = OPJ_TRUE;
187 } else if (strcmp(argv[i], "-size") == 0 && i + 1 < argc) {
188 size = atoi(argv[i + 1]);
189 i ++;
190 } else if (strcmp(argv[i], "-num_threads") == 0 && i + 1 < argc) {
191 num_threads = atoi(argv[i + 1]);
192 i ++;
193 } else if (strcmp(argv[i], "-num_resolutions") == 0 && i + 1 < argc) {
194 num_resolutions = (OPJ_UINT32)atoi(argv[i + 1]);
195 if (num_resolutions == 0 || num_resolutions > 32) {
196 fprintf(stderr,
197 "Invalid value for num_resolutions. Should be >= 1 and <= 32\n");
198 exit(1);
199 }
200 i ++;
201 } else if (strcmp(argv[i], "-offset") == 0 && i + 2 < argc) {
202 offset_x = (OPJ_UINT32)atoi(argv[i + 1]);
203 offset_y = (OPJ_UINT32)atoi(argv[i + 2]);
204 i += 2;
205 } else {
206 usage();
207 }
208 }
209
210 if (irreversible && check) {
211 /* Due to irreversible inverse DWT not being symmetric of forward */
212 /* See BUG_WEIRD_TWO_INVK in dwt.c */
213 printf("-I and -check aren't compatible\n");
214 exit(1);
215 }
216
217 tp = opj_thread_pool_create(num_threads);
218
219 init_tilec(&tilec, (OPJ_INT32)offset_x, (OPJ_INT32)offset_y,
220 (OPJ_INT32)offset_x + size, (OPJ_INT32)offset_y + size,
221 num_resolutions, irreversible);
222
223 if (display) {
224 printf("Before\n");
225 k = 0;
226 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
227 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
228 if (irreversible) {
229 printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
230 } else {
231 printf("%d ", tilec.data[k]);
232 }
233 k ++;
234 }
235 printf("\n");
236 }
237 }
238
239 memset(&tcd, 0, sizeof(tcd));
240 tcd.thread_pool = tp;
241 tcd.whole_tile_decoding = OPJ_TRUE;
242 tcd.win_x0 = (OPJ_UINT32)tilec.x0;
243 tcd.win_y0 = (OPJ_UINT32)tilec.y0;
244 tcd.win_x1 = (OPJ_UINT32)tilec.x1;
245 tcd.win_y1 = (OPJ_UINT32)tilec.y1;
246 tcd.tcd_image = &tcd_image;
247 memset(&tcd_image, 0, sizeof(tcd_image));
248 tcd_image.tiles = &tcd_tile;
249 memset(&tcd_tile, 0, sizeof(tcd_tile));
250 tcd_tile.x0 = tilec.x0;
251 tcd_tile.y0 = tilec.y0;
252 tcd_tile.x1 = tilec.x1;
253 tcd_tile.y1 = tilec.y1;
254 tcd_tile.numcomps = 1;
255 tcd_tile.comps = &tilec;
256 tcd.image = &image;
257 memset(&image, 0, sizeof(image));
258 image.numcomps = 1;
259 image.comps = &image_comp;
260 memset(&image_comp, 0, sizeof(image_comp));
261 image_comp.dx = 1;
262 image_comp.dy = 1;
263
264 start = opj_clock();
265 start_wc = opj_wallclock();
266 if (bench_decode) {
267 if (irreversible) {
268 opj_dwt_decode_real(&tcd, &tilec, tilec.numresolutions);
269 } else {
270 opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
271 }
272 } else {
273 if (irreversible) {
274 opj_dwt_encode_real(&tcd, &tilec);
275 } else {
276 opj_dwt_encode(&tcd, &tilec);
277 }
278 }
279 stop = opj_clock();
280 stop_wc = opj_wallclock();
281 printf("time for %s: total = %.03f s, wallclock = %.03f s\n",
282 bench_decode ? "dwt_decode" : "dwt_encode",
283 stop - start,
284 stop_wc - start_wc);
285
286 if (display) {
287 if (bench_decode) {
288 printf("After IDWT\n");
289 } else {
290 printf("After FDWT\n");
291 }
292 k = 0;
293 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
294 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
295 if (irreversible) {
296 printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
297 } else {
298 printf("%d ", tilec.data[k]);
299 }
300 k ++;
301 }
302 printf("\n");
303 }
304 }
305
306 if ((display || check) && !irreversible) {
307
308 if (bench_decode) {
309 opj_dwt_encode(&tcd, &tilec);
310 } else {
311 opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
312 }
313
314
315 if (display && !irreversible) {
316 if (bench_decode) {
317 printf("After FDWT\n");
318 } else {
319 printf("After IDWT\n");
320 }
321 k = 0;
322 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
323 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
324 if (irreversible) {
325 printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]);
326 } else {
327 printf("%d ", tilec.data[k]);
328 }
329 k ++;
330 }
331 printf("\n");
332 }
333 }
334
335 }
336
337 if (check) {
338
339 size_t idx;
340 size_t nValues = (size_t)(tilec.x1 - tilec.x0) *
341 (size_t)(tilec.y1 - tilec.y0);
342 for (idx = 0; idx < nValues; idx++) {
343 if (tilec.data[idx] != getValue((OPJ_UINT32)idx)) {
344 printf("Difference found at idx = %u\n", (OPJ_UINT32)idx);
345 exit(1);
346 }
347 }
348 }
349
350 free_tilec(&tilec);
351
352 opj_thread_pool_destroy(tp);
353 return 0;
354 }