png_codec.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/codec/png_codec.h"
  5. #include <stdint.h>
  6. #include "base/logging.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/notreached.h"
  9. #include "base/strings/string_util.h"
  10. #include "third_party/libpng/png.h"
  11. #include "third_party/skia/include/core/SkBitmap.h"
  12. #include "third_party/skia/include/core/SkColorPriv.h"
  13. #include "third_party/skia/include/core/SkUnPreMultiply.h"
  14. #include "third_party/skia/include/encode/SkPngEncoder.h"
  15. #include "third_party/zlib/zlib.h"
  16. #include "ui/gfx/codec/vector_wstream.h"
  17. #include "ui/gfx/geometry/size.h"
  18. namespace gfx {
  19. // Decoder --------------------------------------------------------------------
  20. //
  21. // This code is based on WebKit libpng interface (PNGImageDecoder), which is
  22. // in turn based on the Mozilla png decoder.
  23. namespace {
  24. // Gamma constants: We assume we're on Windows which uses a gamma of 2.2.
  25. const double kMaxGamma = 21474.83; // Maximum gamma accepted by png library.
  26. const double kDefaultGamma = 2.2;
  27. const double kInverseGamma = 1.0 / kDefaultGamma;
  28. class PngDecoderState {
  29. public:
  30. // Output is a vector<unsigned char>.
  31. PngDecoderState(PNGCodec::ColorFormat ofmt, std::vector<unsigned char>* o)
  32. : output_format(ofmt),
  33. output_channels(0),
  34. bitmap(nullptr),
  35. is_opaque(true),
  36. output(o),
  37. width(0),
  38. height(0),
  39. done(false) {}
  40. // Output is an SkBitmap.
  41. explicit PngDecoderState(SkBitmap* skbitmap)
  42. : output_format(PNGCodec::FORMAT_SkBitmap),
  43. output_channels(0),
  44. bitmap(skbitmap),
  45. is_opaque(true),
  46. output(nullptr),
  47. width(0),
  48. height(0),
  49. done(false) {}
  50. PngDecoderState(const PngDecoderState&) = delete;
  51. PngDecoderState& operator=(const PngDecoderState&) = delete;
  52. PNGCodec::ColorFormat output_format;
  53. int output_channels;
  54. // An incoming SkBitmap to write to. If NULL, we write to output instead.
  55. raw_ptr<SkBitmap> bitmap;
  56. // Used during the reading of an SkBitmap. Defaults to true until we see a
  57. // pixel with anything other than an alpha of 255.
  58. bool is_opaque;
  59. // The other way to decode output, where we write into an intermediary buffer
  60. // instead of directly to an SkBitmap.
  61. raw_ptr<std::vector<unsigned char>> output;
  62. // Size of the image, set in the info callback.
  63. int width;
  64. int height;
  65. // Set to true when we've found the end of the data.
  66. bool done;
  67. };
  68. // User transform (passed to libpng) which converts a row decoded by libpng to
  69. // Skia format. Expects the row to have 4 channels, otherwise there won't be
  70. // enough room in |data|.
  71. void ConvertRGBARowToSkia(png_structp png_ptr,
  72. png_row_infop row_info,
  73. png_bytep data) {
  74. const int channels = row_info->channels;
  75. DCHECK_EQ(channels, 4);
  76. PngDecoderState* state =
  77. static_cast<PngDecoderState*>(png_get_user_transform_ptr(png_ptr));
  78. DCHECK(state) << "LibPNG user transform pointer is NULL";
  79. unsigned char* const end = data + row_info->rowbytes;
  80. for (unsigned char* p = data; p < end; p += channels) {
  81. uint32_t* sk_pixel = reinterpret_cast<uint32_t*>(p);
  82. const unsigned char alpha = p[channels - 1];
  83. if (alpha != 255) {
  84. state->is_opaque = false;
  85. *sk_pixel = SkPreMultiplyARGB(alpha, p[0], p[1], p[2]);
  86. } else {
  87. *sk_pixel = SkPackARGB32(alpha, p[0], p[1], p[2]);
  88. }
  89. }
  90. }
  91. // Called when the png header has been read. This code is based on the WebKit
  92. // PNGImageDecoder
  93. void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
  94. PngDecoderState* state = static_cast<PngDecoderState*>(
  95. png_get_progressive_ptr(png_ptr));
  96. int bit_depth, color_type, interlace_type, compression_type;
  97. int filter_type;
  98. png_uint_32 w, h;
  99. png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
  100. &interlace_type, &compression_type, &filter_type);
  101. // Bounds check. When the image is unreasonably big, we'll error out and
  102. // end up back at the setjmp call when we set up decoding. "Unreasonably big"
  103. // means "big enough that w * h * 32bpp might overflow an int"; we choose this
  104. // threshold to match WebKit and because a number of places in code assume
  105. // that an image's size (in bytes) fits in a (signed) int.
  106. unsigned long long total_size =
  107. static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h);
  108. if (total_size > ((1 << 29) - 1))
  109. longjmp(png_jmpbuf(png_ptr), 1);
  110. state->width = static_cast<int>(w);
  111. state->height = static_cast<int>(h);
  112. // The following png_set_* calls have to be done in the order dictated by
  113. // the libpng docs. Please take care if you have to move any of them. This
  114. // is also why certain things are done outside of the switch, even though
  115. // they look like they belong there.
  116. // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
  117. if (color_type == PNG_COLOR_TYPE_PALETTE ||
  118. (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8))
  119. png_set_expand(png_ptr);
  120. // The '!= 0' is for silencing a Windows compiler warning.
  121. bool input_has_alpha = ((color_type & PNG_COLOR_MASK_ALPHA) != 0);
  122. // Transparency for paletted images.
  123. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
  124. png_set_expand(png_ptr);
  125. input_has_alpha = true;
  126. }
  127. // Convert 16-bit to 8-bit.
  128. if (bit_depth == 16)
  129. png_set_strip_16(png_ptr);
  130. // Pick our row format converter necessary for this data.
  131. if (!input_has_alpha) {
  132. switch (state->output_format) {
  133. case PNGCodec::FORMAT_RGBA:
  134. state->output_channels = 4;
  135. png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
  136. break;
  137. case PNGCodec::FORMAT_BGRA:
  138. state->output_channels = 4;
  139. png_set_bgr(png_ptr);
  140. png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
  141. break;
  142. case PNGCodec::FORMAT_SkBitmap:
  143. state->output_channels = 4;
  144. png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
  145. break;
  146. }
  147. } else {
  148. switch (state->output_format) {
  149. case PNGCodec::FORMAT_RGBA:
  150. state->output_channels = 4;
  151. break;
  152. case PNGCodec::FORMAT_BGRA:
  153. state->output_channels = 4;
  154. png_set_bgr(png_ptr);
  155. break;
  156. case PNGCodec::FORMAT_SkBitmap:
  157. state->output_channels = 4;
  158. break;
  159. }
  160. }
  161. // Expand grayscale to RGB.
  162. if (color_type == PNG_COLOR_TYPE_GRAY ||
  163. color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  164. png_set_gray_to_rgb(png_ptr);
  165. // Deal with gamma and keep it under our control.
  166. double gamma;
  167. if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
  168. if (gamma <= 0.0 || gamma > kMaxGamma) {
  169. gamma = kInverseGamma;
  170. png_set_gAMA(png_ptr, info_ptr, gamma);
  171. }
  172. png_set_gamma(png_ptr, kDefaultGamma, gamma);
  173. } else {
  174. png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma);
  175. }
  176. // Setting the user transforms here (as opposed to inside the switch above)
  177. // because all png_set_* calls need to be done in the specific order
  178. // mandated by libpng.
  179. if (state->output_format == PNGCodec::FORMAT_SkBitmap) {
  180. png_set_read_user_transform_fn(png_ptr, ConvertRGBARowToSkia);
  181. png_set_user_transform_info(png_ptr, state, 0, 0);
  182. }
  183. // Tell libpng to send us rows for interlaced pngs.
  184. if (interlace_type == PNG_INTERLACE_ADAM7)
  185. png_set_interlace_handling(png_ptr);
  186. png_read_update_info(png_ptr, info_ptr);
  187. if (state->bitmap) {
  188. if (!state->bitmap->tryAllocN32Pixels(state->width, state->height)) {
  189. png_error(png_ptr, "Could not allocate bitmap.");
  190. NOTREACHED() << "png_error should not return.";
  191. return;
  192. }
  193. } else if (state->output) {
  194. state->output->resize(
  195. state->width * state->output_channels * state->height);
  196. }
  197. }
  198. void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row,
  199. png_uint_32 row_num, int pass) {
  200. if (!new_row)
  201. return; // Interlaced image; row didn't change this pass.
  202. PngDecoderState* state = static_cast<PngDecoderState*>(
  203. png_get_progressive_ptr(png_ptr));
  204. if (static_cast<int>(row_num) > state->height) {
  205. NOTREACHED() << "Invalid row";
  206. return;
  207. }
  208. unsigned char* base = NULL;
  209. if (state->bitmap)
  210. base = reinterpret_cast<unsigned char*>(state->bitmap->getAddr32(0, 0));
  211. else if (state->output)
  212. base = &state->output->front();
  213. unsigned char* dest = &base[state->width * state->output_channels * row_num];
  214. png_progressive_combine_row(png_ptr, dest, new_row);
  215. }
  216. void DecodeEndCallback(png_struct* png_ptr, png_info* info) {
  217. PngDecoderState* state = static_cast<PngDecoderState*>(
  218. png_get_progressive_ptr(png_ptr));
  219. // Mark the image as complete, this will tell the Decode function that we
  220. // have successfully found the end of the data.
  221. state->done = true;
  222. }
  223. // Holds png struct and info ensuring the proper destruction.
  224. class PngReadStructInfo {
  225. public:
  226. PngReadStructInfo(): png_ptr_(nullptr), info_ptr_(nullptr) {
  227. }
  228. PngReadStructInfo(const PngReadStructInfo&) = delete;
  229. PngReadStructInfo& operator=(const PngReadStructInfo&) = delete;
  230. ~PngReadStructInfo() {
  231. png_destroy_read_struct(&png_ptr_, &info_ptr_, NULL);
  232. }
  233. bool Build(const unsigned char* input, size_t input_size) {
  234. if (input_size < 8)
  235. return false; // Input data too small to be a png
  236. // Have libpng check the signature, it likes the first 8 bytes.
  237. if (png_sig_cmp(const_cast<unsigned char*>(input), 0, 8) != 0)
  238. return false;
  239. png_ptr_ = png_create_read_struct(
  240. PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  241. if (!png_ptr_)
  242. return false;
  243. info_ptr_ = png_create_info_struct(png_ptr_);
  244. if (!info_ptr_) {
  245. return false;
  246. }
  247. return true;
  248. }
  249. png_struct* png_ptr_;
  250. png_info* info_ptr_;
  251. };
  252. // Holds png struct and info ensuring the proper destruction.
  253. class PngWriteStructInfo {
  254. public:
  255. PngWriteStructInfo() : png_ptr_(nullptr), info_ptr_(nullptr) {
  256. }
  257. PngWriteStructInfo(const PngWriteStructInfo&) = delete;
  258. PngWriteStructInfo& operator=(const PngWriteStructInfo&) = delete;
  259. ~PngWriteStructInfo() {
  260. png_destroy_write_struct(&png_ptr_, &info_ptr_);
  261. }
  262. png_struct* png_ptr_;
  263. png_info* info_ptr_;
  264. };
  265. // Libpng user error and warning functions which allows us to print libpng
  266. // errors and warnings using Chrome's logging facilities instead of stderr.
  267. void LogLibPNGDecodeError(png_structp png_ptr, png_const_charp error_msg) {
  268. DLOG(ERROR) << "libpng decode error: " << error_msg;
  269. longjmp(png_jmpbuf(png_ptr), 1);
  270. }
  271. void LogLibPNGDecodeWarning(png_structp png_ptr, png_const_charp warning_msg) {
  272. DLOG(ERROR) << "libpng decode warning: " << warning_msg;
  273. }
  274. } // namespace
  275. // static
  276. bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
  277. ColorFormat format, std::vector<unsigned char>* output,
  278. int* w, int* h) {
  279. PngReadStructInfo si;
  280. if (!si.Build(input, input_size))
  281. return false;
  282. if (setjmp(png_jmpbuf(si.png_ptr_))) {
  283. // The destroyer will ensure that the structures are cleaned up in this
  284. // case, even though we may get here as a jump from random parts of the
  285. // PNG library called below.
  286. return false;
  287. }
  288. PngDecoderState state(format, output);
  289. png_set_error_fn(si.png_ptr_, NULL,
  290. LogLibPNGDecodeError, LogLibPNGDecodeWarning);
  291. png_set_progressive_read_fn(si.png_ptr_, &state, &DecodeInfoCallback,
  292. &DecodeRowCallback, &DecodeEndCallback);
  293. png_process_data(si.png_ptr_,
  294. si.info_ptr_,
  295. const_cast<unsigned char*>(input),
  296. input_size);
  297. if (!state.done) {
  298. // Fed it all the data but the library didn't think we got all the data, so
  299. // this file must be truncated.
  300. output->clear();
  301. return false;
  302. }
  303. *w = state.width;
  304. *h = state.height;
  305. return true;
  306. }
  307. // static
  308. bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
  309. SkBitmap* bitmap) {
  310. DCHECK(bitmap);
  311. PngReadStructInfo si;
  312. if (!si.Build(input, input_size))
  313. return false;
  314. if (setjmp(png_jmpbuf(si.png_ptr_))) {
  315. // The destroyer will ensure that the structures are cleaned up in this
  316. // case, even though we may get here as a jump from random parts of the
  317. // PNG library called below.
  318. return false;
  319. }
  320. PngDecoderState state(bitmap);
  321. png_set_progressive_read_fn(si.png_ptr_, &state, &DecodeInfoCallback,
  322. &DecodeRowCallback, &DecodeEndCallback);
  323. png_process_data(si.png_ptr_,
  324. si.info_ptr_,
  325. const_cast<unsigned char*>(input),
  326. input_size);
  327. if (!state.done) {
  328. return false;
  329. }
  330. // Set the bitmap's opaqueness based on what we saw.
  331. bitmap->setAlphaType(state.is_opaque ?
  332. kOpaque_SkAlphaType : kPremul_SkAlphaType);
  333. return true;
  334. }
  335. // Encoder --------------------------------------------------------------------
  336. namespace {
  337. static void AddComments(SkPngEncoder::Options& options,
  338. const std::vector<PNGCodec::Comment>& comments) {
  339. std::vector<const char*> comment_pointers;
  340. std::vector<size_t> comment_sizes;
  341. for (const auto& comment : comments) {
  342. comment_pointers.push_back(comment.key.c_str());
  343. comment_pointers.push_back(comment.text.c_str());
  344. comment_sizes.push_back(comment.key.length() + 1);
  345. comment_sizes.push_back(comment.text.length() + 1);
  346. }
  347. options.fComments = SkDataTable::MakeCopyArrays(
  348. (void const* const*)comment_pointers.data(), comment_sizes.data(),
  349. static_cast<int>(comment_pointers.size()));
  350. }
  351. } // namespace
  352. static bool EncodeSkPixmap(const SkPixmap& src,
  353. const std::vector<PNGCodec::Comment>& comments,
  354. std::vector<unsigned char>* output,
  355. int zlib_level) {
  356. output->clear();
  357. VectorWStream dst(output);
  358. SkPngEncoder::Options options;
  359. AddComments(options, comments);
  360. options.fZLibLevel = zlib_level;
  361. return SkPngEncoder::Encode(&dst, src, options);
  362. }
  363. static bool EncodeSkPixmap(const SkPixmap& src,
  364. bool discard_transparency,
  365. const std::vector<PNGCodec::Comment>& comments,
  366. std::vector<unsigned char>* output,
  367. int zlib_level) {
  368. if (discard_transparency) {
  369. SkImageInfo opaque_info = src.info().makeAlphaType(kOpaque_SkAlphaType);
  370. SkBitmap copy;
  371. if (!copy.tryAllocPixels(opaque_info)) {
  372. return false;
  373. }
  374. SkPixmap opaque_pixmap;
  375. bool success = copy.peekPixels(&opaque_pixmap);
  376. DCHECK(success);
  377. // The following step does the unpremul as we set the dst alpha type to be
  378. // kUnpremul_SkAlphaType. Later, because opaque_pixmap has
  379. // kOpaque_SkAlphaType, we'll discard the transparency as required.
  380. success =
  381. src.readPixels(opaque_info.makeAlphaType(kUnpremul_SkAlphaType),
  382. opaque_pixmap.writable_addr(), opaque_pixmap.rowBytes());
  383. DCHECK(success);
  384. return EncodeSkPixmap(opaque_pixmap, comments, output, zlib_level);
  385. }
  386. return EncodeSkPixmap(src, comments, output, zlib_level);
  387. }
  388. // static
  389. bool PNGCodec::Encode(const unsigned char* input,
  390. ColorFormat format,
  391. const Size& size,
  392. int row_byte_width,
  393. bool discard_transparency,
  394. const std::vector<Comment>& comments,
  395. std::vector<unsigned char>* output) {
  396. // Initialization required for Windows although the switch covers all cases.
  397. SkColorType colorType = kN32_SkColorType;
  398. switch (format) {
  399. case FORMAT_RGBA:
  400. colorType = kRGBA_8888_SkColorType;
  401. break;
  402. case FORMAT_BGRA:
  403. colorType = kBGRA_8888_SkColorType;
  404. break;
  405. case FORMAT_SkBitmap:
  406. colorType = kN32_SkColorType;
  407. break;
  408. }
  409. auto alphaType =
  410. format == FORMAT_SkBitmap ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
  411. SkImageInfo info =
  412. SkImageInfo::Make(size.width(), size.height(), colorType, alphaType);
  413. SkPixmap src(info, input, row_byte_width);
  414. return EncodeSkPixmap(src, discard_transparency, comments, output,
  415. DEFAULT_ZLIB_COMPRESSION);
  416. }
  417. static bool EncodeSkBitmap(const SkBitmap& input,
  418. bool discard_transparency,
  419. std::vector<unsigned char>* output,
  420. int zlib_level) {
  421. SkPixmap src;
  422. if (!input.peekPixels(&src)) {
  423. return false;
  424. }
  425. return EncodeSkPixmap(src, discard_transparency,
  426. std::vector<PNGCodec::Comment>(), output, zlib_level);
  427. }
  428. // static
  429. bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input,
  430. bool discard_transparency,
  431. std::vector<unsigned char>* output) {
  432. return EncodeSkBitmap(input, discard_transparency, output,
  433. DEFAULT_ZLIB_COMPRESSION);
  434. }
  435. // static
  436. bool PNGCodec::EncodeA8SkBitmap(const SkBitmap& input,
  437. std::vector<unsigned char>* output) {
  438. DCHECK_EQ(input.colorType(), kAlpha_8_SkColorType);
  439. auto info = input.info()
  440. .makeColorType(kGray_8_SkColorType)
  441. .makeAlphaType(kOpaque_SkAlphaType);
  442. SkPixmap src(info, input.getAddr(0, 0), input.rowBytes());
  443. return EncodeSkPixmap(src, std::vector<PNGCodec::Comment>(), output,
  444. DEFAULT_ZLIB_COMPRESSION);
  445. }
  446. // static
  447. bool PNGCodec::FastEncodeBGRASkBitmap(const SkBitmap& input,
  448. bool discard_transparency,
  449. std::vector<unsigned char>* output) {
  450. return EncodeSkBitmap(input, discard_transparency, output, Z_BEST_SPEED);
  451. }
  452. PNGCodec::Comment::Comment(const std::string& k, const std::string& t)
  453. : key(k), text(t) {
  454. }
  455. PNGCodec::Comment::~Comment() {
  456. }
  457. } // namespace gfx