PNGLoader.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Endian.h>
  27. #include <AK/LexicalPath.h>
  28. #include <AK/MappedFile.h>
  29. #include <LibCore/puff.h>
  30. #include <LibGfx/PNGLoader.h>
  31. #include <fcntl.h>
  32. #include <math.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <sys/mman.h>
  36. #include <sys/stat.h>
  37. #include <unistd.h>
  38. #ifdef __serenity__
  39. # include <serenity.h>
  40. #endif
  41. //#define PNG_DEBUG
  42. namespace Gfx {
  43. static const u8 png_header[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
  44. struct PNG_IHDR {
  45. NetworkOrdered<u32> width;
  46. NetworkOrdered<u32> height;
  47. u8 bit_depth { 0 };
  48. u8 color_type { 0 };
  49. u8 compression_method { 0 };
  50. u8 filter_method { 0 };
  51. u8 interlace_method { 0 };
  52. };
  53. static_assert(sizeof(PNG_IHDR) == 13);
  54. struct Scanline {
  55. u8 filter { 0 };
  56. ReadonlyBytes data {};
  57. };
  58. struct [[gnu::packed]] PaletteEntry
  59. {
  60. u8 r;
  61. u8 g;
  62. u8 b;
  63. //u8 a;
  64. };
  65. template<typename T>
  66. struct [[gnu::packed]] Tuple
  67. {
  68. T gray;
  69. T a;
  70. };
  71. template<typename T>
  72. struct [[gnu::packed]] Triplet
  73. {
  74. T r;
  75. T g;
  76. T b;
  77. };
  78. template<typename T>
  79. struct [[gnu::packed]] Quad
  80. {
  81. T r;
  82. T g;
  83. T b;
  84. T a;
  85. };
  86. enum PngInterlaceMethod {
  87. Null = 0,
  88. Adam7 = 1
  89. };
  90. struct PNGLoadingContext {
  91. enum State {
  92. NotDecoded = 0,
  93. Error,
  94. HeaderDecoded,
  95. SizeDecoded,
  96. ChunksDecoded,
  97. BitmapDecoded,
  98. };
  99. State state { State::NotDecoded };
  100. const u8* data { nullptr };
  101. size_t data_size { 0 };
  102. int width { -1 };
  103. int height { -1 };
  104. u8 bit_depth { 0 };
  105. u8 color_type { 0 };
  106. u8 compression_method { 0 };
  107. u8 filter_method { 0 };
  108. u8 interlace_method { 0 };
  109. u8 channels { 0 };
  110. bool has_seen_zlib_header { false };
  111. bool has_alpha() const { return color_type & 4 || palette_transparency_data.size() > 0; }
  112. Vector<Scanline> scanlines;
  113. RefPtr<Gfx::Bitmap> bitmap;
  114. u8* decompression_buffer { nullptr };
  115. size_t decompression_buffer_size { 0 };
  116. Vector<u8> compressed_data;
  117. Vector<PaletteEntry> palette_data;
  118. Vector<u8> palette_transparency_data;
  119. Checked<int> compute_row_size_for_width(int width)
  120. {
  121. Checked<int> row_size = width;
  122. row_size *= channels;
  123. row_size *= bit_depth;
  124. row_size += 7;
  125. row_size /= 8;
  126. if (row_size.has_overflow()) {
  127. dbgln("PNG too large, integer overflow while computing row size");
  128. state = State::Error;
  129. }
  130. return row_size;
  131. }
  132. };
  133. class Streamer {
  134. public:
  135. Streamer(const u8* data, size_t size)
  136. : m_data_ptr(data)
  137. , m_size_remaining(size)
  138. {
  139. }
  140. template<typename T>
  141. bool read(T& value)
  142. {
  143. if (m_size_remaining < sizeof(T))
  144. return false;
  145. value = *((const NetworkOrdered<T>*)m_data_ptr);
  146. m_data_ptr += sizeof(T);
  147. m_size_remaining -= sizeof(T);
  148. return true;
  149. }
  150. bool read_bytes(u8* buffer, size_t count)
  151. {
  152. if (m_size_remaining < count)
  153. return false;
  154. memcpy(buffer, m_data_ptr, count);
  155. m_data_ptr += count;
  156. m_size_remaining -= count;
  157. return true;
  158. }
  159. bool wrap_bytes(ReadonlyBytes& buffer, size_t count)
  160. {
  161. if (m_size_remaining < count)
  162. return false;
  163. buffer = ReadonlyBytes { m_data_ptr, count };
  164. m_data_ptr += count;
  165. m_size_remaining -= count;
  166. return true;
  167. }
  168. bool at_end() const { return !m_size_remaining; }
  169. private:
  170. const u8* m_data_ptr { nullptr };
  171. size_t m_size_remaining { 0 };
  172. };
  173. static RefPtr<Gfx::Bitmap> load_png_impl(const u8*, size_t);
  174. static bool process_chunk(Streamer&, PNGLoadingContext& context);
  175. RefPtr<Gfx::Bitmap> load_png(const StringView& path)
  176. {
  177. MappedFile mapped_file(path);
  178. if (!mapped_file.is_valid())
  179. return nullptr;
  180. auto bitmap = load_png_impl((const u8*)mapped_file.data(), mapped_file.size());
  181. if (bitmap)
  182. bitmap->set_mmap_name(String::format("Gfx::Bitmap [%dx%d] - Decoded PNG: %s", bitmap->width(), bitmap->height(), LexicalPath::canonicalized_path(path).characters()));
  183. return bitmap;
  184. }
  185. RefPtr<Gfx::Bitmap> load_png_from_memory(const u8* data, size_t length)
  186. {
  187. auto bitmap = load_png_impl(data, length);
  188. if (bitmap)
  189. bitmap->set_mmap_name(String::format("Gfx::Bitmap [%dx%d] - Decoded PNG: <memory>", bitmap->width(), bitmap->height()));
  190. return bitmap;
  191. }
  192. ALWAYS_INLINE static u8 paeth_predictor(int a, int b, int c)
  193. {
  194. int p = a + b - c;
  195. int pa = abs(p - a);
  196. int pb = abs(p - b);
  197. int pc = abs(p - c);
  198. if (pa <= pb && pa <= pc)
  199. return a;
  200. if (pb <= pc)
  201. return b;
  202. return c;
  203. }
  204. union [[gnu::packed]] Pixel
  205. {
  206. RGBA32 rgba { 0 };
  207. u8 v[4];
  208. struct {
  209. u8 r;
  210. u8 g;
  211. u8 b;
  212. u8 a;
  213. };
  214. };
  215. static_assert(sizeof(Pixel) == 4);
  216. template<bool has_alpha, u8 filter_type>
  217. ALWAYS_INLINE static void unfilter_impl(Gfx::Bitmap& bitmap, int y, const void* dummy_scanline_data)
  218. {
  219. auto* dummy_scanline = (const Pixel*)dummy_scanline_data;
  220. if constexpr (filter_type == 0) {
  221. auto* pixels = (Pixel*)bitmap.scanline(y);
  222. for (int i = 0; i < bitmap.width(); ++i) {
  223. auto& x = pixels[i];
  224. swap(x.r, x.b);
  225. }
  226. }
  227. if constexpr (filter_type == 1) {
  228. auto* pixels = (Pixel*)bitmap.scanline(y);
  229. swap(pixels[0].r, pixels[0].b);
  230. for (int i = 1; i < bitmap.width(); ++i) {
  231. auto& x = pixels[i];
  232. swap(x.r, x.b);
  233. auto& a = (const Pixel&)pixels[i - 1];
  234. x.v[0] += a.v[0];
  235. x.v[1] += a.v[1];
  236. x.v[2] += a.v[2];
  237. if constexpr (has_alpha)
  238. x.v[3] += a.v[3];
  239. }
  240. return;
  241. }
  242. if constexpr (filter_type == 2) {
  243. auto* pixels = (Pixel*)bitmap.scanline(y);
  244. auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (const Pixel*)bitmap.scanline(y - 1);
  245. for (int i = 0; i < bitmap.width(); ++i) {
  246. auto& x = pixels[i];
  247. swap(x.r, x.b);
  248. const Pixel& b = pixels_y_minus_1[i];
  249. x.v[0] += b.v[0];
  250. x.v[1] += b.v[1];
  251. x.v[2] += b.v[2];
  252. if constexpr (has_alpha)
  253. x.v[3] += b.v[3];
  254. }
  255. return;
  256. }
  257. if constexpr (filter_type == 3) {
  258. auto* pixels = (Pixel*)bitmap.scanline(y);
  259. auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (const Pixel*)bitmap.scanline(y - 1);
  260. for (int i = 0; i < bitmap.width(); ++i) {
  261. auto& x = pixels[i];
  262. swap(x.r, x.b);
  263. Pixel a;
  264. if (i != 0)
  265. a = pixels[i - 1];
  266. const Pixel& b = pixels_y_minus_1[i];
  267. x.v[0] = x.v[0] + ((a.v[0] + b.v[0]) / 2);
  268. x.v[1] = x.v[1] + ((a.v[1] + b.v[1]) / 2);
  269. x.v[2] = x.v[2] + ((a.v[2] + b.v[2]) / 2);
  270. if constexpr (has_alpha)
  271. x.v[3] = x.v[3] + ((a.v[3] + b.v[3]) / 2);
  272. }
  273. return;
  274. }
  275. if constexpr (filter_type == 4) {
  276. auto* pixels = (Pixel*)bitmap.scanline(y);
  277. auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline(y - 1);
  278. for (int i = 0; i < bitmap.width(); ++i) {
  279. auto& x = pixels[i];
  280. swap(x.r, x.b);
  281. Pixel a;
  282. const Pixel& b = pixels_y_minus_1[i];
  283. Pixel c;
  284. if (i != 0) {
  285. a = pixels[i - 1];
  286. c = pixels_y_minus_1[i - 1];
  287. }
  288. x.v[0] += paeth_predictor(a.v[0], b.v[0], c.v[0]);
  289. x.v[1] += paeth_predictor(a.v[1], b.v[1], c.v[1]);
  290. x.v[2] += paeth_predictor(a.v[2], b.v[2], c.v[2]);
  291. if constexpr (has_alpha)
  292. x.v[3] += paeth_predictor(a.v[3], b.v[3], c.v[3]);
  293. }
  294. }
  295. }
  296. template<typename T>
  297. ALWAYS_INLINE static void unpack_grayscale_without_alpha(PNGLoadingContext& context)
  298. {
  299. for (int y = 0; y < context.height; ++y) {
  300. auto* gray_values = reinterpret_cast<const T*>(context.scanlines[y].data.data());
  301. for (int i = 0; i < context.width; ++i) {
  302. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  303. pixel.r = gray_values[i];
  304. pixel.g = gray_values[i];
  305. pixel.b = gray_values[i];
  306. pixel.a = 0xff;
  307. }
  308. }
  309. }
  310. template<typename T>
  311. ALWAYS_INLINE static void unpack_grayscale_with_alpha(PNGLoadingContext& context)
  312. {
  313. for (int y = 0; y < context.height; ++y) {
  314. auto* tuples = reinterpret_cast<const Tuple<T>*>(context.scanlines[y].data.data());
  315. for (int i = 0; i < context.width; ++i) {
  316. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  317. pixel.r = tuples[i].gray;
  318. pixel.g = tuples[i].gray;
  319. pixel.b = tuples[i].gray;
  320. pixel.a = tuples[i].a;
  321. }
  322. }
  323. }
  324. template<typename T>
  325. ALWAYS_INLINE static void unpack_triplets_without_alpha(PNGLoadingContext& context)
  326. {
  327. for (int y = 0; y < context.height; ++y) {
  328. auto* triplets = reinterpret_cast<const Triplet<T>*>(context.scanlines[y].data.data());
  329. for (int i = 0; i < context.width; ++i) {
  330. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  331. pixel.r = triplets[i].r;
  332. pixel.g = triplets[i].g;
  333. pixel.b = triplets[i].b;
  334. pixel.a = 0xff;
  335. }
  336. }
  337. }
  338. NEVER_INLINE FLATTEN static void unfilter(PNGLoadingContext& context)
  339. {
  340. // First unpack the scanlines to RGBA:
  341. switch (context.color_type) {
  342. case 0:
  343. if (context.bit_depth == 8) {
  344. unpack_grayscale_without_alpha<u8>(context);
  345. } else if (context.bit_depth == 16) {
  346. unpack_grayscale_without_alpha<u16>(context);
  347. } else if (context.bit_depth == 1 || context.bit_depth == 2 || context.bit_depth == 4) {
  348. auto bit_depth_squared = context.bit_depth * context.bit_depth;
  349. auto pixels_per_byte = 8 / context.bit_depth;
  350. auto mask = (1 << context.bit_depth) - 1;
  351. for (int y = 0; y < context.height; ++y) {
  352. auto* gray_values = context.scanlines[y].data.data();
  353. for (int x = 0; x < context.width; ++x) {
  354. auto bit_offset = (8 - context.bit_depth) - (context.bit_depth * (x % pixels_per_byte));
  355. auto value = (gray_values[x / pixels_per_byte] >> bit_offset) & mask;
  356. auto& pixel = (Pixel&)context.bitmap->scanline(y)[x];
  357. pixel.r = value * (0xff / bit_depth_squared);
  358. pixel.g = value * (0xff / bit_depth_squared);
  359. pixel.b = value * (0xff / bit_depth_squared);
  360. pixel.a = 0xff;
  361. }
  362. }
  363. } else {
  364. ASSERT_NOT_REACHED();
  365. }
  366. break;
  367. case 4:
  368. if (context.bit_depth == 8) {
  369. unpack_grayscale_with_alpha<u8>(context);
  370. } else if (context.bit_depth == 16) {
  371. unpack_grayscale_with_alpha<u16>(context);
  372. } else {
  373. ASSERT_NOT_REACHED();
  374. }
  375. break;
  376. case 2:
  377. if (context.bit_depth == 8) {
  378. unpack_triplets_without_alpha<u8>(context);
  379. } else if (context.bit_depth == 16) {
  380. unpack_triplets_without_alpha<u16>(context);
  381. } else {
  382. ASSERT_NOT_REACHED();
  383. }
  384. break;
  385. case 6:
  386. if (context.bit_depth == 8) {
  387. for (int y = 0; y < context.height; ++y) {
  388. memcpy(context.bitmap->scanline(y), context.scanlines[y].data.data(), context.scanlines[y].data.size());
  389. }
  390. } else if (context.bit_depth == 16) {
  391. for (int y = 0; y < context.height; ++y) {
  392. auto* triplets = reinterpret_cast<const Quad<u16>*>(context.scanlines[y].data.data());
  393. for (int i = 0; i < context.width; ++i) {
  394. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  395. pixel.r = triplets[i].r & 0xFF;
  396. pixel.g = triplets[i].g & 0xFF;
  397. pixel.b = triplets[i].b & 0xFF;
  398. pixel.a = triplets[i].a & 0xFF;
  399. }
  400. }
  401. } else {
  402. ASSERT_NOT_REACHED();
  403. }
  404. break;
  405. case 3:
  406. if (context.bit_depth == 8) {
  407. for (int y = 0; y < context.height; ++y) {
  408. auto* palette_index = context.scanlines[y].data.data();
  409. for (int i = 0; i < context.width; ++i) {
  410. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  411. auto& color = context.palette_data.at((int)palette_index[i]);
  412. auto transparency = context.palette_transparency_data.size() >= palette_index[i] + 1u
  413. ? context.palette_transparency_data.data()[palette_index[i]]
  414. : 0xff;
  415. pixel.r = color.r;
  416. pixel.g = color.g;
  417. pixel.b = color.b;
  418. pixel.a = transparency;
  419. }
  420. }
  421. } else if (context.bit_depth == 1 || context.bit_depth == 2 || context.bit_depth == 4) {
  422. auto pixels_per_byte = 8 / context.bit_depth;
  423. auto mask = (1 << context.bit_depth) - 1;
  424. for (int y = 0; y < context.height; ++y) {
  425. auto* palette_indexes = context.scanlines[y].data.data();
  426. for (int i = 0; i < context.width; ++i) {
  427. auto bit_offset = (8 - context.bit_depth) - (context.bit_depth * (i % pixels_per_byte));
  428. auto palette_index = (palette_indexes[i / pixels_per_byte] >> bit_offset) & mask;
  429. auto& pixel = (Pixel&)context.bitmap->scanline(y)[i];
  430. auto& color = context.palette_data.at(palette_index);
  431. auto transparency = context.palette_transparency_data.size() >= palette_index + 1u
  432. ? context.palette_transparency_data.data()[palette_index]
  433. : 0xff;
  434. pixel.r = color.r;
  435. pixel.g = color.g;
  436. pixel.b = color.b;
  437. pixel.a = transparency;
  438. }
  439. }
  440. } else {
  441. ASSERT_NOT_REACHED();
  442. }
  443. break;
  444. default:
  445. ASSERT_NOT_REACHED();
  446. break;
  447. }
  448. u8 dummy_scanline[context.width * sizeof(RGBA32)];
  449. for (int y = 0; y < context.height; ++y) {
  450. auto filter = context.scanlines[y].filter;
  451. if (filter == 0) {
  452. if (context.has_alpha())
  453. unfilter_impl<true, 0>(*context.bitmap, y, dummy_scanline);
  454. else
  455. unfilter_impl<false, 0>(*context.bitmap, y, dummy_scanline);
  456. continue;
  457. }
  458. if (filter == 1) {
  459. if (context.has_alpha())
  460. unfilter_impl<true, 1>(*context.bitmap, y, dummy_scanline);
  461. else
  462. unfilter_impl<false, 1>(*context.bitmap, y, dummy_scanline);
  463. continue;
  464. }
  465. if (filter == 2) {
  466. if (context.has_alpha())
  467. unfilter_impl<true, 2>(*context.bitmap, y, dummy_scanline);
  468. else
  469. unfilter_impl<false, 2>(*context.bitmap, y, dummy_scanline);
  470. continue;
  471. }
  472. if (filter == 3) {
  473. if (context.has_alpha())
  474. unfilter_impl<true, 3>(*context.bitmap, y, dummy_scanline);
  475. else
  476. unfilter_impl<false, 3>(*context.bitmap, y, dummy_scanline);
  477. continue;
  478. }
  479. if (filter == 4) {
  480. if (context.has_alpha())
  481. unfilter_impl<true, 4>(*context.bitmap, y, dummy_scanline);
  482. else
  483. unfilter_impl<false, 4>(*context.bitmap, y, dummy_scanline);
  484. continue;
  485. }
  486. }
  487. }
  488. static bool decode_png_header(PNGLoadingContext& context)
  489. {
  490. if (context.state >= PNGLoadingContext::HeaderDecoded)
  491. return true;
  492. if (!context.data || context.data_size < sizeof(png_header)) {
  493. #ifdef PNG_DEBUG
  494. dbg() << "Missing PNG header";
  495. #endif
  496. context.state = PNGLoadingContext::State::Error;
  497. return false;
  498. }
  499. if (memcmp(context.data, png_header, sizeof(png_header)) != 0) {
  500. #ifdef PNG_DEBUG
  501. dbg() << "Invalid PNG header";
  502. #endif
  503. context.state = PNGLoadingContext::State::Error;
  504. return false;
  505. }
  506. context.state = PNGLoadingContext::HeaderDecoded;
  507. return true;
  508. }
  509. static bool decode_png_size(PNGLoadingContext& context)
  510. {
  511. if (context.state >= PNGLoadingContext::SizeDecoded)
  512. return true;
  513. if (context.state < PNGLoadingContext::HeaderDecoded) {
  514. if (!decode_png_header(context))
  515. return false;
  516. }
  517. const u8* data_ptr = context.data + sizeof(png_header);
  518. size_t data_remaining = context.data_size - sizeof(png_header);
  519. Streamer streamer(data_ptr, data_remaining);
  520. while (!streamer.at_end()) {
  521. if (!process_chunk(streamer, context)) {
  522. context.state = PNGLoadingContext::State::Error;
  523. return false;
  524. }
  525. if (context.width && context.height) {
  526. context.state = PNGLoadingContext::State::SizeDecoded;
  527. return true;
  528. }
  529. }
  530. return false;
  531. }
  532. static bool decode_png_chunks(PNGLoadingContext& context)
  533. {
  534. if (context.state >= PNGLoadingContext::State::ChunksDecoded)
  535. return true;
  536. if (context.state < PNGLoadingContext::HeaderDecoded) {
  537. if (!decode_png_header(context))
  538. return false;
  539. }
  540. const u8* data_ptr = context.data + sizeof(png_header);
  541. int data_remaining = context.data_size - sizeof(png_header);
  542. context.compressed_data.ensure_capacity(context.data_size);
  543. Streamer streamer(data_ptr, data_remaining);
  544. while (!streamer.at_end()) {
  545. if (!process_chunk(streamer, context)) {
  546. context.state = PNGLoadingContext::State::Error;
  547. return false;
  548. }
  549. }
  550. context.state = PNGLoadingContext::State::ChunksDecoded;
  551. return true;
  552. }
  553. static bool decode_png_bitmap_simple(PNGLoadingContext& context)
  554. {
  555. Streamer streamer(context.decompression_buffer, context.decompression_buffer_size);
  556. for (int y = 0; y < context.height; ++y) {
  557. u8 filter;
  558. if (!streamer.read(filter)) {
  559. context.state = PNGLoadingContext::State::Error;
  560. return false;
  561. }
  562. if (filter > 4) {
  563. #ifdef PNG_DEBUG
  564. dbg() << "Invalid PNG filter: " << filter;
  565. #endif
  566. context.state = PNGLoadingContext::State::Error;
  567. return false;
  568. }
  569. context.scanlines.append({ filter });
  570. auto& scanline_buffer = context.scanlines.last().data;
  571. auto row_size = context.compute_row_size_for_width(context.width);
  572. if (row_size.has_overflow())
  573. return false;
  574. if (!streamer.wrap_bytes(scanline_buffer, row_size.value())) {
  575. context.state = PNGLoadingContext::State::Error;
  576. return false;
  577. }
  578. }
  579. context.bitmap = Bitmap::create_purgeable(context.has_alpha() ? BitmapFormat::RGBA32 : BitmapFormat::RGB32, { context.width, context.height });
  580. if (!context.bitmap) {
  581. context.state = PNGLoadingContext::State::Error;
  582. return false;
  583. }
  584. unfilter(context);
  585. return true;
  586. }
  587. static int adam7_height(PNGLoadingContext& context, int pass)
  588. {
  589. switch (pass) {
  590. case 1:
  591. return (context.height + 7) / 8;
  592. case 2:
  593. return (context.height + 7) / 8;
  594. case 3:
  595. return (context.height + 3) / 8;
  596. case 4:
  597. return (context.height + 3) / 4;
  598. case 5:
  599. return (context.height + 1) / 4;
  600. case 6:
  601. return (context.height + 1) / 2;
  602. case 7:
  603. return context.height / 2;
  604. default:
  605. ASSERT_NOT_REACHED();
  606. }
  607. }
  608. static int adam7_width(PNGLoadingContext& context, int pass)
  609. {
  610. switch (pass) {
  611. case 1:
  612. return (context.width + 7) / 8;
  613. case 2:
  614. return (context.width + 3) / 8;
  615. case 3:
  616. return (context.width + 3) / 4;
  617. case 4:
  618. return (context.width + 1) / 4;
  619. case 5:
  620. return (context.width + 1) / 2;
  621. case 6:
  622. return context.width / 2;
  623. case 7:
  624. return context.width;
  625. default:
  626. ASSERT_NOT_REACHED();
  627. }
  628. }
  629. // Index 0 unused (non-interlaced case)
  630. static int adam7_starty[8] = { 0, 0, 0, 4, 0, 2, 0, 1 };
  631. static int adam7_startx[8] = { 0, 0, 4, 0, 2, 0, 1, 0 };
  632. static int adam7_stepy[8] = { 1, 8, 8, 8, 4, 4, 2, 2 };
  633. static int adam7_stepx[8] = { 1, 8, 8, 4, 4, 2, 2, 1 };
  634. static bool decode_adam7_pass(PNGLoadingContext& context, Streamer& streamer, int pass)
  635. {
  636. PNGLoadingContext subimage_context;
  637. subimage_context.width = adam7_width(context, pass);
  638. subimage_context.height = adam7_height(context, pass);
  639. subimage_context.channels = context.channels;
  640. subimage_context.color_type = context.color_type;
  641. subimage_context.palette_data = context.palette_data;
  642. subimage_context.palette_transparency_data = context.palette_transparency_data;
  643. subimage_context.bit_depth = context.bit_depth;
  644. subimage_context.filter_method = context.filter_method;
  645. // For small images, some passes might be empty
  646. if (!subimage_context.width || !subimage_context.height)
  647. return true;
  648. subimage_context.scanlines.clear_with_capacity();
  649. for (int y = 0; y < subimage_context.height; ++y) {
  650. u8 filter;
  651. if (!streamer.read(filter)) {
  652. context.state = PNGLoadingContext::State::Error;
  653. return false;
  654. }
  655. if (filter > 4) {
  656. #ifdef PNG_DEBUG
  657. dbg() << "Invalid PNG filter: " << filter;
  658. #endif
  659. context.state = PNGLoadingContext::State::Error;
  660. return false;
  661. }
  662. subimage_context.scanlines.append({ filter });
  663. auto& scanline_buffer = subimage_context.scanlines.last().data;
  664. auto row_size = context.compute_row_size_for_width(subimage_context.width);
  665. if (row_size.has_overflow())
  666. return false;
  667. if (!streamer.wrap_bytes(scanline_buffer, row_size.value())) {
  668. context.state = PNGLoadingContext::State::Error;
  669. return false;
  670. }
  671. }
  672. subimage_context.bitmap = Bitmap::create(context.bitmap->format(), { subimage_context.width, subimage_context.height });
  673. unfilter(subimage_context);
  674. // Copy the subimage data into the main image according to the pass pattern
  675. for (int y = 0, dy = adam7_starty[pass]; y < subimage_context.height && dy < context.height; ++y, dy += adam7_stepy[pass]) {
  676. for (int x = 0, dx = adam7_startx[pass]; x < subimage_context.width && dy < context.width; ++x, dx += adam7_stepx[pass]) {
  677. context.bitmap->set_pixel(dx, dy, subimage_context.bitmap->get_pixel(x, y));
  678. }
  679. }
  680. return true;
  681. }
  682. static bool decode_png_adam7(PNGLoadingContext& context)
  683. {
  684. Streamer streamer(context.decompression_buffer, context.decompression_buffer_size);
  685. context.bitmap = Bitmap::create_purgeable(context.has_alpha() ? BitmapFormat::RGBA32 : BitmapFormat::RGB32, { context.width, context.height });
  686. if (!context.bitmap)
  687. return false;
  688. for (int pass = 1; pass <= 7; ++pass) {
  689. if (!decode_adam7_pass(context, streamer, pass))
  690. return false;
  691. }
  692. return true;
  693. }
  694. static bool decode_png_bitmap(PNGLoadingContext& context)
  695. {
  696. if (context.state < PNGLoadingContext::State::ChunksDecoded) {
  697. if (!decode_png_chunks(context))
  698. return false;
  699. }
  700. if (context.state >= PNGLoadingContext::State::BitmapDecoded)
  701. return true;
  702. if (context.width == -1 || context.height == -1)
  703. return false; // Didn't see an IHDR chunk.
  704. if (context.color_type == 3 && context.palette_data.size() < (1u << context.bit_depth))
  705. return false; // Didn't see an PLTE chunk for a palettized image, or not enough entries.
  706. unsigned long srclen = context.compressed_data.size() - 6;
  707. unsigned long destlen = 0;
  708. int ret = puff(nullptr, &destlen, context.compressed_data.data() + 2, &srclen);
  709. if (ret != 0) {
  710. context.state = PNGLoadingContext::State::Error;
  711. return false;
  712. }
  713. context.decompression_buffer_size = destlen;
  714. #ifdef __serenity__
  715. context.decompression_buffer = (u8*)mmap_with_name(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "PNG decompression buffer");
  716. #else
  717. context.decompression_buffer = (u8*)mmap(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  718. #endif
  719. ret = puff(context.decompression_buffer, &destlen, context.compressed_data.data() + 2, &srclen);
  720. if (ret != 0) {
  721. context.state = PNGLoadingContext::State::Error;
  722. return false;
  723. }
  724. context.compressed_data.clear();
  725. context.scanlines.ensure_capacity(context.height);
  726. switch (context.interlace_method) {
  727. case PngInterlaceMethod::Null:
  728. if (!decode_png_bitmap_simple(context))
  729. return false;
  730. break;
  731. case PngInterlaceMethod::Adam7:
  732. if (!decode_png_adam7(context))
  733. return false;
  734. break;
  735. default:
  736. ASSERT_NOT_REACHED();
  737. }
  738. munmap(context.decompression_buffer, context.decompression_buffer_size);
  739. context.decompression_buffer = nullptr;
  740. context.decompression_buffer_size = 0;
  741. context.state = PNGLoadingContext::State::BitmapDecoded;
  742. return true;
  743. }
  744. static RefPtr<Gfx::Bitmap> load_png_impl(const u8* data, size_t data_size)
  745. {
  746. PNGLoadingContext context;
  747. context.data = data;
  748. context.data_size = data_size;
  749. if (!decode_png_chunks(context))
  750. return nullptr;
  751. if (!decode_png_bitmap(context))
  752. return nullptr;
  753. return context.bitmap;
  754. }
  755. static bool is_valid_compression_method(u8 compression_method)
  756. {
  757. return compression_method == 0;
  758. }
  759. static bool is_valid_filter_method(u8 filter_method)
  760. {
  761. return filter_method <= 4;
  762. }
  763. static bool process_IHDR(ReadonlyBytes data, PNGLoadingContext& context)
  764. {
  765. if (data.size() < (int)sizeof(PNG_IHDR))
  766. return false;
  767. auto& ihdr = *(const PNG_IHDR*)data.data();
  768. if (ihdr.width > maximum_width_for_decoded_images || ihdr.height > maximum_height_for_decoded_images) {
  769. dbgln("This PNG is too large for comfort: {}x{}", (u32)ihdr.width, (u32)ihdr.height);
  770. return false;
  771. }
  772. if (!is_valid_compression_method(ihdr.compression_method)) {
  773. dbgln("PNG has invalid compression method {}", ihdr.compression_method);
  774. return false;
  775. }
  776. if (!is_valid_filter_method(ihdr.filter_method)) {
  777. dbgln("PNG has invalid filter method {}", ihdr.filter_method);
  778. return false;
  779. }
  780. context.width = ihdr.width;
  781. context.height = ihdr.height;
  782. context.bit_depth = ihdr.bit_depth;
  783. context.color_type = ihdr.color_type;
  784. context.compression_method = ihdr.compression_method;
  785. context.filter_method = ihdr.filter_method;
  786. context.interlace_method = ihdr.interlace_method;
  787. #ifdef PNG_DEBUG
  788. printf("PNG: %dx%d (%d bpp)\n", context.width, context.height, context.bit_depth);
  789. printf(" Color type: %d\n", context.color_type);
  790. printf("Compress Method: %d\n", context.compression_method);
  791. printf(" Filter Method: %d\n", context.filter_method);
  792. printf(" Interlace type: %d\n", context.interlace_method);
  793. #endif
  794. if (context.interlace_method != PngInterlaceMethod::Null && context.interlace_method != PngInterlaceMethod::Adam7) {
  795. #ifdef PNG_DEBUG
  796. dbgprintf("PNGLoader::process_IHDR: unknown interlace method: %d\n", context.interlace_method);
  797. #endif
  798. return false;
  799. }
  800. switch (context.color_type) {
  801. case 0: // Each pixel is a grayscale sample.
  802. if (context.bit_depth != 1 && context.bit_depth != 2 && context.bit_depth != 4 && context.bit_depth != 8 && context.bit_depth != 16)
  803. return false;
  804. context.channels = 1;
  805. break;
  806. case 4: // Each pixel is a grayscale sample, followed by an alpha sample.
  807. if (context.bit_depth != 8 && context.bit_depth != 16)
  808. return false;
  809. context.channels = 2;
  810. break;
  811. case 2: // Each pixel is an RGB sample
  812. if (context.bit_depth != 8 && context.bit_depth != 16)
  813. return false;
  814. context.channels = 3;
  815. break;
  816. case 3: // Each pixel is a palette index; a PLTE chunk must appear.
  817. if (context.bit_depth != 1 && context.bit_depth != 2 && context.bit_depth != 4 && context.bit_depth != 8)
  818. return false;
  819. context.channels = 1;
  820. break;
  821. case 6: // Each pixel is an RGB sample, followed by an alpha sample.
  822. if (context.bit_depth != 8 && context.bit_depth != 16)
  823. return false;
  824. context.channels = 4;
  825. break;
  826. default:
  827. return false;
  828. }
  829. return true;
  830. }
  831. static bool process_IDAT(ReadonlyBytes data, PNGLoadingContext& context)
  832. {
  833. context.compressed_data.append(data.data(), data.size());
  834. return true;
  835. }
  836. static bool process_PLTE(ReadonlyBytes data, PNGLoadingContext& context)
  837. {
  838. context.palette_data.append((const PaletteEntry*)data.data(), data.size() / 3);
  839. return true;
  840. }
  841. static bool process_tRNS(ReadonlyBytes data, PNGLoadingContext& context)
  842. {
  843. switch (context.color_type) {
  844. case 3:
  845. context.palette_transparency_data.append(data.data(), data.size());
  846. break;
  847. }
  848. return true;
  849. }
  850. static bool process_chunk(Streamer& streamer, PNGLoadingContext& context)
  851. {
  852. u32 chunk_size;
  853. if (!streamer.read(chunk_size)) {
  854. #ifdef PNG_DEBUG
  855. printf("Bail at chunk_size\n");
  856. #endif
  857. return false;
  858. }
  859. u8 chunk_type[5];
  860. chunk_type[4] = '\0';
  861. if (!streamer.read_bytes(chunk_type, 4)) {
  862. #ifdef PNG_DEBUG
  863. printf("Bail at chunk_type\n");
  864. #endif
  865. return false;
  866. }
  867. ReadonlyBytes chunk_data;
  868. if (!streamer.wrap_bytes(chunk_data, chunk_size)) {
  869. #ifdef PNG_DEBUG
  870. printf("Bail at chunk_data\n");
  871. #endif
  872. return false;
  873. }
  874. u32 chunk_crc;
  875. if (!streamer.read(chunk_crc)) {
  876. #ifdef PNG_DEBUG
  877. printf("Bail at chunk_crc\n");
  878. #endif
  879. return false;
  880. }
  881. #ifdef PNG_DEBUG
  882. printf("Chunk type: '%s', size: %u, crc: %x\n", chunk_type, chunk_size, chunk_crc);
  883. #endif
  884. if (!strcmp((const char*)chunk_type, "IHDR"))
  885. return process_IHDR(chunk_data, context);
  886. if (!strcmp((const char*)chunk_type, "IDAT"))
  887. return process_IDAT(chunk_data, context);
  888. if (!strcmp((const char*)chunk_type, "PLTE"))
  889. return process_PLTE(chunk_data, context);
  890. if (!strcmp((const char*)chunk_type, "tRNS"))
  891. return process_tRNS(chunk_data, context);
  892. return true;
  893. }
  894. PNGImageDecoderPlugin::PNGImageDecoderPlugin(const u8* data, size_t size)
  895. {
  896. m_context = make<PNGLoadingContext>();
  897. m_context->data = data;
  898. m_context->data_size = size;
  899. }
  900. PNGImageDecoderPlugin::~PNGImageDecoderPlugin()
  901. {
  902. }
  903. IntSize PNGImageDecoderPlugin::size()
  904. {
  905. if (m_context->state == PNGLoadingContext::State::Error)
  906. return {};
  907. if (m_context->state < PNGLoadingContext::State::SizeDecoded) {
  908. bool success = decode_png_size(*m_context);
  909. if (!success)
  910. return {};
  911. }
  912. return { m_context->width, m_context->height };
  913. }
  914. RefPtr<Gfx::Bitmap> PNGImageDecoderPlugin::bitmap()
  915. {
  916. if (m_context->state == PNGLoadingContext::State::Error)
  917. return nullptr;
  918. if (m_context->state < PNGLoadingContext::State::BitmapDecoded) {
  919. // NOTE: This forces the chunk decoding to happen.
  920. bool success = decode_png_bitmap(*m_context);
  921. if (!success)
  922. return nullptr;
  923. }
  924. ASSERT(m_context->bitmap);
  925. return m_context->bitmap;
  926. }
  927. void PNGImageDecoderPlugin::set_volatile()
  928. {
  929. if (m_context->bitmap)
  930. m_context->bitmap->set_volatile();
  931. }
  932. bool PNGImageDecoderPlugin::set_nonvolatile()
  933. {
  934. if (!m_context->bitmap)
  935. return false;
  936. return m_context->bitmap->set_nonvolatile();
  937. }
  938. bool PNGImageDecoderPlugin::sniff()
  939. {
  940. return decode_png_header(*m_context);
  941. }
  942. bool PNGImageDecoderPlugin::is_animated()
  943. {
  944. return false;
  945. }
  946. size_t PNGImageDecoderPlugin::loop_count()
  947. {
  948. return 0;
  949. }
  950. size_t PNGImageDecoderPlugin::frame_count()
  951. {
  952. return 1;
  953. }
  954. ImageFrameDescriptor PNGImageDecoderPlugin::frame(size_t i)
  955. {
  956. if (i > 0) {
  957. return { bitmap(), 0 };
  958. }
  959. return {};
  960. }
  961. }