LCOV - code coverage report
Current view: top level - frmts/mrf - QB3_band.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 51 84 60.7 %
Date: 2024-05-04 12:52:34 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          12 : CPLErr QB3_Band::Compress(buf_mgr &dst, buf_mgr &src)
      23             : {
      24          12 :     auto bands = static_cast<size_t>(img.pagesize.c);
      25          12 :     encsp pQB3 = nullptr;
      26             : #define CREATE_QB3(T)                                                          \
      27             :     qb3_create_encoder(img.pagesize.x, img.pagesize.y, bands, qb3_dtype::T)
      28             : 
      29          12 :     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           0 :         default:
      47           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      48             :                      "MRF:QB3 Data type not supported");
      49           0 :             return CE_Failure;
      50             :     }
      51             : #undef CREATE_QB3
      52             : 
      53          12 :     if (nullptr == pQB3)
      54             :     {
      55           0 :         CPLError(CE_Failure, CPLE_AssertionFailed,
      56             :                  "MRF:QB3 Cannot create encoder");
      57           0 :         return CE_Failure;
      58             :     }
      59             : 
      60          12 :     CPLErr status = CE_None;
      61             :     try
      62             :     {
      63          12 :         if (dst.size < qb3_max_encoded_size(pQB3))
      64             :         {
      65           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      66             :                      "MRF:QB3 encoded buffer size too small");
      67           0 :             throw CE_Failure;
      68             :         }
      69             : 
      70             :         // Use independent band compression when by default band 1 is core band
      71          13 :         if ((3 == bands || 4 == bands) &&
      72           1 :             EQUAL(poMRFDS->GetPhotometricInterpretation(), "MULTISPECTRAL"))
      73             :         {
      74           0 :             size_t corebands[] = {0, 1, 2, 3};  // Identity, no core bands
      75           0 :             qb3_set_encoder_coreband(pQB3, bands, corebands);
      76             :         }
      77             : 
      78             :         // Quality of 90 and above trigger the better encoding
      79          12 :         qb3_set_encoder_mode(pQB3, (img.quality > 90) ? QB3M_BEST : QB3M_BASE);
      80             : 
      81          12 :         dst.size = qb3_encode(pQB3, src.buffer, dst.buffer);
      82          12 :         if (0 == dst.size)
      83             :         {
      84           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      85             :                      "MRF:QB3 encoding failed");
      86           0 :             throw CE_Failure;
      87             :         }
      88             : 
      89             :         // Never happens if qb3_max_encoded doesn't lie
      90          12 :         if (dst.size > qb3_max_encoded_size(pQB3))
      91             :         {
      92           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
      93             :                      "MRF:QB3 encoded size exceeds limit, check QB3 library");
      94           0 :             throw CE_Failure;
      95             :         }
      96             :     }
      97           0 :     catch (CPLErr error)
      98             :     {
      99           0 :         status = error;
     100             :     }
     101          12 :     qb3_destroy_encoder(pQB3);
     102          12 :     return status;
     103             : }
     104             : 
     105           8 : CPLErr QB3_Band::Decompress(buf_mgr &dst, buf_mgr &src)
     106             : {
     107             :     size_t img_size[3];
     108           8 :     auto pdQB3 = qb3_read_start(src.buffer, src.size, img_size);
     109           8 :     if (nullptr == pdQB3)
     110             :     {
     111           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     112             :                  "MRF: QB3 can't create decoder, is it a valid QB3 stream?");
     113           0 :         return CE_Failure;
     114             :     }
     115             : 
     116           8 :     CPLErr status = CE_None;
     117             :     try
     118             :     {
     119           8 :         if (img_size[0] != static_cast<size_t>(img.pagesize.x) ||
     120           8 :             img_size[1] != static_cast<size_t>(img.pagesize.y) ||
     121           8 :             img_size[2] != static_cast<size_t>(img.pagesize.c))
     122             :         {
     123           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     124             :                      "MRF: QB Page has invalid size");
     125           0 :             throw CE_Failure;
     126             :         }
     127             : 
     128           8 :         if (!qb3_read_info(pdQB3))
     129             :         {
     130           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     131             :                      "MRF: QB3 metadata read failure");
     132           0 :             throw CE_Failure;
     133             :         }
     134             : 
     135           8 :         if (static_cast<size_t>(img.pageSizeBytes) != qb3_decoded_size(pdQB3))
     136             :         {
     137           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     138             :                      "MRF: QB3 incorrect decoded tile size");
     139           0 :             throw CE_Failure;
     140             :         }
     141             : 
     142           8 :         dst.size = qb3_read_data(pdQB3, dst.buffer);
     143           8 :         if (static_cast<size_t>(img.pageSizeBytes) != dst.size)
     144             :         {
     145           0 :             CPLError(CE_Failure, CPLE_AppDefined, "MRF: QB3 decoding error");
     146           0 :             throw CE_Failure;
     147             :         }
     148             :     }
     149           0 :     catch (CPLErr error)
     150             :     {
     151           0 :         status = error;
     152             :     }
     153           8 :     qb3_destroy_decoder(pdQB3);
     154           8 :     return status;
     155             : }
     156             : 
     157          42 : QB3_Band::QB3_Band(MRFDataset *pDS, const ILImage &image, int b, int level)
     158          42 :     : MRFRasterBand(pDS, image, b, level)
     159             : {
     160             :     static_assert(CPL_IS_LSB,
     161             :                   "QB3 is only implemented for little endian architectures");
     162          42 :     if (image.pageSizeBytes > INT_MAX / 4)
     163             :     {
     164           0 :         CPLError(CE_Failure, CPLE_AppDefined, "QB3 page too large");
     165           0 :         return;
     166             :     }
     167             : 
     168          42 :     if (0 != nBlockXSize % 4 || 0 != nBlockYSize % 4)
     169             :     {
     170           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     171             :                  "QB3 page size has to be a multiple of 4");
     172           0 :         return;
     173             :     }
     174             : 
     175          42 :     if (image.dt != GDT_Byte && image.dt != GDT_Int16 &&
     176           9 :         image.dt != GDT_UInt16 && image.dt != GDT_Int32 &&
     177           3 :         image.dt != GDT_UInt32)
     178             :     {
     179           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     180             :                  "Data type not supported by QB3 compression");
     181           0 :         return;
     182             :     }
     183             : 
     184             :     // Should use qb3_max_encoded_size();
     185             : 
     186             :     // Enlarge the page buffer, QB3 may expand data.
     187          42 :     pDS->SetPBufferSize(2 * image.pageSizeBytes);
     188             : }
     189             : 
     190             : NAMESPACE_MRF_END

Generated by: LCOV version 1.14