1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 33 #include <algorithm> 34 #include "core/platform/SharedBuffer.h" 35 #include "core/platform/graphics/Image.h" 36 #include "core/platform/graphics/skia/NativeImageSkia.h" 37 #include "core/platform/image-decoders/ImageDecoder.h" 38 #include "public/platform/WebData.h" 39 #include "public/platform/WebImage.h" 40 #include "public/platform/WebSize.h" 41 #include "wtf/OwnPtr.h" 42 #include "wtf/PassOwnPtr.h" 43 #include "wtf/PassRefPtr.h" 44 #include "wtf/Vector.h" 45 46 using namespace WebCore; 47 48 namespace WebKit { 49 50 WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize) 51 { 52 RefPtr<SharedBuffer> buffer = PassRefPtr<SharedBuffer>(data); 53 OwnPtr<ImageDecoder> decoder(ImageDecoder::create(*buffer.get(), ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnored)); 54 if (!decoder) 55 return WebImage(); 56 57 decoder->setData(buffer.get(), true); 58 if (!decoder->isSizeAvailable()) 59 return WebImage(); 60 61 // Frames are arranged by decreasing size, then decreasing bit depth. 62 // Pick the frame closest to |desiredSize|'s area without being smaller, 63 // which has the highest bit depth. 64 const size_t frameCount = decoder->frameCount(); 65 size_t index = 0; // Default to first frame if none are large enough. 66 int frameAreaAtIndex = 0; 67 for (size_t i = 0; i < frameCount; ++i) { 68 const IntSize frameSize = decoder->frameSizeAtIndex(i); 69 if (WebSize(frameSize) == desiredSize) { 70 index = i; 71 break; // Perfect match. 72 } 73 74 const int frameArea = frameSize.width() * frameSize.height(); 75 if (frameArea < (desiredSize.width * desiredSize.height)) 76 break; // No more frames that are large enough. 77 78 if (!i || (frameArea < frameAreaAtIndex)) { 79 index = i; // Closer to desired area than previous best match. 80 frameAreaAtIndex = frameArea; 81 } 82 } 83 84 ImageFrame* frame = decoder->frameBufferAtIndex(index); 85 if (!frame) 86 return WebImage(); 87 88 RefPtr<NativeImageSkia> image = frame->asNewNativeImage(); 89 if (!image) 90 return WebImage(); 91 92 return WebImage(image->bitmap()); 93 } 94 95 WebVector<WebImage> WebImage::framesFromData(const WebData& data) 96 { 97 // This is to protect from malicious images. It should be big enough that it's never hit in pracice. 98 const size_t maxFrameCount = 8; 99 100 RefPtr<SharedBuffer> buffer = PassRefPtr<SharedBuffer>(data); 101 OwnPtr<ImageDecoder> decoder(ImageDecoder::create(*buffer.get(), ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnored)); 102 if (!decoder) 103 return WebVector<WebImage>(); 104 105 decoder->setData(buffer.get(), true); 106 if (!decoder->isSizeAvailable()) 107 return WebVector<WebImage>(); 108 109 // Frames are arranged by decreasing size, then decreasing bit depth. 110 // Keep the first frame at every size, has the highest bit depth. 111 const size_t frameCount = decoder->frameCount(); 112 IntSize lastSize; 113 114 Vector<WebImage> frames; 115 for (size_t i = 0; i < std::min(frameCount, maxFrameCount); ++i) { 116 const IntSize frameSize = decoder->frameSizeAtIndex(i); 117 if (frameSize == lastSize) 118 continue; 119 lastSize = frameSize; 120 121 ImageFrame* frame = decoder->frameBufferAtIndex(i); 122 if (!frame) 123 continue; 124 125 RefPtr<NativeImageSkia> image = frame->asNewNativeImage(); 126 if (image && image->isDataComplete()) 127 frames.append(WebImage(image->bitmap())); 128 } 129 130 return frames; 131 } 132 133 void WebImage::reset() 134 { 135 m_bitmap.reset(); 136 } 137 138 void WebImage::assign(const WebImage& image) 139 { 140 m_bitmap = image.m_bitmap; 141 } 142 143 bool WebImage::isNull() const 144 { 145 return m_bitmap.isNull(); 146 } 147 148 WebSize WebImage::size() const 149 { 150 return WebSize(m_bitmap.width(), m_bitmap.height()); 151 } 152 153 WebImage::WebImage(const PassRefPtr<Image>& image) 154 { 155 operator=(image); 156 } 157 158 WebImage& WebImage::operator=(const PassRefPtr<Image>& image) 159 { 160 RefPtr<NativeImageSkia> p; 161 if (image && (p = image->nativeImageForCurrentFrame())) 162 assign(p->bitmap()); 163 else 164 reset(); 165 return *this; 166 } 167 168 } // namespace WebKit 169