String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { if (m_size.isEmpty()) return "data:,"; enum { EncodeJPEG, EncodePNG, } encodeType = mimeType.lower() == "image/png" ? EncodePNG : EncodeJPEG; // According to http://www.w3.org/TR/html5/the-canvas-element.html, // "For image types that do not support an alpha channel, the image must be" // "composited onto a solid black background using the source-over operator," // "and the resulting image must be the one used to create the data: URL." // JPEG doesn't have alpha channel, so we need premultiplied data. RefPtr<ImageData> imageData = encodeType == EncodePNG ? getUnmultipliedImageData(IntRect(IntPoint(0, 0), m_size)) : getPremultipliedImageData(IntRect(IntPoint(0, 0), m_size)); ASSERT(imageData && imageData->width() == m_size.width() && imageData->height() == m_size.height()); Vector<char> output; const char* header; if (encodeType == EncodePNG) { if (!compressRGBABigEndianToPNG(imageData->data()->data()->data(), m_size, output)) return "data:,"; header = "data:image/png;base64,"; } else { if (!compressRGBABigEndianToJPEG(imageData->data()->data()->data(), m_size, output)) return "data:,"; header = "data:image/jpeg;base64,"; } Vector<char> base64; base64Encode(output, base64); output.clear(); Vector<char> url; url.append(header, strlen(header)); url.append(base64); return String(url.data(), url.size()); }
static bool encodeImageJPEG(unsigned char* data, IntSize size, Vector<char>* output, Optional<double> quality) { return compressRGBABigEndianToJPEG(data, size, *output, quality); }