18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Holger Hans Peter Freyther 48f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 55af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImageBuffer.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImageData.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StillImageQt.h" 36f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include "TransparencyLayer.h" 37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h> 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <wtf/text/StringConcatenate.h> 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QBuffer> 418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <QColor> 428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <QImage> 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QImageWriter> 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QPainter> 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <QPixmap> 460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <math.h> 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectImageBufferData::ImageBufferData(const IntSize& size) 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_pixmap(size) 52e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block , m_painter(0) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 54e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (m_pixmap.isNull()) 55e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return; 56e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pixmap.fill(QColor(Qt::transparent)); 585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 59e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block QPainter* painter = new QPainter; 605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_painter.set(painter); 615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 62e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (!painter->begin(&m_pixmap)) 63e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return; 64e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Since ImageBuffer is used mainly for Canvas, explicitly initialize 665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // its painter's pen and brush with the corresponding canvas defaults 675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // NOTE: keep in sync with CanvasRenderingContext2D::State 685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian QPen pen = painter->pen(); 695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian pen.setColor(Qt::black); 705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian pen.setWidth(1); 715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian pen.setCapStyle(Qt::FlatCap); 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch pen.setJoinStyle(Qt::SvgMiterJoin); 735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian pen.setMiterLimit(10); 745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian painter->setPen(pen); 755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian QBrush brush = painter->brush(); 765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian brush.setColor(Qt::black); 775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian painter->setBrush(brush); 785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian painter->setCompositionMode(QPainter::CompositionMode_SourceOver); 79f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 80f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick m_image = StillImage::createForRendering(&m_pixmap); 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 832bde8e466a4451c7319e3a072d118917957d6554Steve BlockQImage ImageBufferData::toQImage() const 842bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 852bde8e466a4451c7319e3a072d118917957d6554Steve Block QPaintEngine* paintEngine = m_pixmap.paintEngine(); 862bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!paintEngine || paintEngine->type() != QPaintEngine::Raster) 872bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_pixmap.toImage(); 882bde8e466a4451c7319e3a072d118917957d6554Steve Block 892bde8e466a4451c7319e3a072d118917957d6554Steve Block // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it. 902bde8e466a4451c7319e3a072d118917957d6554Steve Block // For performance reasons, we don't want that here, so we temporarily redirect the paint engine. 912bde8e466a4451c7319e3a072d118917957d6554Steve Block QPaintDevice* currentPaintDevice = paintEngine->paintDevice(); 922bde8e466a4451c7319e3a072d118917957d6554Steve Block paintEngine->setPaintDevice(0); 932bde8e466a4451c7319e3a072d118917957d6554Steve Block QImage image = m_pixmap.toImage(); 942bde8e466a4451c7319e3a072d118917957d6554Steve Block paintEngine->setPaintDevice(currentPaintDevice); 952bde8e466a4451c7319e3a072d118917957d6554Steve Block return image; 962bde8e466a4451c7319e3a072d118917957d6554Steve Block} 972bde8e466a4451c7319e3a072d118917957d6554Steve Block 98f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success) 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_data(size) 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_size(size) 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 102e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block success = m_data.m_painter && m_data.m_painter->isActive(); 103e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (!success) 104e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return; 105e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_context.set(new GraphicsContext(m_data.m_painter.get())); 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectImageBuffer::~ImageBuffer() 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 113ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochsize_t ImageBuffer::dataSize() const 114ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{ 115ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch return m_size.width() * m_size.height() * 4; 116ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch} 117ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectGraphicsContext* ImageBuffer::context() const 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_data.m_painter->isActive()); 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_context.get(); 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 125f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickbool ImageBuffer::drawsUsingCopy() const 126967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 127f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return false; 128f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick} 129967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 130f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickPassRefPtr<Image> ImageBuffer::copyImage() const 131f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{ 132f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return StillImage::create(m_data.m_pixmap); 133967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 134967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 135f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, 136f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick CompositeOperator op, bool useLowQualityScale) 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 138f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (destContext == context()) { 139f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. 140f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick RefPtr<Image> copy = copyImage(); 141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale); 142f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick } else 143f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); 144f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick} 145f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 146f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, 147f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) 148f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{ 149f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (destContext == context()) { 150f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first. 151f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick RefPtr<Image> copy = copyImage(); 152f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); 153f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick } else 154f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect); 155f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick} 156f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 157f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const 158f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{ 159f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); 160f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (!nativeImage) 161f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return; 162f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch IntRect rect = enclosingIntRect(floatRect); 164f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick QPixmap alphaMask = *nativeImage; 165f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height()) 166f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick alphaMask = alphaMask.scaled(rect.width(), rect.height()); 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 168f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) 1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch bool isPainting = m_data.m_painter->isActive(); 1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (isPainting) 1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_data.m_painter->end(); 1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1772bde8e466a4451c7319e3a072d118917957d6554Steve Block QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32); 1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(!image.isNull()); 1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 180e14391e94c850b8bd03680c23b38978db68687a8John Reck uchar* bits = image.bits(); 181e14391e94c850b8bd03680c23b38978db68687a8John Reck const int bytesPerLine = image.bytesPerLine(); 182e14391e94c850b8bd03680c23b38978db68687a8John Reck 1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (int y = 0; y < m_size.height(); ++y) { 184e14391e94c850b8bd03680c23b38978db68687a8John Reck quint32* scanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); 185e14391e94c850b8bd03680c23b38978db68687a8John Reck for (int x = 0; x < m_size.width(); ++x) { 186e14391e94c850b8bd03680c23b38978db68687a8John Reck QRgb& pixel = scanLine[x]; 187e14391e94c850b8bd03680c23b38978db68687a8John Reck pixel = qRgba(lookUpTable[qRed(pixel)], 188e14391e94c850b8bd03680c23b38978db68687a8John Reck lookUpTable[qGreen(pixel)], 189e14391e94c850b8bd03680c23b38978db68687a8John Reck lookUpTable[qBlue(pixel)], 190e14391e94c850b8bd03680c23b38978db68687a8John Reck qAlpha(pixel)); 1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_data.m_pixmap = QPixmap::fromImage(image); 1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (isPainting) 1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_data.m_painter->begin(&m_data.m_pixmap); 1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <Multiply multiplied> 201cad810f21b803229eb11403f9209855525a25d57Steve BlockPassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size) 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 203cad810f21b803229eb11403f9209855525a25d57Steve Block RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); 204cad810f21b803229eb11403f9209855525a25d57Steve Block unsigned char* data = result->data(); 2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height()) 207cad810f21b803229eb11403f9209855525a25d57Steve Block memset(data, 0, result->length()); 2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int originx = rect.x(); 2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int destx = 0; 2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (originx < 0) { 2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian destx = -originx; 2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian originx = 0; 2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int endx = rect.maxX(); 216231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (endx > size.width()) 217231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block endx = size.width(); 2188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int numColumns = endx - originx; 2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int originy = rect.y(); 2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int desty = 0; 2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (originy < 0) { 2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian desty = -originy; 2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian originy = 0; 2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int endy = rect.maxY(); 227231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (endy > size.height()) 228231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block endy = size.height(); 2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int numRows = endy - originy; 2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2310617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // NOTE: For unmultiplied data, we undo the premultiplication below. 2322bde8e466a4451c7319e3a072d118917957d6554Steve Block QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); 233231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!image.isNull()); 2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 2360617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen const int bytesPerLine = image.bytesPerLine(); 2370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen const uchar* bits = image.constBits(); 2380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]); 2400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 2410617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (multiplied == Unmultiplied) { 2420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int y = 0; y < numRows; ++y) { 243e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); 2440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int x = 0; x < numColumns; x++) { 2450617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen QRgb pixel = scanLine[x + originx]; 2460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen int alpha = qAlpha(pixel); 2470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // Un-premultiply and convert RGB to BGR. 2480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (alpha == 255) 2490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows[x] = (0xFF000000 2500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | (qBlue(pixel) << 16) 2510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | (qGreen(pixel) << 8) 2520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | (qRed(pixel))); 2530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen else if (alpha > 0) 2540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows[x] = ((alpha << 24) 2550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | (((255 * qBlue(pixel)) / alpha)) << 16) 2560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | (((255 * qGreen(pixel)) / alpha) << 8) 2570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen | ((255 * qRed(pixel)) / alpha); 2580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen else 2590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows[x] = 0; 2600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 2610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows += rect.width(); 2620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 2630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } else { 2640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int y = 0; y < numRows; ++y) { 265e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); 2660617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int x = 0; x < numColumns; x++) { 2670617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen QRgb pixel = scanLine[x + originx]; 2680617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // Convert RGB to BGR. 2690617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); 2700617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 2710617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 2720617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destRows += rect.width(); 2738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 276cad810f21b803229eb11403f9209855525a25d57Steve Block return result.release(); 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 279cad810f21b803229eb11403f9209855525a25d57Steve BlockPassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const 280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 281231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return getImageData<Unmultiplied>(rect, m_data, m_size); 282231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 284cad810f21b803229eb11403f9209855525a25d57Steve BlockPassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const 285231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 286231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return getImageData<Premultiplied>(rect, m_data, m_size); 287231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 288231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2890617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenstatic inline unsigned int premultiplyABGRtoARGB(unsigned int x) 2900617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen{ 2910617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen unsigned int a = x >> 24; 2920617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (a == 255) 2930617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return (x << 16) | ((x >> 16) & 0xff) | (x & 0xff00ff00); 2940617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen unsigned int t = (x & 0xff00ff) * a; 2950617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; 2960617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen t = ((t << 16) | (t >> 16)) & 0xff00ff; 2970617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 2980617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen x = ((x >> 8) & 0xff) * a; 2990617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen x = (x + ((x >> 8) & 0xff) + 0x80); 3000617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen x &= 0xff00; 3010617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen x |= t | (a << 24); 3020617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return x; 3030617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen} 3040617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 305231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <Multiply multiplied> 306cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size) 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(sourceRect.width() > 0); 3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(sourceRect.height() > 0); 3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int originx = sourceRect.x(); 3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int destx = destPoint.x() + sourceRect.x(); 3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(destx >= 0); 314231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(destx < size.width()); 3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(originx >= 0); 3162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(originx <= sourceRect.maxX()); 3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int endx = destPoint.x() + sourceRect.maxX(); 319231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(endx <= size.width()); 3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int numColumns = endx - destx; 3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int originy = sourceRect.y(); 3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int desty = destPoint.y() + sourceRect.y(); 3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(desty >= 0); 326231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(desty < size.height()); 3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(originy >= 0); 3282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(originy <= sourceRect.maxY()); 3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int endy = destPoint.y() + sourceRect.maxY(); 331231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(endy <= size.height()); 3328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int numRows = endy - desty; 3338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 334cad810f21b803229eb11403f9209855525a25d57Steve Block unsigned srcBytesPerRow = 4 * sourceSize.width(); 3358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3360617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // NOTE: For unmultiplied input data, we do the premultiplication below. 3370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen QImage image(numColumns, numRows, QImage::Format_ARGB32_Premultiplied); 3380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen uchar* bits = image.bits(); 3390617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen const int bytesPerLine = image.bytesPerLine(); 3400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 341cad810f21b803229eb11403f9209855525a25d57Steve Block const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data() + originy * srcBytesPerRow + originx * 4); 3420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 3430617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (multiplied == Unmultiplied) { 3440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int y = 0; y < numRows; ++y) { 345e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); 3460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int x = 0; x < numColumns; x++) { 3470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // Premultiply and convert BGR to RGB. 3480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen quint32 pixel = srcScanLine[x]; 3490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destScanLine[x] = premultiplyABGRtoARGB(pixel); 3500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 351cad810f21b803229eb11403f9209855525a25d57Steve Block srcScanLine += sourceSize.width(); 3520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 3530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } else { 3540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int y = 0; y < numRows; ++y) { 355e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); 3560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int x = 0; x < numColumns; x++) { 3570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // Convert BGR to RGB. 3580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen quint32 pixel = srcScanLine[x]; 3590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen destScanLine[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); 3600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 361cad810f21b803229eb11403f9209855525a25d57Steve Block srcScanLine += sourceSize.width(); 3628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 3648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 365e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke bool isPainting = data.m_painter->isActive(); 366e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke if (!isPainting) 367231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block data.m_painter->begin(&data.m_pixmap); 368e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke else { 369e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->save(); 370e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 371e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke // putImageData() should be unaffected by painter state 372e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->resetTransform(); 373e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->setOpacity(1.0); 374e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->setClipping(false); 375e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke } 376e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 377e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->setCompositionMode(QPainter::CompositionMode_Source); 3780617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen data.m_painter->drawImage(destx, desty, image); 379e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 380e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke if (!isPainting) 381e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->end(); 382e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke else 383e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke data.m_painter->restore(); 384231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 385231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 386cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 387231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 388cad810f21b803229eb11403f9209855525a25d57Steve Block putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); 389231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 390231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 391cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 392231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 393cad810f21b803229eb11403f9209855525a25d57Steve Block putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We get a mimeType here but QImageWriter does not support mimetypes but 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// only formats (png, gif, jpeg..., xpm). So assume we get image/ as image 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// mimetypes and then remove the image/ to get the Qt format. 399545e470e52f0ac6a3a072bf559c796b42c6066b6Ben MurdochString ImageBuffer::toDataURL(const String& mimeType, const double* quality) const 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!mimeType.startsWith("image/")) 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return "data:,"; 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // prepare our target 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project QByteArray data; 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project QBuffer buffer(&data); 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.open(QBuffer::WriteOnly); 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 411545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (quality && *quality >= 0.0 && *quality <= 1.0) { 412545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), *quality * 100 + 0.5)) { 413545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch buffer.close(); 414545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return "data:,"; 415545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch } 416545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch } else { 417545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), 100)) { 418545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch buffer.close(); 419545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return "data:,"; 420545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch } 4215af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke } 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project buffer.close(); 424a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 425a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return makeString("data:", mimeType, ";base64,", data.toBase64().data()); 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 429