| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 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 | #ifndef SkJpegCodec_DEFINED | 
|  | 9 | #define SkJpegCodec_DEFINED | 
|  | 10 |  | 
|  | 11 | #include "SkCodec.h" | 
| msarett | ad8bcfe | 2016-03-07 07:09:03 -0800 | [diff] [blame] | 12 | #include "SkColorSpace.h" | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 13 | #include "SkColorSpaceXform.h" | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 14 | #include "SkImageInfo.h" | 
| msarett | 39b2d5a | 2016-02-17 08:26:31 -0800 | [diff] [blame] | 15 | #include "SkSwizzler.h" | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 16 | #include "SkStream.h" | 
| scroggo | 565901d | 2015-12-10 10:44:13 -0800 | [diff] [blame] | 17 | #include "SkTemplates.h" | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 18 |  | 
| msarett | 39b2d5a | 2016-02-17 08:26:31 -0800 | [diff] [blame] | 19 | class JpegDecoderMgr; | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 20 |  | 
|  | 21 | /* | 
|  | 22 | * | 
|  | 23 | * This class implements the decoding for jpeg images | 
|  | 24 | * | 
|  | 25 | */ | 
|  | 26 | class SkJpegCodec : public SkCodec { | 
|  | 27 | public: | 
| scroggo | db30be2 | 2015-12-08 18:54:13 -0800 | [diff] [blame] | 28 | static bool IsJpeg(const void*, size_t); | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 29 |  | 
|  | 30 | /* | 
|  | 31 | * Assumes IsJpeg was called and returned true | 
|  | 32 | * Creates a jpeg decoder | 
|  | 33 | * Takes ownership of the stream | 
|  | 34 | */ | 
|  | 35 | static SkCodec* NewFromStream(SkStream*); | 
|  | 36 |  | 
|  | 37 | protected: | 
|  | 38 |  | 
|  | 39 | /* | 
|  | 40 | * Recommend a set of destination dimensions given a requested scale | 
|  | 41 | */ | 
|  | 42 | SkISize onGetScaledDimensions(float desiredScale) const override; | 
|  | 43 |  | 
|  | 44 | /* | 
|  | 45 | * Initiates the jpeg decode | 
|  | 46 | */ | 
|  | 47 | Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&, | 
| msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 48 | SkPMColor*, int*, int*) override; | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 49 |  | 
| msarett | 4984c3c | 2016-03-10 05:44:43 -0800 | [diff] [blame] | 50 | bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override; | 
| msarett | b714fb0 | 2016-01-22 14:46:42 -0800 | [diff] [blame] | 51 |  | 
| msarett | 4984c3c | 2016-03-10 05:44:43 -0800 | [diff] [blame] | 52 | Result onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override; | 
| msarett | b714fb0 | 2016-01-22 14:46:42 -0800 | [diff] [blame] | 53 |  | 
| Hal Canary | db68301 | 2016-11-23 08:55:18 -0700 | [diff] [blame] | 54 | SkEncodedImageFormat onGetEncodedFormat() const override { | 
|  | 55 | return SkEncodedImageFormat::kJPEG; | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 56 | } | 
|  | 57 |  | 
| scroggo | b427db1 | 2015-08-12 07:24:13 -0700 | [diff] [blame] | 58 | bool onRewind() override; | 
|  | 59 |  | 
| scroggo | e7fc14b | 2015-10-02 13:14:46 -0700 | [diff] [blame] | 60 | bool onDimensionsSupported(const SkISize&) override; | 
|  | 61 |  | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 62 | private: | 
|  | 63 |  | 
|  | 64 | /* | 
|  | 65 | * Read enough of the stream to initialize the SkJpegCodec. | 
|  | 66 | * Returns a bool representing success or failure. | 
|  | 67 | * | 
|  | 68 | * @param codecOut | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 69 | * If this returns true, and codecOut was not nullptr, | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 70 | * codecOut will be set to a new SkJpegCodec. | 
|  | 71 | * | 
|  | 72 | * @param decoderMgrOut | 
| halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 73 | * If this returns true, and codecOut was nullptr, | 
|  | 74 | * decoderMgrOut must be non-nullptr and decoderMgrOut will be set to a new | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 75 | * JpegDecoderMgr pointer. | 
|  | 76 | * | 
|  | 77 | * @param stream | 
|  | 78 | * Deleted on failure. | 
|  | 79 | * codecOut will take ownership of it in the case where we created a codec. | 
|  | 80 | * Ownership is unchanged when we set decoderMgrOut. | 
|  | 81 | * | 
|  | 82 | */ | 
|  | 83 | static bool ReadHeader(SkStream* stream, SkCodec** codecOut, | 
|  | 84 | JpegDecoderMgr** decoderMgrOut); | 
|  | 85 |  | 
|  | 86 | /* | 
|  | 87 | * Creates an instance of the decoder | 
|  | 88 | * Called only by NewFromStream | 
|  | 89 | * | 
| msarett | c30c418 | 2016-04-20 11:53:35 -0700 | [diff] [blame] | 90 | * @param info contains properties of the encoded data | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 91 | * @param stream the encoded image data | 
|  | 92 | * @param decoderMgr holds decompress struct, src manager, and error manager | 
|  | 93 | *                   takes ownership | 
|  | 94 | */ | 
| msarett | c30c418 | 2016-04-20 11:53:35 -0700 | [diff] [blame] | 95 | SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream, | 
| Matt Sarett | a9e9bfc | 2016-11-01 12:19:50 -0400 | [diff] [blame] | 96 | JpegDecoderMgr* decoderMgr, sk_sp<SkColorSpace> colorSpace, Origin origin); | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 97 |  | 
| msarett | 97fdea6 | 2015-04-29 08:17:15 -0700 | [diff] [blame] | 98 | /* | 
| msarett | 1c8a587 | 2015-07-07 08:50:01 -0700 | [diff] [blame] | 99 | * Checks if the conversion between the input image and the requested output | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 100 | * image has been implemented. | 
|  | 101 | * | 
|  | 102 | * Sets the output color space. | 
| msarett | 1c8a587 | 2015-07-07 08:50:01 -0700 | [diff] [blame] | 103 | */ | 
| msarett | 2ecc35f | 2016-09-08 11:55:16 -0700 | [diff] [blame] | 104 | bool setOutputColorSpace(const SkImageInfo& dst); | 
| msarett | 1c8a587 | 2015-07-07 08:50:01 -0700 | [diff] [blame] | 105 |  | 
| msarett | fdb4757 | 2015-10-13 12:50:14 -0700 | [diff] [blame] | 106 | void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options); | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 107 | void allocateStorage(const SkImageInfo& dstInfo); | 
|  | 108 | int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count); | 
|  | 109 |  | 
|  | 110 | /* | 
|  | 111 | * Scanline decoding. | 
|  | 112 | */ | 
| msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 113 | SkSampler* getSampler(bool createIfNecessary) override; | 
| scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 114 | Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options, | 
| msarett | fdb4757 | 2015-10-13 12:50:14 -0700 | [diff] [blame] | 115 | SkPMColor ctable[], int* ctableCount) override; | 
| msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 116 | int onGetScanlines(void* dst, int count, size_t rowBytes) override; | 
|  | 117 | bool onSkipScanlines(int count) override; | 
| scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 118 |  | 
| Ben Wagner | 145dbcd | 2016-11-03 14:40:50 -0400 | [diff] [blame] | 119 | std::unique_ptr<JpegDecoderMgr>    fDecoderMgr; | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 120 |  | 
| msarett | fbccb59 | 2015-09-01 06:43:41 -0700 | [diff] [blame] | 121 | // We will save the state of the decompress struct after reading the header. | 
|  | 122 | // This allows us to safely call onGetScaledDimensions() at any time. | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 123 | const int                          fReadyState; | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 124 |  | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 125 |  | 
|  | 126 | SkAutoTMalloc<uint8_t>             fStorage; | 
|  | 127 | uint8_t*                           fSwizzleSrcRow; | 
|  | 128 | uint32_t*                          fColorXformSrcRow; | 
|  | 129 |  | 
| msarett | 91c22b2 | 2016-02-22 12:27:46 -0800 | [diff] [blame] | 130 | // libjpeg-turbo provides some subsetting.  In the case that libjpeg-turbo | 
|  | 131 | // cannot take the exact the subset that we need, we will use the swizzler | 
|  | 132 | // to further subset the output from libjpeg-turbo. | 
| msarett | 50ce1f2 | 2016-07-29 06:23:33 -0700 | [diff] [blame] | 133 | SkIRect                            fSwizzlerSubset; | 
|  | 134 |  | 
| Ben Wagner | 145dbcd | 2016-11-03 14:40:50 -0400 | [diff] [blame] | 135 | std::unique_ptr<SkSwizzler>        fSwizzler; | 
| msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 136 |  | 
| msarett | e16b04a | 2015-04-15 07:32:19 -0700 | [diff] [blame] | 137 | typedef SkCodec INHERITED; | 
|  | 138 | }; | 
|  | 139 |  | 
|  | 140 | #endif |