diff --git a/image/Deinterlacer.cpp b/image/Deinterlacer.cpp new file mode 100644 index 000000000000..96a6512c3aa3 --- /dev/null +++ b/image/Deinterlacer.cpp @@ -0,0 +1,45 @@ +/* -*- 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/. */ + + +#include "Downscaler.h" + +namespace mozilla { +namespace image { + +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/Deinterlacer.h b/image/Deinterlacer.h new file mode 100644 index 000000000000..74ffd86ea4d1 --- /dev/null +++ b/image/Deinterlacer.h @@ -0,0 +1,50 @@ +/* -*- 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/. */ + + +/** + * 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. + */ + + +#ifndef mozilla_image_Deinterlacer_h +#define mozilla_image_Deinterlacer_h + +#include "Downscaler.h" + +namespace mozilla { +namespace image { + +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 + +#endif // mozilla_image_Deinterlacer_h diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp index a01b67c3a391..d83141b93e84 100644 --- a/image/Downscaler.cpp +++ b/image/Downscaler.cpp @@ -314,36 +314,7 @@ 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 4083e83df96e..a455a222c253 100644 --- a/image/Downscaler.h +++ b/image/Downscaler.h @@ -162,7 +162,7 @@ public: } uint8_t* RowBuffer() { return nullptr; } - void ClearRow(uint32_t = 0); + void ClearRow(uint32_t = 0) { } void CommitRow() { } bool HasInvalidation() const { return false; } DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); } @@ -171,33 +171,7 @@ 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 diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h index 76ddf1ac2230..952c6015a6aa 100644 --- a/image/decoders/nsGIFDecoder2.h +++ b/image/decoders/nsGIFDecoder2.h @@ -8,7 +8,7 @@ #define mozilla_image_decoders_nsGIFDecoder2_h #include "Decoder.h" - +#include "Deinterlacer.h" #include "GIF2.h" #include "nsCOMPtr.h" diff --git a/image/moz.build b/image/moz.build index cf4d51368ec5..7d92a204c331 100644 --- a/image/moz.build +++ b/image/moz.build @@ -54,6 +54,7 @@ UNIFIED_SOURCES += [ 'DecodePool.cpp', 'Decoder.cpp', 'DecoderFactory.cpp', + 'Deinterlacer.cpp', 'DynamicImage.cpp', 'FrameAnimator.cpp', 'FrozenImage.cpp',