Sub-tile decoding: only decode precincts and codeblocks that intersect the window...
[openjpeg.git] / src / lib / openjp2 / t2.c
index 0fd5300c69b3649b9f31c21d0bf6f799bf45f39f..6f956d1c7f6f988d243a86f64c34f2e8020c7f5e 100644 (file)
@@ -13,6 +13,7 @@
  * 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
@@ -369,7 +370,8 @@ static void opj_null_jas_fprintf(FILE* file, const char * format, ...)
 #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,
@@ -434,14 +436,54 @@ OPJ_BOOL opj_t2_decode_packets(opj_t2_t *p_t2,
         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;