Image.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Image.h
  3. * -------
  4. * Purpose: Bitmap and Vector image file handling.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "../common/FileReaderFwd.h"
  12. // GDI+
  13. namespace Gdiplus {
  14. #include <gdipluspixelformats.h>
  15. class Image;
  16. class Bitmap;
  17. class Metafile;
  18. }
  19. OPENMPT_NAMESPACE_BEGIN
  20. class bad_image : public std::runtime_error { public: bad_image() : std::runtime_error("") { } };
  21. class RawGDIDIB
  22. {
  23. public:
  24. struct Pixel
  25. {
  26. // Component order must be compatible with Microsoft DIBs!
  27. uint8 b;
  28. uint8 g;
  29. uint8 r;
  30. uint8 a;
  31. constexpr Pixel() noexcept
  32. : b(0), g(0), r(0), a(0) {}
  33. constexpr Pixel(uint8 r, uint8 g, uint8 b, uint8 a) noexcept
  34. : b(b), g(g), r(r), a(a) {}
  35. constexpr Pixel(COLORREF color) noexcept
  36. : b(GetBValue(color)), g(GetGValue(color)), r(GetRValue(color)), a(0) {}
  37. };
  38. private:
  39. uint32 width;
  40. uint32 height;
  41. std::vector<Pixel> pixels;
  42. public:
  43. RawGDIDIB(uint32 width, uint32 height);
  44. public:
  45. constexpr uint32 Width() const noexcept { return width; }
  46. constexpr uint32 Height() const noexcept { return height; }
  47. MPT_FORCEINLINE Pixel &operator()(uint32 x, uint32 y) noexcept { return pixels[y * width + x]; }
  48. MPT_FORCEINLINE const Pixel &operator()(uint32 x, uint32 y) const noexcept { return pixels[y * width + x]; }
  49. std::vector<Pixel> &Pixels() { return pixels; }
  50. const std::vector<Pixel> &Pixels() const { return pixels; }
  51. };
  52. class GdiplusRAII
  53. {
  54. private:
  55. ULONG_PTR gdiplusToken = 0;
  56. public:
  57. GdiplusRAII();
  58. ~GdiplusRAII();
  59. };
  60. namespace GDIP
  61. {
  62. std::unique_ptr<Gdiplus::Bitmap> LoadPixelImage(mpt::const_byte_span file);
  63. std::unique_ptr<Gdiplus::Bitmap> LoadPixelImage(FileReader file);
  64. std::unique_ptr<Gdiplus::Metafile> LoadVectorImage(mpt::const_byte_span file);
  65. std::unique_ptr<Gdiplus::Metafile> LoadVectorImage(FileReader file);
  66. std::unique_ptr<Gdiplus::Image> ResizeImage(Gdiplus::Image &src, double scaling, int spriteWidth = 0, int spriteHeight = 0);
  67. std::unique_ptr<Gdiplus::Bitmap> ResizeImage(Gdiplus::Bitmap &src, double scaling, int spriteWidth = 0, int spriteHeight = 0);
  68. using Pixel = Gdiplus::ARGB;
  69. template <typename TBitmapData>
  70. inline Pixel * GetScanline(const TBitmapData &bitmapData, std::size_t y) noexcept
  71. {
  72. if(bitmapData.Stride >= 0)
  73. {
  74. return reinterpret_cast<Pixel*>(mpt::void_cast<void*>(mpt::void_cast<std::byte*>(bitmapData.Scan0) + y * bitmapData.Stride));
  75. } else
  76. {
  77. return reinterpret_cast<Pixel*>(mpt::void_cast<void*>(mpt::void_cast<std::byte*>(bitmapData.Scan0) + (bitmapData.Height - 1 - y) * (-bitmapData.Stride)));
  78. }
  79. }
  80. constexpr Pixel AsPixel(uint8 r, uint8 g, uint8 b, uint8 a) noexcept
  81. {
  82. return Pixel(0)
  83. | (static_cast<Pixel>(r) << RED_SHIFT)
  84. | (static_cast<Pixel>(g) << GREEN_SHIFT)
  85. | (static_cast<Pixel>(b) << BLUE_SHIFT)
  86. | (static_cast<Pixel>(a) << ALPHA_SHIFT)
  87. ;
  88. }
  89. constexpr uint8 R(Pixel p) noexcept { return static_cast<uint8>(p >> RED_SHIFT); }
  90. constexpr uint8 G(Pixel p) noexcept { return static_cast<uint8>(p >> GREEN_SHIFT); }
  91. constexpr uint8 B(Pixel p) noexcept { return static_cast<uint8>(p >> BLUE_SHIFT); }
  92. constexpr uint8 A(Pixel p) noexcept { return static_cast<uint8>(p >> ALPHA_SHIFT); }
  93. constexpr RawGDIDIB::Pixel ToRawGDIDIB(Pixel p) noexcept
  94. {
  95. return RawGDIDIB::Pixel(GDIP::R(p), GDIP::G(p), GDIP::B(p), GDIP::A(p));
  96. }
  97. } // namespace GDIP
  98. std::unique_ptr<RawGDIDIB> ToRawGDIDIB(Gdiplus::Bitmap &bitmap);
  99. bool CopyToCompatibleBitmap(CBitmap &dst, CDC &dc, const RawGDIDIB &src);
  100. bool CopyToCompatibleBitmap(CBitmap &dst, CDC &dc, Gdiplus::Image &src);
  101. std::unique_ptr<RawGDIDIB> LoadPixelImage(mpt::const_byte_span file, double scaling = 1.0, int spriteWidth = 0, int spriteHeight = 0);
  102. std::unique_ptr<RawGDIDIB> LoadPixelImage(FileReader file, double scaling = 1.0, int spriteWidth = 0, int spriteHeight = 0);
  103. bool LoadCompatibleBitmapFromPixelImage(CBitmap &dst, CDC &dc, mpt::const_byte_span file);
  104. bool LoadCompatibleBitmapFromPixelImage(CBitmap &dst, CDC &dc, FileReader file);
  105. OPENMPT_NAMESPACE_END