LCOV - code coverage report
Current view: top level - frmts/mrf - QB3_band.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 55 93 59.1 %
Date: 2024-11-25 23:50:41 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             : Copyright 2021 Esri
       3             : Licensed under the Apache License, Version 2.0 (the "License");
       4             : you may not use this file except in compliance with the License.
       5             : You may obtain a copy of the License at
       6             : http://www.apache.org/licenses/LICENSE-2.0
       7             : Unless required by applicable law or agreed to in writing, software
       8             : distributed under the License is distributed on an "AS IS" BASIS,
       9             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      10             : See the License for the specific language governing permissions and
      11             : limitations under the License.
      12             : 
      13             : QB3 band implementation
      14             : QB3 page compression and decompression functions
      15             : 
      16             : Authors:  Lucian Plesea
      17             : */
      18             : #include "marfa.h"
      19             : #include <QB3.h>
      20             : 
      21             : NAMESPACE_MRF_START
      22          13 : CPLErr QB3_Band::Compress(buf_mgr &dst, buf_mgr &src)
      23             : {
      24          13 :     auto bands = static_cast<size_t>(img.pagesize.c);
      25          13 :     encsp pQB3 = nullptr;
      26             : #define CREATE_QB3(T)                                                          \
      27             :     qb3_create_encoder(img.pagesize.x, img.pagesize.y, bands, qb3_dtype::T)
      28             : 
      29          13 :     switch (img.dt)
      30             :     {
      31           8 :         case (GDT_Byte):
      32           8 :             pQB3 = CREATE_QB3(QB3_U8);
      33           8 :             break;
      34           1 :         case (GDT_Int16):
      35           1 :             pQB3 = CREATE_QB3(QB3_I16);
      36           1 :             break;
      37           1 :         case (GDT_UInt16):
      38           1 :             pQB3 = CREATE_QB3(QB3_U16);
      39           1 :             break;
      40           1 :         case (GDT_Int32):
      41           1 :             pQB3 = CREATE_QB3(QB3_I32);
      42           1 :             break;
      43           1 :         case (GDT_UInt32):
      44           1 :             pQB3 = CREATE_QB3(QB3_U32);
      45           1 :             break;
      46           1 :         case (GDT_Int64):
      47           1 :             pQB3 = CREATE_QB3(QB3_I64);
      48           1 :             break;
      49           0 :         case (GDT_UInt64):
      50           0 :             pQB3 = CREATE_QB3(QB3_U64);
      51           0 :             break;
      52           0 :         default:
      53           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      54             :                      "MRF:QB3 Data type not supported");
      55           0 :             return CE_Failure;
      56             :     }
      57             : #undef CREATE_QB3
      58             : 
      59          13 :     if (nullptr == pQB3)
      60             :     {
      61           0 :         CPLError(CE_Failure, CPLE_AssertionFailed,
      62             :                  "MRF:QB3 Cannot create encoder");
      63           0 :         return CE_Failure;
      64             :     }
      65             : 
      66          13 :     CPLErr status = CE_None;
      67             :     try
      68             :     {
      69          13 :         if (dst.size < qb3_max_encoded_size(pQB3))
      70             :         {
      71           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      72             :                      "MRF:QB3 encoded buffer size too small");
      73           0 :             throw CE_Failure;
      74             :         }
      75             : 
      76             :         // Use independent band compression when by default band 1 is core band
      77          14 :         if ((3 == bands || 4 == bands) &&
      78           1 :             EQUAL(poMRFDS->GetPhotometricInterpretation(), "MULTISPECTRAL"))
      79             :         {
      80           0 :             size_t corebands[] = {0, 1, 2, 3};  // Identity, no core bands
      81           0 :             qb3_set_encoder_coreband(pQB3, bands, corebands);
      82             :         }
      83             : 
      84             :         // Quality of 90 and above trigger the better encoding
      85          13 :         qb3_set_encoder_mode(pQB3, (img.quality > 90) ? QB3M_BEST : QB3M_BASE);
      86             : 
      87             : #if defined(QB3_HAS_FTL)
      88             :         // Quality below 5 triggers the faster encoding, when available
      89          13 :         if (img.quality < 5)
      90           0 :             qb3_set_encoder_mode(pQB3, QB3M_FTL);
      91             : #endif
      92             : 
      93          13 :         dst.size = qb3_encode(pQB3, src.buffer, dst.buffer);
      94          13 :         if (0 == dst.size)
      95             :         {
      96           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      97             :                      "MRF:QB3 encoding failed");
      98           0 :             throw CE_Failure;
      99             :         }
     100             : 
     101             :         // Never happens if qb3_max_encoded doesn't lie
     102          13 :         if (dst.size > qb3_max_encoded_size(pQB3))
     103             :         {
     104           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
     105             :                      "MRF:QB3 encoded size exceeds limit, check QB3 library");
     106           0 :             throw CE_Failure;
     107             :         }
     108             :     }
     109           0 :     catch (CPLErr error)
     110             :     {
     111           0 :         status = error;
     112             :     }
     113          13 :     qb3_destroy_encoder(pQB3);
     114          13 :     return status;
     115             : }
     116             : 
     117           9 : CPLErr QB3_Band::Decompress(buf_mgr &dst, buf_mgr &src)
     118             : {
     119             :     size_t img_size[3];
     120           9 :     auto pdQB3 = qb3_read_start(src.buffer, src.size, img_size);
     121           9 :     if (nullptr == pdQB3)
     122             :     {
     123           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     124             :                  "MRF: QB3 can't create decoder, is it a valid QB3 stream?");
     125           0 :         return CE_Failure;
     126             :     }
     127             : 
     128           9 :     CPLErr status = CE_None;
     129             :     try
     130             :     {
     131           9 :         if (img_size[0] != static_cast<size_t>(img.pagesize.x) ||
     132           9 :             img_size[1] != static_cast<size_t>(img.pagesize.y) ||
     133           9 :             img_size[2] != static_cast<size_t>(img.pagesize.c))
     134             :         {
     135           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     136             :                      "MRF: QB Page has invalid size");
     137           0 :             throw CE_Failure;
     138             :         }
     139             : 
     140           9 :         if (!qb3_read_info(pdQB3))
     141             :         {
     142           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     143             :                      "MRF: QB3 metadata read failure");
     144           0 :             throw CE_Failure;
     145             :         }
     146             : 
     147           9 :         if (static_cast<size_t>(img.pageSizeBytes) != qb3_decoded_size(pdQB3))
     148             :         {
     149           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     150             :                      "MRF: QB3 incorrect decoded tile size");
     151           0 :             throw CE_Failure;
     152             :         }
     153             : 
     154           9 :         dst.size = qb3_read_data(pdQB3, dst.buffer);
     155           9 :         if (static_cast<size_t>(img.pageSizeBytes) != dst.size)
     156             :         {
     157           0 :             CPLError(CE_Failure, CPLE_AppDefined, "MRF: QB3 decoding error");
     158           0 :             throw CE_Failure;
     159             :         }
     160             :     }
     161           0 :     catch (CPLErr error)
     162             :     {
     163           0 :         status = error;
     164             :     }
     165           9 :     qb3_destroy_decoder(pdQB3);
     166           9 :     return status;
     167             : }
     168             : 
     169          44 : QB3_Band::QB3_Band(MRFDataset *pDS, const ILImage &image, int b, int level)
     170          44 :     : MRFRasterBand(pDS, image, b, level)
     171             : {
     172             :     static_assert(CPL_IS_LSB,
     173             :                   "QB3 is only implemented for little endian architectures");
     174          44 :     if (image.pageSizeBytes > INT_MAX / 4)
     175             :     {
     176           0 :         CPLError(CE_Failure, CPLE_AppDefined, "QB3 page too large");
     177           0 :         return;
     178             :     }
     179             : 
     180          44 :     if (0 != nBlockXSize % 4 || 0 != nBlockYSize % 4)
     181             :     {
     182           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     183             :                  "QB3 page size has to be a multiple of 4");
     184           0 :         return;
     185             :     }
     186             : 
     187          44 :     if (image.dt != GDT_Byte && image.dt != GDT_Int16 &&
     188          11 :         image.dt != GDT_UInt16 && image.dt != GDT_Int32 &&
     189           5 :         image.dt != GDT_UInt32 && image.dt != GDT_Int64 &&
     190           0 :         image.dt != GDT_UInt64)
     191             :     {
     192           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     193             :                  "Data type not supported by QB3 compression");
     194           0 :         return;
     195             :     }
     196             : 
     197             :     // Should use qb3_max_encoded_size();
     198             : 
     199             :     // Enlarge the page buffer, QB3 may expand data.
     200          44 :     pDS->SetPBufferSize(2 * image.pageSizeBytes);
     201             : }
     202             : 
     203             : NAMESPACE_MRF_END

Generated by: LCOV version 1.14