image_prepare.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "base/flags.h"
  9. #include "ui/rect_part.h"
  10. #include "ui/style/style_core.h"
  11. namespace Storage {
  12. namespace Cache {
  13. struct Key;
  14. } // namespace Cache
  15. } // namespace Storage
  16. enum class ImageRoundRadius {
  17. None,
  18. Large,
  19. Small,
  20. Ellipse,
  21. };
  22. namespace Images {
  23. [[nodiscard]] QPixmap PixmapFast(QImage &&image);
  24. [[nodiscard]] QImage BlurLargeImage(QImage &&image, int radius);
  25. [[nodiscard]] QImage DitherImage(const QImage &image);
  26. [[nodiscard]] QImage GenerateGradient(
  27. QSize size,
  28. const std::vector<QColor> &colors, // colors.size() <= 4.
  29. int rotation = 0,
  30. float progress = 1.f);
  31. [[nodiscard]] QImage GenerateLinearGradient(
  32. QSize size,
  33. const std::vector<QColor> &colors,
  34. int rotation = 0);
  35. [[nodiscard]] QImage GenerateShadow(
  36. int height,
  37. int topAlpha,
  38. int bottomAlpha,
  39. QColor color = QColor(0, 0, 0));
  40. inline constexpr auto kTopLeft = 0;
  41. inline constexpr auto kTopRight = 1;
  42. inline constexpr auto kBottomLeft = 2;
  43. inline constexpr auto kBottomRight = 3;
  44. struct CornersMaskRef {
  45. CornersMaskRef() = default;
  46. explicit CornersMaskRef(gsl::span<const QImage, 4> masks)
  47. : p{ &masks[0], &masks[1], &masks[2], &masks[3] } {
  48. }
  49. explicit CornersMaskRef(std::array<const QImage, 4> masks)
  50. : p{ &masks[0], &masks[1], &masks[2], &masks[3] } {
  51. }
  52. explicit CornersMaskRef(gsl::span<const QImage*, 4> masks)
  53. : p{ masks[0], masks[1], masks[2], masks[3] } {
  54. }
  55. explicit CornersMaskRef(std::array<const QImage*, 4> masks)
  56. : p{ masks[0], masks[1], masks[2], masks[3] } {
  57. }
  58. [[nodiscard]] bool empty() const {
  59. return !p[0] && !p[1] && !p[2] && !p[3];
  60. }
  61. std::array<const QImage*, 4> p{};
  62. friend inline constexpr std::strong_ordering operator<=>(
  63. CornersMaskRef a,
  64. CornersMaskRef b) noexcept {
  65. for (auto i = 0; i != 4; ++i) {
  66. if (a.p[i] < b.p[i]) {
  67. return std::strong_ordering::less;
  68. } else if (a.p[i] > b.p[i]) {
  69. return std::strong_ordering::greater;
  70. }
  71. }
  72. return std::strong_ordering::equal;
  73. }
  74. friend inline constexpr bool operator==(
  75. CornersMaskRef a,
  76. CornersMaskRef b) noexcept = default;
  77. };
  78. [[nodiscard]] const std::array<QImage, 4> &CornersMask(
  79. ImageRoundRadius radius);
  80. [[nodiscard]] std::array<QImage, 4> PrepareCorners(
  81. ImageRoundRadius radius,
  82. const style::color &color);
  83. [[nodiscard]] std::array<QImage, 4> CornersMask(int radius);
  84. [[nodiscard]] QImage EllipseMask(QSize size, double ratio = style::DevicePixelRatio());
  85. [[nodiscard]] std::array<QImage, 4> PrepareCorners(
  86. int radius,
  87. const style::color &color);
  88. [[nodiscard]] QByteArray UnpackGzip(const QByteArray &bytes);
  89. // Try to read images up to 64MB.
  90. inline constexpr auto kReadBytesLimit = 64 * 1024 * 1024;
  91. inline constexpr auto kReadMaxArea = 12'032 * 9'024;
  92. struct ReadArgs {
  93. QString path;
  94. QByteArray content;
  95. QSize maxSize;
  96. bool gzipSvg = false;
  97. bool forceOpaque = false;
  98. bool returnContent = false;
  99. };
  100. struct ReadResult {
  101. QImage image;
  102. QByteArray content;
  103. QByteArray format;
  104. bool animated = false;
  105. };
  106. [[nodiscard]] ReadResult Read(ReadArgs &&args);
  107. enum class Option {
  108. None = 0,
  109. FastTransform = (1 << 0),
  110. Blur = (1 << 1),
  111. RoundCircle = (1 << 2),
  112. RoundLarge = (1 << 3),
  113. RoundSmall = (1 << 4),
  114. RoundSkipTopLeft = (1 << 5),
  115. RoundSkipTopRight = (1 << 6),
  116. RoundSkipBottomLeft = (1 << 7),
  117. RoundSkipBottomRight = (1 << 8),
  118. Colorize = (1 << 9),
  119. TransparentBackground = (1 << 10),
  120. };
  121. using Options = base::flags<Option>;
  122. inline constexpr auto is_flag_type(Option) { return true; };
  123. [[nodiscard]] Options RoundOptions(
  124. ImageRoundRadius radius,
  125. RectParts corners = RectPart::AllCorners);
  126. [[nodiscard]] QImage Round(
  127. QImage &&image,
  128. CornersMaskRef mask,
  129. QRect target = QRect());
  130. [[nodiscard]] QImage Blur(QImage &&image, bool ignoreAlpha = false);
  131. [[nodiscard]] QImage Round(
  132. QImage &&image,
  133. ImageRoundRadius radius,
  134. RectParts corners = RectPart::AllCorners,
  135. QRect target = QRect());
  136. [[nodiscard]] QImage Round(
  137. QImage &&image,
  138. gsl::span<const QImage, 4> cornerMasks,
  139. RectParts corners = RectPart::AllCorners,
  140. QRect target = QRect());
  141. [[nodiscard]] QImage Round(
  142. QImage &&image,
  143. Options options,
  144. QRect target = QRect());
  145. [[nodiscard]] QImage Circle(QImage &&image, QRect target = QRect());
  146. [[nodiscard]] QImage Colored(QImage &&image, style::color add);
  147. [[nodiscard]] QImage Colored(QImage &&image, QColor add);
  148. [[nodiscard]] QImage Opaque(QImage &&image);
  149. struct PrepareArgs {
  150. const style::color *colored = nullptr;
  151. Options options;
  152. QSize outer;
  153. [[nodiscard]] PrepareArgs blurred() const {
  154. auto result = *this;
  155. result.options |= Option::Blur;
  156. return result;
  157. }
  158. };
  159. [[nodiscard]] QImage Prepare(
  160. QImage image,
  161. int w,
  162. int h,
  163. const PrepareArgs &args);
  164. [[nodiscard]] inline QImage Prepare(
  165. QImage image,
  166. int w,
  167. const PrepareArgs &args) {
  168. return Prepare(std::move(image), w, 0, args);
  169. }
  170. [[nodiscard]] inline QImage Prepare(
  171. QImage image,
  172. QSize size,
  173. const PrepareArgs &args) {
  174. return Prepare(std::move(image), size.width(), size.height(), args);
  175. }
  176. [[nodiscard]] bool IsProgressiveJpeg(const QByteArray &bytes);
  177. [[nodiscard]] QByteArray MakeProgressiveJpeg(const QByteArray &bytes);
  178. [[nodiscard]] QByteArray ExpandInlineBytes(const QByteArray &bytes);
  179. [[nodiscard]] QImage FromInlineBytes(const QByteArray &bytes);
  180. [[nodiscard]] QPainterPath PathFromInlineBytes(const QByteArray &bytes);
  181. } // namespace Images