LCOV - code coverage report
Current view: top level - frmts/mrf - BitMask2D.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 44 46 95.7 %
Date: 2024-05-04 12:52:34 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             : Copyright 2016-2017 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             : Contributors:  Lucian Plesea
      14             : */
      15             : 
      16             : /*
      17             : 
      18             : A 2D bitmask stored in 4x4 or 8x8 units
      19             : While it is a template over unit type, the only valid types are
      20             : unsigned 16bit and unsigned 64bit
      21             : 
      22             : Obviously not thread safe while any bit gets modified
      23             : 
      24             : */
      25             : #if !defined(BITMASK2D_H)
      26             : #define BITMASK2D_H
      27             : #include <vector>
      28             : #include <stdexcept>
      29             : 
      30             : // For CPL_MSB and swap functions
      31             : #include "cpl_port.h"
      32             : 
      33             : #include "marfa.h"
      34             : #if defined(PACKER)
      35             : #include "Packer.h"
      36             : #endif
      37             : 
      38             : NAMESPACE_MRF_START
      39             : 
      40             : // integer sqrt at compile time
      41             : // N is the number, M is the number of refining iterations
      42             : template <int N, int M = 4> struct Sqrt
      43             : {
      44             :     static const int value =
      45             :         (Sqrt<N, M - 1>::value + N / Sqrt<N, M - 1>::value) / 2;
      46             : };
      47             : 
      48             : // End condition
      49             : template <int N> struct Sqrt<N, 0>
      50             : {
      51             :     static const int value = N / 2;
      52             : };
      53             : 
      54             : // Round up division by N
      55          60 : template <unsigned int N> static int Chunks(int x)
      56             : {
      57          60 :     return 1 + (x - 1) / N;
      58             : }
      59             : 
      60             : //// These exist in C++11, so we name them with upper case
      61             : // template < typename T1, typename T2 > struct Is_Same {
      62             : //     enum { value = false }; // is_same represents a bool.
      63             : //     typedef Is_Same<T1, T2> type; // to qualify as a metafunction.
      64             : // };
      65             : //
      66             : //
      67             : ////// Specialization
      68             : // template < typename T > struct Is_Same<T,T> {
      69             : //     enum { value = true };
      70             : //     typedef Is_Same<T, T> type;
      71             : // };
      72             : //
      73             : 
      74             : // linear size of storage unit, 4 or 8
      75             : #define TGSIZE Sqrt<sizeof(T) * 8>::value
      76             : 
      77             : template <typename T = unsigned long long> class BitMap2D
      78             : {
      79             :   public:
      80             :     // Initialized to all bits set
      81          20 :     BitMap2D(unsigned int width, unsigned int height) : _w(width), _h(height)
      82             :     {
      83             :         // Prevent creation of bitmasks using any other types
      84             : 
      85             :         // Uncomment these statements to enforce only 64 and 16 bit units
      86             :         // They work but generate warnings on some compilers
      87             :         // Is_Same<T, unsigned long long>::type a;
      88             :         // Is_Same<T, unsigned short>::type b;
      89             :         // if (!(a.value || b.value))
      90             :         //   throw std::out_of_range("Only bitmap units of unsigned 16 and 64
      91             :         //   bits work");
      92             : 
      93             :         // Precalculate row size in storage units, for speed
      94          20 :         _lw = Chunks<TGSIZE>(_w);
      95             :         // Defaults to all set
      96          20 :         init(~(T)0);
      97             : #if defined(PACKER)
      98          20 :         _packer = nullptr;
      99             : #endif
     100          20 :     }
     101             : 
     102          20 :     int getWidth() const
     103             :     {
     104          20 :         return _w;
     105             :     }
     106             : 
     107          20 :     int getHeight() const
     108             :     {
     109          20 :         return _h;
     110             :     }
     111             : 
     112             :     // Size in bytes
     113          32 :     size_t size() const
     114             :     {
     115          32 :         return _bits.size() * sizeof(T);
     116             :     }
     117             : 
     118             :     // Returns the condition of a specific bit
     119     2097150 :     bool isSet(int x, int y) const
     120             :     {
     121     2097150 :         return 0 != (_bits[_idx(x, y)] & _bitmask(x, y));
     122             :     }
     123             : 
     124             :     void set(int x, int y)
     125             :     {
     126             :         _bits[_idx(x, y)] |= _bitmask(x, y);
     127             :     }
     128             : 
     129     2340860 :     void clear(int x, int y)
     130             :     {
     131     2340860 :         _bits[_idx(x, y)] &= ~_bitmask(x, y);
     132     2340860 :     }
     133             : 
     134             :     // Set a location bit to true or false
     135             :     void assign(int x, int y, bool val = true)
     136             :     {
     137             :         if (val)
     138             :             set(x, y);
     139             :         else
     140             :             clear(x, y);
     141             :     }
     142             : 
     143             :     // Flip a bit
     144             :     void flip(int x, int y)
     145             :     {
     146             :         _bits[_idx(x, y)] ^= _bitmask(x, y);
     147             :     }
     148             : 
     149             :     // Set all units to same bit pattern by unit
     150             :     // Use init(~(T)0)) for all set
     151          20 :     void init(T val)
     152             :     {
     153          40 :         _bits.assign(
     154          20 :             static_cast<size_t>(Chunks<TGSIZE>(_w)) * Chunks<TGSIZE>(_h), val);
     155          20 :     }
     156             : 
     157             :     // Support for store and load
     158             : #if defined(PACKER)
     159             : 
     160          20 :     void set_packer(Packer *packer)
     161             :     {
     162          20 :         _packer = packer;
     163          20 :     }
     164             : 
     165          12 :     int store(storage_manager *dst)
     166             :     {
     167             :         int result;
     168          12 :         storage_manager src = {reinterpret_cast<char *>(&_bits[0]), size()};
     169             :         // Store the bytes in little endian format
     170          12 :         swab();
     171          12 :         if (_packer)
     172          12 :             result = _packer->store(&src, dst);
     173             :         else
     174           0 :             result = Packer().store(&src, dst);
     175          12 :         swab();
     176          12 :         return result;
     177             :     }
     178             : 
     179           8 :     int load(storage_manager *src)
     180             :     {
     181             :         int result;
     182           8 :         storage_manager dst = {reinterpret_cast<char *>(&_bits[0]), size()};
     183           8 :         if (_packer)
     184           8 :             result = _packer->load(src, &dst);
     185             :         else
     186           0 :             result = Packer().load(src, &dst);
     187           8 :         swab();
     188           8 :         return result;
     189             :     }
     190             : #endif
     191             : 
     192             :   private:
     193             :     // unit index
     194     4438020 :     unsigned int _idx(int x, int y) const
     195             :     {
     196     4438020 :         return _lw * (y / TGSIZE) + x / TGSIZE;
     197             :     }
     198             : 
     199             :     // one bit mask within a unit
     200     4438020 :     static T _bitmask(int x, int y)
     201             :     {
     202     4438020 :         return static_cast<T>(1) << (TGSIZE * (y % TGSIZE) + x % TGSIZE);
     203             :     }
     204             : 
     205             : #if defined(PACKER)
     206             : // Swap bytes of storage units within the bitmap to low endian
     207             : #if defined(CPL_LSB)
     208          32 :     static void swab()
     209             :     {
     210          32 :     }
     211             : #else
     212             :     void swab()
     213             :     {
     214             :         for (size_t i = 0; i < _bits.size(); i++)
     215             :         {
     216             :             if (sizeof(T) == sizeof(GUIntBig))
     217             :             {
     218             :                 CPL_SWAP64PTR(reinterpret_cast<GUIntBig *>(&_bits[i]));
     219             :             }
     220             :             else
     221             :             {
     222             :                 CPL_SWAP16PTR(reinterpret_cast<GUInt16 *>(&_bits[i]));
     223             :             }
     224             :         }
     225             :     }
     226             : #endif
     227             : 
     228             :     // Class that provides export and import capabilities, not owned
     229             :     Packer *_packer;
     230             : #endif
     231             : 
     232             :     // bit storage vector
     233             :     std::vector<T> _bits;
     234             :     // width and height of bitmap
     235             :     unsigned int _w, _h;
     236             :     // Line size in linear chunks
     237             :     unsigned int _lw;
     238             : };
     239             : 
     240             : #undef TGSIZE
     241             : NAMESPACE_MRF_END
     242             : #endif

Generated by: LCOV version 1.14