From e014eaa3c17201a6c74051cba3fb2ad0fdd1c080 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Thu, 17 Sep 2015 15:03:31 -0700 Subject: [PATCH] Bug 1194058 (Part 1) - Add Deinterlacer to allow Downscaler to work with interlaced images. r=tn --- image/Downscaler.cpp | 31 +++++++++++++++++++++++++++++++ image/Downscaler.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp index 24933d79b8c..0700eeb3229 100644 --- a/image/Downscaler.cpp +++ b/image/Downscaler.cpp @@ -281,5 +281,36 @@ Downscaler::DownscaleInputLine() } } +Deinterlacer::Deinterlacer(const nsIntSize& aImageSize) + : mImageSize(aImageSize) + , mBuffer(MakeUnique(mImageSize.width * + mImageSize.height * + sizeof(uint32_t))) +{ } + +uint32_t +Deinterlacer::RowSize() const +{ + return mImageSize.width * sizeof(uint32_t); +} + +uint8_t* +Deinterlacer::RowBuffer(uint32_t aRow) +{ + uint32_t offset = aRow * RowSize(); + MOZ_ASSERT(offset < mImageSize.width * mImageSize.height * sizeof(uint32_t), + "Row is outside of image"); + return mBuffer.get() + offset; +} + +void +Deinterlacer::PropagatePassToDownscaler(Downscaler& aDownscaler) +{ + for (int32_t row = 0 ; row < mImageSize.height ; ++row) { + memcpy(aDownscaler.RowBuffer(), RowBuffer(row), RowSize()); + aDownscaler.CommitRow(); + } +} + } // namespace image } // namespace mozilla diff --git a/image/Downscaler.h b/image/Downscaler.h index 745d6854ef5..c883d952895 100644 --- a/image/Downscaler.h +++ b/image/Downscaler.h @@ -162,6 +162,34 @@ public: #endif // MOZ_ENABLE_SKIA +/** + * Deinterlacer is a utility class to allow Downscaler to work with interlaced + * images. + + * Since Downscaler needs to receive rows in top-to-bottom or + * bottom-to-top order, it can't natively handle interlaced images, in which the + * rows arrive in an interleaved order. Deinterlacer solves this problem by + * acting as an intermediate buffer that records decoded rows. Unlike + * Downscaler, it allows the rows to be written in arbitrary order. After each + * pass, calling PropagatePassToDownscaler() will downscale every buffered row + * in a single operation. The rows remain in the buffer, so rows that were + * written in one pass will be included in subsequent passes. + */ +class Deinterlacer +{ +public: + explicit Deinterlacer(const nsIntSize& aImageSize); + + uint8_t* RowBuffer(uint32_t aRow); + void PropagatePassToDownscaler(Downscaler& aDownscaler); + +private: + uint32_t RowSize() const; + + nsIntSize mImageSize; + UniquePtr mBuffer; +}; + } // namespace image } // namespace mozilla