LCOV - code coverage report
Current view: top level - frmts/nitf - nitfaridpcm.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 172 0.0 %
Date: 2025-06-19 12:30:01 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  NITF Read/Write Library
       4             :  * Purpose:  ARIDPCM reading code.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2007, Frank Warmerdam
       9             :  * Copyright (c) 2009, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "nitflib.h"
      16             : 
      17             : #include <algorithm>
      18             : #include <cstring>
      19             : 
      20             : #include "gdal.h"
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : 
      24             : constexpr int neighbourhood_size_75[4] = {23, 47, 74, 173};
      25             : constexpr int bits_per_level_by_busycode_75[4 /*busy code*/][4 /*level*/] = {
      26             :     {8, 5, 0, 0},   // BC = 00
      27             :     {8, 5, 2, 0},   // BC = 01
      28             :     {8, 6, 4, 0},   // BC = 10
      29             :     {8, 7, 4, 2}};  // BC = 11
      30             : 
      31             : constexpr int CR075 = 1;
      32             : 
      33             : // Level for each index value.
      34             : constexpr int level_index_table[64] = {
      35             :     0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
      36             :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
      37             :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
      38             : 
      39             : // List of i,j to linear index macros mappings.
      40             : // Note that i is vertical and j is horizontal and progression is
      41             : // right to left, bottom to top.
      42             : 
      43             : #define IND(i, j) (ij_index[i + j * 8] - 1)
      44             : 
      45             : constexpr int ij_index[64] = {
      46             : 
      47             :     1,   // 0, 0
      48             :     18,  // 1, 0
      49             :     6,   // 2, 0
      50             :     30,  // 3, 0
      51             :     3,   // 4, 0
      52             :     42,  // 5, 0
      53             :     12,  // 6, 0
      54             :     54,  // 7, 0
      55             : 
      56             :     17,  // 0, 1
      57             :     19,  // 1, 1
      58             :     29,  // 2, 1
      59             :     31,  // 3, 1
      60             :     41,  // 4, 1
      61             :     43,  // 5, 1
      62             :     53,  // 6, 1
      63             :     55,  // 7, 1
      64             : 
      65             :     5,   // 0, 2
      66             :     21,  // 1, 2
      67             :     7,   // 2, 2
      68             :     33,  // 3, 2
      69             :     11,  // 4, 2
      70             :     45,  // 5, 2
      71             :     13,  // 6, 2
      72             :     57,  // 7, 2
      73             : 
      74             :     20,  // 0, 3
      75             :     22,  // 1, 3
      76             :     32,  // 2, 3
      77             :     34,  // 3, 3
      78             :     44,  // 4, 3
      79             :     46,  // 5, 3
      80             :     56,  // 6, 3
      81             :     58,  // 7, 3
      82             : 
      83             :     2,   // 0, 4
      84             :     24,  // 1, 4
      85             :     9,   // 2, 4
      86             :     36,  // 3, 4
      87             :     4,   // 4, 4
      88             :     48,  // 5, 4
      89             :     15,  // 6, 4
      90             :     60,  // 7, 4
      91             : 
      92             :     23,  // 0, 5
      93             :     25,  // 1, 5
      94             :     35,  // 2, 5
      95             :     37,  // 3, 5
      96             :     47,  // 4, 5
      97             :     49,  // 5, 5
      98             :     59,  // 6, 5
      99             :     61,  // 7, 5
     100             : 
     101             :     8,   // 0, 6
     102             :     27,  // 1, 6
     103             :     10,  // 2, 6
     104             :     39,  // 3, 6
     105             :     14,  // 4, 6
     106             :     51,  // 5, 6
     107             :     16,  // 6, 6
     108             :     63,  // 7, 6
     109             : 
     110             :     26,   // 0, 7
     111             :     28,   // 1, 7
     112             :     38,   // 2, 7
     113             :     40,   // 3, 7
     114             :     50,   // 4, 7
     115             :     52,   // 5, 7
     116             :     62,   // 6, 7
     117             :     64};  // 7, 7
     118             : 
     119             : constexpr int delta_075_level_2_bc_0[32] = {
     120             :     -71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
     121             :     1,   2,   4,   6,   8,   12,  14,  16,  19,  22,  26,  31, 37, 46, 72};
     122             : constexpr int delta_075_level_2_bc_1[32] = {
     123             :     -71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
     124             :     1,   2,   4,   6,   8,   12,  14,  16,  19,  22,  26,  31, 37, 46, 72};
     125             : constexpr int delta_075_level_2_bc_2[64] = {
     126             :     -109, -82, -68, -59, -52, -46, -41, -37, -33, -30, -27, -25, -22,
     127             :     -20,  -18, -16, -15, -13, -11, -10, -9,  -8,  -7,  -6,  -5,  -4,
     128             :     -3,   -2,  -1,  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
     129             :     10,   11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  24,
     130             :     26,   28,  31,  35,  38,  42,  47,  52,  60,  69,  85,  118};
     131             : constexpr int delta_075_level_2_bc_3[128] = {
     132             :     -159, -134, -122, -113, -106, -100, -94, -88, -83, -79, -76, -72, -69,
     133             :     -66,  -63,  -61,  -58,  -56,  -54,  -52, -50, -48, -47, -45, -43, -42,
     134             :     -40,  -39,  -37,  -36,  -35,  -33,  -32, -31, -30, -29, -28, -27, -25,
     135             :     -24,  -23,  -22,  -21,  -20,  -19,  -18, -17, -16, -15, -14, -13, -12,
     136             :     -11,  -10,  -9,   -8,   -7,   -6,   -5,  -4,  -3,  -2,  -1,  0,   1,
     137             :     2,    3,    4,    5,    6,    7,    8,   9,   10,  11,  12,  13,  14,
     138             :     15,   16,   17,   18,   19,   20,   21,  22,  23,  24,  25,  26,  27,
     139             :     28,   29,   30,   31,   32,   33,   34,  35,  36,  37,  38,  39,  40,
     140             :     41,   42,   43,   45,   48,   52,   56,  60,  64,  68,  73,  79,  85,
     141             :     92,   100,  109,  118,  130,  144,  159, 177, 196, 217, 236};
     142             : static const int *const delta_075_level_2[4] = {
     143             :     delta_075_level_2_bc_0, delta_075_level_2_bc_1, delta_075_level_2_bc_2,
     144             :     delta_075_level_2_bc_3};
     145             : 
     146             : constexpr int delta_075_level_3_bc_1[4] = {-24, -6, 6, 24};
     147             : constexpr int delta_075_level_3_bc_2[16] = {-68, -37, -23, -15, -9, -6, -3, -1,
     148             :                                             1,   4,   7,   10,  16, 24, 37, 70};
     149             : constexpr int delta_075_level_3_bc_3[16] = {
     150             :     -117, -72, -50, -36, -25, -17, -10, -5, -1, 3, 7, 14, 25, 45, 82, 166};
     151             : static const int *const delta_075_level_3[4] = {nullptr, delta_075_level_3_bc_1,
     152             :                                                 delta_075_level_3_bc_2,
     153             :                                                 delta_075_level_3_bc_3};
     154             : 
     155             : constexpr int delta_075_level_4_bc_3[4] = {-47, -8, 4, 43};
     156             : static const int *const delta_075_level_4[4] = {nullptr, nullptr, nullptr,
     157             :                                                 delta_075_level_4_bc_3};
     158             : 
     159             : static const int *const *const delta_075_by_level_by_bc[4] = {
     160             :     nullptr, delta_075_level_2, delta_075_level_3, delta_075_level_4};
     161             : 
     162             : /************************************************************************/
     163             : /*                              get_bits()                              */
     164             : /************************************************************************/
     165             : 
     166           0 : static int get_bits(unsigned char *buffer, int first_bit, int num_bits)
     167             : 
     168             : {
     169           0 :     int total = 0;
     170             : 
     171           0 :     for (int i = first_bit; i < first_bit + num_bits; i++)
     172             :     {
     173           0 :         total *= 2;
     174           0 :         if (buffer[i >> 3] & (0x80 >> (i & 7)))
     175           0 :             total++;
     176             :     }
     177             : 
     178           0 :     return total;
     179             : }
     180             : 
     181             : /************************************************************************/
     182             : /*                             get_delta()                              */
     183             : /*                                                                      */
     184             : /*      Compute the delta value for a particular (i,j) location.        */
     185             : /************************************************************************/
     186           0 : static int get_delta(unsigned char *srcdata, int nInputBytes, int busy_code,
     187             :                      CPL_UNUSED int comrat, int block_offset,
     188             :                      CPL_UNUSED int block_size, int i, int j, int *pbError)
     189             : 
     190             : {
     191           0 :     CPLAssert(comrat == CR075);
     192           0 :     const int pixel_index = IND(i, j);
     193           0 :     const int level_index = level_index_table[pixel_index];
     194           0 :     const int *bits_per_level = bits_per_level_by_busycode_75[busy_code];
     195           0 :     const int delta_bits = bits_per_level[level_index];
     196           0 :     int delta_offset = 0;
     197             : 
     198           0 :     *pbError = FALSE;
     199             : 
     200           0 :     if (delta_bits == 0)
     201           0 :         return 0;
     202             : 
     203           0 :     if (level_index == 3)
     204           0 :         delta_offset = bits_per_level[0] + bits_per_level[1] * 3 +
     205           0 :                        bits_per_level[2] * 12 +
     206           0 :                        (pixel_index - 16) * bits_per_level[3];
     207           0 :     else if (level_index == 2)
     208           0 :         delta_offset = bits_per_level[0] + bits_per_level[1] * 3 +
     209           0 :                        (pixel_index - 4) * bits_per_level[2];
     210           0 :     else if (level_index == 1)
     211           0 :         delta_offset =
     212           0 :             bits_per_level[0] + (pixel_index - 1) * bits_per_level[1];
     213             : 
     214           0 :     if (nInputBytes * 8 < block_offset + delta_offset + delta_bits)
     215             :     {
     216           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Input buffer too small");
     217           0 :         *pbError = TRUE;
     218           0 :         return 0;
     219             :     }
     220             : 
     221             :     const int delta_raw =
     222           0 :         get_bits(srcdata, block_offset + delta_offset, delta_bits);
     223             : 
     224             :     /* Should not happen as delta_075_by_level_by_bc[level_index] == NULL if and
     225             :        only if level_index == 0, which means that pixel_index == 0, which means
     226             :        (i, j) = (0, 0). That cannot happen as we are never called with those
     227             :        values
     228             :     */
     229           0 :     CPLAssert(delta_075_by_level_by_bc[level_index] != nullptr);
     230           0 :     const int *lookup_table = delta_075_by_level_by_bc[level_index][busy_code];
     231             : 
     232           0 :     CPLAssert(lookup_table != nullptr);
     233           0 :     int delta = lookup_table[delta_raw];
     234             : 
     235           0 :     return delta;
     236             : }
     237             : 
     238             : /************************************************************************/
     239             : /*                            decode_block()                            */
     240             : /*                                                                      */
     241             : /*      Decode one 8x8 block.  The 9x9 L buffer is pre-loaded with      */
     242             : /*      the left and top values from previous blocks.                   */
     243             : /************************************************************************/
     244           0 : static int decode_block(unsigned char *srcdata, int nInputBytes, int busy_code,
     245             :                         int comrat, int block_offset, int block_size,
     246             :                         int left_side, int top_side, int L[9][9])
     247             : 
     248             : {
     249             :     int bError;
     250             : 
     251             :     // Level 2
     252           0 :     L[0][4] = (L[0][0] + L[0][8]) / 2 +
     253           0 :               get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     254             :                         block_size, 0, 4, &bError);
     255           0 :     if (bError)
     256           0 :         return FALSE;
     257           0 :     L[4][0] = (L[0][0] + L[8][0]) / 2 +
     258           0 :               get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     259             :                         block_size, 4, 0, &bError);
     260           0 :     if (bError)
     261           0 :         return FALSE;
     262           0 :     L[4][4] = (L[0][0] + L[8][0] + L[0][8] + L[8][8]) / 4 +
     263           0 :               get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     264             :                         block_size, 4, 4, &bError);
     265           0 :     if (bError)
     266           0 :         return FALSE;
     267             : 
     268           0 :     if (left_side)
     269           0 :         L[4][8] = L[4][0];
     270           0 :     if (top_side)
     271           0 :         L[8][4] = L[0][4];
     272             : 
     273             :     // Level 3
     274           0 :     for (int i = 0; i < 8; i += 4)
     275             :     {
     276           0 :         for (int j = 0; j < 8; j += 4)
     277             :         {
     278             :             // above
     279           0 :             L[i + 2][j] =
     280           0 :                 (L[i][j] + L[i + 4][j]) / 2 +
     281           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     282             :                           block_size, i + 2, j, &bError);
     283           0 :             if (bError)
     284           0 :                 return FALSE;
     285             :             // left
     286           0 :             L[i][j + 2] =
     287           0 :                 (L[i][j] + L[i][j + 4]) / 2 +
     288           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     289             :                           block_size, i, j + 2, &bError);
     290           0 :             if (bError)
     291           0 :                 return FALSE;
     292             :             // up-left
     293           0 :             L[i + 2][j + 2] =
     294           0 :                 (L[i][j] + L[i][j + 4] + L[i + 4][j] + L[i + 4][j + 4]) / 4 +
     295           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     296             :                           block_size, i + 2, j + 2, &bError);
     297           0 :             if (bError)
     298           0 :                 return FALSE;
     299             :         }
     300             :     }
     301             : 
     302           0 :     if (left_side)
     303             :     {
     304           0 :         L[2][8] = L[2][0];
     305           0 :         L[6][8] = L[6][0];
     306             :     }
     307           0 :     if (top_side)
     308             :     {
     309           0 :         L[8][2] = L[0][2];
     310           0 :         L[8][6] = L[0][6];
     311             :     }
     312             : 
     313             :     // Level 4
     314           0 :     for (int i = 0; i < 8; i += 2)
     315             :     {
     316           0 :         for (int j = 0; j < 8; j += 2)
     317             :         {
     318             :             // above
     319           0 :             L[i + 1][j] =
     320           0 :                 (L[i][j] + L[i + 2][j]) / 2 +
     321           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     322             :                           block_size, i + 1, j, &bError);
     323           0 :             if (bError)
     324           0 :                 return FALSE;
     325             :             // left
     326           0 :             L[i][j + 1] =
     327           0 :                 (L[i][j] + L[i][j + 2]) / 2 +
     328           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     329             :                           block_size, i, j + 1, &bError);
     330           0 :             if (bError)
     331           0 :                 return FALSE;
     332             :             // up-left
     333           0 :             L[i + 1][j + 1] =
     334           0 :                 (L[i][j] + L[i][j + 2] + L[i + 2][j] + L[i + 2][j + 2]) / 4 +
     335           0 :                 get_delta(srcdata, nInputBytes, busy_code, comrat, block_offset,
     336             :                           block_size, i + 1, j + 1, &bError);
     337           0 :             if (bError)
     338           0 :                 return FALSE;
     339             :         }
     340             :     }
     341             : 
     342           0 :     return TRUE;
     343             : }
     344             : 
     345             : /************************************************************************/
     346             : /*                       NITFUncompressARIDPCM()                        */
     347             : /************************************************************************/
     348             : 
     349           0 : int NITFUncompressARIDPCM(NITFImage *psImage, GByte *pabyInputData,
     350             :                           int nInputBytes, GByte *pabyOutputImage)
     351             : 
     352             : {
     353             :     /* -------------------------------------------------------------------- */
     354             :     /*      First, verify that we are a COMRAT 0.75 image, which is all     */
     355             :     /*      we currently support.                                           */
     356             :     /* -------------------------------------------------------------------- */
     357           0 :     if (!EQUAL(psImage->szCOMRAT, "0.75"))
     358             :     {
     359           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     360             :                  "COMRAT=%s ARIDPCM is not supported.\n"
     361             :                  "Currently only 0.75 is supported.",
     362           0 :                  psImage->szCOMRAT);
     363           0 :         return FALSE;
     364             :     }
     365             : 
     366             :     /* -------------------------------------------------------------------- */
     367             :     /*      Setup up the various info we need for each 8x8 neighbourhood    */
     368             :     /*      (which we call blocks in this context).                         */
     369             :     /* -------------------------------------------------------------------- */
     370           0 :     const int blocks_x = (psImage->nBlockWidth + 7) / 8;
     371           0 :     const int blocks_y = (psImage->nBlockHeight + 7) / 8;
     372           0 :     const int block_count = blocks_x * blocks_y;
     373           0 :     const int rowlen = blocks_x * 8;
     374             : 
     375           0 :     if (psImage->nBlockWidth > 1000 || /* to detect int overflow above */
     376           0 :         psImage->nBlockHeight > 1000 || block_count > 1000)
     377             :     {
     378           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too large to be decoded");
     379           0 :         return FALSE;
     380             :     }
     381             : 
     382             :     int block_offset[1000];
     383             :     int block_size[1000];
     384             :     int busy_code[1000];
     385           0 :     const int busy_code_table_size = blocks_x * blocks_y * 2;
     386             :     unsigned char L00[1000];
     387             : 
     388             :     /* to make clang static analyzer happy */
     389           0 :     block_offset[0] = 0;
     390           0 :     block_size[0] = 0;
     391           0 :     busy_code[0] = 0;
     392           0 :     L00[0] = 0;
     393           0 :     CPL_IGNORE_RET_VAL(busy_code[0]);
     394           0 :     CPL_IGNORE_RET_VAL(block_size[0]);
     395           0 :     CPL_IGNORE_RET_VAL(busy_code[0]);
     396           0 :     CPL_IGNORE_RET_VAL(L00[0]);
     397             : 
     398             :     /* -------------------------------------------------------------------- */
     399             :     /*      We allocate a working copy of the full image that may be a      */
     400             :     /*      bit larger than the output buffer if the width or height is     */
     401             :     /*      not divisible by 8.                                             */
     402             :     /* -------------------------------------------------------------------- */
     403             :     GByte *full_image = reinterpret_cast<GByte *>(
     404           0 :         CPLMalloc(static_cast<size_t>(blocks_x) * blocks_y * 8 * 8));
     405             : 
     406             :     /* -------------------------------------------------------------------- */
     407             :     /*      Scan through all the neighbourhoods determining the busyness    */
     408             :     /*      code, and the offset to each's data as well as the L00 value.   */
     409             :     /* -------------------------------------------------------------------- */
     410           0 :     int total = busy_code_table_size;
     411             : 
     412           0 :     for (int i = 0; i < blocks_x * blocks_y; i++)
     413             :     {
     414           0 :         if (nInputBytes * 8 < i * 2 + 2)
     415             :         {
     416           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Input buffer too small");
     417           0 :             CPLFree(full_image);
     418           0 :             return FALSE;
     419             :         }
     420           0 :         busy_code[i] = get_bits(pabyInputData, i * 2, 2);
     421             : 
     422           0 :         block_offset[i] = total;
     423           0 :         block_size[i] = neighbourhood_size_75[busy_code[i]];
     424             : 
     425           0 :         if (nInputBytes * 8 < block_offset[i] + 8)
     426             :         {
     427           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Input buffer too small");
     428           0 :             CPLFree(full_image);
     429           0 :             return FALSE;
     430             :         }
     431           0 :         L00[i] = static_cast<unsigned char>(
     432           0 :             get_bits(pabyInputData, block_offset[i], 8));
     433             : 
     434           0 :         total += block_size[i];
     435             :     }
     436             : 
     437             :     /* -------------------------------------------------------------------- */
     438             :     /*      Process all the blocks, forming into a final image.             */
     439             :     /* -------------------------------------------------------------------- */
     440           0 :     for (int iY = 0; iY < blocks_y; iY++)
     441             :     {
     442           0 :         for (int iX = 0; iX < blocks_x; iX++)
     443             :         {
     444           0 :             int iBlock = iX + iY * blocks_x;
     445             :             int L[9][9];
     446           0 :             unsigned char *full_tl = full_image + iX * 8 + iY * 8 * rowlen;
     447             : 
     448           0 :             L[0][0] = L00[iBlock];
     449           0 :             if (iX > 0)
     450             :             {
     451           0 :                 L[0][8] = full_tl[rowlen * 7 - 1];
     452           0 :                 L[2][8] = full_tl[rowlen * 5 - 1];
     453           0 :                 L[4][8] = full_tl[rowlen * 3 - 1];
     454           0 :                 L[6][8] = full_tl[rowlen * 1 - 1];
     455             :             }
     456             :             else
     457             :             {
     458           0 :                 L[0][8] = L[0][0];
     459           0 :                 L[2][8] = L[0][8];  // need to reconstruct the rest!
     460           0 :                 L[4][8] = L[0][8];
     461           0 :                 L[6][8] = L[0][8];
     462             :             }
     463             : 
     464           0 :             if (iY > 0)
     465             :             {
     466           0 :                 L[8][0] = full_tl[7 - rowlen];
     467           0 :                 L[8][2] = full_tl[5 - rowlen];
     468           0 :                 L[8][4] = full_tl[3 - rowlen];
     469           0 :                 L[8][6] = full_tl[1 - rowlen];
     470             :             }
     471             :             else
     472             :             {
     473           0 :                 L[8][0] = L[0][0];
     474           0 :                 L[8][2] = L[0][0];  // Need to reconstruct the rest!
     475           0 :                 L[8][4] = L[0][0];
     476           0 :                 L[8][5] = L[0][0];
     477             :             }
     478             : 
     479           0 :             if (iX == 0 || iY == 0)
     480           0 :                 L[8][8] = L[0][0];
     481             :             else
     482           0 :                 L[8][8] = full_tl[-1 - rowlen];
     483             : 
     484           0 :             if (!(decode_block(pabyInputData, nInputBytes, busy_code[iBlock],
     485             :                                CR075, block_offset[iBlock], block_size[iBlock],
     486             :                                iX == 0, iY == 0, L)))
     487             :             {
     488           0 :                 CPLFree(full_image);
     489           0 :                 return FALSE;
     490             :             }
     491             : 
     492             :             // Assign to output matrix.
     493           0 :             for (int i = 0; i < 8; i++)
     494             :             {
     495           0 :                 for (int j = 0; j < 8; j++)
     496             :                 {
     497             :                     const unsigned char value =
     498           0 :                         static_cast<unsigned char>(std::clamp(L[i][j], 0, 255));
     499           0 :                     full_tl[8 - j - 1 + (8 - i - 1) * rowlen] = value;
     500             :                 }
     501             :             }
     502             :         }
     503             :     }
     504             : 
     505             :     /* -------------------------------------------------------------------- */
     506             :     /*      Copy full image back into target buffer, and free.              */
     507             :     /* -------------------------------------------------------------------- */
     508           0 :     for (int iY = 0; iY < psImage->nBlockHeight; iY++)
     509             :     {
     510           0 :         memcpy(pabyOutputImage + iY * psImage->nBlockWidth,
     511           0 :                full_image + iY * rowlen, psImage->nBlockWidth);
     512             :     }
     513             : 
     514           0 :     CPLFree(full_image);
     515             : 
     516           0 :     return TRUE;
     517             : }

Generated by: LCOV version 1.14