ImageLoader.cpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. * Copyright 2019 Axel Waggersauser.
  4. */
  5. // SPDX-License-Identifier: Apache-2.0
  6. #include "ImageLoader.h"
  7. #include "BinaryBitmap.h"
  8. #include "ImageView.h"
  9. #include <array>
  10. #include <map>
  11. #include <memory>
  12. #include <stdexcept>
  13. #define STB_IMAGE_IMPLEMENTATION
  14. #include <stb_image.h>
  15. namespace ZXing::Test {
  16. class STBImage : public ImageView
  17. {
  18. std::unique_ptr<stbi_uc[], void (*)(void*)> _memory;
  19. public:
  20. STBImage() : ImageView(), _memory(nullptr, stbi_image_free) {}
  21. void load(const fs::path& imgPath)
  22. {
  23. int width, height, channels;
  24. _memory.reset(stbi_load(imgPath.string().c_str(), &width, &height, &channels, 0));
  25. if (_memory == nullptr)
  26. throw std::runtime_error("Failed to read image: " + imgPath.string() + " (" + stbi_failure_reason() + ")");
  27. auto ImageFormatFromChannels = std::array{ImageFormat::None, ImageFormat::Lum, ImageFormat::LumA, ImageFormat::RGB, ImageFormat::RGBA};
  28. ImageView::operator=({_memory.get(), width, height, ImageFormatFromChannels.at(channels)});
  29. // preconvert from RGB -> Lum to do this only once instead of for each rotation
  30. if (_format == ImageFormat::RGB) {
  31. auto* img = _memory.get();
  32. for (int i = 0; i < width * height; ++i)
  33. img[i] = RGBToLum(img[3 * i + 0], img[3 * i + 1], img[3 * i + 2]);
  34. ImageView::operator=({_memory.get(), width, height, ImageFormat::Lum});
  35. }
  36. }
  37. operator bool() const { return _data; }
  38. };
  39. std::map<fs::path, STBImage> cache;
  40. void ImageLoader::clearCache()
  41. {
  42. cache.clear();
  43. }
  44. const ImageView& ImageLoader::load(const fs::path& imgPath)
  45. {
  46. thread_local std::unique_ptr<BinaryBitmap> localAverage, threshold;
  47. auto& binImg = cache[imgPath];
  48. if (!binImg)
  49. binImg.load(imgPath);
  50. return binImg;
  51. }
  52. } // namespace ZXing::Test