OPJ_BOOL ret;
OPJ_UINT32 it_comp;
+ if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
+ &p_j2k->m_cp.tcps[0].m_data != NULL) {
+ /* In the case of a single-tiled image whose codestream we have already */
+ /* ingested, go on */
+ }
/* Check if we are read the main header */
- if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) {
+ else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) {
opj_event_msg(p_manager, EVT_ERROR,
- "Need to decode the main header before begin to decode the remaining codestream");
+ "Need to decode the main header before begin to decode the remaining codestream.\n");
return OPJ_FALSE;
}
}
for (;;) {
- if (! opj_j2k_read_tile_header(p_j2k,
- &l_current_tile_no,
- NULL,
- &l_tile_x0, &l_tile_y0,
- &l_tile_x1, &l_tile_y1,
- &l_nb_comps,
- &l_go_on,
- p_stream,
- p_manager)) {
- return OPJ_FALSE;
- }
+ if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
+ p_j2k->m_cp.tcps[0].m_data != NULL) {
+ l_current_tile_no = 0;
+ p_j2k->m_current_tile_number = 0;
+ p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA;
+ } else {
+ if (! opj_j2k_read_tile_header(p_j2k,
+ &l_current_tile_no,
+ NULL,
+ &l_tile_x0, &l_tile_y0,
+ &l_tile_x1, &l_tile_y1,
+ &l_nb_comps,
+ &l_go_on,
+ p_stream,
+ p_manager)) {
+ return OPJ_FALSE;
+ }
- if (! l_go_on) {
- break;
+ if (! l_go_on) {
+ break;
+ }
}
if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0,
p_j2k->m_output_image)) {
return OPJ_FALSE;
}
- opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]);
+
+ if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
+ !(p_j2k->m_output_image->x0 == p_j2k->m_private_image->x0 &&
+ p_j2k->m_output_image->y0 == p_j2k->m_private_image->y0 &&
+ p_j2k->m_output_image->x1 == p_j2k->m_private_image->x1 &&
+ p_j2k->m_output_image->y1 == p_j2k->m_private_image->y1)) {
+ /* Keep current tcp data */
+ } else {
+ opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]);
+ }
opj_event_msg(p_manager, EVT_INFO,
"Image data has been updated with tile %d.\n\n", l_current_tile_no + 1);
}
}
- p_j2k->m_output_image = opj_image_create0();
- if (!(p_j2k->m_output_image)) {
- return OPJ_FALSE;
+ if (p_j2k->m_output_image == NULL) {
+ p_j2k->m_output_image = opj_image_create0();
+ if (!(p_j2k->m_output_image)) {
+ return OPJ_FALSE;
+ }
}
opj_copy_image_header(p_image, p_j2k->m_output_image);
for (compno = 0; compno < p_image->numcomps; compno++) {
p_image->comps[compno].resno_decoded =
p_j2k->m_output_image->comps[compno].resno_decoded;
+ opj_image_data_free(p_image->comps[compno].data);
p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
#if 0
char fn[256];
}
}
+ /* Both can be non NULL if for example decoding a full tile and then */
+ /* partially a tile. In which case partial decoding should be the */
+ /* priority */
+ assert((cblk->decoded_data != NULL) || (tilec->data != NULL));
+
if (cblk->decoded_data) {
if (tccp->qmfbid == 1) {
for (j = 0; j < cblk_h; ++j) {
(OPJ_UINT32)precinct->y0,
(OPJ_UINT32)precinct->x1,
(OPJ_UINT32)precinct->y1)) {
+ for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
+ opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
+ if (cblk->decoded_data) {
+#ifdef DEBUG_VERBOSE
+ printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n",
+ cblk->x0, cblk->y0, resno, bandno);
+#endif
+ opj_free(cblk->decoded_data);
+ cblk->decoded_data = NULL;
+ }
+ }
continue;
}
opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
opj_t1_cblk_decode_processing_job_t* job;
- assert(cblk->decoded_data == NULL);
-
if (!opj_tcd_is_subband_area_of_interest(tcd,
tilec->compno,
resno,
(OPJ_UINT32)cblk->y0,
(OPJ_UINT32)cblk->x1,
(OPJ_UINT32)cblk->y1)) {
+ if (cblk->decoded_data) {
+#ifdef DEBUG_VERBOSE
+ printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n",
+ cblk->x0, cblk->y0, resno, bandno);
+#endif
+ opj_free(cblk->decoded_data);
+ cblk->decoded_data = NULL;
+ }
continue;
}
if (!tcd->whole_tile_decoding) {
OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0);
OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0);
+ if (cblk->decoded_data != NULL) {
+#ifdef DEBUG_VERBOSE
+ printf("Reusing codeblock %d,%d at resno=%d, bandno=%d\n",
+ cblk->x0, cblk->y0, resno, bandno);
+#endif
+ continue;
+ }
if (cblk_w == 0 || cblk_h == 0) {
continue;
}
+#ifdef DEBUG_VERBOSE
+ printf("Decoding codeblock %d,%d at resno=%d, bandno=%d\n",
+ cblk->x0, cblk->y0, resno, bandno);
+#endif
/* Zero-init required */
cblk->decoded_data = opj_calloc(1, cblk_w * cblk_h * sizeof(OPJ_INT32));
if (cblk->decoded_data == NULL) {
*pret = OPJ_FALSE;
return;
}
+ } else if (cblk->decoded_data) {
+ /* Not sure if that code path can happen, but better be */
+ /* safe than sorry */
+ opj_free(cblk->decoded_data);
+ cblk->decoded_data = NULL;
}
job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
/*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");
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");
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;
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;
}
} 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) {
}
}
- 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) {