Changeset 53309 in webkit


Ignore:
Timestamp:
Jan 14, 2010 5:45:23 PM (14 years ago)
Author:
pkasting@chromium.org
Message:

Simplify image decoders by making downsampling functions available at
all times, allowing much duplicated logic to be collapsed.
https://bugs.webkit.org/show_bug.cgi?id=28751

Reviewed by Adam Barth.

  • platform/graphics/ImageSource.cpp:

(WebCore::ImageSource::setData):

  • platform/image-decoders/ImageDecoder.cpp:

(WebCore::ImageDecoder::prepareScaleDataIfNecessary):

  • platform/image-decoders/ImageDecoder.h:

(WebCore::ImageDecoder::ImageDecoder):
(WebCore::ImageDecoder::scaledSize):
(WebCore::ImageDecoder::setMaxNumPixels):

  • platform/image-decoders/gif/GIFImageDecoder.cpp:

(WebCore::GIFImageDecoder::sizeNowAvailable):
(WebCore::GIFImageDecoder::initFrameBuffer):
(WebCore::GIFImageDecoder::haveDecodedRow):
(WebCore::GIFImageDecoder::frameComplete):

  • platform/image-decoders/jpeg/JPEGImageDecoder.cpp:

(WebCore::JPEGImageDecoder::setSize):
(WebCore::JPEGImageDecoder::outputScanlines):

  • platform/image-decoders/jpeg/JPEGImageDecoder.h:
  • platform/image-decoders/png/PNGImageDecoder.cpp:

(WebCore::PNGImageDecoder::headerAvailable):
(WebCore::PNGImageDecoder::rowAvailable):

