1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCodec.h" 9 #include "SkColorSpaceXform.h" 10 #include "SkColorTable.h" 11 #include "SkPngChunkReader.h" 12 #include "SkEncodedFormat.h" 13 #include "SkImageInfo.h" 14 #include "SkRefCnt.h" 15 #include "SkSwizzler.h" 16 17 // FIXME (scroggo): GOOGLE3 is currently using an outdated version of libpng, 18 // so we need to work around the lack of the method png_process_data_pause. 19 // This code will be unnecessary once we update GOOGLE3. It would make more 20 // sense to condition this on the version of libpng being used, but we do not 21 // know that here because png.h is only included by the cpp file. 22 #define SK_GOOGLE3_PNG_HACK 23 24 class SkStream; 25 26 class SkPngCodec : public SkCodec { 27 public: 28 static bool IsPng(const char*, size_t); 29 30 // Assume IsPng was called and returned true. 31 static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL); 32 33 virtual ~SkPngCodec(); 34 35 protected: 36 // We hold the png_ptr and info_ptr as voidp to avoid having to include png.h 37 // or forward declare their types here. voidp auto-casts to the real pointer types. 38 struct voidp { voidpvoidp39 voidp(void* ptr) : fPtr(ptr) {} 40 41 template <typename T> 42 operator T*() const { return (T*)fPtr; } 43 44 explicit operator bool() const { return fPtr != nullptr; } 45 46 void* fPtr; 47 }; 48 49 SkPngCodec(const SkEncodedInfo&, const SkImageInfo&, SkStream*, SkPngChunkReader*, 50 void* png_ptr, void* info_ptr, int bitDepth); 51 52 Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*) 53 override; onGetEncodedFormat()54 SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; } 55 bool onRewind() override; 56 uint64_t onGetFillValue(const SkImageInfo&) const override; 57 58 SkSampler* getSampler(bool createIfNecessary) override; 59 void applyXformRow(void* dst, const void* src); 60 png_ptr()61 voidp png_ptr() { return fPng_ptr; } info_ptr()62 voidp info_ptr() { return fInfo_ptr; } 63 swizzler()64 SkSwizzler* swizzler() { return fSwizzler; } 65 66 // Initialize variables used by applyXformRow. 67 void initializeXformParams(); 68 69 /** 70 * Pass available input to libpng to process it. 71 * 72 * libpng will call any relevant callbacks installed. This will continue decoding 73 * until it reaches the end of the file, or until a callback tells libpng to stop. 74 */ 75 void processData(); 76 77 #ifdef SK_GOOGLE3_PNG_HACK 78 // In libpng 1.2.56, png_process_data_pause does not exist, so when we wanted to 79 // read the header, we may have read too far. In that case, we need to delete the 80 // png_ptr and info_ptr and recreate them. This method does that (and attaches the 81 // chunk reader. 82 bool rereadHeaderIfNecessary(); 83 84 // This method sets up the new png_ptr/info_ptr (created in rereadHeaderIfNecessary) 85 // the way we set up the old one the first time in AutoCleanPng.decodeBounds's callback. 86 void rereadInfoCallback(); 87 #endif 88 89 Result onStartIncrementalDecode(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, 90 const SkCodec::Options&, 91 SkPMColor* ctable, int* ctableCount) override; 92 Result onIncrementalDecode(int*) override; 93 94 SkAutoTUnref<SkPngChunkReader> fPngChunkReader; 95 voidp fPng_ptr; 96 voidp fInfo_ptr; 97 98 // These are stored here so they can be used both by normal decoding and scanline decoding. 99 SkAutoTUnref<SkColorTable> fColorTable; // May be unpremul. 100 SkAutoTDelete<SkSwizzler> fSwizzler; 101 std::unique_ptr<SkColorSpaceXform> fColorXform; 102 SkAutoTMalloc<uint8_t> fStorage; 103 uint32_t* fColorXformSrcRow; 104 const int fBitDepth; 105 106 private: 107 108 enum XformMode { 109 // Requires only a swizzle pass. 110 kSwizzleOnly_XformMode, 111 112 // Requires only a color xform pass. 113 kColorOnly_XformMode, 114 115 // Requires a swizzle and a color xform. 116 kSwizzleColor_XformMode, 117 }; 118 119 bool createColorTable(const SkImageInfo& dstInfo, int* ctableCount); 120 // Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info. 121 bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr, 122 int* colorCount); 123 void initializeSwizzler(const SkImageInfo& dstInfo, const Options&); 124 void allocateStorage(const SkImageInfo& dstInfo); 125 void destroyReadStruct(); 126 127 virtual Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) = 0; 128 virtual void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) = 0; 129 virtual Result decode(int* rowsDecoded) = 0; 130 131 XformMode fXformMode; 132 SkColorSpaceXform::ColorFormat fXformColorFormat; 133 SkAlphaType fXformAlphaType; 134 int fXformWidth; 135 136 #ifdef SK_GOOGLE3_PNG_HACK 137 bool fNeedsToRereadHeader; 138 #endif 139 140 typedef SkCodec INHERITED; 141 }; 142