diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2017-09-01 16:30:48 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2017-09-01 16:30:48 +0200 |
| commit | 0ae3cba3404674bbe2028ea9a801301a4c951b33 (patch) | |
| tree | 8150750654ca96ea629ded16cc2731d9e0bd9cdf /tests/test_decode_area.c | |
| parent | 5d07d463fdb0a5eeffa90eba1566cc21697011b8 (diff) | |
Allow several repeated calls to opj_set_decode_area() and opj_decode() for single-tiled images
* Only works for single-tiled images --> will error out cleanly, as currently
in other cases
* Save re-reading the codestream for the tile, and re-use code-blocks of the
previous decoding pass.
* Future improvements might involve improving opj_decompress, and the image writing logic,
to use this strategy.
Diffstat (limited to 'tests/test_decode_area.c')
| -rw-r--r-- | tests/test_decode_area.c | 200 |
1 files changed, 175 insertions, 25 deletions
diff --git a/tests/test_decode_area.c b/tests/test_decode_area.c index e773bc66..92229908 100644 --- a/tests/test_decode_area.c +++ b/tests/test_decode_area.c @@ -99,31 +99,13 @@ static void info_callback(const char *msg, void *client_data) /*fprintf(stdout, "[INFO] %s", msg);*/ } -opj_image_t* decode( - OPJ_BOOL quiet, - const char* input_file, - OPJ_INT32 x0, - OPJ_INT32 y0, - OPJ_INT32 x1, - OPJ_INT32 y1, - OPJ_UINT32* ptilew, - OPJ_UINT32* ptileh, - OPJ_UINT32* pcblkw, - OPJ_UINT32* pcblkh) +static opj_codec_t* create_codec_and_stream(const char* input_file, + opj_stream_t** pOutStream) { opj_dparameters_t l_param; opj_codec_t * l_codec = NULL; - opj_image_t * l_image = NULL; opj_stream_t * l_stream = NULL; - if (!quiet) { - if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) { - printf("Decoding %d,%d,%d,%d\n", x0, y0, x1, y1); - } else { - printf("Decoding full image\n"); - } - } - l_stream = opj_stream_create_default_file_stream(input_file, OPJ_TRUE); if (!l_stream) { fprintf(stderr, "ERROR -> failed to create the stream from the file\n"); @@ -168,6 +150,40 @@ opj_image_t* decode( return NULL; } + *pOutStream = l_stream; + return l_codec; +} + + +opj_image_t* decode( + OPJ_BOOL quiet, + const char* input_file, + OPJ_INT32 x0, + OPJ_INT32 y0, + OPJ_INT32 x1, + OPJ_INT32 y1, + OPJ_UINT32* ptilew, + OPJ_UINT32* ptileh, + OPJ_UINT32* pcblkw, + OPJ_UINT32* pcblkh) +{ + opj_codec_t * l_codec = NULL; + opj_image_t * l_image = NULL; + opj_stream_t * l_stream = NULL; + + if (!quiet) { + if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) { + printf("Decoding %d,%d,%d,%d\n", x0, y0, x1, y1); + } else { + printf("Decoding full image\n"); + } + } + + l_codec = create_codec_and_stream(input_file, &l_stream); + if (l_codec == NULL) { + return NULL; + } + /* Read the main header of the codestream and if necessary the JP2 boxes*/ if (! opj_read_header(l_stream, l_codec, &l_image)) { fprintf(stderr, "ERROR -> failed to read the header\n"); @@ -226,6 +242,122 @@ opj_image_t* decode( return l_image; } +int decode_by_strip(OPJ_BOOL quiet, + const char* input_file, + OPJ_UINT32 strip_height, + opj_image_t* full_image) +{ + /* OPJ_UINT32 tilew, tileh; */ + opj_codec_t * l_codec = NULL; + opj_image_t * l_image = NULL; + opj_stream_t * l_stream = NULL; + OPJ_UINT32 x0, y0, x1, y1, y; + + l_codec = create_codec_and_stream(input_file, &l_stream); + if (l_codec == NULL) { + return 1; + } + + /* Read the main header of the codestream and if necessary the JP2 boxes*/ + if (! opj_read_header(l_stream, l_codec, &l_image)) { + fprintf(stderr, "ERROR -> failed to read the header\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + return 1; + } + + x0 = l_image->x0; + y0 = l_image->y0; + x1 = l_image->x1; + y1 = l_image->y1; + for (y = y0; y < y1; y += strip_height) { + OPJ_UINT32 h_req = strip_height; + if (y + h_req > y1) { + h_req = y1 - y; + } + if (!quiet) { + printf("Decoding %u...%u\n", y, y + h_req); + } + if (!opj_set_decode_area(l_codec, l_image, (OPJ_INT32)x0, (OPJ_INT32)y, + (OPJ_INT32)x1, (OPJ_INT32)(y + h_req))) { + fprintf(stderr, "ERROR -> failed to set the decoded area\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 1; + } + + /* Get the decoded image */ + if (!(opj_decode(l_codec, l_stream, l_image))) { + fprintf(stderr, "ERROR -> failed to decode image!\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 1; + } + + if (full_image) { + OPJ_UINT32 y_check, x; + OPJ_UINT32 compno; + for (compno = 0; compno < l_image->numcomps; compno ++) { + for (y_check = 0; y_check < h_req; y_check++) { + for (x = x0; x < x1; x++) { + OPJ_INT32 sub_image_val = + l_image->comps[compno].data[y_check * (x1 - x0) + x]; + OPJ_INT32 image_val = + full_image->comps[compno].data[(y + y_check) * (x1 - x0) + x]; + if (sub_image_val != image_val) { + fprintf(stderr, + "Difference found at subimage pixel (%u,%u) " + "of compno=%u: got %d, expected %d\n", + x, y_check + y, compno, sub_image_val, image_val); + return 1; + } + } + } + } + } + + } + + /* If image is small enough, try a final whole image read */ + if (x1 - x0 < 10000 && y1 - y0 < 10000) { + if (!quiet) { + printf("Decoding full image\n"); + } + if (!opj_set_decode_area(l_codec, l_image, (OPJ_INT32)x0, (OPJ_INT32)y0, + (OPJ_INT32)x1, (OPJ_INT32)y1)) { + fprintf(stderr, "ERROR -> failed to set the decoded area\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 1; + } + + /* Get the decoded image */ + if (!(opj_decode(l_codec, l_stream, l_image))) { + fprintf(stderr, "ERROR -> failed to decode image!\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 1; + } + } + + if (! opj_end_decompress(l_codec, l_stream)) { + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 1; + } + + + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(l_image); + return 0; +} + OPJ_BOOL check_consistency(opj_image_t* p_image, opj_image_t* p_sub_image) { OPJ_UINT32 compno; @@ -273,10 +405,13 @@ int main(int argc, char** argv) OPJ_UINT32 step_x, step_y; OPJ_BOOL quiet = OPJ_FALSE; OPJ_UINT32 nsteps = 100; + OPJ_UINT32 strip_height = 0; + OPJ_BOOL strip_check = OPJ_FALSE; if (argc < 2) { fprintf(stderr, - "Usage: test_decode_area [-q] [-steps n] input_file_jp2_or_jk2 [x0 y0 x1 y1]\n"); + "Usage: test_decode_area [-q] [-steps n] input_file_jp2_or_jk2 [x0 y0 x1 y1]\n" + "or : test_decode_area [-q] [-strip_height h] [-strip_check] input_file_jp2_or_jk2\n"); return 1; } @@ -288,6 +423,11 @@ int main(int argc, char** argv) } else if (strcmp(argv[iarg], "-steps") == 0 && iarg + 1 < argc) { nsteps = (OPJ_UINT32)atoi(argv[iarg + 1]); iarg ++; + } else if (strcmp(argv[iarg], "-strip_height") == 0 && iarg + 1 < argc) { + strip_height = (OPJ_UINT32)atoi(argv[iarg + 1]); + iarg ++; + } else if (strcmp(argv[iarg], "-strip_check") == 0) { + strip_check = OPJ_TRUE; } else if (input_file == NULL) { input_file = argv[iarg]; } else if (iarg + 3 < argc) { @@ -300,10 +440,20 @@ int main(int argc, char** argv) } } - l_image = decode(quiet, input_file, 0, 0, 0, 0, - &tilew, &tileh, &cblkw, &cblkh); - if (!l_image) { - return 1; + if (!strip_height || strip_check) { + l_image = decode(quiet, input_file, 0, 0, 0, 0, + &tilew, &tileh, &cblkw, &cblkh); + if (!l_image) { + return 1; + } + } + + if (strip_height) { + int ret = decode_by_strip(quiet, input_file, strip_height, l_image); + if (l_image) { + opj_image_destroy(l_image); + } + return ret; } if (da_x0 != 0 || da_x1 != 0 || da_y0 != 0 || da_y1 != 0) { |
