From ff5202060db11813f4b9f002a81f6bd57842267c Mon Sep 17 00:00:00 2001 From: "asqueella%gmail.com" Date: Sat, 25 Aug 2007 20:07:37 +0000 Subject: [PATCH] Bug 392089 - JPEG decoding: Prevent allocation of scanline and remove memcpy p=Alfred Kayser r=stuart, sr=tor, a=stuart --- .../libpr0n/decoders/jpeg/nsJPEGDecoder.cpp | 60 +++++++------------ modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h | 2 - 2 files changed, 20 insertions(+), 42 deletions(-) diff --git a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp index 16b9fd82f2a..0a16c4b008b 100644 --- a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp +++ b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp @@ -83,8 +83,6 @@ nsJPEGDecoder::nsJPEGDecoder() mState = JPEG_HEADER; mReading = PR_TRUE; - mSamples = nsnull; - mBytesToSkip = 0; memset(&mInfo, 0, sizeof(jpeg_decompress_struct)); memset(&mSourceMgr, 0, sizeof(mSourceMgr)); @@ -419,22 +417,6 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR } mObserver->OnStartFrame(nsnull, mFrame); - - /* - * Make a one-row-high sample array that will go away - * when done with image. Always make it big enough to - * hold an RGB row. Since this uses the IJG memory - * manager, it must be allocated before the call to - * jpeg_start_compress(). - */ - /* - * From: http://apodeline.free.fr/DOC/libjpeg/libjpeg-2.html#ss2.3 : - * PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE - */ - mSamples = (*mInfo.mem->alloc_sarray)((j_common_ptr) &mInfo, - JPOOL_IMAGE, - mInfo.output_width * 3, 1); - mState = JPEG_START_DECOMPRESS; } @@ -580,42 +562,40 @@ nsJPEGDecoder::OutputScanlines() while ((mInfo.output_scanline < mInfo.output_height)) { /* Request one scanline. Returns 0 or 1 scanlines. */ - if (jpeg_read_scanlines(&mInfo, mSamples, 1) != 1) { + PRUint32 *imageRow = ((PRUint32*)imageData) + + (mInfo.output_scanline * mInfo.output_width); + + /* Use the Cairo image buffer as scanline buffer */ + JSAMPROW sampleRow = (JSAMPROW)imageRow; + if (!mTransform || mInfo.out_color_space != JCS_GRAYSCALE) { + /* Put the pixels at end of row to enable in-place expansion */ + sampleRow += mInfo.output_width; + } + + if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) { rv = PR_FALSE; /* suspend */ break; } if (mTransform) { + JSAMPROW source = sampleRow; if (mInfo.out_color_space == JCS_GRAYSCALE) { - /* move gray data to end of mSample array so - cmsDoTransform can do in-place transform */ - memcpy(mSamples[0] + 2 * mInfo.output_width, - mSamples[0], - mInfo.output_width); - cmsDoTransform(mTransform, - mSamples[0] + 2 * mInfo.output_width, mSamples[0], - mInfo.output_width); - } else - cmsDoTransform(mTransform, - mSamples[0], mSamples[0], - mInfo.output_width); + /* Convert from the 1byte grey pixels at begin of row + to the 3byte RGB byte pixels at 'end' of row */ + sampleRow += mInfo.output_width; + } + cmsDoTransform(mTransform, source, sampleRow, mInfo.output_width); } else if (gfxPlatform::IsCMSEnabled()) { /* No embedded ICC profile - treat as sRGB */ cmsHTRANSFORM transform = gfxPlatform::GetCMSRGBTransform(); if (transform) { - cmsDoTransform(transform, - mSamples[0], mSamples[0], - mInfo.output_width); + cmsDoTransform(transform, sampleRow, sampleRow, mInfo.output_width); } } - // offset is in Cairo pixels (PRUint32) - PRUint32 offset = (mInfo.output_scanline - 1) * mInfo.output_width; - PRUint32 *ptrOutputBuf = ((PRUint32*)imageData) + offset; - JSAMPLE *j1 = mSamples[0]; for (PRUint32 i=mInfo.output_width; i>0; --i) { - *ptrOutputBuf++ = GFX_PACKED_PIXEL(0xFF, j1[0], j1[1], j1[2]); - j1+=3; + *imageRow++ = GFX_PACKED_PIXEL(0xFF, sampleRow[0], sampleRow[1], sampleRow[2]); + sampleRow += 3; } } diff --git a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h index 83bb8188986..d4f960d42fd 100644 --- a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h +++ b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h @@ -106,8 +106,6 @@ public: decoder_error_mgr mErr; jstate mState; - JSAMPARRAY mSamples; - PRUint32 mBytesToSkip; JOCTET *mBuffer;