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

Generated by: LCOV version 1.14