* Copyright (c) 2010-2011, Kaori Hagihara
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
++l_img_comp;
}
- l_tile_size = (OPJ_UINT32)(l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */
+ /* TODO: where does this magic value come from ? */
+ /* This used to be 1.3 / 8, but with random data and very small code */
+ /* block sizes, this is not enough. For example with */
+ /* bin/test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16 */
+ /* TODO revise this to take into account the overhead linked to the */
+ /* number of packets and number of code blocks in packets */
+ l_tile_size = (OPJ_UINT32)(l_tile_size * 1.4 / 8);
l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k);
OPJ_UINT32 l_current_marker;
OPJ_BYTE l_data [2];
opj_tcp_t * l_tcp;
+ opj_image_t* l_image_for_bounds;
/* preconditions */
assert(p_stream != 00);
return OPJ_FALSE;
}
+ /* When using the opj_read_tile_header / opj_decode_tile_data API */
+ /* such as in test_tile_decoder, m_output_image is NULL, so fall back */
+ /* to the full image dimension. This is a bit surprising that */
+ /* opj_set_decode_area() is only used to determinte intersecting tiles, */
+ /* but full tile decoding is done */
+ l_image_for_bounds = p_j2k->m_output_image ? p_j2k->m_output_image :
+ p_j2k->m_private_image;
if (! opj_tcd_decode_tile(p_j2k->m_tcd,
+ l_image_for_bounds->x0,
+ l_image_for_bounds->y0,
+ l_image_for_bounds->x1,
+ l_image_for_bounds->y1,
l_tcp->m_data,
l_tcp->m_data_size,
p_tile_index,
}
-void opj_t1_decode_cblks(opj_thread_pool_t* tp,
+void opj_t1_decode_cblks(opj_tcd_t* tcd,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp,
OPJ_BOOL check_pterm
)
{
+ opj_thread_pool_t* tp = tcd->thread_pool;
OPJ_UINT32 resno, bandno, precno, cblkno;
for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) {
opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
opj_t1_cblk_decode_processing_job_t* job;
+ if (!opj_tcd_is_subband_area_of_interest(tcd,
+ tilec->compno,
+ resno,
+ band->bandno,
+ (OPJ_UINT32)cblk->x0,
+ (OPJ_UINT32)cblk->y0,
+ (OPJ_UINT32)cblk->x1,
+ (OPJ_UINT32)cblk->y1)) {
+ continue;
+ }
+
job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
sizeof(opj_t1_cblk_decode_processing_job_t));
if (!job) {
/**
Decode the code-blocks of a tile
-@param tp Thread pool
+@param tcd TCD handle
@param pret Pointer to return value
@param tilec The tile to decode
@param tccp Tile coding parameters
@param p_manager_mutex mutex for the event manager
@param check_pterm whether PTERM correct termination should be checked
*/
-void opj_t1_decode_cblks(opj_thread_pool_t* tp,
+void opj_t1_decode_cblks(opj_tcd_t* tcd,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp,
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define JAS_FPRINTF opj_null_jas_fprintf
#endif
-OPJ_BOOL opj_t2_decode_packets(opj_t2_t *p_t2,
+OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
+ opj_t2_t *p_t2,
OPJ_UINT32 p_tile_no,
opj_tcd_tile_t *p_tile,
OPJ_BYTE *p_src,
memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL));
while (opj_pi_next(l_current_pi)) {
+ OPJ_BOOL skip_packet = OPJ_FALSE;
JAS_FPRINTF(stderr,
"packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n",
l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno,
l_current_pi->precno, l_current_pi->layno);
- if (l_tcp->num_layers_to_decode > l_current_pi->layno
- && l_current_pi->resno <
- p_tile->comps[l_current_pi->compno].minimum_num_resolutions) {
+ /* If the packet layer is greater or equal than the maximum */
+ /* number of layers, skip the packet */
+ if (l_current_pi->layno >= l_tcp->num_layers_to_decode) {
+ skip_packet = OPJ_TRUE;
+ }
+ /* If the packet resolution number is greater than the minimum */
+ /* number of resolution allowed, skip the packet */
+ else if (l_current_pi->resno >=
+ p_tile->comps[l_current_pi->compno].minimum_num_resolutions) {
+ skip_packet = OPJ_TRUE;
+ } else {
+ /* If no precincts of any band intersects the area of interest, */
+ /* skip the packet */
+ OPJ_UINT32 bandno;
+ opj_tcd_tilecomp_t *tilec = &p_tile->comps[l_current_pi->compno];
+ opj_tcd_resolution_t *res = &tilec->resolutions[l_current_pi->resno];
+
+ skip_packet = OPJ_TRUE;
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_t* band = &res->bands[bandno];
+ opj_tcd_precinct_t* prec = &band->precincts[l_current_pi->precno];
+
+ if (opj_tcd_is_subband_area_of_interest(tcd,
+ l_current_pi->compno,
+ l_current_pi->resno,
+ band->bandno,
+ (OPJ_UINT32)prec->x0,
+ (OPJ_UINT32)prec->y0,
+ (OPJ_UINT32)prec->x1,
+ (OPJ_UINT32)prec->y1)) {
+ skip_packet = OPJ_FALSE;
+ break;
+ }
+ }
+ /*
+ printf("packet cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d -> %s\n",
+ l_current_pi->compno, l_current_pi->resno,
+ l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept");
+ */
+ }
+
+ if (!skip_packet) {
l_nb_bytes_read = 0;
first_pass_failed[l_current_pi->compno] = OPJ_FALSE;
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/**
Decode the packets of a tile from a source buffer
+@param tcd TCD handle
@param t2 T2 handle
@param tileno number that identifies the tile for which to decode the packets
@param tile tile for which to decode the packets
@return FIXME DOC
*/
-OPJ_BOOL opj_t2_decode_packets(opj_t2_t *t2,
+OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
+ opj_t2_t *t2,
OPJ_UINT32 tileno,
opj_tcd_tile_t *tile,
OPJ_BYTE *src,
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy);
l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx);
l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy);
+ l_tilec->compno = compno;
/*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/
/* compute l_data_size with overflow check */
}
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
+ OPJ_UINT32 decoded_x0,
+ OPJ_UINT32 decoded_y0,
+ OPJ_UINT32 decoded_x1,
+ OPJ_UINT32 decoded_y1,
OPJ_BYTE *p_src,
OPJ_UINT32 p_max_length,
OPJ_UINT32 p_tile_no,
OPJ_UINT32 l_data_read;
p_tcd->tcd_tileno = p_tile_no;
p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]);
+ p_tcd->decoded_x0 = decoded_x0;
+ p_tcd->decoded_y0 = decoded_y0;
+ p_tcd->decoded_x1 = decoded_x1;
+ p_tcd->decoded_y1 = decoded_y1;
#ifdef TODO_MSD /* FIXME */
/* INDEX >> */
}
if (! opj_t2_decode_packets(
+ p_tcd,
l_t2,
p_tcd->tcd_tileno,
p_tcd->tcd_image->tiles,
}
for (compno = 0; compno < l_tile->numcomps; ++compno) {
- opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp,
+ opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp,
p_manager, p_manager_mutex, check_pterm);
if (!ret) {
break;
{
return (band->x1 - band->x0 == 0) || (band->y1 - band->y0 == 0);
}
+
+OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 resno,
+ OPJ_UINT32 bandno,
+ OPJ_UINT32 band_x0,
+ OPJ_UINT32 band_y0,
+ OPJ_UINT32 band_x1,
+ OPJ_UINT32 band_y1)
+{
+ OPJ_UINT32 filter_margin = (tcd->tcp->tccps[compno].qmfbid == 1) ? 2 : 3;
+ opj_tcd_tilecomp_t *tilec = &(tcd->tcd_image->tiles->comps[compno]);
+ opj_image_comp_t* image_comp = &(tcd->image->comps[compno]);
+ /* Compute the intersection of the area of interest, expressed in tile coordinates */
+ /* with the tile coordinates */
+ OPJ_UINT32 tcx0 = opj_uint_max(
+ (OPJ_UINT32)tilec->x0,
+ opj_uint_ceildiv(tcd->decoded_x0, image_comp->dx));
+ OPJ_UINT32 tcy0 = opj_uint_max(
+ (OPJ_UINT32)tilec->y0,
+ opj_uint_ceildiv(tcd->decoded_y0, image_comp->dy));
+ OPJ_UINT32 tcx1 = opj_uint_min(
+ (OPJ_UINT32)tilec->x1,
+ opj_uint_ceildiv(tcd->decoded_x1, image_comp->dx));
+ OPJ_UINT32 tcy1 = opj_uint_min(
+ (OPJ_UINT32)tilec->y1,
+ opj_uint_ceildiv(tcd->decoded_y1, image_comp->dy));
+ /* Compute number of decomposition for this band. See table F-1 */
+ OPJ_UINT32 nb = (resno == 0) ?
+ tilec->numresolutions - 1 :
+ tilec->numresolutions - resno;
+ /* Map above tile-based coordinates to sub-band-based coordinates per */
+ /* equation B-15 of the standard */
+ OPJ_UINT32 x0b = bandno & 1;
+ OPJ_UINT32 y0b = bandno >> 1;
+ OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : opj_uint_ceildiv(tcx0 - (1U <<
+ (nb - 1)) * x0b, 1U << nb);
+ OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : opj_uint_ceildiv(tcy0 - (1U <<
+ (nb - 1)) * y0b, 1U << nb);
+ OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : opj_uint_ceildiv(tcx1 - (1U <<
+ (nb - 1)) * x0b, 1U << nb);
+ OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : opj_uint_ceildiv(tcy1 - (1U <<
+ (nb - 1)) * y0b, 1U << nb);
+ OPJ_BOOL intersects;
+
+ if (tbx0 < filter_margin) {
+ tbx0 = 0;
+ } else {
+ tbx0 -= filter_margin;
+ }
+ if (tby0 < filter_margin) {
+ tby0 = 0;
+ } else {
+ tby0 -= filter_margin;
+ }
+ tbx1 = opj_uint_adds(tbx1, filter_margin);
+ tby1 = opj_uint_adds(tby1, filter_margin);
+
+ intersects = band_x0 < tbx1 && band_y0 < tby1 && band_x1 > tbx0 &&
+ band_y1 > tby0;
+
+#ifdef DEBUG_VERBOSE
+ printf("compno=%u resno=%u nb=%u bandno=%u x0b=%u y0b=%u band=%u,%u,%u,%u tb=%u,%u,%u,%u -> %u\n",
+ compno, resno, nb, bandno, x0b, y0b,
+ band_x0, band_y0, band_x1, band_y1,
+ tbx0, tby0, tbx1, tby1, intersects);
+#endif
+ return intersects;
+}
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef struct opj_tcd_tilecomp {
/* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
OPJ_INT32 x0, y0, x1, y1;
+ /* component number */
+ OPJ_UINT32 compno;
/* number of resolutions level */
OPJ_UINT32 numresolutions;
/* number of resolutions level to decode (at max)*/
OPJ_BITFIELD m_is_decoder : 1;
/** Thread pool */
opj_thread_pool_t* thread_pool;
+ OPJ_UINT32 decoded_x0;
+ OPJ_UINT32 decoded_y0;
+ OPJ_UINT32 decoded_x1;
+ OPJ_UINT32 decoded_y1;
} opj_tcd_t;
/** @name Exported functions */
/**
Decode a tile from a buffer into a raw image
@param tcd TCD handle
+@param decoded_x0 Upper left x of region to decode (in grid coordinates)
+@param decoded_y0 Upper left y of region to decode (in grid coordinates)
+@param decoded_x1 Lower right x of region to decode (in grid coordinates)
+@param decoded_y1 Lower right y of region to decode (in grid coordinates)
@param src Source buffer
@param len Length of source buffer
@param tileno Number that identifies one of the tiles to be decoded
@param manager the event manager.
*/
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *tcd,
+ OPJ_UINT32 decoded_x0,
+ OPJ_UINT32 decoded_y0,
+ OPJ_UINT32 decoded_x1,
+ OPJ_UINT32 decoded_y1,
OPJ_BYTE *src,
OPJ_UINT32 len,
OPJ_UINT32 tileno,
/** Reinitialize a segment */
void opj_tcd_reinit_segment(opj_tcd_seg_t* seg);
+
+/** Returns whether a sub-band region contributes to the area of interest
+ * tcd->decoded_x0,tcd->decoded_y0,tcd->decoded_x1,tcd->decoded_y1.
+ *
+ * @param tcd TCD handle.
+ * @param compno Component number
+ * @param resno Resolution number
+ * @param bandno Band number (*not* band index, ie 0, 1, 2 or 3)
+ * @param x0 Upper left x in subband coordinates
+ * @param y0 Upper left y in subband coordinates
+ * @param x1 Lower right x in subband coordinates
+ * @param y1 Lower right y in subband coordinates
+ * @return OPJ_TRUE whether the sub-band region contributs to the area of
+ * interest.
+ */
+OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 resno,
+ OPJ_UINT32 bandno,
+ OPJ_UINT32 x0,
+ OPJ_UINT32 y0,
+ OPJ_UINT32 x1,
+ OPJ_UINT32 y1);
+
+
/* ----------------------------------------------------------------------- */
/*@}*/
add_executable(test_tile_encoder test_tile_encoder.c)
target_link_libraries(test_tile_encoder ${OPENJPEG_LIBRARY_NAME})
+add_executable(test_decode_area test_decode_area.c)
+target_link_libraries(test_decode_area ${OPENJPEG_LIBRARY_NAME})
+
# Let's try a couple of possibilities:
add_test(NAME tte0 COMMAND test_tile_encoder)
add_test(NAME tte1 COMMAND test_tile_encoder 3 2048 2048 1024 1024 8 1 tte1.j2k)
add_test(NAME rta5 COMMAND j2k_random_tile_access tte5.j2k)
set_property(TEST rta5 APPEND PROPERTY DEPENDS tte5)
+add_test(NAME tda_prep_reversible_no_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1)
+add_test(NAME tda_reversible_no_precinct COMMAND test_decode_area -q reversible_no_precinct.j2k)
+set_property(TEST tda_reversible_no_precinct APPEND PROPERTY DEPENDS tda_prep_reversible_no_precinct)
+
+add_test(NAME tda_prep_reversible_with_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16)
+add_test(NAME tda_reversible_with_precinct COMMAND test_decode_area -q reversible_with_precinct.j2k)
+set_property(TEST tda_reversible_with_precinct APPEND PROPERTY DEPENDS tda_prep_reversible_with_precinct)
+
+add_test(NAME tda_prep_irreversible_no_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 1 irreversible_no_precinct.j2k 4 4 3 0 0 1)
+add_test(NAME tda_irreversible_no_precinct COMMAND test_decode_area -q irreversible_no_precinct.j2k)
+set_property(TEST tda_irreversible_no_precinct APPEND PROPERTY DEPENDS tda_prep_irreversible_no_precinct)
+
add_executable(include_openjpeg include_openjpeg.c)
# No image send to the dashboard if lib PNG is not available.
--- /dev/null
+/*
+ * The copyright in this software is being made available under the 2-clauses
+ * BSD License, included below. This software may be subject to other third
+ * party and contributor rights, including patent rights, and no such rights
+ * are granted under this license.
+ *
+ * Copyright (c) 2017, IntoPix SA <contact@intopix.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "openjpeg.h"
+#include "format_defs.h"
+
+
+/* -------------------------------------------------------------------------- */
+#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
+#define JP2_MAGIC "\x0d\x0a\x87\x0a"
+/* position 45: "\xff\x52" */
+#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
+
+static int infile_format(const char *fname)
+{
+ FILE *reader;
+ unsigned char buf[12];
+ unsigned int l_nb_read;
+
+ reader = fopen(fname, "rb");
+
+ if (reader == NULL) {
+ return -1;
+ }
+
+ memset(buf, 0, 12);
+ l_nb_read = (unsigned int)fread(buf, 1, 12, reader);
+ fclose(reader);
+ if (l_nb_read != 12) {
+ return -1;
+ }
+
+ if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
+ return JP2_CFMT;
+ } else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
+ return J2K_CFMT;
+ } else {
+ return -1;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ sample error debug callback expecting no client object
+ */
+static void error_callback(const char *msg, void *client_data)
+{
+ (void)client_data;
+ fprintf(stdout, "[ERROR] %s", msg);
+}
+/**
+ sample warning debug callback expecting no client object
+ */
+static void warning_callback(const char *msg, void *client_data)
+{
+ (void)client_data;
+ fprintf(stdout, "[WARNING] %s", msg);
+}
+/**
+ sample debug callback expecting no client object
+ */
+static void info_callback(const char *msg, void *client_data)
+{
+ (void)client_data;
+ (void)msg;
+ /*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)
+{
+ 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;
+ }
+
+ /* Set the default decoding parameters */
+ opj_set_default_decoder_parameters(&l_param);
+
+ /* */
+ l_param.decod_format = infile_format(input_file);
+
+
+ switch (l_param.decod_format) {
+ case J2K_CFMT: { /* JPEG-2000 codestream */
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(OPJ_CODEC_J2K);
+ break;
+ }
+ case JP2_CFMT: { /* JPEG 2000 compressed image data */
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(OPJ_CODEC_JP2);
+ break;
+ }
+ default: {
+ fprintf(stderr, "ERROR -> Not a valid JPEG2000 file!\n");
+ opj_stream_destroy(l_stream);
+ return NULL;
+ }
+ }
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_info_handler(l_codec, info_callback, 00);
+ opj_set_warning_handler(l_codec, warning_callback, 00);
+ opj_set_error_handler(l_codec, error_callback, 00);
+
+ /* Setup the decoder decoding parameters using user parameters */
+ if (! opj_setup_decoder(l_codec, &l_param)) {
+ fprintf(stderr, "ERROR ->failed to setup the decoder\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ 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");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ return NULL;
+ }
+
+ {
+ opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(l_codec);
+ if (ptilew) {
+ *ptilew = pCodeStreamInfo->tdx;
+ }
+ if (ptileh) {
+ *ptilew = pCodeStreamInfo->tdy;
+ }
+ //int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
+ if (pcblkw) {
+ *pcblkw = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkw;
+ }
+ if (pcblkh) {
+ *pcblkh = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkh;
+ }
+ opj_destroy_cstr_info(&pCodeStreamInfo);
+ }
+
+ if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) {
+ if (!opj_set_decode_area(l_codec, l_image, x0, y0, x1, 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 NULL;
+ }
+ }
+
+ /* 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 NULL;
+ }
+
+ if (! opj_end_decompress(l_codec, l_stream)) {
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(l_image);
+ return NULL;
+ }
+
+
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ return l_image;
+}
+
+OPJ_BOOL check_consistency(opj_image_t* p_image, opj_image_t* p_sub_image)
+{
+ OPJ_UINT32 compno;
+ for (compno = 0; compno < p_image->numcomps; compno ++) {
+ OPJ_UINT32 y;
+ OPJ_UINT32 shift_y = p_sub_image->comps[compno].y0 - p_image->comps[compno].y0;
+ OPJ_UINT32 shift_x = p_sub_image->comps[compno].x0 - p_image->comps[compno].x0;
+ OPJ_UINT32 image_w = p_image->comps[compno].w;
+ OPJ_UINT32 sub_image_w = p_sub_image->comps[compno].w;
+ for (y = 0; y < p_sub_image->comps[compno].h; y++) {
+ OPJ_UINT32 x;
+
+ for (x = 0; x < sub_image_w; x++) {
+ OPJ_INT32 sub_image_val =
+ p_sub_image->comps[compno].data[y * sub_image_w + x];
+ OPJ_INT32 image_val =
+ p_image->comps[compno].data[(y + shift_y) * image_w + x + shift_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, compno, sub_image_val, image_val);
+ return OPJ_FALSE;
+ }
+ }
+ }
+ }
+ return OPJ_TRUE;
+}
+
+static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
+{
+ return (a < b) ? a : b;
+}
+
+int main(int argc, char** argv)
+{
+ opj_image_t * l_image = NULL;
+ opj_image_t * l_sub_image = NULL;
+ OPJ_INT32 da_x0 = 0, da_y0 = 0, da_x1 = 0, da_y1 = 0;
+ const char* input_file = NULL;
+ OPJ_UINT32 tilew, tileh, cblkw, cblkh;
+ OPJ_UINT32 w, h;
+ OPJ_UINT32 x, y;
+ OPJ_UINT32 step_x, step_y;
+ OPJ_BOOL quiet = OPJ_FALSE;
+ OPJ_UINT32 nsteps = 100;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Usage: test_decode_area [-q] [-steps n] input_file_jp2_or_jk2 [x0 y0 x1 y1]\n");
+ return 1;
+ }
+
+ {
+ int iarg;
+ for (iarg = 1; iarg < argc; iarg++) {
+ if (strcmp(argv[iarg], "-q") == 0) {
+ quiet = OPJ_TRUE;
+ } else if (strcmp(argv[iarg], "-steps") == 0 && iarg + 1 < argc) {
+ nsteps = (OPJ_UINT32)atoi(argv[iarg + 1]);
+ iarg ++;
+ } else if (input_file == NULL) {
+ input_file = argv[iarg];
+ } else if (iarg + 3 < argc) {
+ da_x0 = atoi(argv[iarg]);
+ da_y0 = atoi(argv[iarg + 1]);
+ da_x1 = atoi(argv[iarg + 2]);
+ da_y1 = atoi(argv[iarg + 3]);
+ iarg += 3;
+ }
+ }
+ }
+
+ l_image = decode(quiet, input_file, 0, 0, 0, 0,
+ &tilew, &tileh, &cblkw, &cblkh);
+ if (!l_image) {
+ return 1;
+ }
+
+ if (da_x0 != 0 || da_x1 != 0 || da_y0 != 0 || da_y1 != 0) {
+ l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
+ NULL, NULL, NULL, NULL);
+ if (!l_sub_image) {
+ fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+
+ if (!check_consistency(l_image, l_sub_image)) {
+ fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 0;
+ }
+
+ w = l_image->x1 - l_image->x0;
+ h = l_image->y1 - l_image->y0;
+ step_x = w > nsteps ? w / nsteps : 1;
+ step_y = h > nsteps ? h / nsteps : 1;
+ for (y = 0; y < h; y += step_y) {
+ for (x = 0; x < w; x += step_x) {
+ da_x0 = (OPJ_INT32)(l_image->x0 + x);
+ da_y0 = (OPJ_INT32)(l_image->y0 + y);
+ da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, l_image->x0 + x + 1);
+ da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, l_image->y0 + y + 1);
+ l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
+ NULL, NULL, NULL, NULL);
+ if (!l_sub_image) {
+ fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+
+ if (!check_consistency(l_image, l_sub_image)) {
+ fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+ opj_image_destroy(l_sub_image);
+
+ if (step_x > 1 || step_y > 1) {
+ if (step_x > 1) {
+ da_x0 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x0 + 1);
+ da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x1 + 1);
+ }
+ if (step_y > 1) {
+ da_y0 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y0 + 1);
+ da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y1 + 1);
+ }
+ l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
+ NULL, NULL, NULL, NULL);
+ if (!l_sub_image) {
+ fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+
+ if (!check_consistency(l_image, l_sub_image)) {
+ fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
+ da_x0, da_y0, da_x1, da_y1);
+ opj_image_destroy(l_sub_image);
+ opj_image_destroy(l_image);
+ return 1;
+ }
+ opj_image_destroy(l_sub_image);
+ }
+ }
+ }
+
+ opj_image_destroy(l_image);
+ return 0;
+}
fprintf(stdout, "[INFO] %s", msg);
}
+static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b)
+{
+ return (a > b) ? a : b;
+}
+
+static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
+{
+ return (a < b) ? a : b;
+}
+
/* -------------------------------------------------------------------------- */
#define NUM_COMPS_MAX 4
opj_image_t * l_image;
opj_image_cmptparm_t l_params [NUM_COMPS_MAX];
opj_stream_t * l_stream;
- OPJ_UINT32 l_nb_tiles;
+ OPJ_UINT32 l_nb_tiles_width, l_nb_tiles_height, l_nb_tiles;
OPJ_UINT32 l_data_size;
size_t len;
int comp_prec;
int irreversible;
const char *output_file;
+ int cblockw_init = 64;
+ int cblockh_init = 64;
+ int numresolution = 6;
+ OPJ_UINT32 offsetx = 0;
+ OPJ_UINT32 offsety = 0;
+ int quality_loss = 1;
+ int is_rand = 0;
+
+ opj_set_default_encoder_parameters(&l_param);
- /* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k */
- if (argc == 9) {
+ /* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k [64 64] [6] [0 0] [0] [256 256] */
+ if (argc >= 9) {
num_comps = (OPJ_UINT32)atoi(argv[1]);
image_width = atoi(argv[2]);
image_height = atoi(argv[3]);
comp_prec = atoi(argv[6]);
irreversible = atoi(argv[7]);
output_file = argv[8];
+ if (argc >= 12) {
+ quality_loss = 0;
+ cblockw_init = atoi(argv[9]);
+ cblockh_init = atoi(argv[10]);
+ }
+ if (argc >= 13) {
+ numresolution = atoi(argv[11]);
+ }
+ if (argc >= 14) {
+ offsetx = (OPJ_UINT32)atoi(argv[12]);
+ offsety = (OPJ_UINT32)atoi(argv[13]);
+ }
+ if (argc >= 15) {
+ is_rand = atoi(argv[14]);
+ }
+ for (i = 15; i + 1 < (OPJ_UINT32)argc &&
+ l_param.res_spec < OPJ_J2K_MAXRLVLS; i += 2) {
+ l_param.csty |= 0x01;
+ l_param.prcw_init[l_param.res_spec] = atoi(argv[i]);
+ l_param.prch_init[l_param.res_spec] = atoi(argv[i + 1]);
+ l_param.res_spec ++;
+ }
} else {
num_comps = 3;
image_width = 2000;
if (num_comps > NUM_COMPS_MAX) {
return 1;
}
- l_nb_tiles = (OPJ_UINT32)(image_width / tile_width) * (OPJ_UINT32)(
- image_height / tile_height);
+ l_nb_tiles_width = (offsetx + (OPJ_UINT32)image_width +
+ (OPJ_UINT32)tile_width - 1) / (OPJ_UINT32)tile_width;
+ l_nb_tiles_height = (offsety + (OPJ_UINT32)image_height +
+ (OPJ_UINT32)tile_height - 1) / (OPJ_UINT32)tile_height;
+ l_nb_tiles = l_nb_tiles_width * l_nb_tiles_height;
l_data_size = (OPJ_UINT32)tile_width * (OPJ_UINT32)tile_height *
(OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
fprintf(stdout,
"Encoding random values -> keep in mind that this is very hard to compress\n");
for (i = 0; i < l_data_size; ++i) {
- l_data[i] = (OPJ_BYTE)i; /*rand();*/
+ if (is_rand) {
+ l_data[i] = (OPJ_BYTE)rand();
+ } else {
+ l_data[i] = (OPJ_BYTE)i;
+ }
}
- opj_set_default_encoder_parameters(&l_param);
/** you may here add custom encoding parameters */
/* rate specifications */
/** number of quality layers in the stream */
- l_param.tcp_numlayers = 1;
- l_param.cp_fixed_quality = 1;
- l_param.tcp_distoratio[0] = 20;
+ if (quality_loss) {
+ l_param.tcp_numlayers = 1;
+ l_param.cp_fixed_quality = 1;
+ l_param.tcp_distoratio[0] = 20;
+ }
/* is using others way of calculation */
/* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */
/* l_param.tcp_rates[0] = ... */
l_param.cp_tdx = tile_width;
l_param.cp_tdy = tile_height;
+ /* code block size */
+ l_param.cblockw_init = cblockw_init;
+ l_param.cblockh_init = cblockh_init;
+
/* use irreversible encoding ?*/
l_param.irreversible = irreversible;
/* l_param.mode = 0;*/
/** number of resolutions */
- l_param.numresolution = 6;
+ l_param.numresolution = numresolution;
/** progression order to use*/
/** OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */
l_current_param_ptr->sgnd = 0;
l_current_param_ptr->prec = (OPJ_UINT32)comp_prec;
- l_current_param_ptr->x0 = 0;
- l_current_param_ptr->y0 = 0;
+ l_current_param_ptr->x0 = offsetx;
+ l_current_param_ptr->y0 = offsety;
++l_current_param_ptr;
}
return 1;
}
- l_image->x0 = 0;
- l_image->y0 = 0;
- l_image->x1 = (OPJ_UINT32)image_width;
- l_image->y1 = (OPJ_UINT32)image_height;
+ l_image->x0 = offsetx;
+ l_image->y0 = offsety;
+ l_image->x1 = offsetx + (OPJ_UINT32)image_width;
+ l_image->y1 = offsety + (OPJ_UINT32)image_height;
l_image->color_space = OPJ_CLRSPC_SRGB;
if (! opj_setup_encoder(l_codec, &l_param, l_image)) {
}
for (i = 0; i < l_nb_tiles; ++i) {
- if (! opj_write_tile(l_codec, i, l_data, l_data_size, l_stream)) {
+ OPJ_UINT32 tile_y = i / l_nb_tiles_width;
+ OPJ_UINT32 tile_x = i % l_nb_tiles_width;
+ OPJ_UINT32 tile_x0 = opj_uint_max(l_image->x0, tile_x * (OPJ_UINT32)tile_width);
+ OPJ_UINT32 tile_y0 = opj_uint_max(l_image->y0,
+ tile_y * (OPJ_UINT32)tile_height);
+ OPJ_UINT32 tile_x1 = opj_uint_min(l_image->x1,
+ (tile_x + 1) * (OPJ_UINT32)tile_width);
+ OPJ_UINT32 tile_y1 = opj_uint_min(l_image->y1,
+ (tile_y + 1) * (OPJ_UINT32)tile_height);
+ OPJ_UINT32 tilesize = (tile_x1 - tile_x0) * (tile_y1 - tile_y0) *
+ (OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
+ if (! opj_write_tile(l_codec, i, l_data, tilesize, l_stream)) {
fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",
i);
opj_stream_destroy(l_stream);