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" 12 #include "SkImageInfo.h" 13 #include "SkSwizzler.h" 14 #include "SkStream.h" 15 #include "SkTemplates.h" 16 17 class JpegDecoderMgr; 18 19 /* 20 * 21 * This class implements the decoding for jpeg images 22 * 23 */ 24 class SkJpegCodec : public SkCodec { 25 public: 26 static bool IsJpeg(const void*, size_t); 27 28 /* 29 * Assumes IsJpeg was called and returned true 30 * Creates a jpeg decoder 31 * Takes ownership of the stream 32 */ 33 static SkCodec* NewFromStream(SkStream*); 34 35 protected: 36 37 /* 38 * Recommend a set of destination dimensions given a requested scale 39 */ 40 SkISize onGetScaledDimensions(float desiredScale) const override; 41 42 /* 43 * Initiates the jpeg decode 44 */ 45 Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&, 46 SkPMColor*, int*, int*) override; 47 48 bool onQueryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override; 49 50 Result onGetYUV8Planes(const YUVSizeInfo& sizeInfo, void* pixels[3]) override; 51 52 SkEncodedFormat onGetEncodedFormat() const override { 53 return kJPEG_SkEncodedFormat; 54 } 55 56 bool onRewind() override; 57 58 bool onDimensionsSupported(const SkISize&) override; 59 60 private: 61 62 /* 63 * Read enough of the stream to initialize the SkJpegCodec. 64 * Returns a bool representing success or failure. 65 * 66 * @param codecOut 67 * If this returns true, and codecOut was not nullptr, 68 * codecOut will be set to a new SkJpegCodec. 69 * 70 * @param decoderMgrOut 71 * If this returns true, and codecOut was nullptr, 72 * decoderMgrOut must be non-nullptr and decoderMgrOut will be set to a new 73 * JpegDecoderMgr pointer. 74 * 75 * @param stream 76 * Deleted on failure. 77 * codecOut will take ownership of it in the case where we created a codec. 78 * Ownership is unchanged when we set decoderMgrOut. 79 * 80 */ 81 static bool ReadHeader(SkStream* stream, SkCodec** codecOut, 82 JpegDecoderMgr** decoderMgrOut); 83 84 /* 85 * Creates an instance of the decoder 86 * Called only by NewFromStream 87 * 88 * @param srcInfo contains the source width and height 89 * @param stream the encoded image data 90 * @param decoderMgr holds decompress struct, src manager, and error manager 91 * takes ownership 92 */ 93 SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, JpegDecoderMgr* decoderMgr); 94 95 /* 96 * Checks if the conversion between the input image and the requested output 97 * image has been implemented 98 * Sets the output color space 99 */ 100 bool setOutputColorSpace(const SkImageInfo& dst); 101 102 // scanline decoding 103 void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options); 104 SkSampler* getSampler(bool createIfNecessary) override; 105 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options, 106 SkPMColor ctable[], int* ctableCount) override; 107 int onGetScanlines(void* dst, int count, size_t rowBytes) override; 108 bool onSkipScanlines(int count) override; 109 110 SkAutoTDelete<JpegDecoderMgr> fDecoderMgr; 111 // We will save the state of the decompress struct after reading the header. 112 // This allows us to safely call onGetScaledDimensions() at any time. 113 const int fReadyState; 114 115 // scanline decoding 116 SkAutoTMalloc<uint8_t> fStorage; // Only used if sampling is needed 117 uint8_t* fSrcRow; // Only used if sampling is needed 118 // libjpeg-turbo provides some subsetting. In the case that libjpeg-turbo 119 // cannot take the exact the subset that we need, we will use the swizzler 120 // to further subset the output from libjpeg-turbo. 121 SkIRect fSwizzlerSubset; 122 SkAutoTDelete<SkSwizzler> fSwizzler; 123 124 typedef SkCodec INHERITED; 125 }; 126 127 #endif 128