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.
7 * Copyright (c) 2017, IntoPix SA <contact@intopix.com>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 #include "opj_includes.h"
38 #include <sys/resource.h>
39 #include <sys/times.h>
42 OPJ_INT32 getValue(OPJ_UINT32 i)
44 return ((OPJ_INT32)i % 511) - 256;
47 void init_tilec(opj_tcd_tilecomp_t * l_tilec,
52 OPJ_UINT32 numresolutions)
54 opj_tcd_resolution_t* l_res;
55 OPJ_UINT32 resno, l_level_no;
58 memset(l_tilec, 0, sizeof(*l_tilec));
63 nValues = (size_t)(l_tilec->x1 - l_tilec->x0) *
64 (size_t)(l_tilec->y1 - l_tilec->y0);
65 l_tilec->data = (OPJ_INT32*) opj_malloc(sizeof(OPJ_INT32) * nValues);
66 for (i = 0; i < nValues; i++) {
67 l_tilec->data[i] = getValue((OPJ_UINT32)i);
69 l_tilec->numresolutions = numresolutions;
70 l_tilec->minimum_num_resolutions = numresolutions;
71 l_tilec->resolutions = (opj_tcd_resolution_t*) opj_calloc(
72 l_tilec->numresolutions,
73 sizeof(opj_tcd_resolution_t));
75 l_level_no = l_tilec->numresolutions;
76 l_res = l_tilec->resolutions;
78 /* Adapted from opj_tcd_init_tile() */
79 for (resno = 0; resno < l_tilec->numresolutions; ++resno) {
83 /* border for each resolution level (global) */
84 l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no);
85 l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no);
86 l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no);
87 l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no);
93 void free_tilec(opj_tcd_tilecomp_t * l_tilec)
95 opj_free(l_tilec->data);
96 opj_free(l_tilec->resolutions);
102 "bench_dwt [-decode|encode] [-size value] [-check] [-display]\n");
104 " [-num_resolutions val] [-offset x y] [-num_threads val]\n");
109 OPJ_FLOAT64 opj_clock(void)
112 /* _WIN32: use QueryPerformance (very accurate) */
113 LARGE_INTEGER freq, t ;
114 /* freq is the clock speed of the CPU */
115 QueryPerformanceFrequency(&freq) ;
116 /* cout << "freq = " << ((double) freq.QuadPart) << endl; */
117 /* t is the high resolution performance counter (see MSDN) */
118 QueryPerformanceCounter(& t) ;
119 return freq.QuadPart ? (t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) : 0 ;
121 /* Unix or Linux: use resource usage */
123 OPJ_FLOAT64 procTime;
124 /* (1) Get the rusage data structure at this moment (man getrusage) */
126 /* (2) What is the elapsed time ? - CPU time = User time + System time */
127 /* (2a) Get the seconds */
128 procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec);
129 /* (2b) More precisely! Get the microseconds part ! */
130 return (procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) *
135 static OPJ_FLOAT64 opj_wallclock(void)
141 gettimeofday(&tv, NULL);
142 return (OPJ_FLOAT64)tv.tv_sec + 1e-6 * (OPJ_FLOAT64)tv.tv_usec;
146 int main(int argc, char** argv)
150 opj_tcd_image_t tcd_image;
151 opj_tcd_tile_t tcd_tile;
152 opj_tcd_tilecomp_t tilec;
154 opj_image_comp_t image_comp;
155 opj_thread_pool_t* tp;
157 OPJ_BOOL display = OPJ_FALSE;
158 OPJ_BOOL check = OPJ_FALSE;
159 OPJ_INT32 size = 16384 - 1;
160 OPJ_FLOAT64 start, stop;
161 OPJ_FLOAT64 start_wc, stop_wc;
162 OPJ_UINT32 offset_x = ((OPJ_UINT32)size + 1) / 2 - 1;
163 OPJ_UINT32 offset_y = ((OPJ_UINT32)size + 1) / 2 - 1;
164 OPJ_UINT32 num_resolutions = 6;
165 OPJ_BOOL bench_decode = OPJ_TRUE;
167 for (i = 1; i < argc; i++) {
168 if (strcmp(argv[i], "-encode") == 0) {
169 bench_decode = OPJ_FALSE;
170 } else if (strcmp(argv[i], "-decode") == 0) {
171 bench_decode = OPJ_TRUE;
172 } else if (strcmp(argv[i], "-display") == 0) {
175 } else if (strcmp(argv[i], "-check") == 0) {
177 } else if (strcmp(argv[i], "-size") == 0 && i + 1 < argc) {
178 size = atoi(argv[i + 1]);
180 } else if (strcmp(argv[i], "-num_threads") == 0 && i + 1 < argc) {
181 num_threads = atoi(argv[i + 1]);
183 } else if (strcmp(argv[i], "-num_resolutions") == 0 && i + 1 < argc) {
184 num_resolutions = (OPJ_UINT32)atoi(argv[i + 1]);
185 if (num_resolutions == 0 || num_resolutions > 32) {
187 "Invalid value for num_resolutions. Should be >= 1 and <= 32\n");
191 } else if (strcmp(argv[i], "-offset") == 0 && i + 2 < argc) {
192 offset_x = (OPJ_UINT32)atoi(argv[i + 1]);
193 offset_y = (OPJ_UINT32)atoi(argv[i + 2]);
200 tp = opj_thread_pool_create(num_threads);
202 init_tilec(&tilec, (OPJ_INT32)offset_x, (OPJ_INT32)offset_y,
203 (OPJ_INT32)offset_x + size, (OPJ_INT32)offset_y + size,
209 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
210 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
211 printf("%d ", tilec.data[k]);
218 memset(&tcd, 0, sizeof(tcd));
219 tcd.thread_pool = tp;
220 tcd.whole_tile_decoding = OPJ_TRUE;
221 tcd.win_x0 = (OPJ_UINT32)tilec.x0;
222 tcd.win_y0 = (OPJ_UINT32)tilec.y0;
223 tcd.win_x1 = (OPJ_UINT32)tilec.x1;
224 tcd.win_y1 = (OPJ_UINT32)tilec.y1;
225 tcd.tcd_image = &tcd_image;
226 memset(&tcd_image, 0, sizeof(tcd_image));
227 tcd_image.tiles = &tcd_tile;
228 memset(&tcd_tile, 0, sizeof(tcd_tile));
229 tcd_tile.x0 = tilec.x0;
230 tcd_tile.y0 = tilec.y0;
231 tcd_tile.x1 = tilec.x1;
232 tcd_tile.y1 = tilec.y1;
233 tcd_tile.numcomps = 1;
234 tcd_tile.comps = &tilec;
236 memset(&image, 0, sizeof(image));
238 image.comps = &image_comp;
239 memset(&image_comp, 0, sizeof(image_comp));
244 start_wc = opj_wallclock();
246 opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
248 opj_dwt_encode(&tcd, &tilec);
251 stop_wc = opj_wallclock();
252 printf("time for %s: total = %.03f s, wallclock = %.03f s\n",
253 bench_decode ? "dwt_decode" : "dwt_encode",
257 if (display || check) {
260 printf("After IDWT\n");
262 printf("After FDWT\n");
265 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
266 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
267 printf("%d ", tilec.data[k]);
275 opj_dwt_encode(&tcd, &tilec);
277 opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
282 printf("After FDWT\n");
284 printf("After IDWT\n");
287 for (j = 0; j < tilec.y1 - tilec.y0; j++) {
288 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
289 printf("%d ", tilec.data[k]);
298 size_t nValues = (size_t)(tilec.x1 - tilec.x0) *
299 (size_t)(tilec.y1 - tilec.y0);
300 for (idx = 0; idx < nValues; idx++) {
301 if (tilec.data[idx] != getValue((OPJ_UINT32)idx)) {
302 printf("Difference found at idx = %u\n", (OPJ_UINT32)idx);
311 opj_thread_pool_destroy(tp);