Downscaler.h (4880B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * Downscaler is a high-quality, streaming image downscaler based upon Skia's 9 * scaling implementation. 10 */ 11 12 #ifndef mozilla_image_Downscaler_h 13 #define mozilla_image_Downscaler_h 14 15 #include "mozilla/Maybe.h" 16 #include "mozilla/UniquePtr.h" 17 #include "gfxPoint.h" 18 #include "nsRect.h" 19 #include "mozilla/gfx/ConvolutionFilter.h" 20 #include "mozilla/gfx/Matrix.h" 21 22 namespace mozilla { 23 namespace image { 24 25 /** 26 * DownscalerInvalidRect wraps two invalidation rects: one in terms of the 27 * original image size, and one in terms of the target size. 28 */ 29 struct DownscalerInvalidRect { 30 nsIntRect mOriginalSizeRect; 31 nsIntRect mTargetSizeRect; 32 }; 33 34 /** 35 * Downscaler is a high-quality, streaming image downscaler based upon Skia's 36 * scaling implementation. 37 * 38 * Decoders can construct a Downscaler once they know their target size, then 39 * call BeginFrame() for each frame they decode. They should write a decoded row 40 * into the buffer returned by RowBuffer(), and then call CommitRow() to signal 41 * that they have finished. 42 * 43 44 * Because invalidations need to be computed in terms of the scaled version of 45 * the image, Downscaler also tracks them. Decoders can call HasInvalidation() 46 * and TakeInvalidRect() instead of tracking invalidations themselves. 47 */ 48 class Downscaler { 49 public: 50 /// Constructs a new Downscaler which to scale to size @aTargetSize. 51 explicit Downscaler(const nsIntSize& aTargetSize); 52 ~Downscaler(); 53 54 const nsIntSize& OriginalSize() const { return mOriginalSize; } 55 const nsIntSize& TargetSize() const { return mTargetSize; } 56 const nsIntSize FrameSize() const { 57 return nsIntSize(mFrameRect.Width(), mFrameRect.Height()); 58 } 59 const gfx::MatrixScalesDouble& Scale() const { return mScale; } 60 61 /** 62 * Begins a new frame and reinitializes the Downscaler. 63 * 64 * @param aOriginalSize The original size of this frame, before scaling. 65 * @param aFrameRect The region of the original image which has data. 66 * Every pixel outside @aFrameRect is considered blank and 67 * has zero alpha. 68 * @param aOutputBuffer The buffer to which the Downscaler should write its 69 * output; this is the same buffer where the Decoder 70 * would write its output when not downscaling during 71 * decode. 72 * @param aFormat The format of this frame. Performance is a little better if 73 * it is opaque. 74 * @param aFlipVertically If true, output rows will be written to the output 75 * buffer in reverse order vertically, which matches 76 * the way they are stored in some image formats. 77 */ 78 nsresult BeginFrame(const nsIntSize& aOriginalSize, 79 const Maybe<nsIntRect>& aFrameRect, 80 uint8_t* aOutputBuffer, gfx::SurfaceFormat aFormat, 81 bool aFlipVertically = false); 82 83 bool IsFrameComplete() const { 84 return mCurrentInLine >= mOriginalSize.height; 85 } 86 87 /// Retrieves the buffer into which the Decoder should write each row. 88 uint8_t* RowBuffer() { 89 return mRowBuffer.get() + mFrameRect.X() * sizeof(uint32_t); 90 } 91 92 /// Clears the current row buffer. 93 void ClearRow() { ClearRestOfRow(0); } 94 95 /// Clears the current row buffer starting at @aStartingAtCol. 96 void ClearRestOfRow(uint32_t aStartingAtCol); 97 98 /// Signals that the decoder has finished writing a row into the row buffer. 99 void CommitRow(); 100 101 /// Returns true if there is a non-empty invalid rect available. 102 bool HasInvalidation() const; 103 104 /// Takes the Downscaler's current invalid rect and resets it. 105 DownscalerInvalidRect TakeInvalidRect(); 106 107 /** 108 * Resets the Downscaler's position in the image, for a new progressive pass 109 * over the same frame. Because the same data structures can be reused, this 110 * is more efficient than calling BeginFrame. 111 */ 112 void ResetForNextProgressivePass(); 113 114 private: 115 void DownscaleInputLine(); 116 void ReleaseWindow(); 117 void SkipToRow(int32_t aRow); 118 119 nsIntSize mOriginalSize; 120 nsIntSize mTargetSize; 121 nsIntRect mFrameRect; 122 gfx::MatrixScalesDouble mScale; 123 124 uint8_t* mOutputBuffer; 125 126 UniquePtr<uint8_t[]> mRowBuffer; 127 UniquePtr<uint8_t*[]> mWindow; 128 129 gfx::ConvolutionFilter mXFilter; 130 gfx::ConvolutionFilter mYFilter; 131 132 int32_t mWindowCapacity; 133 134 int32_t mLinesInBuffer; 135 int32_t mPrevInvalidatedLine; 136 int32_t mCurrentOutLine; 137 int32_t mCurrentInLine; 138 139 gfx::SurfaceFormat mFormat; 140 bool mFlipVertically : 1; 141 }; 142 143 } // namespace image 144 } // namespace mozilla 145 146 #endif // mozilla_image_Downscaler_h