Commit c8bfc082 authored by xlai@chromium.org's avatar xlai@chromium.org

The toBlob method in HTMLCanvasElement has been implemented.

Changes include:
(1) HTMLCanvasElement: 

The toBlob function is implemented in a similar fashion as the existing toDataURL function, taking in parameters like mimeType and qualityArgument. It has an additional argument FileCallback which accepts user-defined callback function.

(2) ImageDataBuffer:

encodeImage is made public.

(3) File:

A new create factory method is added to allow HTMLCanvasElement to create a new File object using the blob data. File object is a subtype of Blob object; it has two additional attributes -- name, last modification time -- as compared to Blob. We use empty string and current time to fill in these two attributes; FF creates the latter attribute in the same way.

(4) FileCallback: 

Moved from module/ to core/. 



BUG=67587

Review URL: https://codereview.chromium.org/1257253004

git-svn-id: svn://svn.chromium.org/blink/trunk@201327 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 20511984
...@@ -817,6 +817,16 @@ crbug.com/364614 [ Mac ] virtual/threaded/fast/scroll-behavior/overflow-scroll-r ...@@ -817,6 +817,16 @@ crbug.com/364614 [ Mac ] virtual/threaded/fast/scroll-behavior/overflow-scroll-r
crbug.com/364614 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Skip ] crbug.com/364614 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Skip ]
crbug.com/364614 [ Mac ] virtual/threaded_animation_timelines/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Skip ] crbug.com/364614 [ Mac ] virtual/threaded_animation_timelines/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Skip ]
crbug.com/67587 fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
crbug.com/67587 fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
crbug.com/67587 fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/gpu/fast/canvas/canvas-toBlob-jpeg-maximum-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/gpu/fast/canvas/canvas-toBlob-jpeg-medium-quality.html [ NeedsRebaseline ]
crbug.com/67587 virtual/gpu/fast/canvas/canvas-toBlob-webp-maximum-quality.html [ NeedsRebaseline ]
crbug.com/524596 paint/invalidation/composited-non-stacking-context-descendant-change-color.html [ ImageOnlyFailure ] crbug.com/524596 paint/invalidation/composited-non-stacking-context-descendant-change-color.html [ ImageOnlyFailure ]
crbug.com/524596 paint/invalidation/composited-non-stacking-context-descendant-move.html [ ImageOnlyFailure ] crbug.com/524596 paint/invalidation/composited-non-stacking-context-descendant-move.html [ ImageOnlyFailure ]
crbug.com/524596 paint/invalidation/fixed-position-descendant-paint-offset-indirect.html [ ImageOnlyFailure ] crbug.com/524596 paint/invalidation/fixed-position-descendant-paint-offset-indirect.html [ ImageOnlyFailure ]
......
Test that toBlob(mimeType) ignores the case of 'mimeType'.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE
PASS
PASS
PASS
PASS
<script src = "../../resources/js-test.js"></script>
<script type = "text/javascript">
if (window.testRunner)
{
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
description("Test that toBlob(mimeType) ignores the case of 'mimeType'.");
canvas = document.createElement('canvas');
var counter;
function tryMimeType(mimeType, expectedMimeType)
{
canvas.toBlob(function(blob) {
if (blob.type === expectedMimeType) {
testPassed("");
}
else {
testFailed(blob.type + " does not match " + expectedMimeType);
}
counter = counter - 1;
if (window.testRunner) {
if (counter == 0) {
testRunner.notifyDone();
}
}
}, mimeType);
}
counter = 4;
//Note that due to the async nature of toBlob, these callbacks may complete
// at random order but they will all print PASS when they pass.
tryMimeType("image/PNG", "image/png");
tryMimeType("imaGE/jpEg", "image/jpeg");
tryMimeType("ImAgE/WeBp", "image/webp");
//Unsupported mime type falls back to png
tryMimeType("image/bmp", "image/png");
</Script>
Test that verifies whether the image data survives the toBlob process
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE
PASS ctx.getImageData(0, 0, 150, 75).data[4] is ctx2.getImageData(0, 0, 150, 75).data[4]
<script src = "../../resources/js-test.js"></script>
<script type = 'text/javascript'>
description("Test that verifies whether the image data survives the toBlob process");
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
var canvas2 = document.createElement("canvas");
var ctx2 = canvas2.getContext("2d");
var newImg = new Image();
newImg.onload = function() {
ctx2.drawImage(newImg, 0, 0, 150, 75);
//Randomly pick a pixel to check whether they match
shouldBe('ctx.getImageData(0, 0, 150, 75).data[4]', 'ctx2.getImageData(0, 0, 150, 75).data[4]');
if (window.testRunner)
testRunner.notifyDone();
}
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
newImg.src = url;
});
</script>
<canvas id="mycanvas"></canvas>
<img id="result" onload="testDone()">
<script type = 'text/javascript'>
if (window.testRunner) {
testRunner.dumpAsTextWithPixelResults();
testRunner.waitUntilDone();
}
function testDone()
{
if (window.testRunner)
testRunner.notifyDone();
}
var image = new Image();
image.onload = function() {
var canvas = document.getElementById("mycanvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
result.src = url;
}, "image/jpeg", 1.0);
}
image.src = "resources/letters.png";
</script>
<canvas id="mycanvas"></canvas>
<img id="result" onload="testDone()">
<script type = 'text/javascript'>
if (window.testRunner) {
testRunner.dumpAsTextWithPixelResults();
testRunner.waitUntilDone();
}
function testDone()
{
if (window.testRunner)
testRunner.notifyDone();
}
var image = new Image();
image.onload = function() {
var canvas = document.getElementById("mycanvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
result.src = url;
}, "image/jpeg", 0.2);
}
image.src = "resources/letters.png";
</script>
<canvas id="mycanvas"></canvas>
<img id="result" onload="testDone()">
<script type = 'text/javascript'>
if (window.testRunner) {
testRunner.dumpAsTextWithPixelResults();
testRunner.waitUntilDone();
}
function testDone()
{
if (window.testRunner)
testRunner.notifyDone();
}
var image = new Image();
image.onload = function() {
var canvas = document.getElementById("mycanvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
result.src = url;
}, "image/webp", 1.0);
}
image.src = "resources/letters.png";
</script>
...@@ -49,4 +49,14 @@ test(function () { ...@@ -49,4 +49,14 @@ test(function () {
assert_unreached('toDataURL should throw'); assert_unreached('toDataURL should throw');
}); });
}, 'toDataURL'); }, 'toDataURL');
test(function () {
assert_throws(
"SecurityError",
function() {
context.drawImage(image, 0, 0, 100, 100);
canvas.toBlob(function(blob){});
assert_unreached('toBlob should throw');
});
}, 'toBlob');
</script> </script>
...@@ -395,6 +395,7 @@ html element button ...@@ -395,6 +395,7 @@ html element button
html element canvas html element canvas
property getContext property getContext
property height property height
property toBlob
property toDataURL property toDataURL
property width property width
html element caption html element caption
......
...@@ -1688,6 +1688,7 @@ interface HTMLCanvasElement ...@@ -1688,6 +1688,7 @@ interface HTMLCanvasElement
getter width getter width
method constructor method constructor
method getContext method getContext
method toBlob
method toDataURL method toDataURL
setter height setter height
setter width setter width
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
'events/WheelEvent.idl', 'events/WheelEvent.idl',
'fileapi/Blob.idl', 'fileapi/Blob.idl',
'fileapi/File.idl', 'fileapi/File.idl',
'fileapi/FileCallback.idl',
'fileapi/FileError.idl', 'fileapi/FileError.idl',
'fileapi/FileList.idl', 'fileapi/FileList.idl',
'fileapi/FileReader.idl', 'fileapi/FileReader.idl',
...@@ -1483,6 +1484,7 @@ ...@@ -1483,6 +1484,7 @@
'fileapi/Blob.h', 'fileapi/Blob.h',
'fileapi/File.cpp', 'fileapi/File.cpp',
'fileapi/File.h', 'fileapi/File.h',
'fileapi/FileCallback.h',
'fileapi/FileError.cpp', 'fileapi/FileError.cpp',
'fileapi/FileError.h', 'fileapi/FileError.h',
'fileapi/FileList.cpp', 'fileapi/FileList.cpp',
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "core/fileapi/FilePropertyBag.h" #include "core/fileapi/FilePropertyBag.h"
#include "platform/FileMetadata.h" #include "platform/FileMetadata.h"
#include "platform/MIMETypeRegistry.h" #include "platform/MIMETypeRegistry.h"
#include "platform/blob/BlobData.h"
#include "public/platform/Platform.h" #include "public/platform/Platform.h"
#include "public/platform/WebFileUtilities.h" #include "public/platform/WebFileUtilities.h"
#include "wtf/CurrentTime.h" #include "wtf/CurrentTime.h"
...@@ -101,7 +102,6 @@ File* File::create(const HeapVector<BlobOrStringOrArrayBufferViewOrArrayBuffer>& ...@@ -101,7 +102,6 @@ File* File::create(const HeapVector<BlobOrStringOrArrayBufferViewOrArrayBuffer>&
lastModified = static_cast<double>(options.lastModified()); lastModified = static_cast<double>(options.lastModified());
else else
lastModified = currentTimeMS(); lastModified = currentTimeMS();
ASSERT(options.hasEndings()); ASSERT(options.hasEndings());
bool normalizeLineEndingsToNative = options.endings() == "native"; bool normalizeLineEndingsToNative = options.endings() == "native";
...@@ -113,6 +113,19 @@ File* File::create(const HeapVector<BlobOrStringOrArrayBufferViewOrArrayBuffer>& ...@@ -113,6 +113,19 @@ File* File::create(const HeapVector<BlobOrStringOrArrayBufferViewOrArrayBuffer>&
return File::create(fileName, lastModified, BlobDataHandle::create(blobData.release(), fileSize)); return File::create(fileName, lastModified, BlobDataHandle::create(blobData.release(), fileSize));
} }
File* File::create(char* data, size_t bytes, const String& mimeType)
{
ASSERT(data);
OwnPtr<BlobData> blobData = BlobData::create();
blobData->setContentType(mimeType);
blobData->appendBytes(data, bytes);
long long blobSize = blobData->length();
// create blob as the type of file with two additional attributes -- name and lastModificationTime
return File::create("", currentTimeMS(), BlobDataHandle::create(blobData.release(), blobSize));
}
File* File::createWithRelativePath(const String& path, const String& relativePath) File* File::createWithRelativePath(const String& path, const String& relativePath)
{ {
File* file = new File(path, File::AllContentTypes, File::IsUserVisible); File* file = new File(path, File::AllContentTypes, File::IsUserVisible);
......
...@@ -68,6 +68,8 @@ public: ...@@ -68,6 +68,8 @@ public:
return new File(name, modificationTime, blobDataHandle); return new File(name, modificationTime, blobDataHandle);
} }
static File* create(char* data, size_t bytes, const String& mimeType);
// For deserialization. // For deserialization.
static File* createFromSerialization(const String& path, const String& name, const String& relativePath, UserVisibility userVisibility, bool hasSnaphotData, uint64_t size, double lastModified, PassRefPtr<BlobDataHandle> blobDataHandle) static File* createFromSerialization(const String& path, const String& name, const String& relativePath, UserVisibility userVisibility, bool hasSnaphotData, uint64_t size, double lastModified, PassRefPtr<BlobDataHandle> blobDataHandle)
{ {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "core/HTMLNames.h" #include "core/HTMLNames.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h" #include "core/dom/ExceptionCode.h"
#include "core/fileapi/File.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h" #include "core/frame/Settings.h"
#include "core/html/ImageData.h" #include "core/html/ImageData.h"
...@@ -54,6 +55,8 @@ ...@@ -54,6 +55,8 @@
#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h" #include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
#include "platform/transforms/AffineTransform.h" #include "platform/transforms/AffineTransform.h"
#include "public/platform/Platform.h" #include "public/platform/Platform.h"
#include "public/platform/WebTraceLocation.h"
#include "wtf/Functional.h"
#include <math.h> #include <math.h>
#include <v8.h> #include <v8.h>
...@@ -538,6 +541,40 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q ...@@ -538,6 +541,40 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q
return toDataURLInternal(mimeType, qualityPtr, BackBuffer); return toDataURLInternal(mimeType, qualityPtr, BackBuffer);
} }
void HTMLCanvasElement::toBlob(FileCallback* callback, const String& mimeType, const ScriptValue& qualityArgument, ExceptionState& exceptionState) const
{
if (!originClean()) {
exceptionState.throwSecurityError("Tainted canvases may not be exported.");
return;
}
File* resultBlob = nullptr;
if (!isPaintable()) {
// If the canvas element's bitmap has no pixels
return;
}
double quality;
if (!qualityArgument.isEmpty()) {
v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
if (v8Value->IsNumber()) {
quality = v8Value.As<v8::Number>()->Value();
}
}
String encodingMimeType = toEncodingMimeType(mimeType);
ImageData* imageData = toImageData(BackBuffer);
ScopedDisposal<ImageData> disposer(imageData);
// Perform image encoding
Vector<char> encodedImage;
ImageDataBuffer(imageData->size(), imageData->data()->data()).encodeImage(encodingMimeType, &quality, &encodedImage);
resultBlob = File::create(encodedImage.data(), encodedImage.size(), encodingMimeType);
Platform::current()->mainThread()->postTask(FROM_HERE, bind(&FileCallback::handleEvent, callback, resultBlob));
}
SecurityOrigin* HTMLCanvasElement::securityOrigin() const SecurityOrigin* HTMLCanvasElement::securityOrigin() const
{ {
return document().securityOrigin(); return document().securityOrigin();
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "core/CoreExport.h" #include "core/CoreExport.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/dom/DocumentVisibilityObserver.h" #include "core/dom/DocumentVisibilityObserver.h"
#include "core/fileapi/FileCallback.h"
#include "core/html/HTMLElement.h" #include "core/html/HTMLElement.h"
#include "core/html/canvas/CanvasImageSource.h" #include "core/html/canvas/CanvasImageSource.h"
#include "platform/geometry/FloatRect.h" #include "platform/geometry/FloatRect.h"
...@@ -113,6 +114,9 @@ public: ...@@ -113,6 +114,9 @@ public:
String toDataURL(const String& mimeType, const ScriptValue& qualityArgument, ExceptionState&) const; String toDataURL(const String& mimeType, const ScriptValue& qualityArgument, ExceptionState&) const;
String toDataURL(const String& mimeType, ExceptionState& exceptionState) const { return toDataURL(mimeType, ScriptValue(), exceptionState); } String toDataURL(const String& mimeType, ExceptionState& exceptionState) const { return toDataURL(mimeType, ScriptValue(), exceptionState); }
void toBlob(FileCallback*, const String& mimeType, const ScriptValue& qualityArgument, ExceptionState&) const;
void toBlob(FileCallback* callback, const String& mimeType, ExceptionState& exceptionState) { return toBlob(callback, mimeType, ScriptValue(), exceptionState); }
// Used for rendering // Used for rendering
void didDraw(const FloatRect&); void didDraw(const FloatRect&);
void notifyObserversCanvasChanged(const FloatRect&); void notifyObserversCanvasChanged(const FloatRect&);
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
// https://html.spec.whatwg.org/#the-canvas-element // https://html.spec.whatwg.org/#the-canvas-element
interface HTMLCanvasElement : HTMLElement { interface HTMLCanvasElement : HTMLElement
{
// FIXME: width and height should be unsigned long. // FIXME: width and height should be unsigned long.
attribute long width; attribute long width;
attribute long height; attribute long height;
...@@ -51,4 +52,6 @@ interface HTMLCanvasElement : HTMLElement { ...@@ -51,4 +52,6 @@ interface HTMLCanvasElement : HTMLElement {
// only one extra argument is actually used. // only one extra argument is actually used.
// FIXME: type should not have a default value. // FIXME: type should not have a default value.
[RaisesException] DOMString toDataURL(optional DOMString type = null, optional any arguments); [RaisesException] DOMString toDataURL(optional DOMString type = null, optional any arguments);
[RaisesException, RuntimeEnabled=ExperimentalCanvasFeatures] void toBlob(FileCallback? _callback, optional DOMString type = null, optional any arguments);
}; };
...@@ -31,10 +31,10 @@ ...@@ -31,10 +31,10 @@
#include "config.h" #include "config.h"
#include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/DOMFileSystem.h"
#include "core/fileapi/FileCallback.h"
#include "modules/filesystem/DOMFilePath.h" #include "modules/filesystem/DOMFilePath.h"
#include "modules/filesystem/DirectoryEntry.h" #include "modules/filesystem/DirectoryEntry.h"
#include "modules/filesystem/ErrorCallback.h" #include "modules/filesystem/ErrorCallback.h"
#include "modules/filesystem/FileCallback.h"
#include "modules/filesystem/FileEntry.h" #include "modules/filesystem/FileEntry.h"
#include "modules/filesystem/FileSystemCallbacks.h" #include "modules/filesystem/FileSystemCallbacks.h"
#include "modules/filesystem/FileWriter.h" #include "modules/filesystem/FileWriter.h"
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
#include "modules/filesystem/FileEntry.h" #include "modules/filesystem/FileEntry.h"
#include "core/fileapi/File.h" #include "core/fileapi/File.h"
#include "core/fileapi/FileCallback.h"
#include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/DOMFileSystem.h"
#include "modules/filesystem/ErrorCallback.h" #include "modules/filesystem/ErrorCallback.h"
#include "modules/filesystem/FileCallback.h"
#include "modules/filesystem/FileWriterCallback.h" #include "modules/filesystem/FileWriterCallback.h"
namespace blink { namespace blink {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
#include "core/fileapi/File.h" #include "core/fileapi/File.h"
#include "core/fileapi/FileCallback.h"
#include "core/fileapi/FileError.h" #include "core/fileapi/FileError.h"
#include "core/html/VoidCallback.h" #include "core/html/VoidCallback.h"
#include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/InspectorInstrumentation.h"
...@@ -44,7 +45,6 @@ ...@@ -44,7 +45,6 @@
#include "modules/filesystem/Entry.h" #include "modules/filesystem/Entry.h"
#include "modules/filesystem/EntryCallback.h" #include "modules/filesystem/EntryCallback.h"
#include "modules/filesystem/ErrorCallback.h" #include "modules/filesystem/ErrorCallback.h"
#include "modules/filesystem/FileCallback.h"
#include "modules/filesystem/FileEntry.h" #include "modules/filesystem/FileEntry.h"
#include "modules/filesystem/FileSystemCallback.h" #include "modules/filesystem/FileSystemCallback.h"
#include "modules/filesystem/FileWriterBase.h" #include "modules/filesystem/FileWriterBase.h"
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/events/Event.h" #include "core/events/Event.h"
#include "core/fileapi/File.h" #include "core/fileapi/File.h"
#include "core/fileapi/FileCallback.h"
#include "core/fileapi/FileError.h" #include "core/fileapi/FileError.h"
#include "core/fileapi/FileReader.h" #include "core/fileapi/FileReader.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
...@@ -53,7 +54,6 @@ ...@@ -53,7 +54,6 @@
#include "modules/filesystem/Entry.h" #include "modules/filesystem/Entry.h"
#include "modules/filesystem/EntryCallback.h" #include "modules/filesystem/EntryCallback.h"
#include "modules/filesystem/ErrorCallback.h" #include "modules/filesystem/ErrorCallback.h"
#include "modules/filesystem/FileCallback.h"
#include "modules/filesystem/FileEntry.h" #include "modules/filesystem/FileEntry.h"
#include "modules/filesystem/FileSystemCallbacks.h" #include "modules/filesystem/FileSystemCallbacks.h"
#include "modules/filesystem/LocalFileSystem.h" #include "modules/filesystem/LocalFileSystem.h"
......
...@@ -72,7 +72,6 @@ ...@@ -72,7 +72,6 @@
'filesystem/EntryCallback.idl', 'filesystem/EntryCallback.idl',
'filesystem/EntrySync.idl', 'filesystem/EntrySync.idl',
'filesystem/ErrorCallback.idl', 'filesystem/ErrorCallback.idl',
'filesystem/FileCallback.idl',
'filesystem/FileEntry.idl', 'filesystem/FileEntry.idl',
'filesystem/FileEntrySync.idl', 'filesystem/FileEntrySync.idl',
'filesystem/FileSystemCallback.idl', 'filesystem/FileSystemCallback.idl',
...@@ -963,7 +962,6 @@ ...@@ -963,7 +962,6 @@
'filesystem/EntrySync.cpp', 'filesystem/EntrySync.cpp',
'filesystem/EntrySync.h', 'filesystem/EntrySync.h',
'filesystem/ErrorCallback.h', 'filesystem/ErrorCallback.h',
'filesystem/FileCallback.h',
'filesystem/FileEntry.cpp', 'filesystem/FileEntry.cpp',
'filesystem/FileEntry.h', 'filesystem/FileEntry.h',
'filesystem/FileEntrySync.cpp', 'filesystem/FileEntrySync.cpp',
......
...@@ -341,7 +341,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, const unsigned char* source, ...@@ -341,7 +341,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, const unsigned char* source,
m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY); m_surface->writePixels(info, srcAddr, srcBytesPerRow, destX, destY);
} }
static bool encodeImage(const ImageDataBuffer& source, const String& mimeType, const double* quality, Vector<char>* output) bool ImageDataBuffer::encodeImage(const String& mimeType, const double* quality, Vector<char>* output) const
{ {
Vector<unsigned char>* encodedImage = reinterpret_cast<Vector<unsigned char>*>(output); Vector<unsigned char>* encodedImage = reinterpret_cast<Vector<unsigned char>*>(output);
...@@ -349,16 +349,16 @@ static bool encodeImage(const ImageDataBuffer& source, const String& mimeType, c ...@@ -349,16 +349,16 @@ static bool encodeImage(const ImageDataBuffer& source, const String& mimeType, c
int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality; int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
if (quality && *quality >= 0.0 && *quality <= 1.0) if (quality && *quality >= 0.0 && *quality <= 1.0)
compressionQuality = static_cast<int>(*quality * 100 + 0.5); compressionQuality = static_cast<int>(*quality * 100 + 0.5);
if (!JPEGImageEncoder::encode(source, compressionQuality, encodedImage)) if (!JPEGImageEncoder::encode(*this, compressionQuality, encodedImage))
return false; return false;
} else if (mimeType == "image/webp") { } else if (mimeType == "image/webp") {
int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality; int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality;
if (quality && *quality >= 0.0 && *quality <= 1.0) if (quality && *quality >= 0.0 && *quality <= 1.0)
compressionQuality = static_cast<int>(*quality * 100 + 0.5); compressionQuality = static_cast<int>(*quality * 100 + 0.5);
if (!WEBPImageEncoder::encode(source, compressionQuality, encodedImage)) if (!WEBPImageEncoder::encode(*this, compressionQuality, encodedImage))
return false; return false;
} else { } else {
if (!PNGImageEncoder::encode(source, encodedImage)) if (!PNGImageEncoder::encode(*this, encodedImage))
return false; return false;
ASSERT(mimeType == "image/png"); ASSERT(mimeType == "image/png");
} }
...@@ -371,7 +371,7 @@ String ImageDataBuffer::toDataURL(const String& mimeType, const double* quality) ...@@ -371,7 +371,7 @@ String ImageDataBuffer::toDataURL(const String& mimeType, const double* quality)
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
Vector<char> encodedImage; Vector<char> encodedImage;
if (!encodeImage(*this, mimeType, quality, &encodedImage)) if (!encodeImage(mimeType, quality, &encodedImage))
return "data:,"; return "data:,";
return "data:" + mimeType + ";base64," + base64Encode(encodedImage); return "data:" + mimeType + ";base64," + base64Encode(encodedImage);
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#include "wtf/PassOwnPtr.h" #include "wtf/PassOwnPtr.h"
#include "wtf/PassRefPtr.h" #include "wtf/PassRefPtr.h"
#include "wtf/Uint8ClampedArray.h" #include "wtf/Uint8ClampedArray.h"
#include "wtf/Vector.h"
#include "wtf/text/WTFString.h"
namespace WTF { namespace WTF {
...@@ -152,6 +154,7 @@ private: ...@@ -152,6 +154,7 @@ private:
struct ImageDataBuffer { struct ImageDataBuffer {
ImageDataBuffer(const IntSize& size, unsigned char* data) : m_data(data), m_size(size) { } ImageDataBuffer(const IntSize& size, unsigned char* data) : m_data(data), m_size(size) { }
String PLATFORM_EXPORT toDataURL(const String& mimeType, const double* quality) const; String PLATFORM_EXPORT toDataURL(const String& mimeType, const double* quality) const;
bool PLATFORM_EXPORT encodeImage(const String& mimeType, const double* quality, Vector<char>* output) const;
unsigned char* pixels() const { return m_data; } unsigned char* pixels() const { return m_data; }
int height() const { return m_size.height(); } int height() const { return m_size.height(); }
int width() const { return m_size.width(); } int width() const { return m_size.width(); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment