LCOV - code coverage report
Current view: top level - core/bitmap - SPBitmap.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 195 216 90.3 %
Date: 2024-05-12 00:16:13 Functions: 21 25 84.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "SPBitmap.h"
      25             : #include "SPBytesView.h"
      26             : #include "SPString.h"
      27             : #include "SPBuffer.h"
      28             : #include "SPLog.h"
      29             : #include "SPFilesystem.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler::bitmap {
      32             : 
      33             : const BitmapFormat &getDefaultFormat(uint32_t);
      34             : SPUNUSED static std::unique_lock<std::mutex> lockFormatList();
      35             : SPUNUSED static void addCustomFormat(BitmapFormat &&fmt);
      36             : SPUNUSED static const std::vector<BitmapFormat *> &getCustomFormats();
      37             : 
      38        1177 : static Pair<FileFormat, StringView> _loadData(BitmapWriter &w, const uint8_t * data, size_t dataLen) {
      39        1502 :         for (int i = 0; i < toInt(FileFormat::Custom); ++i) {
      40        1477 :                 auto &fmt = getDefaultFormat(i);
      41        1477 :                 if (fmt.is(data, dataLen) && fmt.isReadable()) {
      42        1152 :                         if (fmt.load(data, dataLen, w)) {
      43        1152 :                                 return pair(FileFormat(i), fmt.getName());
      44             :                         }
      45             :                 }
      46             :         }
      47             : 
      48          25 :         memory::vector<BitmapFormat *> fns;
      49             : 
      50          25 :         auto lock = lockFormatList();
      51             : 
      52          25 :         fns.reserve(getCustomFormats().size());
      53          50 :         for (auto &it : getCustomFormats()) {
      54          25 :                 if (it->isReadable()) {
      55          25 :                         fns.emplace_back(it);
      56             :                 }
      57             :         }
      58             : 
      59          25 :         lock.unlock();
      60             : 
      61          25 :         for (auto &it : fns) {
      62          25 :                 if (it->is(data, dataLen) && it->load(data, dataLen, w)) {
      63          25 :                         return pair(FileFormat::Custom, it->getName());
      64             :                 }
      65             :         }
      66             : 
      67           0 :         return pair(FileFormat::Custom, StringView());
      68          25 : }
      69             : 
      70             : struct BitmapPoolTarget {
      71             :         memory::PoolInterface::BytesType *bytes;
      72             :         const StrideFn *strideFn;
      73             : };
      74             : 
      75             : struct BitmapStdTarget {
      76             :         memory::StandartInterface::BytesType *bytes;
      77             :         const StrideFn *strideFn;
      78             : };
      79             : 
      80        1725 : static void _makeBitmapWriter(BitmapWriter &w, BitmapPoolTarget *target, BitmapTemplate<memory::PoolInterface> &bmp) {
      81        1725 :         w.target = target;
      82        1725 :         w.color = bmp.format();
      83        1725 :         w.alpha = bmp.alpha();
      84        1725 :         w.width = bmp.width();
      85        1725 :         w.height = bmp.height();
      86        1725 :         w.stride = bmp.stride();
      87             : 
      88        1725 :         if (target && target->strideFn) {
      89           0 :                 w.getStride = [] (void *ptr, PixelFormat f, uint32_t w) {
      90           0 :                         return (*((BitmapPoolTarget *)ptr)->strideFn)(f, w);
      91           0 :                 };
      92           0 :         } else {
      93        1725 :                 w.getStride = nullptr;
      94             :         }
      95             : 
      96        6825 :         w.push = [] (void *ptr, const uint8_t *data, uint32_t size) {
      97        5100 :                 auto bytes = ((BitmapPoolTarget *)ptr)->bytes;
      98        5100 :                 auto origSize = bytes->size();
      99        5100 :                 bytes->resize(origSize + size);
     100        5100 :                 memcpy(bytes->data() + origSize, data, size);
     101        1725 :         };
     102        1950 :         w.resize = [] (void *ptr, uint32_t size) {
     103         225 :                 ((BitmapPoolTarget *)ptr)->bytes->resize(size);
     104        1725 :         };
     105       28550 :         w.getData = [] (void *ptr, uint32_t location) {
     106       26825 :                 return ((BitmapPoolTarget *)ptr)->bytes->data() + location;
     107        1725 :         };
     108        1750 :         w.assign = [] (void *ptr, const uint8_t *data, uint32_t size) {
     109          25 :                 auto bytes = ((BitmapPoolTarget *)ptr)->bytes;
     110          25 :                 bytes->resize(size);
     111          25 :                 memcpy(bytes->data(), data, size);
     112        1725 :         };
     113        1725 :         w.clear = [] (void *ptr) {
     114           0 :                 ((BitmapPoolTarget *)ptr)->bytes->clear();
     115        1725 :         };
     116        1725 : }
     117             : 
     118        1628 : static void _makeBitmapWriter(BitmapWriter &w, BitmapStdTarget *target, BitmapTemplate<memory::StandartInterface> &bmp) {
     119        1628 :         w.target = target;
     120        1628 :         w.color = bmp.format();
     121        1628 :         w.alpha = bmp.alpha();
     122        1628 :         w.width = bmp.width();
     123        1628 :         w.height = bmp.height();
     124        1628 :         w.stride = bmp.stride();
     125             : 
     126        1628 :         if (target && target->strideFn) {
     127           0 :                 w.getStride = [] (void *ptr, PixelFormat f, uint32_t w) {
     128           0 :                         return (*((BitmapPoolTarget *)ptr)->strideFn)(f, w);
     129           0 :                 };
     130           0 :         } else {
     131        1628 :                 w.getStride = nullptr;
     132             :         }
     133             : 
     134        9872 :         w.push = [] (void *ptr, const uint8_t *data, uint32_t size) {
     135        8244 :                 auto bytes = ((BitmapStdTarget *)ptr)->bytes;
     136        8244 :                 auto origSize = bytes->size();
     137        8244 :                 bytes->resize(origSize + size);
     138        8244 :                 memcpy(bytes->data() + origSize, data, size);
     139        1628 :         };
     140        2730 :         w.resize = [] (void *ptr, uint32_t size) {
     141        1102 :                 ((BitmapStdTarget *)ptr)->bytes->resize(size);
     142        1628 :         };
     143      303330 :         w.getData = [] (void *ptr, uint32_t location) {
     144      301702 :                 return ((BitmapStdTarget *)ptr)->bytes->data() + location;
     145        1628 :         };
     146        1703 :         w.assign = [] (void *ptr, const uint8_t *data, uint32_t size) {
     147          75 :                 auto bytes = ((BitmapStdTarget *)ptr)->bytes;
     148          75 :                 bytes->resize(size);
     149          75 :                 memcpy(bytes->data(), data, size);
     150        1628 :         };
     151        1628 :         w.clear = [] (void *ptr) {
     152           0 :                 ((BitmapStdTarget *)ptr)->bytes->clear();
     153        1628 :         };
     154        1628 : }
     155             : 
     156             : template <>
     157         175 : bool BitmapTemplate<memory::PoolInterface>::loadData(const uint8_t * data, size_t dataLen, const StrideFn &strideFn) {
     158         175 :         BitmapPoolTarget target { &_data, strideFn ? &strideFn : nullptr };
     159         175 :         BitmapWriter w;
     160         175 :         _makeBitmapWriter(w, &target, *this);
     161         175 :         auto ret = _loadData(w, data, dataLen);
     162         175 :         if (!ret.second.empty()) {
     163         175 :                 _color = w.color;
     164         175 :                 _alpha = w.alpha;
     165         175 :                 _width = w.width;
     166         175 :                 _height = w.height;
     167         175 :                 _stride = w.stride;
     168         175 :                 _originalFormat = ret.first;
     169         175 :                 _originalFormatName = ret.second;
     170         175 :                 return true;
     171             :         }
     172           0 :         return false;
     173             : }
     174             : 
     175             : template <>
     176        1002 : bool BitmapTemplate<memory::StandartInterface>::loadData(const uint8_t * data, size_t dataLen, const StrideFn &strideFn) {
     177        1002 :         BitmapStdTarget target { &_data, strideFn ? &strideFn : nullptr };
     178        1002 :         BitmapWriter w;
     179        1002 :         _makeBitmapWriter(w, &target, *this);
     180        1002 :         auto ret = _loadData(w, data, dataLen);
     181        1002 :         if (!ret.second.empty()) {
     182        1002 :                 _color = w.color;
     183        1002 :                 _alpha = w.alpha;
     184        1002 :                 _width = w.width;
     185        1002 :                 _height = w.height;
     186        1002 :                 _stride = w.stride;
     187        1002 :                 _originalFormat = ret.first;
     188        1002 :                 _originalFormatName = ret.second;
     189        1002 :                 return true;
     190             :         }
     191           0 :         return false;
     192             : }
     193             : 
     194             : template <>
     195         250 : bool BitmapTemplate<memory::StandartInterface>::save(FileFormat fmt, StringView path, bool invert) {
     196         250 :         BitmapWriter w;
     197         250 :         _makeBitmapWriter(w, nullptr, *this);
     198         250 :         auto &support = getDefaultFormat(toInt(fmt));
     199         250 :         if (support.isWritable()) {
     200         250 :                 return support.save(path, _data.data(), w, invert);
     201             :         } else {
     202             :                 // fallback to png
     203           0 :                 return getDefaultFormat(toInt(FileFormat::Png))
     204           0 :                         .save(path, _data.data(), w, invert);
     205             :         }
     206             :         return false;
     207             : }
     208             : 
     209             : template <>
     210        1375 : bool BitmapTemplate<memory::PoolInterface>::save(FileFormat fmt, StringView path, bool invert) {
     211        1375 :         BitmapWriter w;
     212        1375 :         _makeBitmapWriter(w, nullptr, *this);
     213        1375 :         auto &support = getDefaultFormat(toInt(fmt));
     214        1375 :         if (support.isWritable()) {
     215        1350 :                 return support.save(path, _data.data(), w, invert);
     216             :         } else {
     217             :                 // fallback to png
     218          50 :                 return getDefaultFormat(toInt(FileFormat::Png))
     219          25 :                         .save(path, _data.data(), w, invert);
     220             :         }
     221             :         return false;
     222             : }
     223             : 
     224             : template <>
     225          25 : bool BitmapTemplate<memory::StandartInterface>::save(StringView name, StringView path, bool invert) {
     226          25 :         BitmapFormat::save_fn fn = nullptr;
     227             : 
     228          25 :         auto lock = lockFormatList();
     229             : 
     230          50 :         for (auto &it : getCustomFormats()) {
     231          25 :                 if (it->getName() == name && it->isWritable()) {
     232          25 :                         fn = it->getSaveFn();
     233             :                 }
     234             :         }
     235             : 
     236          25 :         lock.unlock();
     237             : 
     238          25 :         if (fn) {
     239          25 :                 BitmapWriter w;
     240          25 :                 _makeBitmapWriter(w, nullptr, *this);
     241          25 :                 return fn(path, _data.data(), w, invert);
     242             :         }
     243           0 :         return false;
     244          25 : }
     245             : 
     246             : template <>
     247          25 : bool BitmapTemplate<memory::PoolInterface>::save(StringView name, StringView path, bool invert) {
     248          25 :         BitmapFormat::save_fn fn = nullptr;
     249             : 
     250          25 :         auto lock = lockFormatList();
     251             : 
     252          50 :         for (auto &it : getCustomFormats()) {
     253          25 :                 if (it->getName() == name && it->isWritable()) {
     254          25 :                         fn = it->getSaveFn();
     255             :                 }
     256             :         }
     257             : 
     258          25 :         lock.unlock();
     259             : 
     260          25 :         if (fn) {
     261          25 :                 BitmapWriter w;
     262          25 :                 _makeBitmapWriter(w, nullptr, *this);
     263          25 :                 return fn(path, _data.data(), w, invert);
     264             :         }
     265           0 :         return false;
     266          25 : }
     267             : 
     268             : template <>
     269         326 : auto BitmapTemplate<memory::StandartInterface>::write(FileFormat fmt, bool invert) -> memory::StandartInterface::BytesType {
     270         326 :         memory::StandartInterface::BytesType ret;
     271         326 :         BitmapStdTarget target { &ret, nullptr };
     272         326 :         BitmapWriter w;
     273         326 :         _makeBitmapWriter(w, &target, *this);
     274             : 
     275         326 :         auto &support = getDefaultFormat(toInt(fmt));
     276         326 :         if (support.isWritable() && support.write(_data.data(), w, invert)) {
     277         276 :                 return ret;
     278          50 :         } else if (getDefaultFormat(toInt(FileFormat::Png)).write(_data.data(), w, invert)) {
     279          50 :                 return ret;
     280             :         }
     281           0 :         return memory::StandartInterface::BytesType();
     282         326 : }
     283             : 
     284             : template <>
     285         125 : auto BitmapTemplate<memory::PoolInterface>::write(FileFormat fmt, bool invert) -> memory::PoolInterface::BytesType {
     286         125 :         memory::PoolInterface::BytesType ret;
     287         125 :         BitmapPoolTarget target { &ret, nullptr };
     288         125 :         BitmapWriter w;
     289         125 :         _makeBitmapWriter(w, &target, *this);
     290             : 
     291         125 :         auto &support = getDefaultFormat(toInt(fmt));
     292         125 :         if (support.isWritable() && support.write(_data.data(), w, invert)) {
     293          75 :                 return ret;
     294          50 :         } else if (getDefaultFormat(toInt(FileFormat::Png)).write(_data.data(), w, invert)) {
     295          50 :                 return ret;
     296             :         }
     297           0 :         return memory::PoolInterface::BytesType();
     298         125 : }
     299             : 
     300             : template <>
     301          25 : auto BitmapTemplate<memory::StandartInterface>::write(StringView name, bool invert) -> memory::StandartInterface::BytesType {
     302          25 :         BitmapFormat::write_fn fn = nullptr;
     303             : 
     304          25 :         auto lock = lockFormatList();
     305             : 
     306          50 :         for (auto &it : getCustomFormats()) {
     307          25 :                 if (it->getName() == name && it->isWritable()) {
     308          25 :                         fn = it->getWriteFn();
     309             :                 }
     310             :         }
     311             : 
     312          25 :         lock.unlock();
     313             : 
     314          25 :         if (fn) {
     315          25 :                 memory::StandartInterface::BytesType ret;
     316          25 :                 BitmapStdTarget target { &ret, nullptr };
     317          25 :                 BitmapWriter w;
     318          25 :                 _makeBitmapWriter(w, &target, *this);
     319          25 :                 if (fn(_data.data(), w, invert)) {
     320          25 :                         return ret;
     321             :                 }
     322          25 :         }
     323           0 :         return memory::StandartInterface::BytesType();
     324          25 : }
     325             : 
     326             : template <>
     327          25 : auto BitmapTemplate<memory::PoolInterface>::write(StringView name, bool invert) -> memory::PoolInterface::BytesType {
     328          25 :         BitmapFormat::write_fn fn = nullptr;
     329             : 
     330          25 :         auto lock = lockFormatList();
     331             : 
     332          50 :         for (auto &it : getCustomFormats()) {
     333          25 :                 if (it->getName() == name && it->isWritable()) {
     334          25 :                         fn = it->getWriteFn();
     335             :                 }
     336             :         }
     337             : 
     338          25 :         lock.unlock();
     339             : 
     340          25 :         if (fn) {
     341          25 :                 memory::PoolInterface::BytesType ret;
     342          25 :                 BitmapPoolTarget target { &ret, nullptr };
     343          25 :                 BitmapWriter w;
     344          25 :                 _makeBitmapWriter(w, &target, *this);
     345          25 :                 if (fn(_data.data(), w, invert)) {
     346          25 :                         return ret;
     347             :                 }
     348          25 :         }
     349           0 :         return memory::PoolInterface::BytesType();
     350          25 : }
     351             : 
     352             : }

Generated by: LCOV version 1.14