LCOV - code coverage report
Current view: top level - frmts/mrf - mrf_util.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 180 213 84.5 %
Date: 2024-05-04 12:52:34 Functions: 22 25 88.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2002-2012, California Institute of Technology.
       3             :  * All rights reserved.  Based on Government Sponsored Research under contracts
       4             :  * NAS7-1407 and/or NAS7-03001.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are met:
       8             :  *   1. Redistributions of source code must retain the above copyright notice,
       9             :  * this list of conditions and the following disclaimer.
      10             :  *   2. Redistributions in binary form must reproduce the above copyright
      11             :  * notice, this list of conditions and the following disclaimer in the
      12             :  * documentation and/or other materials provided with the distribution.
      13             :  *   3. Neither the name of the California Institute of Technology (Caltech),
      14             :  * its operating division the Jet Propulsion Laboratory (JPL), the National
      15             :  * Aeronautics and Space Administration (NASA), nor the names of its
      16             :  * contributors may be used to endorse or promote products derived from this
      17             :  * software without specific prior written permission.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      20             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE
      23             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      24             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      25             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      27             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      28             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      29             :  * POSSIBILITY OF SUCH DAMAGE.
      30             :  *
      31             :  * Copyright 2014-2021 Esri
      32             :  *
      33             :  * Licensed under the Apache License, Version 2.0 (the "License");
      34             :  * you may not use this file except in compliance with the License.
      35             :  * You may obtain a copy of the License at
      36             :  *
      37             :  * http://www.apache.org/licenses/LICENSE-2.0
      38             :  *
      39             :  * Unless required by applicable law or agreed to in writing, software
      40             :  * distributed under the License is distributed on an "AS IS" BASIS,
      41             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      42             :  * See the License for the specific language governing permissions and
      43             :  * limitations under the License.
      44             :  *
      45             :  *  Functions used by the driver, should have prototypes in the header file
      46             :  *
      47             :  *  Author: Lucian Plesea
      48             :  */
      49             : 
      50             : #include "marfa.h"
      51             : #include <zlib.h>
      52             : #include <algorithm>
      53             : #include <limits>
      54             : #include "mrfdrivercore.h"
      55             : 
      56             : // LERC and QB3 only work on little endian machines
      57             : #if defined(WORDS_BIGENDIAN)
      58             : #undef LERC
      59             : #undef QB3_SUPPORT
      60             : #endif
      61             : 
      62             : CPL_C_START
      63             : void GDALRegister_mrf(void);
      64             : CPL_C_END
      65             : 
      66             : NAMESPACE_MRF_START
      67             : 
      68             : // These have to be positionally in sync with the enums in marfa.h
      69             : static const char *const ILC_N[] = {
      70             : #ifdef HAVE_PNG
      71             :     "PNG",    "PPNG",
      72             : #endif
      73             : #ifdef HAVE_JPEG
      74             :     "JPEG",
      75             : #endif
      76             : #if defined(HAVE_PNG) && defined(HAVE_JPEG)
      77             :     "JPNG",
      78             : #endif
      79             :     "NONE",   "DEFLATE", "TIF",
      80             : #if defined(LERC)
      81             :     "LERC",
      82             : #endif
      83             : #if defined(ZSTD_SUPPORT)
      84             :     "ZSTD",
      85             : #endif
      86             : #if defined(QB3_SUPPORT)
      87             :     "QB3",
      88             : #endif
      89             :     "Unknown"};
      90             : 
      91             : static const char *const ILC_E[] = {
      92             : #ifdef HAVE_PNG
      93             :     ".ppg", ".ppg",
      94             : #endif
      95             : #ifdef HAVE_JPEG
      96             :     ".pjg",
      97             : #endif
      98             : #if defined(HAVE_PNG) && defined(HAVE_JPEG)
      99             :     ".pjp",
     100             : #endif
     101             :     ".til", ".pzp", ".ptf",
     102             : #if defined(LERC)
     103             :     ".lrc",
     104             : #endif
     105             : #if defined(ZSTD_SUPPORT)
     106             :     ".pzs",
     107             : #endif
     108             : #if defined(QB3_SUPPORT)
     109             :     ".pq3",
     110             : #endif
     111             :     ""};
     112             : 
     113             : static const char *const ILO_N[] = {"PIXEL", "BAND", "LINE", "Unknown"};
     114             : 
     115             : char const *const *ILComp_Name = ILC_N;
     116             : char const *const *ILComp_Ext = ILC_E;
     117             : char const *const *ILOrder_Name = ILO_N;
     118             : 
     119             : /**
     120             :  *  Get the string for a compression type
     121             :  */
     122         539 : const char *CompName(ILCompression comp)
     123             : {
     124         539 :     if (comp >= IL_ERR_COMP)
     125           0 :         return ILComp_Name[IL_ERR_COMP];
     126         539 :     return ILComp_Name[comp];
     127             : }
     128             : 
     129             : /**
     130             :  *  Get the string for an order type
     131             :  */
     132         351 : const char *OrderName(ILOrder val)
     133             : {
     134         351 :     if (val >= IL_ERR_ORD)
     135           0 :         return ILOrder_Name[IL_ERR_ORD];
     136         351 :     return ILOrder_Name[val];
     137             : }
     138             : 
     139         441 : ILCompression CompToken(const char *opt, ILCompression def)
     140             : {
     141             :     int i;
     142         441 :     if (nullptr == opt)
     143           0 :         return def;
     144        2282 :     for (i = 0; ILCompression(i) < IL_ERR_COMP; i++)
     145        2282 :         if (EQUAL(opt, ILComp_Name[i]))
     146         441 :             break;
     147         441 :     if (IL_ERR_COMP == ILCompression(i))
     148           0 :         return def;
     149         441 :     return ILCompression(i);
     150             : }
     151             : 
     152             : /**
     153             :  *  Find a compression token
     154             :  */
     155         474 : ILOrder OrderToken(const char *opt, ILOrder def)
     156             : {
     157             :     int i;
     158         474 :     if (nullptr == opt)
     159           0 :         return def;
     160         582 :     for (i = 0; ILOrder(i) < IL_ERR_ORD; i++)
     161         582 :         if (EQUAL(opt, ILOrder_Name[i]))
     162         474 :             break;
     163         474 :     if (IL_ERR_ORD == ILOrder(i))
     164           0 :         return def;
     165         474 :     return ILOrder(i);
     166             : }
     167             : 
     168             : //
     169             : //  Inserters for ILSize and ILIdx types
     170             : //
     171           0 : std::ostream &operator<<(std::ostream &out, const ILSize &sz)
     172             : {
     173           0 :     out << "X=" << sz.x << ",Y=" << sz.y << ",Z=" << sz.z << ",C=" << sz.c
     174           0 :         << ",L=" << sz.l;
     175           0 :     return out;
     176             : }
     177             : 
     178           0 : std::ostream &operator<<(std::ostream &out, const ILIdx &t)
     179             : {
     180           0 :     out << "offset=" << t.offset << ",size=" << t.size;
     181           0 :     return out;
     182             : }
     183             : 
     184             : // Define PPMW to enable this handy debug function
     185             : #ifdef PPMW
     186             : void ppmWrite(const char *fname, const char *data, const ILSize &sz)
     187             : {
     188             :     FILE *fp = fopen(fname, "wb");
     189             :     switch (sz.c)
     190             :     {
     191             :         case 4:  // Strip the alpha
     192             :             fprintf(fp, "P6 %d %d 255\n", sz.x, sz.y);
     193             :             {
     194             :                 char *d = (char *)data;
     195             :                 for (int i = sz.x * sz.y; i; i--)
     196             :                 {
     197             :                     fwrite(d, 3, 1, fp);
     198             :                     d += 4;
     199             :                 }
     200             :             }
     201             :             break;
     202             :         case 3:
     203             :             fprintf(fp, "P6 %d %d 255\n", sz.x, sz.y);
     204             :             fwrite(data, sz.x * sz.y, 3, fp);
     205             :             break;
     206             :         case 1:
     207             :             fprintf(fp, "P5 %d %d 255\n", sz.x, sz.y);
     208             :             fwrite(data, sz.x, sz.y, fp);
     209             :             break;
     210             :         default:
     211             :             fprintf(stderr, "Can't write ppm file with %d bands\n", /*ok*/
     212             :                     sz.c);
     213             :     }
     214             :     fclose(fp);
     215             :     return;
     216             : }
     217             : #endif
     218             : 
     219             : // Returns the size of the index for image and overlays
     220             : // If scale is zero, only base image
     221         297 : GIntBig IdxSize(const ILImage &full, const int scale)
     222             : {
     223         594 :     ILImage img = full;
     224         297 :     img.pagecount = pcount(img.size, img.pagesize);
     225         297 :     GIntBig sz = img.pagecount.l;
     226         336 :     while (scale != 0 && 1 != img.pagecount.x * img.pagecount.y)
     227             :     {
     228          39 :         img.size.x = pcount(img.size.x, scale);
     229          39 :         img.size.y = pcount(img.size.y, scale);
     230          39 :         img.pagecount = pcount(img.size, img.pagesize);
     231          39 :         sz += img.pagecount.l;
     232             :     }
     233             : 
     234         297 :     if (sz >
     235         297 :         std::numeric_limits<GIntBig>::max() / static_cast<int>(sizeof(ILIdx)))
     236             :     {
     237           0 :         CPLError(CE_Failure, CPLE_AppDefined, "IdxSize: integer overflow");
     238           0 :         return 0;
     239             :     }
     240         297 :     return sz * sizeof(ILIdx);
     241             : }
     242             : 
     243         838 : ILImage::ILImage()
     244             :     : dataoffset(0), idxoffset(0), quality(85), pageSizeBytes(0),
     245             :       size(ILSize(1, 1, 1, 1, 0)), pagesize(ILSize(384, 384, 1, 1, 0)),
     246         838 :       pagecount(pcount(size, pagesize)),
     247             : #ifdef HAVE_PNG
     248             :       comp(IL_PNG),
     249             : #else
     250             :       comp(IL_NONE),
     251             : #endif
     252             :       order(IL_Interleaved), nbo(false), hasNoData(FALSE), NoDataValue(0.0),
     253        1676 :       dt(GDT_Unknown), ci(GCI_Undefined)
     254             : {
     255         838 : }
     256             : 
     257             : /**
     258             :  *\brief Get a file name by replacing the extension.
     259             :  * pass the data file name and the default extension starting with .
     260             :  * If name length is not sufficient, it returns the extension
     261             :  * If the input name is curl with parameters, the base file extension gets
     262             :  *changed and parameters are preserved.
     263             :  */
     264             : 
     265        1644 : CPLString getFname(const CPLString &in, const char *ext)
     266             : {
     267        1644 :     if (strlen(in) < strlen(ext))
     268           0 :         return CPLString(ext);
     269             : 
     270        3288 :     CPLString ret(in);
     271             :     // Is it a web file with parameters?
     272        1644 :     size_t extlen = strlen(ext);
     273        1644 :     size_t qmark = ret.find_first_of('?');
     274        1644 :     if (!(qmark != std::string::npos && 0 == in.find("/vsicurl/http") &&
     275             :           qmark >= extlen))
     276        1644 :         qmark = ret.size();
     277        1644 :     return ret.replace(qmark - extlen, extlen, ext);
     278             : }
     279             : 
     280             : /**
     281             :  *\brief Get a file name, either from the configuration or from the default file
     282             :  *name If the token is not defined by CPLGetXMLValue, if the extension of the in
     283             :  *name is .xml, it returns the token with the extension changed to defext.
     284             :  * Otherwise it returns the token itself
     285             :  * It is pretty hard to separate local vs remote due to the gdal file name
     286             :  *ornaments Absolute file names start with: ?:/ or /
     287             :  *
     288             :  */
     289             : 
     290         700 : CPLString getFname(CPLXMLNode *node, const char *token, const CPLString &in,
     291             :                    const char *def)
     292             : {
     293        1400 :     CPLString fn = CPLGetXMLValue(node, token, "");
     294         700 :     if (fn.empty())  // Not provided
     295         688 :         return getFname(in, def);
     296          12 :     size_t slashPos = fn.find_first_of("\\/");
     297             : 
     298             :     // Does it look like an absolute path or we won't find the basename of 'in'
     299          12 :     if (slashPos == 0                       // Starts with slash
     300           6 :         || (slashPos == 2 && fn[1] == ':')  // Starts with disk letter column
     301             :         // Does not start with dots then slash
     302           6 :         || (slashPos != fn.npos && slashPos != fn.find_first_not_of('.')) ||
     303           6 :         EQUALN(in, "<MRF_META>", 10)  // XML string input
     304          18 :         || in.find_first_of("\\/") ==
     305             :                in.npos)  // We can't get a basename from 'in'
     306           6 :         return fn;
     307             : 
     308             :     // Relative path, prepend the path from the in file name
     309          12 :     return in.substr(0, in.find_last_of("\\/") + 1) + fn;
     310             : }
     311             : 
     312             : /**
     313             :  *\brief Extracts a numerical value from a XML node
     314             :  * It works like CPLGetXMLValue except for the default value being
     315             :  * a number instead of a string
     316             :  */
     317             : 
     318        4463 : double getXMLNum(CPLXMLNode *node, const char *pszPath, double def)
     319             : {
     320        4463 :     const char *textval = CPLGetXMLValue(node, pszPath, nullptr);
     321        4463 :     if (textval)
     322        2900 :         return atof(textval);
     323        1563 :     return def;
     324             : }
     325             : 
     326             : //
     327             : // Calculate offset of index, pos is in pages
     328             : //
     329             : 
     330        8971 : GIntBig IdxOffset(const ILSize &pos, const ILImage &img)
     331             : {
     332        8971 :     return img.idxoffset +
     333        8971 :            sizeof(ILIdx) *
     334        8971 :                (pos.c +
     335        8971 :                 img.pagecount.c *
     336        8971 :                     (pos.x + img.pagecount.x *
     337        8971 :                                  (pos.y + img.pagecount.y *
     338        8971 :                                               static_cast<GIntBig>(pos.z))));
     339             : }
     340             : 
     341             : // Is compression type endianness dependent?
     342        7957 : bool is_Endianness_Dependent(GDALDataType dt, ILCompression comp)
     343             : {
     344             :     // Add here all endianness dependent compressions
     345        7957 :     if (IL_ZLIB == comp || IL_NONE == comp)
     346         654 :         if (GDALGetDataTypeSize(dt) > 8)
     347         444 :             return true;
     348        7513 :     return false;
     349             : }
     350             : 
     351         530 : MRFRasterBand *newMRFRasterBand(MRFDataset *pDS, const ILImage &image, int b,
     352             :                                 int level)
     353             : {
     354         530 :     MRFRasterBand *bnd = nullptr;
     355         530 :     CPLErrorReset();
     356         530 :     switch (pDS->current.comp)
     357             :     {
     358             : #ifdef HAVE_PNG
     359         155 :         case IL_PPNG:  // Uses the PNG code, just has a palette in each PNG
     360             :         case IL_PNG:
     361         155 :             bnd = new PNG_Band(pDS, image, b, level);
     362         155 :             break;
     363             : #endif
     364             : #ifdef HAVE_JPEG
     365          49 :         case IL_JPEG:
     366          49 :             bnd = new JPEG_Band(pDS, image, b, level);
     367          49 :             break;
     368             : #endif
     369             : #if defined(HAVE_PNG) && defined(HAVE_JPEG)
     370           0 :         case IL_JPNG:
     371           0 :             bnd = new JPNG_Band(pDS, image, b, level);
     372           0 :             break;
     373             : #endif
     374         137 :         case IL_NONE:
     375         137 :             bnd = new Raw_Band(pDS, image, b, level);
     376         137 :             break;
     377             : #if defined(LERC)
     378          75 :         case IL_LERC:
     379          75 :             bnd = new LERC_Band(pDS, image, b, level);
     380          75 :             break;
     381             : #endif
     382             : #if defined(QB3_SUPPORT)
     383          42 :         case IL_QB3:
     384          42 :             bnd = new QB3_Band(pDS, image, b, level);
     385          42 :             break;
     386             : #endif
     387             :         // ZLIB is just raw + deflate
     388          21 :         case IL_ZLIB:
     389          21 :             bnd = new Raw_Band(pDS, image, b, level);
     390          21 :             bnd->SetDeflate(1);
     391          21 :             break;
     392             :             // Same for ZSTD
     393             : #if defined(ZSTD_SUPPORT)
     394          39 :         case IL_ZSTD:
     395          39 :             bnd = new Raw_Band(pDS, image, b, level);
     396          39 :             bnd->SetZstd(1);
     397          39 :             break;
     398             : #endif
     399          12 :         case IL_TIF:
     400          12 :             if (image.pageSizeBytes > INT_MAX - 1024)
     401           0 :                 return nullptr;
     402          12 :             bnd = new TIF_Band(pDS, image, b, level);
     403          12 :             break;
     404           0 :         default:
     405           0 :             CPLError(CE_Failure, CPLE_AssertionFailed,
     406             :                      "Unsupported MRF compression");
     407           0 :             return nullptr;
     408             :     }
     409             : 
     410             :     // If something was flagged during band creation
     411         530 :     if (CPLGetLastErrorNo() != CE_None)
     412             :     {
     413          53 :         delete bnd;
     414          53 :         return nullptr;
     415             :     }
     416             : 
     417             :     // Copy the RW mode from the dataset
     418         477 :     bnd->SetAccess(pDS->eAccess);
     419         477 :     return bnd;
     420             : }
     421             : 
     422             : /**
     423             :  *\brief log in a given base
     424             :  */
     425          66 : double logbase(double val, double base)
     426             : {
     427          66 :     return log(val) / log(base);
     428             : }
     429             : 
     430             : /**
     431             :  *\brief Is logbase(val, base) an integer?
     432             :  *
     433             :  */
     434          33 : int IsPower(double value, double base)
     435             : {
     436          33 :     double v = logbase(value, base);
     437          33 :     return CPLIsEqual(v, int(v + 0.5));
     438             : }
     439             : 
     440             : /************************************************************************/
     441             : /*                           SearchXMLSiblings()                        */
     442             : /************************************************************************/
     443             : 
     444             : /**
     445             :  *\brief Search for a sibling of the root node with a given name.
     446             :  *
     447             :  * Searches only the next siblings of the node passed in for the named element
     448             :  *or attribute. If the first character of the pszElement is '=', the search
     449             :  *includes the psRoot node
     450             :  *
     451             :  * @param psRoot the root node to search.  This should be a node of type
     452             :  * CXT_Element.  NULL is safe.
     453             :  *
     454             :  * @param pszElement the name of the element or attribute to search for.
     455             :  *
     456             :  * @return The first matching node or NULL on failure.
     457             :  */
     458             : 
     459         256 : CPLXMLNode *SearchXMLSiblings(CPLXMLNode *psRoot, const char *pszElement)
     460             : {
     461         256 :     if (psRoot == nullptr || pszElement == nullptr)
     462           0 :         return nullptr;
     463             : 
     464             :     // If the strings starts with '=', skip it and test the root
     465             :     // If not, start testing with the next sibling
     466         256 :     if (pszElement[0] == '=')
     467           0 :         pszElement++;
     468             :     else
     469         256 :         psRoot = psRoot->psNext;
     470             : 
     471         256 :     for (; psRoot != nullptr; psRoot = psRoot->psNext)
     472         255 :         if ((psRoot->eType == CXT_Element || psRoot->eType == CXT_Attribute) &&
     473         255 :             EQUAL(pszElement, psRoot->pszValue))
     474         255 :             return psRoot;
     475           1 :     return nullptr;
     476             : }
     477             : 
     478             : //
     479             : // Print a double so it can be read with strod while preserving precision
     480             : // Unfortunately this is not quite possible or portable enough at this time
     481             : //
     482        3412 : CPLString PrintDouble(double d, const char *frmt)
     483             : {
     484        6824 :     CPLString res;
     485        3412 :     res.FormatC(d, nullptr);
     486        3412 :     if (CPLStrtod(res.c_str(), nullptr) == d)
     487        3394 :         return res;
     488             : 
     489             :     //  This would be the right code with a C99 compiler that supports %a
     490             :     //  readback in strod()
     491             :     //    return CPLString().Printf("%a",d);
     492             : 
     493          36 :     return CPLString().FormatC(d, frmt);
     494             : }
     495             : 
     496        3260 : void XMLSetAttributeVal(CPLXMLNode *parent, const char *pszName,
     497             :                         const char *pszVal)
     498             : {
     499        3260 :     CPLCreateXMLNode(parent, CXT_Attribute, pszName);
     500        3260 :     CPLSetXMLValue(parent, pszName, pszVal);
     501        3260 : }
     502             : 
     503        3256 : void XMLSetAttributeVal(CPLXMLNode *parent, const char *pszName,
     504             :                         const double val, const char *frmt)
     505             : {
     506        3256 :     XMLSetAttributeVal(parent, pszName, PrintDouble(val, frmt));
     507        3256 : }
     508             : 
     509         656 : CPLXMLNode *XMLSetAttributeVal(CPLXMLNode *parent, const char *pszName,
     510             :                                const ILSize &sz, const char *frmt)
     511             : {
     512         656 :     CPLXMLNode *node = CPLCreateXMLNode(parent, CXT_Element, pszName);
     513         656 :     XMLSetAttributeVal(node, "x", sz.x, frmt);
     514         656 :     XMLSetAttributeVal(node, "y", sz.y, frmt);
     515         656 :     if (sz.z != 1)
     516           0 :         XMLSetAttributeVal(node, "z", sz.z, frmt);
     517         656 :     XMLSetAttributeVal(node, "c", sz.c, frmt);
     518         656 :     return node;
     519             : }
     520             : 
     521             : //
     522             : // Prints a vector of doubles into a string and sets that string as the value of
     523             : // an XML attribute If all values are the same, it only prints one
     524             : //
     525         117 : void XMLSetAttributeVal(CPLXMLNode *parent, const char *pszName,
     526             :                         std::vector<double> const &values)
     527             : {
     528         117 :     if (values.empty())
     529          55 :         return;
     530             : 
     531         124 :     CPLString value;
     532          62 :     double val = values[0];
     533          62 :     int single_val = true;
     534         124 :     for (int i = 0; i < int(values.size()); i++)
     535             :     {
     536          62 :         if (val != values[i])
     537           0 :             single_val = false;
     538          62 :         value.append(PrintDouble(values[i]) + " ");
     539             :     }
     540          62 :     value.resize(value.size() - 1);  // Cut the last space
     541          62 :     if (single_val)
     542          62 :         value = PrintDouble(values[0]);
     543          62 :     CPLCreateXMLNode(parent, CXT_Attribute, pszName);
     544          62 :     CPLSetXMLValue(parent, pszName, value);
     545             : }
     546             : 
     547             : /**
     548             :  *\brief Verify or make a file that big
     549             :  *
     550             :  * @return true if size is OK or if extend succeeded
     551             :  */
     552             : 
     553         182 : int CheckFileSize(const char *fname, GIntBig sz, GDALAccess eAccess)
     554             : {
     555             : 
     556             :     VSIStatBufL statb;
     557         182 :     if (VSIStatL(fname, &statb))
     558           0 :         return false;
     559         182 :     if (statb.st_size >= sz)
     560          81 :         return true;
     561             : 
     562             :     // Don't change anything unless updating
     563         101 :     if (eAccess != GA_Update)
     564           0 :         return false;
     565             : 
     566             :     // There is no ftruncate in VSI, only truncate()
     567         101 :     VSILFILE *ifp = VSIFOpenL(fname, "r+b");
     568         101 :     if (ifp == nullptr)
     569           0 :         return false;
     570             : 
     571         101 :     int ret = VSIFTruncateL(ifp, sz);
     572         101 :     VSIFCloseL(ifp);
     573         101 :     return !ret;
     574             : }
     575             : 
     576             : NAMESPACE_MRF_END
     577             : 
     578             : /************************************************************************/
     579             : /*                          GDALRegister_mrf()                          */
     580             : /************************************************************************/
     581             : 
     582             : USING_NAMESPACE_MRF
     583             : 
     584        1520 : void GDALRegister_mrf()
     585             : {
     586        1520 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     587         301 :         return;
     588             : 
     589        1219 :     GDALDriver *driver = new GDALDriver();
     590        1219 :     MRFDriverSetCommonMetadata(driver);
     591             : 
     592        1219 :     driver->SetMetadataItem(
     593             :         GDAL_DMD_CREATIONOPTIONLIST,
     594             :         "<CreationOptionList>"
     595             :         "   <Option name='COMPRESS' type='string-select' "
     596             : #ifdef HAVE_PNG
     597             :         "default='PNG' description='PPNG = Palette PNG; DEFLATE = zlib '>"
     598             : #else
     599             :         "default='NONE' description='DEFLATE = zlib '>"
     600             : #endif
     601             : #ifdef HAVE_JPEG
     602             :         "       <Value>JPEG</Value>"
     603             : #endif
     604             : #ifdef HAVE_PNG
     605             :         "       <Value>PNG</Value>"
     606             :         "       <Value>PPNG</Value>"
     607             : #endif
     608             : #if defined(HAVE_JPEG) && defined(HAVE_PNG)
     609             :         "       <Value>JPNG</Value>"
     610             : #endif
     611             :         "       <Value>TIF</Value>"
     612             :         "       <Value>DEFLATE</Value>"
     613             :         "       <Value>NONE</Value>"
     614             : #if defined(LERC)
     615             :         "       <Value>LERC</Value>"
     616             : #endif
     617             : #if defined(ZSTD_SUPPORT)
     618             :         "       <Value>ZSTD</Value>"
     619             : #endif
     620             : #if defined(QB3_SUPPORT)
     621             :         "       <Value>QB3</Value>"
     622             : #endif
     623             :         "   </Option>"
     624             :         "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
     625             :         "       <Value>PIXEL</Value>"
     626             :         "       <Value>BAND</Value>"
     627             :         "   </Option>\n"
     628             :         "   <Option name='ZSIZE' type='int' description='Third dimension size' "
     629             :         "default='1'/>"
     630             :         "   <Option name='QUALITY' type='int' description='Compression "
     631             :         "dependent control value, for JPEG best=99, bad=0, default=85'/>\n"
     632             :         "   <Option name='BLOCKSIZE' type='int' description='Block size, both "
     633             :         "x and y, default 512'/>\n"
     634             :         "   <Option name='BLOCKXSIZE' type='int' description='Block x size, "
     635             :         "default=512'/>\n"
     636             :         "   <Option name='BLOCKYSIZE' type='int' description='Block y size, "
     637             :         "default=512'/>\n"
     638             :         "   <Option name='NETBYTEORDER' type='boolean' "
     639             :         "description='Force endian for certain compress options, default is "
     640             :         "host order'/>\n"
     641             :         "   <Option name='CACHEDSOURCE' type='string' "
     642             :         "description='The source raster, if this is a cache'/>\n"
     643             :         "   <Option name='UNIFORM_SCALE' type='int' description='Scale of "
     644             :         "overlays in MRF, usually 2'/>\n"
     645             :         "   <Option name='NOCOPY' type='boolean' description='Leave created "
     646             :         "MRF empty, default=no'/>\n"
     647             :         "   <Option name='DATANAME' type='string' description='Data file "
     648             :         "name'/>\n"
     649             :         "   <Option name='INDEXNAME' type='string' description='Index file "
     650             :         "name'/>\n"
     651             :         "   <Option name='SPACING' type='int' "
     652             :         "description='Leave this many unused bytes before each tile, "
     653             :         "default=0'/>\n"
     654             :         "   <Option name='PHOTOMETRIC' type='string-select' default='DEFAULT' "
     655             :         "description='Band interpretation, may affect block encoding'>\n"
     656             :         "       <Value>MULTISPECTRAL</Value>"
     657             :         "       <Value>RGB</Value>"
     658             :         "       <Value>YCC</Value>"
     659             :         "   </Option>\n"
     660             :         "   <Option name='OPTIONS' type='string' description='\n"
     661             :         "     Compression dependent parameters, space separated:\n"
     662             : #if defined(ZSTD_SUPPORT)
     663             :         "       ZSTD - boolean, enable libzstd as final stage, preferred over "
     664             :         "DEFLATE\n"
     665             : #endif
     666             :         "       DEFLATE - boolean, enable zlib as final stage\n"
     667             :         "       GZ - boolean, for DEFLATE enable gzip headers instead of zlib "
     668             :         "ones when using zlib\n"
     669             :         "       RAWZ - boolean, for DEFLATE disable all zlib headers\n"
     670             :         "       Z_STRATEGY - Z_HUFFMAN_ONLY | Z_FILTERED | Z_RLE | Z_FIXED: "
     671             :         "restricts DEFLATE and PNG strategy\n"
     672             : #if defined(LERC)
     673             :         "       LERC_PREC - numeric, set LERC precision, defaults to 0.5 for "
     674             :         "int and 0.001 for float\n"
     675             :         "       V1 - boolean, use LERC V1 (older) format\n"
     676             :         "       L2_VER - numeric, encode specific version of Lerc, default is "
     677             :         "library default\n"
     678             :         "                except for single band or INTERLEAVE=BAND, when it "
     679             :         "defaults to 2\n"
     680             : #endif
     681             :         "       OPTIMIZE - boolean, for JPEG, enables Huffman table "
     682             :         "optimization\n"
     683             : #if defined(BRUNSLI)
     684             :         "       JFIF - boolean, for JPEG, disable brunsli encoding\n"
     685             : #endif
     686             :         "'/>"
     687        1219 :         "</CreationOptionList>\n");
     688             : 
     689        1219 :     driver->pfnOpen = MRFDataset::Open;
     690        1219 :     driver->pfnCreateCopy = MRFDataset::CreateCopy;
     691        1219 :     driver->pfnCreate = MRFDataset::Create;
     692        1219 :     driver->pfnDelete = MRFDataset::Delete;
     693        1219 :     GetGDALDriverManager()->RegisterDriver(driver);
     694             : }
     695             : 
     696             : extern "C" void CPL_DLL GDALRegister_MRF(void);
     697             : 
     698           0 : void GDALRegister_MRF()
     699             : {
     700           0 :     GDALRegister_mrf();
     701           0 : }

Generated by: LCOV version 1.14