PNGLoader.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Vector.h>
  8. #include <LibGfx/ImageFormats/ExifOrientedBitmap.h>
  9. #include <LibGfx/ImageFormats/PNGLoader.h>
  10. #include <LibGfx/ImageFormats/TIFFLoader.h>
  11. #include <LibGfx/ImageFormats/TIFFMetadata.h>
  12. #include <LibGfx/ImmutableBitmap.h>
  13. #include <LibGfx/Painter.h>
  14. #include <png.h>
  15. namespace Gfx {
  16. struct PNGLoadingContext {
  17. ReadonlyBytes data;
  18. IntSize size;
  19. u32 frame_count { 0 };
  20. u32 loop_count { 0 };
  21. Vector<ImageFrameDescriptor> frame_descriptors;
  22. Optional<ByteBuffer> icc_profile;
  23. OwnPtr<ExifMetadata> exif_metadata;
  24. ErrorOr<size_t> read_frames(png_structp, png_infop);
  25. ErrorOr<void> apply_exif_orientation();
  26. };
  27. ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> PNGImageDecoderPlugin::create(ReadonlyBytes bytes)
  28. {
  29. auto decoder = adopt_own(*new PNGImageDecoderPlugin(bytes));
  30. TRY(decoder->initialize());
  31. return decoder;
  32. }
  33. PNGImageDecoderPlugin::PNGImageDecoderPlugin(ReadonlyBytes data)
  34. : m_context(adopt_own(*new PNGLoadingContext))
  35. {
  36. m_context->data = data;
  37. }
  38. size_t PNGImageDecoderPlugin::first_animated_frame_index()
  39. {
  40. return 0;
  41. }
  42. IntSize PNGImageDecoderPlugin::size()
  43. {
  44. return m_context->size;
  45. }
  46. bool PNGImageDecoderPlugin::is_animated()
  47. {
  48. return m_context->frame_count > 1;
  49. }
  50. size_t PNGImageDecoderPlugin::loop_count()
  51. {
  52. return m_context->loop_count;
  53. }
  54. size_t PNGImageDecoderPlugin::frame_count()
  55. {
  56. return m_context->frame_count;
  57. }
  58. ErrorOr<ImageFrameDescriptor> PNGImageDecoderPlugin::frame(size_t index, Optional<IntSize>)
  59. {
  60. if (index >= m_context->frame_descriptors.size())
  61. return Error::from_errno(EINVAL);
  62. return m_context->frame_descriptors[index];
  63. }
  64. ErrorOr<Optional<ReadonlyBytes>> PNGImageDecoderPlugin::icc_data()
  65. {
  66. if (m_context->icc_profile.has_value())
  67. return Optional<ReadonlyBytes>(*m_context->icc_profile);
  68. return OptionalNone {};
  69. }
  70. static void log_png_error(png_structp png_ptr, char const* error_message)
  71. {
  72. dbgln("libpng error: {}", error_message);
  73. png_longjmp(png_ptr, 1);
  74. }
  75. static void log_png_warning(png_structp, char const* warning_message)
  76. {
  77. dbgln("libpng warning: {}", warning_message);
  78. }
  79. ErrorOr<void> PNGImageDecoderPlugin::initialize()
  80. {
  81. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  82. if (!png_ptr)
  83. return Error::from_string_view("Failed to allocate read struct"sv);
  84. png_infop info_ptr = png_create_info_struct(png_ptr);
  85. if (!info_ptr) {
  86. png_destroy_read_struct(&png_ptr, nullptr, nullptr);
  87. return Error::from_string_view("Failed to allocate info struct"sv);
  88. }
  89. if (auto error_value = setjmp(png_jmpbuf(png_ptr)); error_value) {
  90. png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  91. return Error::from_errno(error_value);
  92. }
  93. png_set_read_fn(png_ptr, &m_context->data, [](png_structp png_ptr, png_bytep data, png_size_t length) {
  94. auto* read_data = reinterpret_cast<ReadonlyBytes*>(png_get_io_ptr(png_ptr));
  95. if (read_data->size() < length) {
  96. png_error(png_ptr, "Read error");
  97. return;
  98. }
  99. memcpy(data, read_data->data(), length);
  100. *read_data = read_data->slice(length);
  101. });
  102. png_set_error_fn(png_ptr, nullptr, log_png_error, log_png_warning);
  103. png_read_info(png_ptr, info_ptr);
  104. u32 width = 0;
  105. u32 height = 0;
  106. int bit_depth = 0;
  107. int color_type = 0;
  108. int interlace_type = 0;
  109. png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, nullptr, nullptr);
  110. m_context->size = { static_cast<int>(width), static_cast<int>(height) };
  111. if (color_type == PNG_COLOR_TYPE_PALETTE)
  112. png_set_palette_to_rgb(png_ptr);
  113. if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
  114. png_set_expand_gray_1_2_4_to_8(png_ptr);
  115. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
  116. png_set_tRNS_to_alpha(png_ptr);
  117. if (bit_depth == 16)
  118. png_set_strip_16(png_ptr);
  119. if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  120. png_set_gray_to_rgb(png_ptr);
  121. if (interlace_type != PNG_INTERLACE_NONE)
  122. png_set_interlace_handling(png_ptr);
  123. png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
  124. png_set_bgr(png_ptr);
  125. char* profile_name = nullptr;
  126. int compression_type = 0;
  127. u8* profile_data = nullptr;
  128. u32 profile_len = 0;
  129. if (png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_len))
  130. m_context->icc_profile = TRY(ByteBuffer::copy(profile_data, profile_len));
  131. png_read_update_info(png_ptr, info_ptr);
  132. m_context->frame_count = TRY(m_context->read_frames(png_ptr, info_ptr));
  133. u8* exif_data = nullptr;
  134. u32 exif_length = 0;
  135. int const num_exif_chunks = png_get_eXIf_1(png_ptr, info_ptr, &exif_length, &exif_data);
  136. if (num_exif_chunks > 0)
  137. m_context->exif_metadata = TRY(TIFFImageDecoderPlugin::read_exif_metadata({ exif_data, exif_length }));
  138. if (m_context->exif_metadata)
  139. TRY(m_context->apply_exif_orientation());
  140. png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  141. return {};
  142. }
  143. ErrorOr<void> PNGLoadingContext::apply_exif_orientation()
  144. {
  145. auto orientation = exif_metadata->orientation().value_or(TIFF::Orientation::Default);
  146. if (orientation == TIFF::Orientation::Default)
  147. return {};
  148. for (auto& img_frame_descriptor : frame_descriptors) {
  149. auto& img = img_frame_descriptor.image;
  150. auto oriented_bmp = TRY(ExifOrientedBitmap::create(orientation, img->size(), img->format()));
  151. for (int y = 0; y < img->size().height(); ++y) {
  152. for (int x = 0; x < img->size().width(); ++x) {
  153. auto pixel = img->get_pixel(x, y);
  154. oriented_bmp.set_pixel(x, y, pixel.value());
  155. }
  156. }
  157. img_frame_descriptor.image = oriented_bmp.bitmap();
  158. }
  159. size = ExifOrientedBitmap::oriented_size(size, orientation);
  160. return {};
  161. }
  162. ErrorOr<size_t> PNGLoadingContext::read_frames(png_structp png_ptr, png_infop info_ptr)
  163. {
  164. if (png_get_acTL(png_ptr, info_ptr, &frame_count, &loop_count)) {
  165. // acTL chunk present: This is an APNG.
  166. png_set_acTL(png_ptr, info_ptr, frame_count, loop_count);
  167. // Conceptually, at the beginning of each play the output buffer must be completely initialized to a fully transparent black rectangle, with width and height dimensions from the `IHDR` chunk.
  168. auto output_buffer = TRY(Bitmap::create(BitmapFormat::BGRA8888, AlphaType::Unpremultiplied, size));
  169. auto painter = Painter::create(output_buffer);
  170. Vector<u8*> row_pointers;
  171. for (size_t frame_index = 0; frame_index < frame_count; ++frame_index) {
  172. png_read_frame_head(png_ptr, info_ptr);
  173. u32 width = 0;
  174. u32 height = 0;
  175. u32 x = 0;
  176. u32 y = 0;
  177. u16 delay_num = 0;
  178. u16 delay_den = 0;
  179. u8 dispose_op = PNG_DISPOSE_OP_NONE;
  180. u8 blend_op = PNG_BLEND_OP_SOURCE;
  181. auto duration_ms = [&]() -> int {
  182. if (delay_num == 0)
  183. return 1;
  184. u32 const denominator = delay_den != 0 ? static_cast<u32>(delay_den) : 100u;
  185. auto unsigned_duration_ms = (delay_num * 1000) / denominator;
  186. if (unsigned_duration_ms > INT_MAX)
  187. return INT_MAX;
  188. return static_cast<int>(unsigned_duration_ms);
  189. };
  190. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_fcTL)) {
  191. png_get_next_frame_fcTL(png_ptr, info_ptr, &width, &height, &x, &y, &delay_num, &delay_den, &dispose_op, &blend_op);
  192. } else {
  193. width = png_get_image_width(png_ptr, info_ptr);
  194. height = png_get_image_height(png_ptr, info_ptr);
  195. }
  196. auto frame_rect = FloatRect { x, y, width, height };
  197. auto decoded_frame_bitmap = TRY(Bitmap::create(BitmapFormat::BGRA8888, AlphaType::Unpremultiplied, IntSize { static_cast<int>(width), static_cast<int>(height) }));
  198. row_pointers.resize(height);
  199. for (u32 i = 0; i < height; ++i) {
  200. row_pointers[i] = decoded_frame_bitmap->scanline_u8(i);
  201. }
  202. png_read_image(png_ptr, row_pointers.data());
  203. RefPtr<Bitmap> prev_output_buffer;
  204. if (dispose_op == PNG_DISPOSE_OP_PREVIOUS) // Only actually clone if it's necessary
  205. prev_output_buffer = TRY(output_buffer->clone());
  206. switch (blend_op) {
  207. case PNG_BLEND_OP_SOURCE:
  208. // All color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
  209. painter->clear_rect(frame_rect, Gfx::Color::Transparent);
  210. painter->draw_bitmap(frame_rect, Gfx::ImmutableBitmap::create(*decoded_frame_bitmap), decoded_frame_bitmap->rect(), Gfx::ScalingMode::NearestNeighbor, 1.0f);
  211. break;
  212. case PNG_BLEND_OP_OVER:
  213. // The frame should be composited onto the output buffer based on its alpha, using a simple OVER operation as described in the "Alpha Channel Processing" section of the PNG specification.
  214. painter->draw_bitmap(frame_rect, Gfx::ImmutableBitmap::create(*decoded_frame_bitmap), decoded_frame_bitmap->rect(), ScalingMode::NearestNeighbor, 1.0f);
  215. break;
  216. default:
  217. VERIFY_NOT_REACHED();
  218. }
  219. frame_descriptors.append({ TRY(output_buffer->clone()), duration_ms() });
  220. switch (dispose_op) {
  221. case PNG_DISPOSE_OP_NONE:
  222. // No disposal is done on this frame before rendering the next; the contents of the output buffer are left as is.
  223. break;
  224. case PNG_DISPOSE_OP_BACKGROUND:
  225. // The frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
  226. painter->clear_rect(frame_rect, Gfx::Color::Transparent);
  227. break;
  228. case PNG_DISPOSE_OP_PREVIOUS:
  229. // The frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame.
  230. painter->clear_rect(frame_rect, Gfx::Color::Transparent);
  231. painter->draw_bitmap(frame_rect, Gfx::ImmutableBitmap::create(*prev_output_buffer), IntRect { x, y, width, height }, Gfx::ScalingMode::NearestNeighbor, 1.0f);
  232. break;
  233. default:
  234. VERIFY_NOT_REACHED();
  235. }
  236. }
  237. } else {
  238. // This is a single-frame PNG.
  239. frame_count = 1;
  240. loop_count = 0;
  241. auto decoded_frame_bitmap = TRY(Bitmap::create(BitmapFormat::BGRA8888, AlphaType::Unpremultiplied, size));
  242. Vector<u8*> row_pointers;
  243. row_pointers.resize(size.height());
  244. for (int i = 0; i < size.height(); ++i)
  245. row_pointers[i] = decoded_frame_bitmap->scanline_u8(i);
  246. png_read_image(png_ptr, row_pointers.data());
  247. frame_descriptors.append({ move(decoded_frame_bitmap), 0 });
  248. }
  249. return this->frame_count;
  250. }
  251. PNGImageDecoderPlugin::~PNGImageDecoderPlugin() = default;
  252. bool PNGImageDecoderPlugin::sniff(ReadonlyBytes data)
  253. {
  254. auto constexpr png_signature_size_in_bytes = 8;
  255. if (data.size() < png_signature_size_in_bytes)
  256. return false;
  257. return png_sig_cmp(data.data(), 0, png_signature_size_in_bytes) == 0;
  258. }
  259. Optional<Metadata const&> PNGImageDecoderPlugin::metadata()
  260. {
  261. if (m_context->exif_metadata)
  262. return *m_context->exif_metadata;
  263. return OptionalNone {};
  264. }
  265. }