Location:
trunk/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r53308 r53309  
     12010-01-14  Peter Kasting  <pkasting@google.com>
     2
     3        Reviewed by Adam Barth.
     4
     5        Simplify image decoders by making downsampling functions available at
     6        all times, allowing much duplicated logic to be collapsed.
     7        https://bugs.webkit.org/show_bug.cgi?id=28751
     8
     9        * platform/graphics/ImageSource.cpp:
     10        (WebCore::ImageSource::setData):
     11        * platform/image-decoders/ImageDecoder.cpp:
     12        (WebCore::ImageDecoder::prepareScaleDataIfNecessary):
     13        * platform/image-decoders/ImageDecoder.h:
     14        (WebCore::ImageDecoder::ImageDecoder):
     15        (WebCore::ImageDecoder::scaledSize):
     16        (WebCore::ImageDecoder::setMaxNumPixels):
     17        * platform/image-decoders/gif/GIFImageDecoder.cpp:
     18        (WebCore::GIFImageDecoder::sizeNowAvailable):
     19        (WebCore::GIFImageDecoder::initFrameBuffer):
     20        (WebCore::GIFImageDecoder::haveDecodedRow):
     21        (WebCore::GIFImageDecoder::frameComplete):
     22        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
     23        (WebCore::JPEGImageDecoder::setSize):
     24        (WebCore::JPEGImageDecoder::outputScanlines):
     25        * platform/image-decoders/jpeg/JPEGImageDecoder.h:
     26        * platform/image-decoders/png/PNGImageDecoder.cpp:
     27        (WebCore::PNGImageDecoder::headerAvailable):
     28        (WebCore::PNGImageDecoder::rowAvailable):
     29
    1302010-01-14  Jian Li  <jianli@chromium.org>
    231
  • trunk/WebCore/platform/graphics/ImageSource.cpp

    r52102 r53309  
    3434#else
    3535#include "ImageDecoder.h"
    36 #endif
    37 
    38 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    39 #ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS
    40 #define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024)
    41 #endif
    4236#endif
    4337
     
    8276        m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data));
    8377#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     78#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS
     79#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024)
     80#endif
    8481        if (m_decoder)
    8582            m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS);
  • trunk/WebCore/platform/image-decoders/ImageDecoder.cpp

    r53152 r53309  
    2424#include "ImageDecoder.h"
    2525
    26 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    2726#include <algorithm>
    28 #endif
     27#include <cmath>
    2928
    3029#include "BMPImageDecoder.h"
     
    185184#endif
    186185
    187 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    188 
    189186namespace {
    190187
     
    211208template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart)
    212209{
     210    if (scaledValues.isEmpty())
     211        return valueToMatch;
     212
    213213    const int* dataStart = scaledValues.data();
    214214    const int* dataEnd = dataStart + scaledValues.size();
     
    229229void ImageDecoder::prepareScaleDataIfNecessary()
    230230{
    231     int width = m_size.width();
    232     int height = m_size.height();
     231    int width = size().width();
     232    int height = size().height();
    233233    int numPixels = height * width;
    234     if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels) {
     234    if (m_maxNumPixels > 0 && numPixels > m_maxNumPixels) {
     235        m_scaled = true;
     236        double scale = sqrt(m_maxNumPixels / (double)numPixels);
     237        fillScaledValues(m_scaledColumns, scale, width);
     238        fillScaledValues(m_scaledRows, scale, height);
     239    } else if (m_scaled) {
    235240        m_scaled = false;
    236         return;
    237     }
    238 
    239     m_scaled = true;
    240     double scale = sqrt(m_maxNumPixels / (double)numPixels);
    241     fillScaledValues(m_scaledColumns, scale, width);
    242     fillScaledValues(m_scaledRows, scale, height);
     241        m_scaledColumns.clear();
     242        m_scaledRows.clear();
     243    }
    243244}
    244245
     
    268269}
    269270
    270 #endif // ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    271 
    272 }
     271}
  • trunk/WebCore/platform/image-decoders/ImageDecoder.h

    r53148 r53309  
    131131        }
    132132
    133 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    134         const IntRect& scaledRect() const { return m_scaledRect; }
    135         void setScaledRect(const IntRect& r) { m_scaledRect = r; }
    136 #endif
    137 
    138133#if PLATFORM(QT)
    139134        void setDecodedImage(const QImage& image);
     
    193188        FrameDisposalMethod m_disposalMethod;
    194189                              // What to do with this frame's data when initializing the next frame.
    195 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    196         IntRect m_scaledRect;
    197 #endif
    198190    };
    199191
     
    208200        // images that are bigger than m_maxNumPixels. (Not supported by all image decoders yet)
    209201        ImageDecoder()
    210             : m_failed(false)
     202            : m_scaled(false)
     203            , m_failed(false)
    211204            , m_sizeAvailable(false)
    212205            , m_isAllDataReceived(false)
    213 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    214206            , m_maxNumPixels(-1)
    215             , m_scaled(false)
    216 #endif
    217207        {
    218208        }
     
    251241            ASSERT(!m_failed);
    252242            return m_size;
     243        }
     244
     245        IntSize scaledSize() const
     246        {
     247            return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
    253248        }
    254249
     
    308303#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    309304        void setMaxNumPixels(int m) { m_maxNumPixels = m; }
    310         IntSize scaledSize() const { return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : m_size; }
    311305#endif
    312306
    313307    protected:
    314 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    315308        void prepareScaleDataIfNecessary();
    316309        int upperBoundScaledX(int origX, int searchStart = 0);
     
    319312        int lowerBoundScaledY(int origY, int searchStart = 0);
    320313        int scaledY(int origY, int searchStart = 0);
    321 #endif
    322314
    323315        RefPtr<SharedBuffer> m_data; // The encoded data.
    324 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    325         int m_maxNumPixels;
    326316        Vector<int> m_scaledColumns;
    327317        Vector<int> m_scaledRows;
    328318        bool m_scaled;
    329 #endif
    330319        Vector<RGBA32Buffer> m_frameBufferCache;
    331320        bool m_failed;
     
    346335        bool m_sizeAvailable;
    347336        bool m_isAllDataReceived;
     337        int m_maxNumPixels;
    348338    };
    349339
  • trunk/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp

    r53148 r53309  
    249249    if (!setSize(width, height))
    250250        return false;
    251 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    252251    prepareScaleDataIfNecessary();
    253 #endif
    254252    return true;
    255253}
     
    273271
    274272    RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
    275     buffer->setRect(frameRect);
    276 
    277 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    278     if (m_scaled) {
    279         int left = upperBoundScaledX(frameRect.x());
    280         int right = lowerBoundScaledX(frameRect.right(), left);
    281         int top = upperBoundScaledY(frameRect.y());
    282         int bottom = lowerBoundScaledY(frameRect.bottom(), top);
    283         buffer->setScaledRect(IntRect(left, top, right - left, bottom - top));
    284     } else
    285         buffer->setScaledRect(frameRect);
    286 #endif
    287    
     273    int left = upperBoundScaledX(frameRect.x());
     274    int right = lowerBoundScaledX(frameRect.right(), left);
     275    int top = upperBoundScaledY(frameRect.y());
     276    int bottom = lowerBoundScaledY(frameRect.bottom(), top);
     277    buffer->setRect(IntRect(left, top, right - left, bottom - top));
     278
    288279    if (frameIndex == 0) {
    289280        // This is the first frame, so we're not relying on any previous data.
    290 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    291         const IntSize& bufferSize = scaledSize();
    292 #else
    293         const IntSize& bufferSize = size();
    294 #endif
    295         if (!buffer->setSize(bufferSize.width(), bufferSize.height())) {
     281        if (!buffer->setSize(scaledSize().width(), scaledSize().height())) {
    296282            m_failed = true;
    297283            return false;
     
    323309            // We want to clear the previous frame to transparent, without
    324310            // affecting pixels in the image outside of the frame.
    325 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    326             const IntRect& prevRect = prevBuffer->scaledRect();
     311            const IntRect& prevRect = prevBuffer->rect();
    327312            const IntSize& bufferSize = scaledSize();
    328 #else
    329             const IntRect& prevRect = prevBuffer->rect();
    330             const IntSize& bufferSize = size();
    331 #endif
    332313            if ((frameIndex == 0)
    333314                || prevRect.contains(IntRect(IntPoint(), bufferSize))) {
     
    359340}
    360341
    361 static inline void copyOnePixel(const GIFImageDecoderPrivate* reader, const unsigned char* sourceAddr, unsigned char* colorMap,
    362                                 unsigned colorMapSize, bool writeTransparentPixels, RGBA32Buffer& buffer, int x, int  y, bool& sawAlpha)
    363 {
    364     const unsigned char sourceValue = *sourceAddr;
    365     if ((!reader->isTransparent() || (sourceValue != reader->transparentPixel())) && (sourceValue < colorMapSize)) {
    366         const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
    367         buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
    368     } else {
    369         sawAlpha = true;
    370         // We may or may not need to write transparent pixels to the buffer.
    371         // If we're compositing against a previous image, it's wrong, and if
    372         // we're writing atop a cleared, fully transparent buffer, it's
    373         // unnecessary; but if we're decoding an interlaced gif and
    374         // displaying it "Haeberli"-style, we must write these for passes
    375         // beyond the first, or the initial passes will "show through" the
    376         // later ones.
    377         if (writeTransparentPixels)
    378             buffer.setRGBA(x, y, 0, 0, 0, 0);
    379     }
    380 }
    381 
    382342bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
    383343                                     unsigned char* rowBuffer,
     
    389349    // The pixel data and coordinates supplied to us are relative to the frame's
    390350    // origin within the entire image size, i.e.
    391     // (m_reader->frameXOffset(), m_reader->frameYOffset()).
    392     int x = m_reader->frameXOffset();
    393     int y = m_reader->frameYOffset() + rowNumber;
    394 
    395     // Sanity-check the arguments.
    396     if ((rowBuffer == 0) || (y >= size().height()))
     351    // (m_reader->frameXOffset(), m_reader->frameYOffset()).  There is no
     352    // guarantee that
     353    // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so
     354    // we must ensure we don't run off the end of either the source data or the
     355    // row's X-coordinates.
     356    int xBegin = upperBoundScaledX(m_reader->frameXOffset());
     357    int yBegin = upperBoundScaledY(m_reader->frameYOffset() + rowNumber);
     358    int xEnd = lowerBoundScaledX(std::min(xBegin + (rowEnd - rowBuffer), size().width()) - 1, xBegin + 1) + 1;
     359    int yEnd = lowerBoundScaledY(std::min(yBegin + static_cast<int>(repeatCount), size().height()) - 1, yBegin + 1) + 1;
     360    if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
    397361        return true;
    398362
     
    409373        return false;
    410374
    411 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    412     int destYBegin = y;
    413     int destYEnd = std::min(y + static_cast<int>(repeatCount), size().height());
    414     int destXBegin = x;
    415     int destXEnd = std::min(x + (rowEnd - rowBuffer), size().width());
    416 
    417     if (m_scaled) {
    418         destYBegin = upperBoundScaledY(destYBegin);
    419         if (destYBegin < 0)
    420             return true;
    421         destYEnd = lowerBoundScaledY(destYEnd - 1, destYBegin + 1);
    422         if (destYEnd < destYBegin)
    423             return true;
    424 
    425         destXBegin = upperBoundScaledX(destXBegin);
    426         if (destXBegin < 0)
    427             return true;
    428         destXEnd = lowerBoundScaledX(destXEnd - 1, destXBegin + 1);
    429         if (destXEnd < destXBegin)
    430             return true;
    431 
    432         ++destXEnd;
    433         ++destYEnd;
    434         x = destXBegin;
    435         y = destYBegin;
    436     }
    437 #endif
    438 
    439     // Write one row's worth of data into the frame.  There is no guarantee that
    440     // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so
    441     // we must ensure we don't run off the end of either the source data or the
    442     // row's X-coordinates.
    443 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    444     if (m_scaled) {
    445         for (; x < destXEnd; ++x) {
    446             unsigned char* sourceAddr = rowBuffer + m_scaledColumns[x] - m_reader->frameXOffset();
    447             copyOnePixel(m_reader, sourceAddr, colorMap, colorMapSize, writeTransparentPixels, buffer, x, y, m_currentBufferSawAlpha);
    448         }
    449     } else
    450 #endif
    451     for (unsigned char* sourceAddr = rowBuffer; sourceAddr < rowEnd && x < size().width(); ++sourceAddr, ++x)
    452         copyOnePixel(m_reader, sourceAddr, colorMap, colorMapSize, writeTransparentPixels, buffer, x, y, m_currentBufferSawAlpha);
    453 
    454      // Tell the frame to copy the row data if need be.
    455     if (repeatCount > 1) {
    456 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    457         buffer.copyRowNTimes(destXBegin, destXEnd, destYBegin, destYEnd);
    458 #else
    459         buffer.copyRowNTimes(m_reader->frameXOffset(), x, y, std::min(y + static_cast<int>(repeatCount), size().height()));
    460 #endif
    461     }
     375    // Write one row's worth of data into the frame. 
     376    for (int x = xBegin; x < xEnd; ++x) {
     377        const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - m_reader->frameXOffset());
     378        if ((!m_reader->isTransparent() || (sourceValue != m_reader->transparentPixel())) && (sourceValue < colorMapSize)) {
     379            const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
     380            buffer.setRGBA(x, yBegin, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
     381        } else {
     382            m_currentBufferSawAlpha = true;
     383            // We may or may not need to write transparent pixels to the buffer.
     384            // If we're compositing against a previous image, it's wrong, and if
     385            // we're writing atop a cleared, fully transparent buffer, it's
     386            // unnecessary; but if we're decoding an interlaced gif and
     387            // displaying it "Haeberli"-style, we must write these for passes
     388            // beyond the first, or the initial passes will "show through" the
     389            // later ones.
     390            if (writeTransparentPixels)
     391                buffer.setRGBA(x, yBegin, 0, 0, 0, 0);
     392        }
     393    }
     394
     395    // Tell the frame to copy the row data if need be.
     396    if (repeatCount > 1)
     397        buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd);
    462398
    463399    return true;
     
    479415        // The whole frame was non-transparent, so it's possible that the entire
    480416        // resulting buffer was non-transparent, and we can setHasAlpha(false).
    481 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    482         if (buffer.scaledRect().contains(IntRect(IntPoint(), scaledSize())))
    483 #else
    484         if (buffer.rect().contains(IntRect(IntPoint(), size())))
    485 #endif
     417        if (buffer.rect().contains(IntRect(IntPoint(), scaledSize())))
    486418            buffer.setHasAlpha(false);
    487419        else if (frameIndex > 0) {
     
    508440            // rect, we know the current frame has no alpha.
    509441            if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor)
    510 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    511                 && !prevBuffer->hasAlpha() && buffer.scaledRect().contains(prevBuffer->scaledRect()))
    512 #else
    513442                && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
    514 #endif
    515443                buffer.setHasAlpha(false);
    516444        }
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

    r53305 r53309  
    432432}
    433433
     434bool JPEGImageDecoder::setSize(unsigned width, unsigned height)
     435{
     436    if (!ImageDecoder::setSize(width, height))
     437        return false;
     438    prepareScaleDataIfNecessary();
     439    return true;
     440}
     441
    434442RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
    435443{
     
    461469}
    462470
    463 static void convertCMYKToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, JDIMENSION srcWidth
    464 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    465                               , bool scaled, const Vector<int>& scaledColumns
    466 #endif
    467                               )
    468 {
    469 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    470     if (scaled) {
    471         int numColumns = scaledColumns.size();
    472         for (int x = 0; x < numColumns; ++x) {
    473             JSAMPLE* jsample = src + scaledColumns[x] * 4;
    474             unsigned c = jsample[0];
    475             unsigned m = jsample[1];
    476             unsigned y = jsample[2];
    477             unsigned k = jsample[3];
    478             dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF);
    479         }
    480         return;
    481     }
    482 #endif
    483     for (JDIMENSION x = 0; x < srcWidth; ++x) {
    484         unsigned c = *src++;
    485         unsigned m = *src++;
    486         unsigned y = *src++;
    487         unsigned k = *src++;
    488 
    489         // Source is 'Inverted CMYK', output is RGB.
    490         // See: http://www.easyrgb.com/math.php?MATH=M12#text12
    491         // Or:  http://www.ilkeratalay.com/colorspacesfaq.php#rgb
    492 
    493         // From CMYK to CMY
    494         // C = C * ( 1 - K ) + K
    495         // M = M * ( 1 - K ) + K
    496         // Y = Y * ( 1 - K ) + K
    497 
    498         // From Inverted CMYK to CMY is thus:
    499         // C = (1-iC) * (1 - (1-iK)) + (1-iK) => 1 - iC*iK
    500         // Same for M and Y
    501 
    502         // Convert from CMY (0..1) to RGB (0..1)
    503         // R = 1 - C => 1 - (1 - iC*iK) => iC*iK
    504         // G = 1 - M => 1 - (1 - iM*iK) => iM*iK
    505         // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
    506 
    507         dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF);
    508     }
    509 }
    510 
    511 static void convertRGBToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, JDIMENSION srcWidth
    512 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    513                               , bool scaled, const Vector<int>& scaledColumns
    514 #endif
    515                               )
    516 {
    517 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    518     if (scaled) {
    519         int numColumns = scaledColumns.size();
    520         for (int x = 0; x < numColumns; ++x) {
    521             JSAMPLE* jsample = src + scaledColumns[x] * 3;
    522             dest.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
    523         }
    524         return;
    525     }
    526 #endif
    527     for (JDIMENSION x = 0; x < srcWidth; ++x) {
    528         unsigned r = *src++;
    529         unsigned g = *src++;
    530         unsigned b = *src++;
    531         dest.setRGBA(x, destY, r, g, b, 0xFF);
    532     }
    533 }
    534 
    535471bool JPEGImageDecoder::outputScanlines()
    536472{
     
    541477    RGBA32Buffer& buffer = m_frameBufferCache[0];
    542478    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    543         int bufferWidth = size().width();
    544         int bufferHeight = size().height();
    545 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    546         // Let's resize our buffer now to the correct width/height.
    547         if (m_scaled) {
    548             bufferWidth = m_scaledColumns.size();
    549             bufferHeight = m_scaledRows.size();
    550         }
    551 #endif
    552 
    553         if (!buffer.setSize(bufferWidth, bufferHeight)) {
     479        if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
    554480            m_failed = true;
    555481            return false;
     
    573499            return false;
    574500
    575         int destY = sourceY;
    576 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    577         if (m_scaled) {
    578             destY = scaledY(sourceY);
    579             if (destY < 0)
    580                 continue;
     501        int destY = scaledY(sourceY);
     502        if (destY < 0)
     503            continue;
     504        int width = m_scaled ? m_scaledColumns.size() : info->output_width;
     505        for (int x = 0; x < width; ++x) {
     506            JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4);
     507            if (info->out_color_space == JCS_RGB)
     508                buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
     509            else if (info->out_color_space == JCS_CMYK) {
     510                // Source is 'Inverted CMYK', output is RGB.
     511                // See: http://www.easyrgb.com/math.php?MATH=M12#text12
     512                // Or:  http://www.ilkeratalay.com/colorspacesfaq.php#rgb
     513                // From CMYK to CMY:
     514                // X =   X    * (1 -   K   ) +   K  [for X = C, M, or Y]
     515                // Thus, from Inverted CMYK to CMY is:
     516                // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
     517                // From CMY (0..1) to RGB (0..1):
     518                // R = 1 - C => 1 - (1 - iC*iK) => iC*iK  [G and B similar]
     519                unsigned k = jsample[3];
     520                buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
     521            } else {
     522                ASSERT_NOT_REACHED();
     523                m_failed = true;
     524                return false;
     525            }
    581526        }
    582         if (info->out_color_space == JCS_RGB)
    583             convertRGBToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns);
    584         else if (info->out_color_space == JCS_CMYK)
    585             convertCMYKToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns);
    586         else
    587             return false;
    588 #else
    589         if (info->out_color_space == JCS_RGB)
    590             convertRGBToRGBA(buffer, destY, *samples, info->output_width);
    591         else if (info->out_color_space == JCS_CMYK)
    592             convertCMYKToRGBA(buffer, destY, *samples, info->output_width);
    593         else
    594             return false;
    595 #endif
    596527    }
    597528
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h

    r47381 r53309  
    4848        virtual bool isSizeAvailable();
    4949
     50        virtual bool setSize(unsigned width, unsigned height);
     51
    5052        virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
    5153       
     
    5961        void jpegComplete();
    6062
    61 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    62         bool setSize(int width, int height)
    63         {
    64             if (!ImageDecoder::setSize(width, height))
    65                 return false;
    66             prepareScaleDataIfNecessary();
    67             return true;
    68         }
    69 #endif
    70 
    7163    private:
    7264        JPEGImageReader* m_reader;
  • trunk/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

    r53305 r53309  
    257257            return;
    258258        }
    259 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    260259        prepareScaleDataIfNecessary();
    261 #endif
    262260    }
    263261
     
    331329    RGBA32Buffer& buffer = m_frameBufferCache[0];
    332330    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    333 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    334         int width = m_scaled ? m_scaledColumns.size() : size().width();
    335         int height = m_scaled ? m_scaledRows.size() : size().height();
    336 #else
    337         int width = size().width();
    338         int height = size().height();
    339 #endif
    340         if (!buffer.setSize(width, height)) {
     331        if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
    341332            static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed();
    342333            longjmp(reader()->pngPtr()->jmpbuf, 1);
     
    397388
    398389    // Copy the data into our buffer.
    399 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    400     if (m_scaled) {
    401         int destY = scaledY(rowIndex);
    402         if (destY < 0)
    403             return;
    404         int columns = m_scaledColumns.size();
    405         bool sawAlpha = buffer.hasAlpha();
    406         for (int x = 0; x < columns; ++x) {
    407             png_bytep pixel = row + m_scaledColumns[x] * colorChannels;
    408             unsigned alpha = (hasAlpha ? pixel[3] : 255);
    409             buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
    410             if (!sawAlpha && alpha < 255) {
    411                 sawAlpha = true;
    412                 buffer.setHasAlpha(true);
    413             }
    414         }
    415         return;
    416     }
    417 #endif
    418     int width = size().width();
     390    int width = scaledSize().width();
     391    int destY = scaledY(rowIndex);
     392    if (destY < 0)
     393        return;
    419394    bool sawAlpha = buffer.hasAlpha();
    420395    for (int x = 0; x < width; x++) {
    421         unsigned red = *row++;
    422         unsigned green = *row++;
    423         unsigned blue = *row++;
    424         unsigned alpha = (hasAlpha ? *row++ : 255);
    425         buffer.setRGBA(x, rowIndex, red, green, blue, alpha);
     396        png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
     397        unsigned alpha = hasAlpha ? pixel[3] : 255;
     398        buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
    426399        if (!sawAlpha && alpha < 255) {
    427400            sawAlpha = true;
Note: See TracChangeset for help on using the changeset viewer.