/src/compiler/android/jni/ftk/SkImageDecoder_libpng.cpp

http://ftk.googlecode.com/ · C++ · 1165 lines · 856 code · 158 blank · 151 comment · 199 complexity · 725d551e74dbf0798983a29f13a8a630 MD5 · raw file

  1. /* libs/graphics/images/SkImageDecoder_libpng.cpp
  2. **
  3. ** Copyright 2006, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. #include "SkImageDecoder.h"
  18. #include "SkImageEncoder.h"
  19. #include "SkColor.h"
  20. #include "SkColorPriv.h"
  21. #include "SkDither.h"
  22. #include "SkMath.h"
  23. #include "SkScaledBitmapSampler.h"
  24. #include "SkStream.h"
  25. #include "SkTemplates.h"
  26. #include "SkUtils.h"
  27. extern "C" {
  28. #include "png.h"
  29. }
  30. class SkPNGImageIndex {
  31. public:
  32. SkPNGImageIndex() {
  33. inputStream = NULL;
  34. png_ptr = NULL;
  35. }
  36. virtual ~SkPNGImageIndex() {
  37. if (png_ptr) {
  38. png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
  39. }
  40. if (inputStream) {
  41. delete inputStream;
  42. }
  43. }
  44. png_structp png_ptr;
  45. png_infop info_ptr;
  46. SkStream *inputStream;
  47. };
  48. class SkPNGImageDecoderMy : public SkImageDecoder {
  49. public:
  50. SkPNGImageDecoderMy() {
  51. index = NULL;
  52. }
  53. virtual Format getFormat() const {
  54. return kPNG_Format;
  55. }
  56. virtual ~SkPNGImageDecoderMy() {
  57. if (index) {
  58. delete index;
  59. }
  60. }
  61. virtual bool buildTileIndex(SkStream *stream,
  62. int *width, int *height, bool isShareable);
  63. protected:
  64. // virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
  65. virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
  66. private:
  67. bool onDecodeInit(SkStream* stream, png_structp *png_ptrp,
  68. png_infop *info_ptrp);
  69. bool decodePalette(png_structp png_ptr, png_infop info_ptr,
  70. bool *hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep);
  71. bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
  72. SkBitmap::Config *config, bool *hasAlpha, bool *doDither,
  73. SkPMColor *theTranspColor);
  74. SkPNGImageIndex *index;
  75. };
  76. #ifndef png_jmpbuf
  77. # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
  78. #endif
  79. #define PNG_BYTES_TO_CHECK 4
  80. /* Automatically clean up after throwing an exception */
  81. struct PNGAutoClean {
  82. PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
  83. ~PNGAutoClean() {
  84. png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
  85. }
  86. private:
  87. png_structp png_ptr;
  88. png_infop info_ptr;
  89. };
  90. static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
  91. SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
  92. size_t bytes = sk_stream->read(data, length);
  93. if (bytes != length) {
  94. png_error(png_ptr, "Read Error!");
  95. }
  96. }
  97. static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
  98. SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
  99. sk_stream->rewind();
  100. (void)sk_stream->skip(offset);
  101. }
  102. static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
  103. SkImageDecoder::Peeker* peeker =
  104. (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
  105. // peek() returning true means continue decoding
  106. return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
  107. 1 : -1;
  108. }
  109. static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
  110. #if 0
  111. SkDebugf("------ png error %s\n", msg);
  112. #endif
  113. longjmp(png_jmpbuf(png_ptr), 1);
  114. }
  115. static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) {
  116. for (int i = 0; i < count; i++) {
  117. uint8_t* tmp = storage;
  118. png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
  119. }
  120. }
  121. static bool pos_le(int value, int max) {
  122. return value > 0 && value <= max;
  123. }
  124. static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
  125. SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config);
  126. bool reallyHasAlpha = false;
  127. for (int y = bm->height() - 1; y >= 0; --y) {
  128. SkPMColor* p = bm->getAddr32(0, y);
  129. for (int x = bm->width() - 1; x >= 0; --x) {
  130. if (match == *p) {
  131. *p = 0;
  132. reallyHasAlpha = true;
  133. }
  134. p += 1;
  135. }
  136. }
  137. return reallyHasAlpha;
  138. }
  139. static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig,
  140. bool srcHasAlpha) {
  141. switch (dstConfig) {
  142. case SkBitmap::kARGB_8888_Config:
  143. case SkBitmap::kARGB_4444_Config:
  144. return true;
  145. case SkBitmap::kRGB_565_Config:
  146. // only return true if the src is opaque (since 565 is opaque)
  147. return !srcHasAlpha;
  148. default:
  149. return false;
  150. }
  151. }
  152. // call only if color_type is PALETTE. Returns true if the ctable has alpha
  153. static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
  154. png_bytep trans;
  155. int num_trans;
  156. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
  157. png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
  158. return num_trans > 0;
  159. }
  160. return false;
  161. }
  162. bool SkPNGImageDecoderMy::onDecodeInit(SkStream* sk_stream,
  163. png_structp *png_ptrp, png_infop *info_ptrp)
  164. {
  165. /* Create and initialize the png_struct with the desired error handler
  166. * functions. If you want to use the default stderr and longjump method,
  167. * you can supply NULL for the last three parameters. We also supply the
  168. * the compiler header file version, so that we know if the application
  169. * was compiled with a compatible version of the library. */
  170. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
  171. NULL, sk_error_fn, NULL);
  172. // png_voidp user_error_ptr, user_error_fn, user_warning_fn);
  173. if (png_ptr == NULL) {
  174. return false;
  175. }
  176. *png_ptrp = png_ptr;
  177. /* Allocate/initialize the memory for image information. */
  178. png_infop info_ptr = png_create_info_struct(png_ptr);
  179. if (info_ptr == NULL) {
  180. png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
  181. return false;
  182. }
  183. *info_ptrp = info_ptr;
  184. /* Set error handling if you are using the setjmp/longjmp method (this is
  185. * the normal method of doing things with libpng). REQUIRED unless you
  186. * set up your own error handlers in the png_create_read_struct() earlier.
  187. */
  188. if (setjmp(png_jmpbuf(png_ptr))) {
  189. return false;
  190. }
  191. /* If you are using replacement read functions, instead of calling
  192. * png_init_io() here you would call:
  193. */
  194. png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
  195. png_set_seek_fn(png_ptr, sk_seek_fn);
  196. /* where user_io_ptr is a structure you want available to the callbacks */
  197. /* If we have already read some of the signature */
  198. // png_set_sig_bytes(png_ptr, 0 /* sig_read */ );
  199. // hookup our peeker so we can see any user-chunks the caller may be interested in
  200. png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
  201. if (this->getPeeker()) {
  202. png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk);
  203. }
  204. /* The call to png_read_info() gives us all of the information from the
  205. * PNG file before the first IDAT (image data chunk). */
  206. png_read_info(png_ptr, info_ptr);
  207. png_uint_32 origWidth, origHeight;
  208. int bit_depth, color_type, interlace_type;
  209. png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
  210. &color_type, &interlace_type, int_p_NULL, int_p_NULL);
  211. /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  212. if (bit_depth == 16) {
  213. png_set_strip_16(png_ptr);
  214. }
  215. /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
  216. * byte into separate bytes (useful for paletted and grayscale images). */
  217. if (bit_depth < 8) {
  218. png_set_packing(png_ptr);
  219. }
  220. /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  221. if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
  222. png_set_gray_1_2_4_to_8(png_ptr);
  223. }
  224. /* Make a grayscale image into RGB. */
  225. if (color_type == PNG_COLOR_TYPE_GRAY ||
  226. color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
  227. png_set_gray_to_rgb(png_ptr);
  228. }
  229. return true;
  230. }
  231. bool SkPNGImageDecoderMy::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
  232. Mode mode) {
  233. png_structp png_ptr;
  234. png_infop info_ptr;
  235. if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
  236. return false;
  237. }
  238. if (setjmp(png_jmpbuf(png_ptr))) {
  239. return false;
  240. }
  241. PNGAutoClean autoClean(png_ptr, info_ptr);
  242. png_uint_32 origWidth, origHeight;
  243. int bit_depth, color_type, interlace_type;
  244. png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
  245. &color_type, &interlace_type, int_p_NULL, int_p_NULL);
  246. SkBitmap::Config config;
  247. bool hasAlpha = false;
  248. bool doDither = this->getDitherImage();
  249. SkPMColor theTranspColor = 0; // 0 tells us not to try to match
  250. if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha,
  251. &doDither, &theTranspColor) == false) {
  252. return false;
  253. }
  254. const int sampleSize = this->getSampleSize();
  255. SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
  256. decodedBitmap->setConfig(config, sampler.scaledWidth(),
  257. sampler.scaledHeight(), 0);
  258. if (SkImageDecoder::kDecodeBounds_Mode == mode) {
  259. return true;
  260. }
  261. // from here down we are concerned with colortables and pixels
  262. // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
  263. // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
  264. // draw lots faster if we can flag the bitmap has being opaque
  265. bool reallyHasAlpha = false;
  266. SkColorTable* colorTable = NULL;
  267. if (color_type == PNG_COLOR_TYPE_PALETTE) {
  268. decodePalette(png_ptr, info_ptr, &hasAlpha,
  269. &reallyHasAlpha, &colorTable);
  270. }
  271. SkAutoUnref aur(colorTable);
  272. if (!this->allocPixelRef(decodedBitmap,
  273. SkBitmap::kIndex8_Config == config ?
  274. colorTable : NULL)) {
  275. return false;
  276. }
  277. SkAutoLockPixels alp(*decodedBitmap);
  278. /* Add filler (or alpha) byte (before/after each RGB triplet) */
  279. if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
  280. png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  281. }
  282. /* Turn on interlace handling. REQUIRED if you are not using
  283. * png_read_image(). To see how to handle interlacing passes,
  284. * see the png_read_row() method below:
  285. */
  286. const int number_passes = interlace_type != PNG_INTERLACE_NONE ?
  287. png_set_interlace_handling(png_ptr) : 1;
  288. /* Optional call to gamma correct and add the background to the palette
  289. * and update info structure. REQUIRED if you are expecting libpng to
  290. * update the palette for you (ie you selected such a transform above).
  291. */
  292. png_read_update_info(png_ptr, info_ptr);
  293. if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
  294. for (int i = 0; i < number_passes; i++) {
  295. for (png_uint_32 y = 0; y < origHeight; y++) {
  296. uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
  297. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  298. }
  299. }
  300. } else {
  301. SkScaledBitmapSampler::SrcConfig sc;
  302. int srcBytesPerPixel = 4;
  303. if (colorTable != NULL) {
  304. sc = SkScaledBitmapSampler::kIndex;
  305. srcBytesPerPixel = 1;
  306. } else if (hasAlpha) {
  307. sc = SkScaledBitmapSampler::kRGBA;
  308. } else {
  309. sc = SkScaledBitmapSampler::kRGBX;
  310. }
  311. /* We have to pass the colortable explicitly, since we may have one
  312. even if our decodedBitmap doesn't, due to the request that we
  313. upscale png's palette to a direct model
  314. */
  315. SkAutoLockColors ctLock(colorTable);
  316. if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
  317. return false;
  318. }
  319. const int height = decodedBitmap->height();
  320. if (number_passes > 1) {
  321. SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
  322. uint8_t* base = (uint8_t*)storage.get();
  323. size_t rb = origWidth * srcBytesPerPixel;
  324. for (int i = 0; i < number_passes; i++) {
  325. uint8_t* row = base;
  326. for (png_uint_32 y = 0; y < origHeight; y++) {
  327. uint8_t* bmRow = row;
  328. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  329. row += rb;
  330. }
  331. }
  332. // now sample it
  333. base += sampler.srcY0() * rb;
  334. for (int y = 0; y < height; y++) {
  335. reallyHasAlpha |= sampler.next(base);
  336. base += sampler.srcDY() * rb;
  337. }
  338. } else {
  339. SkAutoMalloc storage(origWidth * srcBytesPerPixel);
  340. uint8_t* srcRow = (uint8_t*)storage.get();
  341. skip_src_rows(png_ptr, srcRow, sampler.srcY0());
  342. for (int y = 0; y < height; y++) {
  343. uint8_t* tmp = srcRow;
  344. png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
  345. reallyHasAlpha |= sampler.next(srcRow);
  346. if (y < height - 1) {
  347. skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
  348. }
  349. }
  350. // skip the rest of the rows (if any)
  351. png_uint_32 read = (height - 1) * sampler.srcDY() +
  352. sampler.srcY0() + 1;
  353. SkASSERT(read <= origHeight);
  354. skip_src_rows(png_ptr, srcRow, origHeight - read);
  355. }
  356. }
  357. /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
  358. png_read_end(png_ptr, info_ptr);
  359. if (0 != theTranspColor) {
  360. reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
  361. }
  362. decodedBitmap->setIsOpaque(!reallyHasAlpha);
  363. return true;
  364. }
  365. bool SkPNGImageDecoderMy::buildTileIndex(SkStream* sk_stream,
  366. int *width, int *height, bool isShareable) {
  367. png_structp png_ptr;
  368. png_infop info_ptr;
  369. this->index = new SkPNGImageIndex();
  370. if (!isShareable) {
  371. size_t len, inputLen = 0;
  372. size_t bufferSize = 4096;
  373. void *tmp = sk_malloc_throw(bufferSize);
  374. while ((len = sk_stream->read((char*) tmp + inputLen,
  375. bufferSize - inputLen)) != 0) {
  376. inputLen += len;
  377. if (inputLen == bufferSize) {
  378. bufferSize *= 2;
  379. tmp = sk_realloc_throw(tmp, bufferSize);
  380. }
  381. }
  382. tmp = sk_realloc_throw(tmp, inputLen);
  383. SkMemoryStream *mem_stream = new SkMemoryStream(tmp, inputLen, true);
  384. this->index->inputStream = mem_stream;
  385. sk_stream = mem_stream;
  386. }
  387. if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
  388. return false;
  389. }
  390. int bit_depth, color_type, interlace_type;
  391. png_uint_32 origWidth, origHeight;
  392. png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
  393. &color_type, &interlace_type, int_p_NULL, int_p_NULL);
  394. *width = origWidth;
  395. *height = origHeight;
  396. png_build_index(png_ptr);
  397. this->index->png_ptr = png_ptr;
  398. this->index->info_ptr = info_ptr;
  399. return true;
  400. }
  401. bool SkPNGImageDecoderMy::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
  402. SkBitmap::Config *configp, bool *hasAlphap, bool *doDitherp,
  403. SkPMColor *theTranspColorp) {
  404. png_uint_32 origWidth, origHeight;
  405. int bit_depth, color_type, interlace_type;
  406. png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
  407. &color_type, &interlace_type, int_p_NULL, int_p_NULL);
  408. // check for sBIT chunk data, in case we should disable dithering because
  409. // our data is not truely 8bits per component
  410. if (*doDitherp) {
  411. #if 0
  412. SkDebugf("----- sBIT %d %d %d %d\n", info_ptr->sig_bit.red,
  413. info_ptr->sig_bit.green, info_ptr->sig_bit.blue,
  414. info_ptr->sig_bit.alpha);
  415. #endif
  416. // 0 seems to indicate no information available
  417. if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) &&
  418. pos_le(info_ptr->sig_bit.green, SK_G16_BITS) &&
  419. pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) {
  420. *doDitherp = false;
  421. }
  422. }
  423. if (color_type == PNG_COLOR_TYPE_PALETTE) {
  424. bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
  425. *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
  426. // now see if we can upscale to their requested config
  427. if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) {
  428. *configp = SkBitmap::kIndex8_Config;
  429. }
  430. } else {
  431. png_color_16p transpColor = NULL;
  432. int numTransp = 0;
  433. png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
  434. bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
  435. if (valid && numTransp == 1 && transpColor != NULL) {
  436. /* Compute our transparent color, which we'll match against later.
  437. We don't really handle 16bit components properly here, since we
  438. do our compare *after* the values have been knocked down to 8bit
  439. which means we will find more matches than we should. The real
  440. fix seems to be to see the actual 16bit components, do the
  441. compare, and then knock it down to 8bits ourselves.
  442. */
  443. if (color_type & PNG_COLOR_MASK_COLOR) {
  444. if (16 == bit_depth) {
  445. *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
  446. transpColor->green >> 8, transpColor->blue >> 8);
  447. } else {
  448. *theTranspColorp = SkPackARGB32(0xFF, transpColor->red,
  449. transpColor->green, transpColor->blue);
  450. }
  451. } else { // gray
  452. if (16 == bit_depth) {
  453. *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8,
  454. transpColor->gray >> 8, transpColor->gray >> 8);
  455. } else {
  456. *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray,
  457. transpColor->gray, transpColor->gray);
  458. }
  459. }
  460. }
  461. if (valid ||
  462. PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
  463. PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
  464. *hasAlphap = true;
  465. }
  466. *configp = this->getPrefConfig(k32Bit_SrcDepth, *hasAlphap);
  467. // now match the request against our capabilities
  468. if (*hasAlphap) {
  469. if (*configp != SkBitmap::kARGB_4444_Config) {
  470. *configp = SkBitmap::kARGB_8888_Config;
  471. }
  472. } else {
  473. if (*configp != SkBitmap::kRGB_565_Config &&
  474. *configp != SkBitmap::kARGB_4444_Config) {
  475. *configp = SkBitmap::kARGB_8888_Config;
  476. }
  477. }
  478. }
  479. // sanity check for size
  480. {
  481. Sk64 size;
  482. size.setMul(origWidth, origHeight);
  483. if (size.isNeg() || !size.is32()) {
  484. return false;
  485. }
  486. // now check that if we are 4-bytes per pixel, we also don't overflow
  487. if (size.get32() > (0x7FFFFFFF >> 2)) {
  488. return false;
  489. }
  490. }
  491. if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) {
  492. return false;
  493. }
  494. return true;
  495. }
  496. bool SkPNGImageDecoderMy::decodePalette(png_structp png_ptr, png_infop info_ptr,
  497. bool *hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep) {
  498. int num_palette;
  499. png_colorp palette;
  500. png_bytep trans;
  501. int num_trans;
  502. bool reallyHasAlpha = false;
  503. SkColorTable* colorTable = NULL;
  504. png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
  505. /* BUGGY IMAGE WORKAROUND
  506. We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count
  507. which is a problem since we use the byte as an index. To work around this we grow
  508. the colortable by 1 (if its < 256) and duplicate the last color into that slot.
  509. */
  510. int colorCount = num_palette + (num_palette < 256);
  511. colorTable = SkNEW_ARGS(SkColorTable, (colorCount));
  512. SkPMColor* colorPtr = colorTable->lockColors();
  513. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
  514. png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
  515. *hasAlphap = (num_trans > 0);
  516. } else {
  517. num_trans = 0;
  518. colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
  519. }
  520. // check for bad images that might make us crash
  521. if (num_trans > num_palette) {
  522. num_trans = num_palette;
  523. }
  524. int index = 0;
  525. int transLessThanFF = 0;
  526. for (; index < num_trans; index++) {
  527. transLessThanFF |= (int)*trans - 0xFF;
  528. *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue);
  529. palette++;
  530. }
  531. reallyHasAlpha |= (transLessThanFF < 0);
  532. for (; index < num_palette; index++) {
  533. *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
  534. palette++;
  535. }
  536. // see BUGGY IMAGE WORKAROUND comment above
  537. if (num_palette < 256) {
  538. *colorPtr = colorPtr[-1];
  539. }
  540. colorTable->unlockColors(true);
  541. *colorTablep = colorTable;
  542. *reallyHasAlphap = reallyHasAlpha;
  543. return true;
  544. }
  545. #if 0
  546. bool SkPNGImageDecoderMy::onDecodeRegion(SkBitmap* bm, SkIRect rect) {
  547. int i;
  548. png_structp png_ptr = this->index->png_ptr;
  549. png_infop info_ptr = this->index->info_ptr;
  550. if (setjmp(png_jmpbuf(png_ptr))) {
  551. return false;
  552. }
  553. int requestedHeight = rect.fBottom - rect.fTop;
  554. int requestedWidth = rect.fRight - rect.fLeft;
  555. png_uint_32 origWidth, origHeight;
  556. int bit_depth, color_type, interlace_type;
  557. png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
  558. &color_type, &interlace_type, int_p_NULL, int_p_NULL);
  559. SkBitmap::Config config;
  560. bool hasAlpha = false;
  561. bool doDither = this->getDitherImage();
  562. SkPMColor theTranspColor = 0; // 0 tells us not to try to match
  563. if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha,
  564. &doDither, &theTranspColor) == false) {
  565. return false;
  566. }
  567. const int sampleSize = this->getSampleSize();
  568. SkScaledBitmapSampler sampler(origWidth, requestedHeight, sampleSize);
  569. SkBitmap *decodedBitmap = new SkBitmap;
  570. SkAutoTDelete<SkBitmap> adb(decodedBitmap);
  571. decodedBitmap->setConfig(config, sampler.scaledWidth(),
  572. sampler.scaledHeight(), 0);
  573. // from here down we are concerned with colortables and pixels
  574. // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
  575. // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
  576. // draw lots faster if we can flag the bitmap has being opaque
  577. bool reallyHasAlpha = false;
  578. SkColorTable* colorTable = NULL;
  579. if (color_type == PNG_COLOR_TYPE_PALETTE) {
  580. decodePalette(png_ptr, info_ptr, &hasAlpha,
  581. &reallyHasAlpha, &colorTable);
  582. }
  583. SkAutoUnref aur(colorTable);
  584. if (!this->allocPixelRef(decodedBitmap,
  585. SkBitmap::kIndex8_Config == config ?
  586. colorTable : NULL)) {
  587. return false;
  588. }
  589. SkAutoLockPixels alp(*decodedBitmap);
  590. /* Add filler (or alpha) byte (before/after each RGB triplet) */
  591. if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
  592. png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  593. }
  594. /* Turn on interlace handling. REQUIRED if you are not using
  595. * png_read_image(). To see how to handle interlacing passes,
  596. * see the png_read_row() method below:
  597. */
  598. const int number_passes = interlace_type != PNG_INTERLACE_NONE ?
  599. png_set_interlace_handling(png_ptr) : 1;
  600. /* Optional call to gamma correct and add the background to the palette
  601. * and update info structure. REQUIRED if you are expecting libpng to
  602. * update the palette for you (ie you selected such a transform above).
  603. */
  604. png_ptr->pass = 0;
  605. png_read_update_info(png_ptr, info_ptr);
  606. SkDebugf("Request size %d %d\n", requestedWidth, requestedHeight);
  607. int actualTop = rect.fTop;
  608. if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
  609. for (int i = 0; i < number_passes; i++) {
  610. png_configure_decoder(png_ptr, &actualTop, i);
  611. for (int j = 0; j < rect.fTop - actualTop; j++) {
  612. uint8_t* bmRow = decodedBitmap->getAddr8(0, 0);
  613. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  614. }
  615. for (png_uint_32 y = 0; y < origHeight; y++) {
  616. uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
  617. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  618. }
  619. }
  620. } else {
  621. SkScaledBitmapSampler::SrcConfig sc;
  622. int srcBytesPerPixel = 4;
  623. if (colorTable != NULL) {
  624. sc = SkScaledBitmapSampler::kIndex;
  625. srcBytesPerPixel = 1;
  626. } else if (hasAlpha) {
  627. sc = SkScaledBitmapSampler::kRGBA;
  628. } else {
  629. sc = SkScaledBitmapSampler::kRGBX;
  630. }
  631. /* We have to pass the colortable explicitly, since we may have one
  632. even if our decodedBitmap doesn't, due to the request that we
  633. upscale png's palette to a direct model
  634. */
  635. SkAutoLockColors ctLock(colorTable);
  636. if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
  637. return false;
  638. }
  639. const int height = decodedBitmap->height();
  640. if (number_passes > 1) {
  641. SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
  642. uint8_t* base = (uint8_t*)storage.get();
  643. size_t rb = origWidth * srcBytesPerPixel;
  644. for (int i = 0; i < number_passes; i++) {
  645. png_configure_decoder(png_ptr, &actualTop, i);
  646. for (int j = 0; j < rect.fTop - actualTop; j++) {
  647. uint8_t* bmRow = decodedBitmap->getAddr8(0, 0);
  648. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  649. }
  650. uint8_t* row = base;
  651. for (png_uint_32 y = 0; y < requestedHeight; y++) {
  652. uint8_t* bmRow = row;
  653. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  654. row += rb;
  655. }
  656. }
  657. // now sample it
  658. base += sampler.srcY0() * rb;
  659. for (int y = 0; y < height; y++) {
  660. reallyHasAlpha |= sampler.next(base);
  661. base += sampler.srcDY() * rb;
  662. }
  663. } else {
  664. SkAutoMalloc storage(origWidth * srcBytesPerPixel);
  665. uint8_t* srcRow = (uint8_t*)storage.get();
  666. png_configure_decoder(png_ptr, &actualTop, 0);
  667. skip_src_rows(png_ptr, srcRow, sampler.srcY0());
  668. for (int i = 0; i < rect.fTop - actualTop; i++) {
  669. uint8_t* bmRow = decodedBitmap->getAddr8(0, 0);
  670. png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
  671. }
  672. for (int y = 0; y < height; y++) {
  673. uint8_t* tmp = srcRow;
  674. png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
  675. reallyHasAlpha |= sampler.next(srcRow);
  676. if (y < height - 1) {
  677. skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
  678. }
  679. }
  680. }
  681. }
  682. cropBitmap(bm, decodedBitmap, sampleSize, rect.fLeft, rect.fTop,
  683. requestedWidth, requestedHeight, 0, rect.fTop);
  684. if (0 != theTranspColor) {
  685. reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
  686. }
  687. decodedBitmap->setIsOpaque(!reallyHasAlpha);
  688. return true;
  689. }
  690. #endif
  691. ///////////////////////////////////////////////////////////////////////////////
  692. #include "SkColorPriv.h"
  693. #include "SkUnPreMultiply.h"
  694. static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
  695. SkWStream* sk_stream = (SkWStream*)png_ptr->io_ptr;
  696. if (!sk_stream->write(data, len)) {
  697. png_error(png_ptr, "sk_write_fn Error!");
  698. }
  699. }
  700. typedef void (*transform_scanline_proc)(const char* SK_RESTRICT src,
  701. int width, char* SK_RESTRICT dst);
  702. static void transform_scanline_565(const char* SK_RESTRICT src, int width,
  703. char* SK_RESTRICT dst) {
  704. const uint16_t* SK_RESTRICT srcP = (const uint16_t*)src;
  705. for (int i = 0; i < width; i++) {
  706. unsigned c = *srcP++;
  707. *dst++ = SkPacked16ToR32(c);
  708. *dst++ = SkPacked16ToG32(c);
  709. *dst++ = SkPacked16ToB32(c);
  710. }
  711. }
  712. static void transform_scanline_888(const char* SK_RESTRICT src, int width,
  713. char* SK_RESTRICT dst) {
  714. const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src;
  715. for (int i = 0; i < width; i++) {
  716. SkPMColor c = *srcP++;
  717. *dst++ = SkGetPackedR32(c);
  718. *dst++ = SkGetPackedG32(c);
  719. *dst++ = SkGetPackedB32(c);
  720. }
  721. }
  722. static void transform_scanline_444(const char* SK_RESTRICT src, int width,
  723. char* SK_RESTRICT dst) {
  724. const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src;
  725. for (int i = 0; i < width; i++) {
  726. SkPMColor16 c = *srcP++;
  727. *dst++ = SkPacked4444ToR32(c);
  728. *dst++ = SkPacked4444ToG32(c);
  729. *dst++ = SkPacked4444ToB32(c);
  730. }
  731. }
  732. static void transform_scanline_8888(const char* SK_RESTRICT src, int width,
  733. char* SK_RESTRICT dst) {
  734. const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src;
  735. const SkUnPreMultiply::Scale* SK_RESTRICT table =
  736. SkUnPreMultiply::GetScaleTable();
  737. for (int i = 0; i < width; i++) {
  738. SkPMColor c = *srcP++;
  739. unsigned a = SkGetPackedA32(c);
  740. unsigned r = SkGetPackedR32(c);
  741. unsigned g = SkGetPackedG32(c);
  742. unsigned b = SkGetPackedB32(c);
  743. if (0 != a && 255 != a) {
  744. SkUnPreMultiply::Scale scale = table[a];
  745. r = SkUnPreMultiply::ApplyScale(scale, r);
  746. g = SkUnPreMultiply::ApplyScale(scale, g);
  747. b = SkUnPreMultiply::ApplyScale(scale, b);
  748. }
  749. *dst++ = r;
  750. *dst++ = g;
  751. *dst++ = b;
  752. *dst++ = a;
  753. }
  754. }
  755. static void transform_scanline_4444(const char* SK_RESTRICT src, int width,
  756. char* SK_RESTRICT dst) {
  757. const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src;
  758. const SkUnPreMultiply::Scale* SK_RESTRICT table =
  759. SkUnPreMultiply::GetScaleTable();
  760. for (int i = 0; i < width; i++) {
  761. SkPMColor16 c = *srcP++;
  762. unsigned a = SkPacked4444ToA32(c);
  763. unsigned r = SkPacked4444ToR32(c);
  764. unsigned g = SkPacked4444ToG32(c);
  765. unsigned b = SkPacked4444ToB32(c);
  766. if (0 != a && 255 != a) {
  767. SkUnPreMultiply::Scale scale = table[a];
  768. r = SkUnPreMultiply::ApplyScale(scale, r);
  769. g = SkUnPreMultiply::ApplyScale(scale, g);
  770. b = SkUnPreMultiply::ApplyScale(scale, b);
  771. }
  772. *dst++ = r;
  773. *dst++ = g;
  774. *dst++ = b;
  775. *dst++ = a;
  776. }
  777. }
  778. static void transform_scanline_index8(const char* SK_RESTRICT src, int width,
  779. char* SK_RESTRICT dst) {
  780. memcpy(dst, src, width);
  781. }
  782. static transform_scanline_proc choose_proc(SkBitmap::Config config,
  783. bool hasAlpha) {
  784. // we don't care about search on alpha if we're kIndex8, since only the
  785. // colortable packing cares about that distinction, not the pixels
  786. if (SkBitmap::kIndex8_Config == config) {
  787. hasAlpha = false; // we store false in the table entries for kIndex8
  788. }
  789. static const struct {
  790. SkBitmap::Config fConfig;
  791. bool fHasAlpha;
  792. transform_scanline_proc fProc;
  793. } gMap[] = {
  794. { SkBitmap::kRGB_565_Config, false, transform_scanline_565 },
  795. { SkBitmap::kARGB_8888_Config, false, transform_scanline_888 },
  796. { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 },
  797. { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 },
  798. { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 },
  799. { SkBitmap::kIndex8_Config, false, transform_scanline_index8 },
  800. };
  801. for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) {
  802. if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) {
  803. return gMap[i].fProc;
  804. }
  805. }
  806. sk_throw();
  807. return NULL;
  808. }
  809. // return the minimum legal bitdepth (by png standards) for this many colortable
  810. // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16,
  811. // we can use fewer bits per in png
  812. static int computeBitDepth(int colorCount) {
  813. #if 0
  814. int bits = SkNextLog2(colorCount);
  815. SkASSERT(bits >= 1 && bits <= 8);
  816. // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8)
  817. return SkNextPow2(bits);
  818. #else
  819. // for the moment, we don't know how to pack bitdepth < 8
  820. return 8;
  821. #endif
  822. }
  823. /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also
  824. pack trans[] and return the number of trans[] entries written. If hasAlpha
  825. is false, the return value will always be 0.
  826. Note: this routine takes care of unpremultiplying the RGB values when we
  827. have alpha in the colortable, since png doesn't support premul colors
  828. */
  829. static inline int pack_palette(SkColorTable* ctable,
  830. png_color* SK_RESTRICT palette,
  831. png_byte* SK_RESTRICT trans, bool hasAlpha) {
  832. SkAutoLockColors alc(ctable);
  833. const SkPMColor* SK_RESTRICT colors = alc.colors();
  834. const int ctCount = ctable->count();
  835. int i, num_trans = 0;
  836. if (hasAlpha) {
  837. /* first see if we have some number of fully opaque at the end of the
  838. ctable. PNG allows num_trans < num_palette, but all of the trans
  839. entries must come first in the palette. If I was smarter, I'd
  840. reorder the indices and ctable so that all non-opaque colors came
  841. first in the palette. But, since that would slow down the encode,
  842. I'm leaving the indices and ctable order as is, and just looking
  843. at the tail of the ctable for opaqueness.
  844. */
  845. num_trans = ctCount;
  846. for (i = ctCount - 1; i >= 0; --i) {
  847. if (SkGetPackedA32(colors[i]) != 0xFF) {
  848. break;
  849. }
  850. num_trans -= 1;
  851. }
  852. const SkUnPreMultiply::Scale* SK_RESTRICT table =
  853. SkUnPreMultiply::GetScaleTable();
  854. for (i = 0; i < num_trans; i++) {
  855. const SkPMColor c = *colors++;
  856. const unsigned a = SkGetPackedA32(c);
  857. const SkUnPreMultiply::Scale s = table[a];
  858. trans[i] = a;
  859. palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c));
  860. palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c));
  861. palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c));
  862. }
  863. // now fall out of this if-block to use common code for the trailing
  864. // opaque entries
  865. }
  866. // these (remaining) entries are opaque
  867. for (i = num_trans; i < ctCount; i++) {
  868. SkPMColor c = *colors++;
  869. palette[i].red = SkGetPackedR32(c);
  870. palette[i].green = SkGetPackedG32(c);
  871. palette[i].blue = SkGetPackedB32(c);
  872. }
  873. return num_trans;
  874. }
  875. class SkPNGImageEncoderMy : public SkImageEncoder {
  876. protected:
  877. virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
  878. };
  879. bool SkPNGImageEncoderMy::onEncode(SkWStream* stream, const SkBitmap& bitmap,
  880. int /*quality*/) {
  881. SkBitmap::Config config = bitmap.getConfig();
  882. const bool hasAlpha = !bitmap.isOpaque();
  883. int colorType = PNG_COLOR_MASK_COLOR;
  884. int bitDepth = 8; // default for color
  885. png_color_8 sig_bit;
  886. switch (config) {
  887. case SkBitmap::kIndex8_Config:
  888. colorType |= PNG_COLOR_MASK_PALETTE;
  889. // fall through to the ARGB_8888 case
  890. case SkBitmap::kARGB_8888_Config:
  891. sig_bit.red = 8;
  892. sig_bit.green = 8;
  893. sig_bit.blue = 8;
  894. sig_bit.alpha = 8;
  895. break;
  896. case SkBitmap::kARGB_4444_Config:
  897. sig_bit.red = 4;
  898. sig_bit.green = 4;
  899. sig_bit.blue = 4;
  900. sig_bit.alpha = 4;
  901. break;
  902. case SkBitmap::kRGB_565_Config:
  903. sig_bit.red = 5;
  904. sig_bit.green = 6;
  905. sig_bit.blue = 5;
  906. sig_bit.alpha = 0;
  907. break;
  908. default:
  909. return false;
  910. }
  911. if (hasAlpha) {
  912. // don't specify alpha if we're a palette, even if our ctable has alpha
  913. if (!(colorType & PNG_COLOR_MASK_PALETTE)) {
  914. colorType |= PNG_COLOR_MASK_ALPHA;
  915. }
  916. } else {
  917. sig_bit.alpha = 0;
  918. }
  919. SkAutoLockPixels alp(bitmap);
  920. // readyToDraw checks for pixels (and colortable if that is required)
  921. if (!bitmap.readyToDraw()) {
  922. return false;
  923. }
  924. // we must do this after we have locked the pixels
  925. SkColorTable* ctable = bitmap.getColorTable();
  926. if (NULL != ctable) {
  927. if (ctable->count() == 0) {
  928. return false;
  929. }
  930. // check if we can store in fewer than 8 bits
  931. bitDepth = computeBitDepth(ctable->count());
  932. }
  933. png_structp png_ptr;
  934. png_infop info_ptr;
  935. png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
  936. NULL);
  937. if (NULL == png_ptr) {
  938. return false;
  939. }
  940. info_ptr = png_create_info_struct(png_ptr);
  941. if (NULL == info_ptr) {
  942. png_destroy_write_struct(&png_ptr, png_infopp_NULL);
  943. return false;
  944. }
  945. /* Set error handling. REQUIRED if you aren't supplying your own
  946. * error handling functions in the png_create_write_struct() call.
  947. */
  948. if (setjmp(png_jmpbuf(png_ptr))) {
  949. png_destroy_write_struct(&png_ptr, &info_ptr);
  950. return false;
  951. }
  952. png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
  953. /* Set the image information here. Width and height are up to 2^31,
  954. * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
  955. * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
  956. * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
  957. * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
  958. * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
  959. * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
  960. */
  961. png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
  962. bitDepth, colorType,
  963. PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
  964. PNG_FILTER_TYPE_BASE);
  965. // set our colortable/trans arrays if needed
  966. png_color paletteColors[256];
  967. png_byte trans[256];
  968. if (SkBitmap::kIndex8_Config == config) {
  969. SkColorTable* ct = bitmap.getColorTable();
  970. int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha);
  971. png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count());
  972. if (numTrans > 0) {
  973. png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL);
  974. }
  975. }
  976. png_set_sBIT(png_ptr, info_ptr, &sig_bit);
  977. png_write_info(png_ptr, info_ptr);
  978. const char* srcImage = (const char*)bitmap.getPixels();
  979. SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2);
  980. char* storage = (char*)rowStorage.get();
  981. transform_scanline_proc proc = choose_proc(config, hasAlpha);
  982. for (int y = 0; y < bitmap.height(); y++) {
  983. png_bytep row_ptr = (png_bytep)storage;
  984. proc(srcImage, bitmap.width(), storage);
  985. png_write_rows(png_ptr, &row_ptr, 1);
  986. srcImage += bitmap.rowBytes();
  987. }
  988. png_write_end(png_ptr, info_ptr);
  989. /* clean up after the write, and free any memory allocated */
  990. png_destroy_write_struct(&png_ptr, &info_ptr);
  991. return true;
  992. }
  993. ///////////////////////////////////////////////////////////////////////////////
  994. #include "SkTRegistry.h"
  995. extern "C" SkImageDecoder* PNG_DFactory(SkStream* stream) {
  996. char buf[PNG_BYTES_TO_CHECK];
  997. if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
  998. !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
  999. return SkNEW(SkPNGImageDecoderMy);
  1000. }
  1001. return NULL;
  1002. }
  1003. extern "C" SkImageEncoder* PNG_EFactory(SkImageEncoder::Type t) {
  1004. return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoderMy) : NULL;
  1005. }