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 "include/codec/SkCodec.h" 12 #include "include/codec/SkEncodedImageFormat.h" 13 #include "include/codec/SkEncodedOrigin.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkSize.h" 16 #include "include/core/SkTypes.h" 17 #include "include/core/SkYUVAPixmaps.h" 18 #include "include/private/SkEncodedInfo.h" 19 #include "include/private/base/SkTemplates.h" 20 21 #include <cstddef> 22 #include <cstdint> 23 #include <memory> 24 25 class JpegDecoderMgr; 26 class SkSampler; 27 class SkStream; 28 class SkSwizzler; 29 struct SkGainmapInfo; 30 struct SkImageInfo; 31 32 /* 33 * 34 * This class implements the decoding for jpeg images 35 * 36 */ 37 class SkJpegCodec : public SkCodec { 38 public: 39 ~SkJpegCodec() override; 40 41 static bool IsJpeg(const void*, size_t); 42 decoderMgr()43 JpegDecoderMgr* decoderMgr() {return fDecoderMgr.get();} 44 45 /* 46 * Assumes IsJpeg was called and returned true 47 * Takes ownership of the stream 48 */ 49 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*); 50 51 protected: 52 53 /* 54 * Recommend a set of destination dimensions given a requested scale 55 */ 56 SkISize onGetScaledDimensions(float desiredScale) const override; 57 58 /* 59 * Initiates the jpeg decode 60 */ 61 Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&, 62 int*) override; 63 64 bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&, 65 SkYUVAPixmapInfo*) const override; 66 67 Result onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) override; 68 onGetEncodedFormat()69 SkEncodedImageFormat onGetEncodedFormat() const override { 70 return SkEncodedImageFormat::kJPEG; 71 } 72 73 bool onRewind() override; 74 75 bool onDimensionsSupported(const SkISize&) override; 76 77 bool conversionSupported(const SkImageInfo&, bool, bool) override; 78 79 bool onGetGainmapCodec(SkGainmapInfo* info, std::unique_ptr<SkCodec>* gainmapCodec) override; 80 bool onGetGainmapInfo(SkGainmapInfo* info, 81 std::unique_ptr<SkStream>* gainmapImageStream) override; 82 83 private: 84 /* 85 * Allows SkRawCodec to communicate the color profile from the exif data. 86 */ 87 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*, 88 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile); 89 90 /* 91 * Read enough of the stream to initialize the SkJpegCodec. 92 * Returns a bool representing success or failure. 93 * 94 * @param codecOut 95 * If this returns true, and codecOut was not nullptr, 96 * codecOut will be set to a new SkJpegCodec. 97 * 98 * @param decoderMgrOut 99 * If this returns true, and codecOut was nullptr, 100 * decoderMgrOut must be non-nullptr and decoderMgrOut will be set to a new 101 * JpegDecoderMgr pointer. 102 * 103 * @param stream 104 * Deleted on failure. 105 * codecOut will take ownership of it in the case where we created a codec. 106 * Ownership is unchanged when we set decoderMgrOut. 107 * 108 * @param defaultColorProfile 109 * If the jpeg does not have an embedded color profile, the image data should 110 * be tagged with this color profile. 111 */ 112 static Result ReadHeader(SkStream* stream, SkCodec** codecOut, 113 JpegDecoderMgr** decoderMgrOut, 114 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile); 115 116 /* 117 * Creates an instance of the decoder 118 * Called only by NewFromStream 119 * 120 * @param info contains properties of the encoded data 121 * @param stream the encoded image data 122 * @param decoderMgr holds decompress struct, src manager, and error manager 123 * takes ownership 124 * @param origin indicates the image orientation as specified in Exif metadata. 125 * @param xmpMetadata holds the XMP metadata included in the image, if any. 126 */ 127 SkJpegCodec(SkEncodedInfo&& info, 128 std::unique_ptr<SkStream> stream, 129 JpegDecoderMgr* decoderMgr, 130 SkEncodedOrigin origin); 131 132 void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options, 133 bool needsCMYKToRGB); 134 [[nodiscard]] bool allocateStorage(const SkImageInfo& dstInfo); 135 Result readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count, 136 const Options&, int* rowsDecoded); 137 138 /* 139 * Scanline decoding. 140 */ 141 SkSampler* getSampler(bool createIfNecessary) override; 142 Result onStartScanlineDecode(const SkImageInfo& dstInfo, 143 const Options& options) override; 144 int onGetScanlines(void* dst, int count, size_t rowBytes) override; 145 bool onSkipScanlines(int count) override; 146 147 std::unique_ptr<JpegDecoderMgr> fDecoderMgr; 148 149 // We will save the state of the decompress struct after reading the header. 150 // This allows us to safely call onGetScaledDimensions() at any time. 151 const int fReadyState; 152 153 154 skia_private::AutoTMalloc<uint8_t> fStorage; 155 uint8_t* fSwizzleSrcRow = nullptr; 156 uint32_t* fColorXformSrcRow = nullptr; 157 158 // libjpeg-turbo provides some subsetting. In the case that libjpeg-turbo 159 // cannot take the exact the subset that we need, we will use the swizzler 160 // to further subset the output from libjpeg-turbo. 161 SkIRect fSwizzlerSubset = SkIRect::MakeEmpty(); 162 163 std::unique_ptr<SkSwizzler> fSwizzler; 164 165 friend class SkRawCodec; 166 167 using INHERITED = SkCodec; 168 }; 169 170 #endif 171