blob: 7a2ebae2109f787978fff74180e489d4d4aa3225 [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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 */
Hal Canary03a7f5f2017-02-10 09:06:38 -05007#ifndef SkPngCodec_DEFINED
8#define SkPngCodec_DEFINED
scroggof24f2242015-03-03 08:59:20 -08009
10#include "SkCodec.h"
msarettd1ec89b2016-08-03 12:59:27 -070011#include "SkColorSpaceXform.h"
scroggo05245902015-03-25 11:11:52 -070012#include "SkColorTable.h"
scroggocf98fa92015-11-23 08:14:40 -080013#include "SkPngChunkReader.h"
Hal Canarydb683012016-11-23 08:55:18 -070014#include "SkEncodedImageFormat.h"
scroggof24f2242015-03-03 08:59:20 -080015#include "SkImageInfo.h"
scroggo05245902015-03-25 11:11:52 -070016#include "SkRefCnt.h"
17#include "SkSwizzler.h"
scroggof24f2242015-03-03 08:59:20 -080018
scroggo8e6c7ad2016-09-16 08:20:38 -070019// FIXME (scroggo): GOOGLE3 is currently using an outdated version of libpng,
20// so we need to work around the lack of the method png_process_data_pause.
21// This code will be unnecessary once we update GOOGLE3. It would make more
22// sense to condition this on the version of libpng being used, but we do not
23// know that here because png.h is only included by the cpp file.
24#define SK_GOOGLE3_PNG_HACK
25
scroggof24f2242015-03-03 08:59:20 -080026class SkStream;
27
28class SkPngCodec : public SkCodec {
29public:
scroggodb30be22015-12-08 18:54:13 -080030 static bool IsPng(const char*, size_t);
scroggo9b2cdbf42015-07-10 12:07:02 -070031
scroggo1c005e42015-08-04 09:24:45 -070032 // Assume IsPng was called and returned true.
scroggocf98fa92015-11-23 08:14:40 -080033 static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
scroggo1c005e42015-08-04 09:24:45 -070034
scroggo9b2cdbf42015-07-10 12:07:02 -070035 virtual ~SkPngCodec();
36
scroggof24f2242015-03-03 08:59:20 -080037protected:
mtklein6dc5b9a2016-08-24 12:22:32 -070038 // We hold the png_ptr and info_ptr as voidp to avoid having to include png.h
39 // or forward declare their types here. voidp auto-casts to the real pointer types.
40 struct voidp {
41 voidp(void* ptr) : fPtr(ptr) {}
42
43 template <typename T>
44 operator T*() const { return (T*)fPtr; }
45
46 explicit operator bool() const { return fPtr != nullptr; }
47
48 void* fPtr;
49 };
50
scroggo8e6c7ad2016-09-16 08:20:38 -070051 SkPngCodec(const SkEncodedInfo&, const SkImageInfo&, SkStream*, SkPngChunkReader*,
52 void* png_ptr, void* info_ptr, int bitDepth);
53
msarette6dd0042015-10-09 11:07:34 -070054 Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*)
mtklein36352bf2015-03-25 18:17:31 -070055 override;
Hal Canarydb683012016-11-23 08:55:18 -070056 SkEncodedImageFormat onGetEncodedFormat() const override { return SkEncodedImageFormat::kPNG; }
scroggob427db12015-08-12 07:24:13 -070057 bool onRewind() override;
msarettf7eb6fc2016-09-13 09:04:11 -070058 uint64_t onGetFillValue(const SkImageInfo&) const override;
scroggo46c57472015-09-30 08:57:13 -070059
msarett400a93b2016-09-01 18:32:52 -070060 SkSampler* getSampler(bool createIfNecessary) override;
scroggo8e6c7ad2016-09-16 08:20:38 -070061 void applyXformRow(void* dst, const void* src);
msarettd1ec89b2016-08-03 12:59:27 -070062
scroggo8e6c7ad2016-09-16 08:20:38 -070063 voidp png_ptr() { return fPng_ptr; }
64 voidp info_ptr() { return fInfo_ptr; }
scroggo46c57472015-09-30 08:57:13 -070065
Ben Wagner145dbcd2016-11-03 14:40:50 -040066 SkSwizzler* swizzler() { return fSwizzler.get(); }
scroggo8e6c7ad2016-09-16 08:20:38 -070067
68 // Initialize variables used by applyXformRow.
msarettc0444612016-09-16 11:45:58 -070069 void initializeXformParams();
scroggo8e6c7ad2016-09-16 08:20:38 -070070
71 /**
72 * Pass available input to libpng to process it.
73 *
74 * libpng will call any relevant callbacks installed. This will continue decoding
75 * until it reaches the end of the file, or until a callback tells libpng to stop.
76 */
77 void processData();
78
79#ifdef SK_GOOGLE3_PNG_HACK
80 // In libpng 1.2.56, png_process_data_pause does not exist, so when we wanted to
81 // read the header, we may have read too far. In that case, we need to delete the
82 // png_ptr and info_ptr and recreate them. This method does that (and attaches the
83 // chunk reader.
84 bool rereadHeaderIfNecessary();
85
86 // This method sets up the new png_ptr/info_ptr (created in rereadHeaderIfNecessary)
87 // the way we set up the old one the first time in AutoCleanPng.decodeBounds's callback.
88 void rereadInfoCallback();
89#endif
90
91 Result onStartIncrementalDecode(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
92 const SkCodec::Options&,
93 SkPMColor* ctable, int* ctableCount) override;
94 Result onIncrementalDecode(int*) override;
scroggod8d68552016-06-06 11:26:17 -070095
Hal Canary67b39de2016-11-07 11:47:44 -050096 sk_sp<SkPngChunkReader> fPngChunkReader;
97 voidp fPng_ptr;
98 voidp fInfo_ptr;
scroggo05245902015-03-25 11:11:52 -070099
scroggod8d68552016-06-06 11:26:17 -0700100 // These are stored here so they can be used both by normal decoding and scanline decoding.
Hal Canary67b39de2016-11-07 11:47:44 -0500101 sk_sp<SkColorTable> fColorTable; // May be unpremul.
102 std::unique_ptr<SkSwizzler> fSwizzler;
103 SkAutoTMalloc<uint8_t> fStorage;
Matt Sarett379938e2017-01-12 18:34:29 -0500104 void* fColorXformSrcRow;
Hal Canary67b39de2016-11-07 11:47:44 -0500105 const int fBitDepth;
scroggo6f29a3c2015-07-07 06:09:08 -0700106
msarettd1ec89b2016-08-03 12:59:27 -0700107private:
msarett400a93b2016-09-01 18:32:52 -0700108
109 enum XformMode {
110 // Requires only a swizzle pass.
111 kSwizzleOnly_XformMode,
112
113 // Requires only a color xform pass.
114 kColorOnly_XformMode,
115
116 // Requires a swizzle and a color xform.
117 kSwizzleColor_XformMode,
118 };
119
msarettdcd5e652016-08-22 08:48:40 -0700120 bool createColorTable(const SkImageInfo& dstInfo, int* ctableCount);
scroggo8e6c7ad2016-09-16 08:20:38 -0700121 // Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info.
122 bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr,
123 int* colorCount);
Matt Sarett379938e2017-01-12 18:34:29 -0500124 void initializeSwizzler(const SkImageInfo& dstInfo, const Options&, bool skipFormatConversion);
scroggo8e6c7ad2016-09-16 08:20:38 -0700125 void allocateStorage(const SkImageInfo& dstInfo);
scroggo3eada2a2015-04-01 09:33:23 -0700126 void destroyReadStruct();
scroggo05245902015-03-25 11:11:52 -0700127
scroggo8e6c7ad2016-09-16 08:20:38 -0700128 virtual Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) = 0;
129 virtual void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) = 0;
130 virtual Result decode(int* rowsDecoded) = 0;
131
msarettc0444612016-09-16 11:45:58 -0700132 XformMode fXformMode;
133 SkColorSpaceXform::ColorFormat fXformColorFormat;
134 SkAlphaType fXformAlphaType;
135 int fXformWidth;
scroggo8e6c7ad2016-09-16 08:20:38 -0700136
137#ifdef SK_GOOGLE3_PNG_HACK
138 bool fNeedsToRereadHeader;
139#endif
msarett400a93b2016-09-01 18:32:52 -0700140
scroggof24f2242015-03-03 08:59:20 -0800141 typedef SkCodec INHERITED;
142};
Hal Canary03a7f5f2017-02-10 09:06:38 -0500143#endif // SkPngCodec_DEFINED