summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/image-decoders
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/platform/image-decoders
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/platform/image-decoders')
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.cpp94
-rw-r--r--Source/WebCore/platform/image-decoders/ImageDecoder.h159
-rw-r--r--Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp4
-rw-r--r--Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp24
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp8
-rw-r--r--Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h1
-rw-r--r--Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp9
-rw-r--r--Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp9
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp2
-rw-r--r--Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h1
12 files changed, 155 insertions, 160 deletions
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
index 17208b5..2aae205 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -38,7 +38,9 @@ using namespace std;
namespace WebCore {
-static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
+namespace {
+
+unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
{
unsigned bytesExtracted = 0;
const char* moreData;
@@ -53,55 +55,80 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const
return bytesExtracted;
}
+<<<<<<< HEAD
#if !OS(ANDROID)
// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
// JPEGDecoder, which aren't used on Android, and which don't all compile.
// TODO: Find a better fix.
+=======
+bool matchesGIFSignature(char* contents)
+{
+ return !memcmp(contents, "GIF8", 4);
+}
+
+bool matchesPNGSignature(char* contents)
+{
+ return !memcmp(contents, "\x89\x50\x4E\x47", 4);
+}
+
+bool matchesJPEGSignature(char* contents)
+{
+ return !memcmp(contents, "\xFF\xD8\xFF", 3);
+}
+
+#if USE(WEBP)
+bool matchesWebPSignature(char* contents)
+{
+ return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
+}
+#endif
+
+bool matchesBMPSignature(char* contents)
+{
+ return !memcmp(contents, "BM", 2);
+}
+
+bool matchesICOSignature(char* contents)
+{
+ return !memcmp(contents, "\x00\x00\x01\x00", 4);
+}
+
+bool matchesCURSignature(char* contents)
+{
+ return !memcmp(contents, "\x00\x00\x02\x00", 4);
+}
+
+}
+
+>>>>>>> webkit.org at r78450
ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
{
- // We need at least 4 bytes to figure out what kind of image we're dealing
- // with.
- static const unsigned maxMarkerLength = 4;
- char contents[maxMarkerLength];
- unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0);
- if (length < maxMarkerLength)
+ static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
+ char contents[lengthOfLongestSignature];
+ unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
+ if (length < lengthOfLongestSignature)
return 0;
- // GIFs begin with GIF8(7 or 9).
- if (strncmp(contents, "GIF8", 4) == 0)
+ if (matchesGIFSignature(contents))
return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
- // Test for PNG.
- if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
+ if (matchesPNGSignature(contents))
return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
- // JPEG
- if (!memcmp(contents, "\xFF\xD8\xFF", 3))
+ if (matchesJPEGSignature(contents))
return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
#if USE(WEBP)
- if (!memcmp(contents, "RIFF", 4)) {
- static const unsigned webpExtraMarker = 6;
- static const unsigned webpExtraMarkeroffset = 8;
- char header[webpExtraMarker];
- unsigned length = copyFromSharedBuffer(header, webpExtraMarker, data, webpExtraMarkeroffset);
- if (length >= webpExtraMarker) {
- if (!memcmp(header, "WEBPVP", webpExtraMarker))
- return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
- }
- }
+ if (matchesWebPSignature(contents))
+ return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
#endif
- // BMP
- if (strncmp(contents, "BM", 2) == 0)
+ if (matchesBMPSignature(contents))
return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
- // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
- // CURs begin with 2-byte 0 followed by 2-byte 2.
- if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
+ if (matchesICOSignature(contents) || matchesCURSignature(contents))
return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
- // Give up. We don't know what the heck this is.
return 0;
}
#endif // !OS(ANDROID)
@@ -123,7 +150,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
copyReferenceToBitmapData(other);
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
@@ -131,7 +158,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_backingStore.clear();
m_bytes = 0;
@@ -142,7 +169,7 @@ void ImageFrame::clear()
// later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
m_hasAlpha = true;
@@ -176,8 +203,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
m_bytes = m_backingStore.data();
m_size = IntSize(newWidth, newHeight);
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h
index c581ba1..7d0d0d4 100644
--- a/Source/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h
@@ -50,9 +50,8 @@ namespace WebCore {
// FIXME: Do we want better encapsulation?
typedef Vector<char> ColorProfile;
- // The ImageFrame object represents the decoded image data in RGBA32
- // format. This buffer is what all decoders write a single frame into.
- // Frames are then instantiated for drawing by being handed this buffer.
+ // ImageFrame represents the decoded image data. This buffer is what all
+ // decoders write a single frame into.
class ImageFrame {
public:
enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
@@ -80,19 +79,17 @@ namespace WebCore {
// create a new copy of the image data, only increase the ref count.
ImageFrame& operator=(const ImageFrame& other);
- // Deletes the pixel data entirely; used by ImageDecoder to save memory
- // when we no longer need to display a frame and only need its metadata.
- void clear();
+ // These do not touch other metadata, only the raw pixel data.
+ void clearPixelData();
+ void zeroFillPixelData();
- // Zeroes the pixel data in the buffer, setting it to fully-transparent.
- void zeroFill();
-
- // Creates a new copy of the image data in |other|, so the two images
- // can be modified independently. Returns whether the copy succeeded.
+ // Makes this frame have an independent copy of the provided image's
+ // pixel data, so that modifications in one frame are not reflected in
+ // the other. Returns whether the copy succeeded.
bool copyBitmapData(const ImageFrame&);
- // Creates a new reference to the image data in |other|. The two images
- // share a common backing store.
+ // Makes this frame reference the provided image's pixel data, so that
+ // modifications in one frame are reflected in the other.
void copyReferenceToBitmapData(const ImageFrame&);
// Copies the pixel data at [(startX, startY), (endX, startY)) to the
@@ -116,18 +113,17 @@ namespace WebCore {
#endif
// Allocates space for the pixel data. Must be called before any pixels
- // are written. Will return true on success, false if the memory
- // allocation fails. Calling this multiple times is undefined and may
- // leak memory.
+ // are written. Must only be called once. Returns whether allocation
+ // succeeded.
bool setSize(int newWidth, int newHeight);
- // To be used by ImageSource::createFrameAtIndex(). Returns a pointer
- // to the underlying native image data. This pointer will be owned by
- // the BitmapImage and freed in FrameData::clear().
+ // Returns a caller-owned pointer to the underlying native image data.
+ // (Actual use: This pointer will be owned by BitmapImage and freed in
+ // FrameData::clear()).
NativeImagePtr asNewNativeImage() const;
bool hasAlpha() const;
- const IntRect& rect() const { return m_rect; }
+ const IntRect& originalFrameRect() const { return m_originalFrameRect; }
FrameStatus status() const { return m_status; }
unsigned duration() const { return m_duration; }
FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
@@ -135,7 +131,7 @@ namespace WebCore {
void setHasAlpha(bool alpha);
void setColorProfile(const ColorProfile&);
- void setRect(const IntRect& r) { m_rect = r; }
+ void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
void setStatus(FrameStatus status);
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
@@ -184,7 +180,11 @@ namespace WebCore {
g = static_cast<unsigned>(g * alphaPercent);
b = static_cast<unsigned>(b * alphaPercent);
}
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
+=======
+#if PLATFORM(SKIA)
+>>>>>>> webkit.org at r78450
*dest = SkPackARGB32(a, r, g, b);
#else
*dest = (a << 24 | r << 16 | g << 8 | b);
@@ -202,35 +202,26 @@ namespace WebCore {
#else
NativeBackingStore m_backingStore;
PixelData* m_bytes; // The memory is backed by m_backingStore.
- IntSize m_size; // The size of the buffer. This should be the
- // same as ImageDecoder::m_size.
- bool m_hasAlpha; // Whether or not any of the pixels in the buffer
- // have transparency.
+ IntSize m_size;
+ bool m_hasAlpha;
ColorProfile m_colorProfile;
#endif
- IntRect m_rect; // The rect of the original specified frame within
- // the overall buffer. This will always just be
- // the entire buffer except for GIF frames whose
- // original rect was smaller than the overall
- // image size.
- FrameStatus m_status; // Whether or not this frame is completely
- // finished decoding.
- unsigned m_duration; // The animation delay.
- FrameDisposalMethod m_disposalMethod; // What to do with this frame's data when
- // initializing the next frame.
- bool m_premultiplyAlpha; // Whether to premultiply alpha into R, G, B
- // channels; by default it's true.
+ IntRect m_originalFrameRect; // This will always just be the entire
+ // buffer except for GIF frames whose
+ // original rect was smaller than the
+ // overall image size.
+ FrameStatus m_status;
+ unsigned m_duration;
+ FrameDisposalMethod m_disposalMethod;
+ bool m_premultiplyAlpha;
};
- // The ImageDecoder class represents a base class for specific image format
- // decoders (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode
- // into RGBA32 format and the base class manages the RGBA32 frame cache.
+ // ImageDecoder is a base for all format-specific decoders
+ // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
//
- // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write
- // directly to scaled output buffers by down sampling. Call
- // setMaxNumPixels() to specify the biggest size that decoded images can
- // have. Image decoders will deflate those images that are bigger than
- // m_maxNumPixels. (Not supported by all image decoders yet)
+ // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
+ // at decode time. Image decoders will downsample any images larger than
+ // |m_maxNumPixels|. FIXME: Not yet supported by all decoders.
class ImageDecoder {
WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -241,19 +232,15 @@ namespace WebCore {
, m_sizeAvailable(false)
, m_maxNumPixels(-1)
, m_isAllDataReceived(false)
- , m_failed(false)
- {
- }
+ , m_failed(false) { }
- virtual ~ImageDecoder() {}
+ virtual ~ImageDecoder() { }
- // Factory function to create an ImageDecoder. Ports that subclass
- // ImageDecoder can provide their own implementation of this to avoid
- // needing to write a dedicated setData() implementation.
+ // Returns a caller-owned decoder of the appropriate type. Returns 0 if
+ // we can't sniff a supported type from the provided data (possibly
+ // because there isn't enough data yet).
static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
- // The the filename extension usually associated with an undecoded image
- // of this type.
virtual String filenameExtension() const = 0;
bool isAllDataReceived() const { return m_isAllDataReceived; }
@@ -266,41 +253,33 @@ namespace WebCore {
m_isAllDataReceived = allDataReceived;
}
- // Whether or not the size information has been decoded yet. This
- // default implementation just returns true if the size has been set and
- // we have not seen a failure. Decoders may want to override this to
- // lazily decode enough of the image to get the size.
+ // Lazily-decodes enough of the image to get the size (if possible).
+ // FIXME: Right now that has to be done by each subclass; factor the
+ // decode call out and use it here.
virtual bool isSizeAvailable()
{
- return !m_failed && m_sizeAvailable;
+ return !m_failed && m_sizeAvailable;
}
- // Returns the size of the image.
- virtual IntSize size() const
- {
- return m_size;
- }
+ virtual IntSize size() const { return m_size; }
IntSize scaledSize() const
{
return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
}
- // Returns the size of frame |index|. This will only differ from size()
- // for formats where different frames are different sizes (namely ICO,
- // where each frame represents a different icon within the master file).
- // Notably, this does not return different sizes for different GIF
- // frames, since while these may be stored as smaller rectangles, during
- // decoding they are composited to create a full-size frame.
+ // This will only differ from size() for ICO (where each frame is a
+ // different icon) or other formats where different frames are different
+ // sizes. This does NOT differ from size() for GIF, since decoding GIFs
+ // composites any smaller frames against previous frames to create full-
+ // size frames.
virtual IntSize frameSizeAtIndex(size_t) const
{
return size();
}
- // Called by the image decoders to set their decoded size, this also
- // checks the size for validity. It will return true if the size was
- // set, or false if there is an error. On error, the m_failed flag will
- // be set and the caller should immediately stop decoding.
+ // Returns whether the size is legal (i.e. not going to result in
+ // overflow elsewhere). If not, marks decoding as failed.
virtual bool setSize(unsigned width, unsigned height)
{
if (isOverSize(width, height))
@@ -310,26 +289,19 @@ namespace WebCore {
return true;
}
- // The total number of frames for the image. Classes that support
- // multiple frames will scan the image data for the answer if they need
- // to (without necessarily decoding all of the individual frames).
+ // Lazily-decodes enough of the image to get the frame count (if
+ // possible), without decoding the individual frames.
+ // FIXME: Right now that has to be done by each subclass; factor the
+ // decode call out and use it here.
virtual size_t frameCount() { return 1; }
- // The number of repetitions to perform for an animation loop.
virtual int repetitionCount() const { return cAnimationNone; }
- // Called to obtain the ImageFrame full of decoded data for rendering.
- // The decoder plugin will decode as much of the frame as it can before
- // handing back the buffer.
+ // Decodes as much of the requested frame as possible, and returns an
+ // ImageDecoder-owned pointer.
virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
- // Whether or not the underlying image format even supports alpha
- // transparency.
- virtual bool supportsAlpha() const { return true; }
-
void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
-
- // Whether or not the gamma and color profile are applied.
bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
// Sets the "decode failure" flag. For caller convenience (since so
@@ -344,13 +316,10 @@ namespace WebCore {
bool failed() const { return m_failed; }
- // Wipe out frames in the frame buffer cache before |clearBeforeFrame|,
- // assuming this can be done without breaking decoding. Different
- // decoders place different restrictions on what frames are safe to
- // destroy, so this is left to them to implement.
- // For convenience's sake, we provide a default (empty) implementation,
- // since in practice only GIFs will ever use this.
- virtual void clearFrameBufferCache(size_t clearBeforeFrame) { }
+ // Clears decoded pixel data from before the provided frame unless that
+ // data may be needed to decode future frames (e.g. due to GIF frame
+ // compositing).
+ virtual void clearFrameBufferCache(size_t) { }
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
void setMaxNumPixels(int m) { m_maxNumPixels = m; }
@@ -378,8 +347,6 @@ namespace WebCore {
// and return it as a (signed) int. Avoid overflow.
static bool isOverSize(unsigned width, unsigned height)
{
- // width * height must not exceed (2 ^ 29) - 1, so that we don't
- // overflow when we multiply by 4.
unsigned long long total_size = static_cast<unsigned long long>(width)
* static_cast<unsigned long long>(height);
return total_size > ((1 << 29) - 1);
diff --git a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
index 1805bc7..5c00553 100644
--- a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
+++ b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp
@@ -87,7 +87,7 @@ bool BMPImageReader::decodeBMP(bool onlySize)
m_buffer->setHasAlpha(false);
// For BMPs, the frame always fills the entire image.
- m_buffer->setRect(IntRect(IntPoint(), m_parent->size()));
+ m_buffer->setOriginalFrameRect(IntRect(IntPoint(), m_parent->size()));
if (!m_isTopDown)
m_coord.setY(m_parent->size().height() - 1);
@@ -707,7 +707,7 @@ BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, i
} else {
m_seenNonZeroAlphaPixel = true;
if (m_seenZeroAlphaPixel) {
- m_buffer->zeroFill();
+ m_buffer->zeroFillPixelData();
m_seenZeroAlphaPixel = false;
} else if (alpha != 255)
m_buffer->setHasAlpha(true);
diff --git a/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp b/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
index 0b90107..43d6a52 100644
--- a/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
+++ b/Source/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp
@@ -72,7 +72,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
m_bytes = reinterpret_cast<PixelData*>(CFDataGetMutableBytePtr(m_backingStore.get()));
m_size = IntSize(newWidth, newHeight);
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index e6de597..7e334a9 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -174,14 +174,14 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
Vector<ImageFrame>::iterator i(end);
for (; (i != m_frameBufferCache.begin()) && ((i->status() == ImageFrame::FrameEmpty) || (i->disposalMethod() == ImageFrame::DisposeOverwritePrevious)); --i) {
if ((i->status() == ImageFrame::FrameComplete) && (i != end))
- i->clear();
+ i->clearPixelData();
}
// Now |i| holds the last frame we need to preserve; clear prior frames.
for (Vector<ImageFrame>::iterator j(m_frameBufferCache.begin()); j != i; ++j) {
ASSERT(j->status() != ImageFrame::FramePartial);
if (j->status() != ImageFrame::FrameEmpty)
- j->clear();
+ j->clearPixelData();
}
}
@@ -266,7 +266,7 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
if (!m_currentBufferSawAlpha) {
// The whole frame was non-transparent, so it's possible that the entire
// resulting buffer was non-transparent, and we can setHasAlpha(false).
- if (buffer.rect().contains(IntRect(IntPoint(), scaledSize())))
+ if (buffer.originalFrameRect().contains(IntRect(IntPoint(), scaledSize())))
buffer.setHasAlpha(false);
else if (frameIndex) {
// Tricky case. This frame does not have alpha only if everywhere
@@ -289,7 +289,7 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// The only remaining case is a DisposeOverwriteBgcolor frame. If
// it had no alpha, and its rect is contained in the current frame's
// rect, we know the current frame has no alpha.
- if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
+ if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
buffer.setHasAlpha(false);
}
}
@@ -327,17 +327,17 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height);
// Make sure the frameRect doesn't extend outside the buffer.
- if (frameRect.right() > size().width())
+ if (frameRect.maxX() > size().width())
frameRect.setWidth(size().width() - frameReader->x_offset);
- if (frameRect.bottom() > size().height())
+ if (frameRect.maxY() > size().height())
frameRect.setHeight(size().height() - frameReader->y_offset);
ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
int left = upperBoundScaledX(frameRect.x());
- int right = lowerBoundScaledX(frameRect.right(), left);
+ int right = lowerBoundScaledX(frameRect.maxX(), left);
int top = upperBoundScaledY(frameRect.y());
- int bottom = lowerBoundScaledY(frameRect.bottom(), top);
- buffer->setRect(IntRect(left, top, right - left, bottom - top));
+ int bottom = lowerBoundScaledY(frameRect.maxY(), top);
+ buffer->setOriginalFrameRect(IntRect(left, top, right - left, bottom - top));
if (!frameIndex) {
// This is the first frame, so we're not relying on any previous data.
@@ -367,7 +367,7 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
} else {
// We want to clear the previous frame to transparent, without
// affecting pixels in the image outside of the frame.
- const IntRect& prevRect = prevBuffer->rect();
+ const IntRect& prevRect = prevBuffer->originalFrameRect();
const IntSize& bufferSize = scaledSize();
if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
// Clearing the first frame, or a frame the size of the whole
@@ -378,8 +378,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// Copy the whole previous buffer, then clear just its frame.
if (!buffer->copyBitmapData(*prevBuffer))
return setFailed();
- for (int y = prevRect.y(); y < prevRect.bottom(); ++y) {
- for (int x = prevRect.x(); x < prevRect.right(); ++x)
+ for (int y = prevRect.y(); y < prevRect.maxY(); ++y) {
+ for (int x = prevRect.x(); x < prevRect.maxX(); ++x)
buffer->setRGBA(x, y, 0, 0, 0, 0);
}
if ((prevRect.width() > 0) && (prevRect.height() > 0))
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index a255c25..1434c65 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -222,6 +222,12 @@ public:
// jpeglib cannot convert these to rgb, but it can convert ycck
// to cmyk.
m_info.out_color_space = JCS_CMYK;
+
+ // Same as with grayscale images, we convert CMYK images to RGBA
+ // ones. When we keep the color profiles of these CMYK images,
+ // CoreGraphics will convert their colors again. So, we discard
+ // their color profiles to prevent color corruption.
+ m_decoder->setIgnoreGammaAndColorProfile(true);
break;
default:
return m_decoder->setFailed();
@@ -462,7 +468,7 @@ bool JPEGImageDecoder::outputScanlines()
buffer.setColorProfile(m_colorProfile);
// For JPEGs, the frame always fills the entire image.
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
}
jpeg_decompress_struct* info = m_reader->info();
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 801f1ab..d095cbb 100644
--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -45,7 +45,6 @@ namespace WebCore {
virtual bool isSizeAvailable();
virtual bool setSize(unsigned width, unsigned height);
virtual ImageFrame* frameBufferAtIndex(size_t index);
- virtual bool supportsAlpha() const { return false; }
// CAUTION: setFailed() deletes |m_reader|. Be careful to avoid
// accessing deleted memory, especially when calling this from inside
// JPEGImageReader!
diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 755d704..8edfe36 100644
--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -341,7 +341,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
buffer.setColorProfile(m_colorProfile);
// For PNGs, the frame always fills the entire image.
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
if (m_reader->pngPtr()->interlaced)
m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
diff --git a/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp b/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
index 81c22cf..a3cfbf6 100644
--- a/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
+++ b/Source/WebCore/platform/image-decoders/qt/ImageFrameQt.cpp
@@ -50,14 +50,14 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
copyBitmapData(other);
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_pixmap = QPixmap();
m_image = QImage();
@@ -68,7 +68,7 @@ void ImageFrame::clear()
// other metadata out of this frame later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
if (m_pixmap.isNull() && !m_image.isNull()) {
m_pixmap = QPixmap(m_image.width(), m_image.height());
@@ -101,8 +101,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
if (m_pixmap.isNull())
return false;
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index a1c8261..c7dcc7a 100644
--- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -51,7 +51,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
// Keep the pixels locked since we will be writing directly into the
// bitmap throughout this object's lifetime.
m_bitmap.lockPixels();
- setRect(other.rect());
+ setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
setDisposalMethod(other.disposalMethod());
@@ -59,7 +59,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other)
return *this;
}
-void ImageFrame::clear()
+void ImageFrame::clearPixelData()
{
m_bitmap.reset();
m_status = FrameEmpty;
@@ -69,7 +69,7 @@ void ImageFrame::clear()
// other metadata out of this frame later.
}
-void ImageFrame::zeroFill()
+void ImageFrame::zeroFillPixelData()
{
m_bitmap.eraseARGB(0, 0, 0, 0);
}
@@ -93,8 +93,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight)
if (!m_bitmap.allocPixels())
return false;
- // Zero the image.
- zeroFill();
+ zeroFillPixelData();
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 8045ada..3db00f6 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -116,7 +116,7 @@ bool WEBPImageDecoder::decode(bool onlySize)
}
buffer.setStatus(ImageFrame::FrameComplete);
buffer.setHasAlpha(false);
- buffer.setRect(IntRect(IntPoint(), size()));
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
return true;
}
diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
index cde1bbf..c32e047 100644
--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -42,7 +42,6 @@ public:
virtual String filenameExtension() const { return "vp8"; }
virtual bool isSizeAvailable();
virtual ImageFrame* frameBufferAtIndex(size_t index);
- virtual bool supportsAlpha() const { return false; }
private:
// Returns false in case of decoding failure.