| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
| 9 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 SkPNGImageDecoder() { | 75 SkPNGImageDecoder() { |
| 76 fImageIndex = nullptr; | 76 fImageIndex = nullptr; |
| 77 } | 77 } |
| 78 Format getFormat() const override { | 78 Format getFormat() const override { |
| 79 return kPNG_Format; | 79 return kPNG_Format; |
| 80 } | 80 } |
| 81 | 81 |
| 82 virtual ~SkPNGImageDecoder() { delete fImageIndex; } | 82 virtual ~SkPNGImageDecoder() { delete fImageIndex; } |
| 83 | 83 |
| 84 protected: | 84 protected: |
| 85 #ifdef SK_PNG_INDEX_SUPPORTED | |
| 86 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; | |
| 87 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) override; | |
| 88 #endif | |
| 89 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; | 85 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; |
| 90 | 86 |
| 91 private: | 87 private: |
| 92 SkPNGImageIndex* fImageIndex; | 88 SkPNGImageIndex* fImageIndex; |
| 93 | 89 |
| 94 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); | 90 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p
trp); |
| 95 bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth, | 91 bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth, |
| 96 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, | 92 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, |
| 97 SkColorTable **colorTablep); | 93 SkColorTable **colorTablep); |
| 98 bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha
, | 94 bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha
, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 119 }; | 115 }; |
| 120 | 116 |
| 121 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { | 117 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { |
| 122 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr); | 118 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr); |
| 123 size_t bytes = sk_stream->read(data, length); | 119 size_t bytes = sk_stream->read(data, length); |
| 124 if (bytes != length) { | 120 if (bytes != length) { |
| 125 png_error(png_ptr, "Read Error!"); | 121 png_error(png_ptr, "Read Error!"); |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 | 124 |
| 129 #ifdef SK_PNG_INDEX_SUPPORTED | |
| 130 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { | |
| 131 SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr
); | |
| 132 if (!sk_stream->rewind()) { | |
| 133 png_error(png_ptr, "Failed to rewind stream!"); | |
| 134 } | |
| 135 (void)sk_stream->skip(offset); | |
| 136 } | |
| 137 #endif | |
| 138 | |
| 139 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED | 125 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
| 140 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { | 126 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { |
| 141 SkImageDecoder::Peeker* peeker = | 127 SkImageDecoder::Peeker* peeker = |
| 142 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); | 128 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); |
| 143 // peek() returning true means continue decoding | 129 // peek() returning true means continue decoding |
| 144 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? | 130 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? |
| 145 1 : -1; | 131 1 : -1; |
| 146 } | 132 } |
| 147 #endif | 133 #endif |
| 148 | 134 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 */ | 235 */ |
| 250 if (setjmp(png_jmpbuf(png_ptr))) { | 236 if (setjmp(png_jmpbuf(png_ptr))) { |
| 251 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); | 237 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); |
| 252 return false; | 238 return false; |
| 253 } | 239 } |
| 254 | 240 |
| 255 /* If you are using replacement read functions, instead of calling | 241 /* If you are using replacement read functions, instead of calling |
| 256 * png_init_io() here you would call: | 242 * png_init_io() here you would call: |
| 257 */ | 243 */ |
| 258 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); | 244 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); |
| 259 #ifdef SK_PNG_INDEX_SUPPORTED | |
| 260 png_set_seek_fn(png_ptr, sk_seek_fn); | |
| 261 #endif | |
| 262 /* where user_io_ptr is a structure you want available to the callbacks */ | 245 /* where user_io_ptr is a structure you want available to the callbacks */ |
| 263 /* If we have already read some of the signature */ | 246 /* If we have already read some of the signature */ |
| 264 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); | 247 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); |
| 265 | 248 |
| 266 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED | 249 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
| 267 // hookup our peeker so we can see any user-chunks the caller may be interes
ted in | 250 // hookup our peeker so we can see any user-chunks the caller may be interes
ted in |
| 268 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"",
0); | 251 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"",
0); |
| 269 if (this->getPeeker()) { | 252 if (this->getPeeker()) { |
| 270 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea
d_user_chunk); | 253 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea
d_user_chunk); |
| 271 } | 254 } |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0)
; | 696 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0)
; |
| 714 for (; index < colorCount; index++) { | 697 for (; index < colorCount; index++) { |
| 715 *colorPtr++ = lastColor; | 698 *colorPtr++ = lastColor; |
| 716 } | 699 } |
| 717 | 700 |
| 718 *colorTablep = new SkColorTable(colorStorage, colorCount); | 701 *colorTablep = new SkColorTable(colorStorage, colorCount); |
| 719 *reallyHasAlphap = reallyHasAlpha; | 702 *reallyHasAlphap = reallyHasAlpha; |
| 720 return true; | 703 return true; |
| 721 } | 704 } |
| 722 | 705 |
| 723 #ifdef SK_PNG_INDEX_SUPPORTED | |
| 724 | |
| 725 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *wid
th, int *height) { | |
| 726 SkAutoTDelete<SkStreamRewindable> streamDeleter(sk_stream); | |
| 727 png_structp png_ptr; | |
| 728 png_infop info_ptr; | |
| 729 | |
| 730 if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) { | |
| 731 return false; | |
| 732 } | |
| 733 | |
| 734 if (setjmp(png_jmpbuf(png_ptr)) != 0) { | |
| 735 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); | |
| 736 return false; | |
| 737 } | |
| 738 | |
| 739 png_uint_32 origWidth, origHeight; | |
| 740 int bitDepth, colorType; | |
| 741 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | |
| 742 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | |
| 743 | |
| 744 *width = origWidth; | |
| 745 *height = origHeight; | |
| 746 | |
| 747 png_build_index(png_ptr); | |
| 748 | |
| 749 if (fImageIndex) { | |
| 750 delete fImageIndex; | |
| 751 } | |
| 752 fImageIndex = new SkPNGImageIndex(streamDeleter.detach(), png_ptr, info_ptr)
; | |
| 753 | |
| 754 return true; | |
| 755 } | |
| 756 | |
| 757 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { | |
| 758 if (nullptr == fImageIndex) { | |
| 759 return false; | |
| 760 } | |
| 761 | |
| 762 png_structp png_ptr = fImageIndex->fPng_ptr; | |
| 763 png_infop info_ptr = fImageIndex->fInfo_ptr; | |
| 764 if (setjmp(png_jmpbuf(png_ptr))) { | |
| 765 return false; | |
| 766 } | |
| 767 | |
| 768 png_uint_32 origWidth, origHeight; | |
| 769 int bitDepth, pngColorType, interlaceType; | |
| 770 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | |
| 771 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); | |
| 772 | |
| 773 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); | |
| 774 | |
| 775 if (!rect.intersect(region)) { | |
| 776 // If the requested region is entirely outside the image, just | |
| 777 // returns false | |
| 778 return false; | |
| 779 } | |
| 780 | |
| 781 SkColorType colorType; | |
| 782 bool hasAlpha = false; | |
| 783 SkPMColor theTranspColor = 0; // 0 tells us not to try to match | |
| 784 | |
| 785 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &the
TranspColor)) { | |
| 786 return false; | |
| 787 } | |
| 788 | |
| 789 const int sampleSize = this->getSampleSize(); | |
| 790 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); | |
| 791 | |
| 792 SkBitmap decodedBitmap; | |
| 793 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), | |
| 794 colorType, kPremul_SkAlphaType)); | |
| 795 | |
| 796 // from here down we are concerned with colortables and pixels | |
| 797 | |
| 798 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | |
| 799 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | |
| 800 // draw lots faster if we can flag the bitmap has being opaque | |
| 801 bool reallyHasAlpha = false; | |
| 802 SkColorTable* colorTable = nullptr; | |
| 803 | |
| 804 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { | |
| 805 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); | |
| 806 } | |
| 807 | |
| 808 SkAutoUnref aur(colorTable); | |
| 809 | |
| 810 // Check ahead of time if the swap(dest, src) is possible. | |
| 811 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. | |
| 812 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. | |
| 813 int w = rect.width() / sampleSize; | |
| 814 int h = rect.height() / sampleSize; | |
| 815 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | |
| 816 (h == decodedBitmap.height()) && bm->isNull(); | |
| 817 const bool needColorTable = kIndex_8_SkColorType == colorType; | |
| 818 if (swapOnly) { | |
| 819 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : n
ullptr)) { | |
| 820 return false; | |
| 821 } | |
| 822 } else { | |
| 823 if (!decodedBitmap.tryAllocPixels(nullptr, needColorTable ? colorTable :
nullptr)) { | |
| 824 return false; | |
| 825 } | |
| 826 } | |
| 827 SkAutoLockPixels alp(decodedBitmap); | |
| 828 | |
| 829 /* Turn on interlace handling. REQUIRED if you are not using | |
| 830 * png_read_image(). To see how to handle interlacing passes, | |
| 831 * see the png_read_row() method below: | |
| 832 */ | |
| 833 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? | |
| 834 png_set_interlace_handling(png_ptr) : 1; | |
| 835 | |
| 836 /* Optional call to gamma correct and add the background to the palette | |
| 837 * and update info structure. REQUIRED if you are expecting libpng to | |
| 838 * update the palette for you (ie you selected such a transform above). | |
| 839 */ | |
| 840 | |
| 841 // Direct access to png_ptr fields is deprecated in libpng > 1.2. | |
| 842 #if defined(PNG_1_0_X) || defined (PNG_1_2_X) | |
| 843 png_ptr->pass = 0; | |
| 844 #else | |
| 845 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok? | |
| 846 png_set_interlaced_pass(png_ptr, 0); | |
| 847 #endif | |
| 848 png_read_update_info(png_ptr, info_ptr); | |
| 849 | |
| 850 int actualTop = rect.fTop; | |
| 851 | |
| 852 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) | |
| 853 && 1 == sampleSize) { | |
| 854 if (kAlpha_8_SkColorType == colorType) { | |
| 855 // For an A8 bitmap, we assume there is an alpha for speed. It is | |
| 856 // possible the bitmap is opaque, but that is an unlikely use case | |
| 857 // since it would not be very interesting. | |
| 858 reallyHasAlpha = true; | |
| 859 // A8 is only allowed if the original was GRAY. | |
| 860 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | |
| 861 } | |
| 862 | |
| 863 for (int i = 0; i < number_passes; i++) { | |
| 864 png_configure_decoder(png_ptr, &actualTop, i); | |
| 865 for (int j = 0; j < rect.fTop - actualTop; j++) { | |
| 866 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); | |
| 867 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | |
| 868 } | |
| 869 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); | |
| 870 for (png_uint_32 y = 0; y < bitmapHeight; y++) { | |
| 871 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); | |
| 872 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | |
| 873 } | |
| 874 } | |
| 875 } else { | |
| 876 SkScaledBitmapSampler::SrcConfig sc; | |
| 877 int srcBytesPerPixel = 4; | |
| 878 | |
| 879 if (colorTable != nullptr) { | |
| 880 sc = SkScaledBitmapSampler::kIndex; | |
| 881 srcBytesPerPixel = 1; | |
| 882 } else if (kAlpha_8_SkColorType == colorType) { | |
| 883 // A8 is only allowed if the original was GRAY. | |
| 884 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | |
| 885 sc = SkScaledBitmapSampler::kGray; | |
| 886 srcBytesPerPixel = 1; | |
| 887 } else if (hasAlpha) { | |
| 888 sc = SkScaledBitmapSampler::kRGBA; | |
| 889 } else { | |
| 890 sc = SkScaledBitmapSampler::kRGBX; | |
| 891 } | |
| 892 | |
| 893 /* We have to pass the colortable explicitly, since we may have one | |
| 894 even if our decodedBitmap doesn't, due to the request that we | |
| 895 upscale png's palette to a direct model | |
| 896 */ | |
| 897 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt
r; | |
| 898 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) { | |
| 899 return false; | |
| 900 } | |
| 901 const int height = decodedBitmap.height(); | |
| 902 | |
| 903 if (number_passes > 1) { | |
| 904 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | |
| 905 uint8_t* base = (uint8_t*)storage.get(); | |
| 906 size_t rb = origWidth * srcBytesPerPixel; | |
| 907 | |
| 908 for (int i = 0; i < number_passes; i++) { | |
| 909 png_configure_decoder(png_ptr, &actualTop, i); | |
| 910 for (int j = 0; j < rect.fTop - actualTop; j++) { | |
| 911 png_read_rows(png_ptr, &base, png_bytepp_NULL, 1); | |
| 912 } | |
| 913 uint8_t* row = base; | |
| 914 for (int32_t y = 0; y < rect.height(); y++) { | |
| 915 uint8_t* bmRow = row; | |
| 916 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | |
| 917 row += rb; | |
| 918 } | |
| 919 } | |
| 920 // now sample it | |
| 921 base += sampler.srcY0() * rb; | |
| 922 for (int y = 0; y < height; y++) { | |
| 923 reallyHasAlpha |= sampler.next(base); | |
| 924 base += sampler.srcDY() * rb; | |
| 925 } | |
| 926 } else { | |
| 927 SkAutoMalloc storage(origWidth * srcBytesPerPixel); | |
| 928 uint8_t* srcRow = (uint8_t*)storage.get(); | |
| 929 | |
| 930 png_configure_decoder(png_ptr, &actualTop, 0); | |
| 931 skip_src_rows(png_ptr, srcRow, sampler.srcY0()); | |
| 932 | |
| 933 for (int i = 0; i < rect.fTop - actualTop; i++) { | |
| 934 png_read_rows(png_ptr, &srcRow, png_bytepp_NULL, 1); | |
| 935 } | |
| 936 for (int y = 0; y < height; y++) { | |
| 937 uint8_t* tmp = srcRow; | |
| 938 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); | |
| 939 reallyHasAlpha |= sampler.next(srcRow); | |
| 940 if (y < height - 1) { | |
| 941 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); | |
| 942 } | |
| 943 } | |
| 944 } | |
| 945 } | |
| 946 | |
| 947 if (0 != theTranspColor) { | |
| 948 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor); | |
| 949 } | |
| 950 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { | |
| 951 switch (decodedBitmap.colorType()) { | |
| 952 case kIndex_8_SkColorType: | |
| 953 // Fall through. | |
| 954 case kARGB_4444_SkColorType: | |
| 955 // We have chosen not to support unpremul for these colortypess. | |
| 956 return false; | |
| 957 default: { | |
| 958 // Fall through to finish the decode. This config either | |
| 959 // supports unpremul or it is irrelevant because it has no | |
| 960 // alpha (or only alpha). | |
| 961 // These brackets prevent a warning. | |
| 962 } | |
| 963 } | |
| 964 } | |
| 965 SkAlphaType alphaType = kOpaque_SkAlphaType; | |
| 966 if (reallyHasAlpha) { | |
| 967 if (this->getRequireUnpremultipliedColors()) { | |
| 968 alphaType = kUnpremul_SkAlphaType; | |
| 969 } else { | |
| 970 alphaType = kPremul_SkAlphaType; | |
| 971 } | |
| 972 } | |
| 973 decodedBitmap.setAlphaType(alphaType); | |
| 974 | |
| 975 if (swapOnly) { | |
| 976 bm->swap(decodedBitmap); | |
| 977 return true; | |
| 978 } | |
| 979 return this->cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y
(), | |
| 980 region.width(), region.height(), 0, rect.y()); | |
| 981 } | |
| 982 #endif | |
| 983 | |
| 984 /////////////////////////////////////////////////////////////////////////////// | 706 /////////////////////////////////////////////////////////////////////////////// |
| 985 | 707 |
| 986 #include "SkColorPriv.h" | 708 #include "SkColorPriv.h" |
| 987 #include "SkUnPreMultiply.h" | 709 #include "SkUnPreMultiply.h" |
| 988 | 710 |
| 989 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { | 711 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { |
| 990 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); | 712 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); |
| 991 if (!sk_stream->write(data, len)) { | 713 if (!sk_stream->write(data, len)) { |
| 992 png_error(png_ptr, "sk_write_fn Error!"); | 714 png_error(png_ptr, "sk_write_fn Error!"); |
| 993 } | 715 } |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 return SkImageDecoder::kUnknown_Format; | 997 return SkImageDecoder::kUnknown_Format; |
| 1276 } | 998 } |
| 1277 | 999 |
| 1278 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1000 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 1279 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; | 1001 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
| 1280 } | 1002 } |
| 1281 | 1003 |
| 1282 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1004 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
| 1283 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1005 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
| 1284 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1006 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |