Changeset 47371 in webkit


Ignore:
Timestamp:
Aug 17, 2009 11:37:21 AM (15 years ago)
Author:
yong.li@torchmobile.com
Message:

2009-08-17 Yong Li <yong.li@torchmobile.com>

Reviewed by Adam Treat.

Allow image decoders to down-sample the image directly
to scaled output buffer. This can be enabled/disabled by
macro ENABLE(IMAGE_DECODER_DOWN_SAMPLING).
Only JPEG and PNG decoders are modified to support it now.
https://bugs.webkit.org/show_bug.cgi?id=28308

  • platform/graphics/ImageSource.cpp: (WebCore::ImageSource::setData):
  • platform/image-decoders/ImageDecoder.cpp: Added.
  • platform/image-decoders/ImageDecoder.h: (WebCore::ImageDecoder::ImageDecoder): (WebCore::ImageDecoder::setMaxNumPixels):
  • platform/image-decoders/jpeg/JPEGImageDecoder.cpp: (WebCore::convertCMYKToRGBA): (WebCore::convertRGBToRGBA): (WebCore::JPEGImageDecoder::outputScanlines):
  • platform/image-decoders/jpeg/JPEGImageDecoder.h: (WebCore::JPEGImageDecoder::setSize):
  • platform/image-decoders/png/PNGImageDecoder.cpp: (WebCore::PNGImageDecoder::headerAvailable): (WebCore::PNGImageDecoder::rowAvailable):
Location:
trunk/WebCore
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r47370 r47371  
     12009-08-17  Yong Li  <yong.li@torchmobile.com>
     2
     3        Reviewed by Adam Treat.
     4
     5        Allow image decoders to down-sample the image directly
     6        to scaled output buffer. This can be enabled/disabled by
     7        macro ENABLE(IMAGE_DECODER_DOWN_SAMPLING).
     8        Only JPEG and PNG decoders are modified to support it now.
     9        https://bugs.webkit.org/show_bug.cgi?id=28308
     10
     11        * platform/graphics/ImageSource.cpp:
     12        (WebCore::ImageSource::setData):
     13        * platform/image-decoders/ImageDecoder.cpp: Added.
     14        * platform/image-decoders/ImageDecoder.h:
     15        (WebCore::ImageDecoder::ImageDecoder):
     16        (WebCore::ImageDecoder::setMaxNumPixels):
     17        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
     18        (WebCore::convertCMYKToRGBA):
     19        (WebCore::convertRGBToRGBA):
     20        (WebCore::JPEGImageDecoder::outputScanlines):
     21        * platform/image-decoders/jpeg/JPEGImageDecoder.h:
     22        (WebCore::JPEGImageDecoder::setSize):
     23        * platform/image-decoders/png/PNGImageDecoder.cpp:
     24        (WebCore::PNGImageDecoder::headerAvailable):
     25        (WebCore::PNGImageDecoder::rowAvailable):
     26
    1272009-08-17  Simon Fraser  <simon.fraser@apple.com>
    228
  • trunk/WebCore/platform/graphics/ImageSource.cpp

    r47081 r47371  
    33 * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
    44 * Copyright (C) 2008, Google Inc. All rights reserved.
     5 * Copyright (C) 2007-2009 Torch Mobile, Inc
    56 *
    67 * Redistribution and use in source and binary forms, with or without
     
    3435#include "JPEGImageDecoder.h"
    3536#include "PNGImageDecoder.h"
     37#include "SharedBuffer.h"
    3638#include "XBMImageDecoder.h"
    37 #include "SharedBuffer.h"
     39
     40#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     41#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS
     42#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024)
     43#endif
     44#endif
    3845
    3946namespace WebCore {
     
    119126    // If insufficient bytes are available to determine the image type, no decoder plugin will be
    120127    // made.
    121     if (!m_decoder)
     128    if (!m_decoder) {
    122129        m_decoder = createDecoder(data->buffer());
     130#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     131        if (m_decoder)
     132            m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS);
     133#endif
     134    }
    123135
    124136    if (m_decoder)
  • trunk/WebCore/platform/image-decoders/ImageDecoder.h

    r47144 r47371  
    11/*
    22 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     3 * Copyright (C) 2008-2009 Torch Mobile, Inc.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    183184    class ImageDecoder {
    184185    public:
     186        // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write directly to
     187        // scaled output buffers by down sampling. Call setMaxNumPixels() to specify the
     188        // biggest size that decoded images can have. Image decoders will deflate those
     189        // images that are bigger than m_maxNumPixels. (Not supported by all image decoders yet)
    185190        ImageDecoder()
    186191            : m_failed(false)
    187192            , m_sizeAvailable(false)
     193#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     194            , m_maxNumPixels(-1)
     195            , m_scaled(false)
     196#endif
    188197        {
    189198        }
     
    267276        virtual void clearFrameBufferCache(size_t clearBeforeFrame) { }
    268277
     278#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     279        void setMaxNumPixels(int m) { m_maxNumPixels = m; }
     280#endif
     281
    269282    protected:
     283#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     284        void prepareScaleDataIfNecessary();
     285        int upperBoundScaledX(int origX, int searchStart = 0);
     286        int lowerBoundScaledX(int origX, int searchStart = 0);
     287        int scaledY(int origY, int searchStart = 0);
     288#endif
     289
    270290        RefPtr<SharedBuffer> m_data; // The encoded data.
     291#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     292        int m_maxNumPixels;
     293        Vector<int> m_scaledColumns;
     294        Vector<int> m_scaledRows;
     295        bool m_scaled;
     296#endif
    271297        Vector<RGBA32Buffer> m_frameBufferCache;
    272298        bool m_failed;
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

    r46931 r47371  
    462462}
    463463
    464 static void convertCMYKToRGBA(RGBA32Buffer& dest, JSAMPROW src, jpeg_decompress_struct* info)
    465 {
    466     ASSERT(info->out_color_space == JCS_CMYK);
    467 
    468     for (unsigned x = 0; x < info->output_width; ++x) {
     464static void convertCMYKToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, int srcWidth
     465#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     466                              , bool scaled, const Vector<int>& scaledColumns
     467#endif
     468                              )
     469{
     470#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     471    if (scaled) {
     472        int numColumns = scaledColumns.size();
     473        for (int x = 0; x < numColumns; ++x) {
     474            JSAMPLE* jsample = src + scaledColumns[x] * 3;
     475            unsigned c = jsample[0];
     476            unsigned m = jsample[1];
     477            unsigned y = jsample[2];
     478            unsigned k = jsample[3];
     479            dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF);
     480        }
     481        return;
     482    }
     483#endif
     484    for (unsigned x = 0; x < srcWidth; ++x) {
    469485        unsigned c = *src++;
    470486        unsigned m = *src++;
     
    490506        // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
    491507
    492         // read_scanlines has increased the scanline counter, so we
    493         // actually mean the previous one.
    494         dest.setRGBA(x, info->output_scanline - 1, c * k / 255, m * k / 255, y * k / 255, 0xFF);
    495     }
    496 }
    497 
    498 static void convertRGBToRGBA(RGBA32Buffer& dest, JSAMPROW src, jpeg_decompress_struct* info)
    499 {
    500     ASSERT(info->out_color_space == JCS_RGB);
    501 
    502     for (unsigned x = 0; x < info->output_width; ++x) {
     508        dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF);
     509    }
     510}
     511
     512static void convertRGBToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, int srcWidth
     513#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     514                              , bool scaled, const Vector<int>& scaledColumns
     515#endif
     516                              )
     517{
     518#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     519    if (scaled) {
     520        int numColumns = scaledColumns.size();
     521        for (int x = 0; x < numColumns; ++x) {
     522            JSAMPLE* jsample = src + scaledColumns[x] * 3;
     523            dest.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
     524        }
     525        return;
     526    }
     527#endif
     528    for (unsigned x = 0; x < srcWidth; ++x) {
    503529        unsigned r = *src++;
    504530        unsigned g = *src++;
    505531        unsigned b = *src++;
    506         // read_scanlines has increased the scanline counter, so we
    507         // actually mean the previous one.
    508         dest.setRGBA(x, info->output_scanline - 1, r, g, b, 0xFF);
     532        dest.setRGBA(x, destY, r, g, b, 0xFF);
    509533    }
    510534}
     
    518542    RGBA32Buffer& buffer = m_frameBufferCache[0];
    519543    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    520         if (!buffer.setSize(size().width(), size().height())) {
     544        int bufferWidth = size().width();
     545        int bufferHeight = size().height();
     546#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     547        // Let's resize our buffer now to the correct width/height.
     548        if (m_scaled) {
     549            bufferWidth = m_scaledColumns.size();
     550            bufferHeight = m_scaledRows.size();
     551        }
     552#endif
     553
     554        if (!buffer.setSize(bufferWidth, bufferHeight)) {
    521555            m_failed = true;
    522556            return false;
     
    533567
    534568    while (info->output_scanline < info->output_height) {
     569        // jpeg_read_scanlines will increase the scanline counter, so we
     570        // save the scanline before calling it.
     571        int sourceY = info->output_scanline;
    535572        /* Request one scanline.  Returns 0 or 1 scanlines. */
    536573        if (jpeg_read_scanlines(info, samples, 1) != 1)
    537574            return false;
    538575
     576        int destY = sourceY;
     577#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     578        if (m_scaled) {
     579            destY = scaledY(sourceY);
     580            if (destY < 0)
     581                continue;
     582        }
    539583        if (info->out_color_space == JCS_RGB)
    540             convertRGBToRGBA(buffer, *samples, info);
     584            convertRGBToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns);
    541585        else if (info->out_color_space == JCS_CMYK)
    542             convertCMYKToRGBA(buffer, *samples, info);
     586            convertCMYKToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns);
    543587        else
    544588            return false;
     589#else
     590        if (info->out_color_space == JCS_RGB)
     591            convertRGBToRGBA(buffer, destY, *samples, info->output_width);
     592        else if (info->out_color_space == JCS_CMYK)
     593            convertCMYKToRGBA(buffer, destY, *samples, info->output_width);
     594        else
     595            return false;
     596#endif
    545597    }
    546598
  • trunk/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h

    r44825 r47371  
    11/*
    22 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     3 * Copyright (C) 2008-2009 Torch Mobile, Inc.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    5859        void jpegComplete();
    5960
     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
    6071    private:
    6172        JPEGImageReader* m_reader;
  • trunk/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

    r44825 r47371  
    11/*
    22 * Copyright (C) 2006 Apple Computer, Inc.
     3 * Copyright (C) 2007-2009 Torch Mobile, Inc.
    34 *
    45 * Portions are Copyright (C) 2001 mozilla.org
     
    243244            return;
    244245        }
     246#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     247        prepareScaleDataIfNecessary();
     248#endif
    245249    }
    246250
     
    314318    RGBA32Buffer& buffer = m_frameBufferCache[0];
    315319    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
    316         if (!buffer.setSize(size().width(), size().height())) {
     320#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     321        int width = m_scaled ? m_scaledColumns.size() : size().width();
     322        int height = m_scaled ? m_scaledRows.size() : size().height();
     323#else
     324        int width = size().width();
     325        int height = size().height();
     326#endif
     327        if (!buffer.setSize(width, height)) {
    317328            static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed();
    318329            longjmp(reader()->pngPtr()->jmpbuf, 1);
     
    359370    * old row and the new row.
    360371    */
    361    
     372
    362373    png_structp png = reader()->pngPtr();
    363374    bool hasAlpha = reader()->hasAlpha();
     
    373384
    374385    // Copy the data into our buffer.
     386#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     387    if (m_scaled) {
     388        int destY = scaledY(rowIndex);
     389        if (destY < 0)
     390            return;
     391        int columns = m_scaledColumns.size();
     392        bool sawAlpha = buffer.hasAlpha();
     393        for (int x = 0; x < columns; ++x) {
     394            png_bytep pixel = row + m_scaledColumns[x] * 4;
     395            unsigned alpha = pixel[3];
     396            buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
     397            if (!sawAlpha && alpha < 255) {
     398                sawAlpha = true;
     399                buffer.setHasAlpha(true);
     400            }
     401        }
     402        return;
     403    }
     404#endif
    375405    int width = size().width();
    376     bool sawAlpha = false;
     406    bool sawAlpha = buffer.hasAlpha();
    377407    for (int x = 0; x < width; x++) {
    378408        unsigned red = *row++;
     
    386416        }
    387417    }
     418#endif
    388419}
    389420
Note: See TracChangeset for help on using the changeset viewer.