mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1045929 (Part 2) - Implement downscale-during-decode for JPEG images. r=tn
This commit is contained in:
parent
5b8d5a0e13
commit
89a1c6658e
@ -139,6 +139,20 @@ nsJPEGDecoder::SpeedHistogram()
|
||||
return Telemetry::IMAGE_DECODE_SPEED_JPEG;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJPEGDecoder::SetTargetSize(const nsIntSize& aSize)
|
||||
{
|
||||
// Make sure the size is reasonable.
|
||||
if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Create a downscaler that we'll filter our output through.
|
||||
mDownscaler.emplace(aSize);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsJPEGDecoder::InitInternal()
|
||||
{
|
||||
@ -394,6 +408,17 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDownscaler) {
|
||||
nsresult rv = mDownscaler->BeginFrame(GetSize(),
|
||||
mImageData,
|
||||
/* aHasAlpha = */ false);
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = JPEG_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
|
||||
(" JPEGDecoderAccounting: nsJPEGDecoder::"
|
||||
"Write -- created image frame with %ux%u pixels",
|
||||
@ -512,6 +537,7 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
break;
|
||||
|
||||
mInfo.output_scanline = 0;
|
||||
mDownscaler->ResetForNextProgressivePass();
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,9 +617,15 @@ nsJPEGDecoder::OutputScanlines(bool* suspend)
|
||||
const uint32_t top = mInfo.output_scanline;
|
||||
|
||||
while ((mInfo.output_scanline < mInfo.output_height)) {
|
||||
// Use the Cairo image buffer as scanline buffer
|
||||
uint32_t* imageRow = ((uint32_t*)mImageData) +
|
||||
(mInfo.output_scanline * mInfo.output_width);
|
||||
uint32_t* imageRow = nullptr;
|
||||
if (mDownscaler) {
|
||||
imageRow = reinterpret_cast<uint32_t*>(mDownscaler->RowBuffer());
|
||||
} else {
|
||||
imageRow = reinterpret_cast<uint32_t*>(mImageData) +
|
||||
(mInfo.output_scanline * mInfo.output_width);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(imageRow, "Should have a row buffer here");
|
||||
|
||||
if (mInfo.out_color_space == MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB) {
|
||||
// Special case: scanline will be directly converted into packed ARGB
|
||||
@ -601,6 +633,9 @@ nsJPEGDecoder::OutputScanlines(bool* suspend)
|
||||
*suspend = true; // suspend
|
||||
break;
|
||||
}
|
||||
if (mDownscaler) {
|
||||
mDownscaler->CommitRow();
|
||||
}
|
||||
continue; // all done for this row!
|
||||
}
|
||||
|
||||
@ -676,13 +711,22 @@ nsJPEGDecoder::OutputScanlines(bool* suspend)
|
||||
sampleRow[2]);
|
||||
sampleRow += 3;
|
||||
}
|
||||
|
||||
if (mDownscaler) {
|
||||
mDownscaler->CommitRow();
|
||||
}
|
||||
}
|
||||
|
||||
if (top != mInfo.output_scanline) {
|
||||
nsIntRect r(0, top, mInfo.output_width, mInfo.output_scanline-top);
|
||||
PostInvalidation(r);
|
||||
PostInvalidation(nsIntRect(0, top,
|
||||
mInfo.output_width,
|
||||
mInfo.output_scanline - top),
|
||||
mDownscaler ? Some(mDownscaler->TakeInvalidRect())
|
||||
: Nothing());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mDownscaler || !mDownscaler->HasInvalidation(),
|
||||
"Didn't send downscaler's invalidation");
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "Decoder.h"
|
||||
|
||||
#include "Downscaler.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "nsIInputStream.h"
|
||||
@ -55,6 +56,8 @@ public:
|
||||
nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle);
|
||||
virtual ~nsJPEGDecoder();
|
||||
|
||||
virtual nsresult SetTargetSize(const nsIntSize& aSize) MOZ_OVERRIDE;
|
||||
|
||||
virtual void InitInternal() MOZ_OVERRIDE;
|
||||
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE;
|
||||
virtual void FinishInternal() MOZ_OVERRIDE;
|
||||
@ -66,6 +69,8 @@ protected:
|
||||
Orientation ReadOrientationFromEXIF();
|
||||
void OutputScanlines(bool* suspend);
|
||||
|
||||
Maybe<Downscaler> mDownscaler;
|
||||
|
||||
public:
|
||||
struct jpeg_decompress_struct mInfo;
|
||||
struct jpeg_source_mgr mSourceMgr;
|
||||
|
@ -34,8 +34,9 @@ ImageFactory::Initialize()
|
||||
static bool
|
||||
ShouldDownscaleDuringDecode(const nsCString& aMimeType)
|
||||
{
|
||||
// Not enabled for anything yet.
|
||||
return false;
|
||||
return aMimeType.EqualsLiteral(IMAGE_JPEG) ||
|
||||
aMimeType.EqualsLiteral(IMAGE_JPG) ||
|
||||
aMimeType.EqualsLiteral(IMAGE_PJPEG);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
Loading…
Reference in New Issue
Block a user