123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /**
- * Downscaler is a high-quality, streaming image downscaler based upon Skia's
- * scaling implementation.
- */
- #ifndef mozilla_image_Downscaler_h
- #define mozilla_image_Downscaler_h
- #include "mozilla/Maybe.h"
- #include "mozilla/UniquePtr.h"
- #include "gfxPoint.h"
- #include "nsRect.h"
- namespace skia {
- class ConvolutionFilter1D;
- } // namespace skia
- namespace mozilla {
- namespace image {
- /**
- * DownscalerInvalidRect wraps two invalidation rects: one in terms of the
- * original image size, and one in terms of the target size.
- */
- struct DownscalerInvalidRect
- {
- nsIntRect mOriginalSizeRect;
- nsIntRect mTargetSizeRect;
- };
- #ifdef MOZ_ENABLE_SKIA
- /**
- * Downscaler is a high-quality, streaming image downscaler based upon Skia's
- * scaling implementation.
- *
- * Decoders can construct a Downscaler once they know their target size, then
- * call BeginFrame() for each frame they decode. They should write a decoded row
- * into the buffer returned by RowBuffer(), and then call CommitRow() to signal
- * that they have finished.
- *
- * Because invalidations need to be computed in terms of the scaled version of
- * the image, Downscaler also tracks them. Decoders can call HasInvalidation()
- * and TakeInvalidRect() instead of tracking invalidations themselves.
- */
- class Downscaler
- {
- public:
- /// Constructs a new Downscaler which to scale to size @aTargetSize.
- explicit Downscaler(const nsIntSize& aTargetSize);
- ~Downscaler();
- const nsIntSize& OriginalSize() const { return mOriginalSize; }
- const nsIntSize& TargetSize() const { return mTargetSize; }
- const nsIntSize FrameSize() const { return nsIntSize(mFrameRect.width, mFrameRect.height); }
- const gfxSize& Scale() const { return mScale; }
- /**
- * Begins a new frame and reinitializes the Downscaler.
- *
- * @param aOriginalSize The original size of this frame, before scaling.
- * @param aFrameRect The region of the original image which has data.
- * Every pixel outside @aFrameRect is considered blank and
- * has zero alpha.
- * @param aOutputBuffer The buffer to which the Downscaler should write its
- * output; this is the same buffer where the Decoder
- * would write its output when not downscaling during
- * decode.
- * @param aHasAlpha Whether or not this frame has an alpha channel.
- * Performance is a little better if it doesn't have one.
- * @param aFlipVertically If true, output rows will be written to the output
- * buffer in reverse order vertically, which matches
- * the way they are stored in some image formats.
- */
- nsresult BeginFrame(const nsIntSize& aOriginalSize,
- const Maybe<nsIntRect>& aFrameRect,
- uint8_t* aOutputBuffer,
- bool aHasAlpha,
- bool aFlipVertically = false);
- bool IsFrameComplete() const { return mCurrentInLine >= mOriginalSize.height; }
- /// Retrieves the buffer into which the Decoder should write each row.
- uint8_t* RowBuffer()
- {
- return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
- }
- /// Clears the current row buffer.
- void ClearRow() { ClearRestOfRow(0); }
- /// Clears the current row buffer starting at @aStartingAtCol.
- void ClearRestOfRow(uint32_t aStartingAtCol);
- /// Signals that the decoder has finished writing a row into the row buffer.
- void CommitRow();
- /// Returns true if there is a non-empty invalid rect available.
- bool HasInvalidation() const;
- /// Takes the Downscaler's current invalid rect and resets it.
- DownscalerInvalidRect TakeInvalidRect();
- /**
- * Resets the Downscaler's position in the image, for a new progressive pass
- * over the same frame. Because the same data structures can be reused, this
- * is more efficient than calling BeginFrame.
- */
- void ResetForNextProgressivePass();
- private:
- void DownscaleInputLine();
- void ReleaseWindow();
- void SkipToRow(int32_t aRow);
- nsIntSize mOriginalSize;
- nsIntSize mTargetSize;
- nsIntRect mFrameRect;
- gfxSize mScale;
- uint8_t* mOutputBuffer;
- UniquePtr<uint8_t[]> mRowBuffer;
- UniquePtr<uint8_t*[]> mWindow;
- UniquePtr<skia::ConvolutionFilter1D> mXFilter;
- UniquePtr<skia::ConvolutionFilter1D> mYFilter;
- int32_t mWindowCapacity;
- int32_t mLinesInBuffer;
- int32_t mPrevInvalidatedLine;
- int32_t mCurrentOutLine;
- int32_t mCurrentInLine;
- bool mHasAlpha : 1;
- bool mFlipVertically : 1;
- };
- #else
- /**
- * Downscaler requires Skia to work, so we provide a dummy implementation if
- * Skia is disabled that asserts if constructed.
- */
- class Downscaler
- {
- public:
- explicit Downscaler(const nsIntSize&)
- {
- MOZ_RELEASE_ASSERT(false, "Skia is not enabled");
- }
- const nsIntSize& OriginalSize() const { return nsIntSize(); }
- const nsIntSize& TargetSize() const { return nsIntSize(); }
- const gfxSize& Scale() const { return gfxSize(1.0, 1.0); }
- nsresult BeginFrame(const nsIntSize&, const Maybe<nsIntRect>&, uint8_t*, bool, bool = false)
- {
- return NS_ERROR_FAILURE;
- }
- bool IsFrameComplete() const { return false; }
- uint8_t* RowBuffer() { return nullptr; }
- void ClearRow() { }
- void ClearRestOfRow(uint32_t) { }
- void CommitRow() { }
- bool HasInvalidation() const { return false; }
- DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }
- void ResetForNextProgressivePass() { }
- const nsIntSize FrameSize() const { return nsIntSize(0, 0); }
- };
- #endif // MOZ_ENABLE_SKIA
- } // namespace image
- } // namespace mozilla
- #endif // mozilla_image_Downscaler_h
|