Merge pull request #8858 from electron/native-image-add-representation
Add nativeImage.addRepresentation API
This commit is contained in:
commit
14b548f27a
6 changed files with 132 additions and 3 deletions
|
@ -15,7 +15,6 @@
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/strings/pattern.h"
|
#include "base/strings/pattern.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "native_mate/dictionary.h"
|
|
||||||
#include "native_mate/object_template_builder.h"
|
#include "native_mate/object_template_builder.h"
|
||||||
#include "net/base/data_url.h"
|
#include "net/base/data_url.h"
|
||||||
#include "third_party/skia/include/core/SkPixelRef.h"
|
#include "third_party/skia/include/core/SkPixelRef.h"
|
||||||
|
@ -387,6 +386,46 @@ mate::Handle<NativeImage> NativeImage::Crop(v8::Isolate* isolate,
|
||||||
new NativeImage(isolate, gfx::Image(cropped)));
|
new NativeImage(isolate, gfx::Image(cropped)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeImage::AddRepresentation(const mate::Dictionary& options) {
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
float scale_factor = 1.0f;
|
||||||
|
options.Get("width", &width);
|
||||||
|
options.Get("height", &height);
|
||||||
|
options.Get("scaleFactor", &scale_factor);
|
||||||
|
|
||||||
|
bool skia_rep_added = false;
|
||||||
|
gfx::ImageSkia image_skia = image_.AsImageSkia();
|
||||||
|
|
||||||
|
v8::Local<v8::Value> buffer;
|
||||||
|
GURL url;
|
||||||
|
if (options.Get("buffer", &buffer) && node::Buffer::HasInstance(buffer)) {
|
||||||
|
AddImageSkiaRep(
|
||||||
|
&image_skia,
|
||||||
|
reinterpret_cast<unsigned char*>(node::Buffer::Data(buffer)),
|
||||||
|
node::Buffer::Length(buffer),
|
||||||
|
width, height, scale_factor);
|
||||||
|
skia_rep_added = true;
|
||||||
|
} else if (options.Get("dataURL", &url)) {
|
||||||
|
std::string mime_type, charset, data;
|
||||||
|
if (net::DataURL::Parse(url, &mime_type, &charset, &data)) {
|
||||||
|
if (mime_type == "image/png" || mime_type == "image/jpeg") {
|
||||||
|
AddImageSkiaRep(
|
||||||
|
&image_skia,
|
||||||
|
reinterpret_cast<const unsigned char*>(data.c_str()),
|
||||||
|
data.size(),
|
||||||
|
width, height, scale_factor);
|
||||||
|
skia_rep_added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-initialize image when first representation is added to an empty image
|
||||||
|
if (skia_rep_added && IsEmpty()) {
|
||||||
|
gfx::Image image(image_skia);
|
||||||
|
image_.SwapRepresentations(&image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(OS_MACOSX)
|
#if !defined(OS_MACOSX)
|
||||||
void NativeImage::SetTemplateImage(bool setAsTemplate) {
|
void NativeImage::SetTemplateImage(bool setAsTemplate) {
|
||||||
|
@ -504,6 +543,7 @@ void NativeImage::BuildPrototype(
|
||||||
.SetMethod("resize", &NativeImage::Resize)
|
.SetMethod("resize", &NativeImage::Resize)
|
||||||
.SetMethod("crop", &NativeImage::Crop)
|
.SetMethod("crop", &NativeImage::Crop)
|
||||||
.SetMethod("getAspectRatio", &NativeImage::GetAspectRatio)
|
.SetMethod("getAspectRatio", &NativeImage::GetAspectRatio)
|
||||||
|
.SetMethod("addRepresentation", &NativeImage::AddRepresentation)
|
||||||
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
|
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
|
||||||
.SetMethod("toPng", &NativeImage::ToPNG)
|
.SetMethod("toPng", &NativeImage::ToPNG)
|
||||||
.SetMethod("toJpeg", &NativeImage::ToJPEG);
|
.SetMethod("toJpeg", &NativeImage::ToJPEG);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/handle.h"
|
#include "native_mate/handle.h"
|
||||||
#include "native_mate/wrappable.h"
|
#include "native_mate/wrappable.h"
|
||||||
#include "ui/gfx/geometry/rect.h"
|
#include "ui/gfx/geometry/rect.h"
|
||||||
|
@ -85,6 +86,7 @@ class NativeImage : public mate::Wrappable<NativeImage> {
|
||||||
bool IsEmpty();
|
bool IsEmpty();
|
||||||
gfx::Size GetSize();
|
gfx::Size GetSize();
|
||||||
float GetAspectRatio();
|
float GetAspectRatio();
|
||||||
|
void AddRepresentation(const mate::Dictionary& options);
|
||||||
|
|
||||||
// Mark the image as template image.
|
// Mark the image as template image.
|
||||||
void SetTemplateImage(bool setAsTemplate);
|
void SetTemplateImage(bool setAsTemplate);
|
||||||
|
|
|
@ -247,8 +247,8 @@ Returns `NativeImage` - The cropped image.
|
||||||
#### `image.resize(options)`
|
#### `image.resize(options)`
|
||||||
|
|
||||||
* `options` Object
|
* `options` Object
|
||||||
* `width` Integer (optional)
|
* `width` Integer (optional) - Defaults to the image's width.
|
||||||
* `height` Integer (optional)
|
* `height` Integer (optional) - Defaults to the image's height
|
||||||
* `quality` String (optional) - The desired quality of the resize image.
|
* `quality` String (optional) - The desired quality of the resize image.
|
||||||
Possible values are `good`, `better` or `best`. The default is `best`.
|
Possible values are `good`, `better` or `best`. The default is `best`.
|
||||||
These values express a desired quality/speed tradeoff. They are translated
|
These values express a desired quality/speed tradeoff. They are translated
|
||||||
|
@ -265,4 +265,20 @@ will be preserved in the resized image.
|
||||||
|
|
||||||
Returns `Float` - The image's aspect ratio.
|
Returns `Float` - The image's aspect ratio.
|
||||||
|
|
||||||
|
#### `image.addRepresentation(options)`
|
||||||
|
|
||||||
|
* `options` Object
|
||||||
|
* `scaleFactor` Double - The scale factor to add the image representation for.
|
||||||
|
* `width` Integer (optional) - Defaults to 0. Required if a bitmap buffer
|
||||||
|
is specified as `buffer`.
|
||||||
|
* `height` Integer (optional) - Defaults to 0. Required if a bitmap buffer
|
||||||
|
is specified as `buffer`.
|
||||||
|
* `buffer` Buffer (optional) - The buffer containing the raw image data.
|
||||||
|
* `dataURL` String (optional) - The data URL containing either a base 64
|
||||||
|
encoded PNG or JPEG image.
|
||||||
|
|
||||||
|
Add an image representation for a specific scale factor. This can be used
|
||||||
|
to explicitly add different scale factor representations to an image. This
|
||||||
|
can be called on empty images.
|
||||||
|
|
||||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||||
|
|
|
@ -249,4 +249,75 @@ describe('nativeImage module', () => {
|
||||||
assert.equal(nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', 'logo.png')).getAspectRatio(), 2.8315789699554443)
|
assert.equal(nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', 'logo.png')).getAspectRatio(), 2.8315789699554443)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('addRepresentation()', () => {
|
||||||
|
it('supports adding a buffer representation for a scale factor', () => {
|
||||||
|
const image = nativeImage.createEmpty()
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 1.0,
|
||||||
|
buffer: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '1x1.png')).toPNG()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 2.0,
|
||||||
|
buffer: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '2x2.jpg')).toPNG()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 3.0,
|
||||||
|
buffer: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '3x3.png')).toPNG()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 4.0,
|
||||||
|
buffer: 'invalid'
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(image.isEmpty(), false)
|
||||||
|
assert.deepEqual(image.getSize(), {width: 1, height: 1})
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 1.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYlWNgAAIAAAUAAdafFs0AAAAASUVORK5CYII=')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 2.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFUlEQVQYlWP8////fwYGBgYmBigAAD34BABBrq9BAAAAAElFTkSuQmCC')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 3.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAADElEQVQYlWNgIAoAAAAnAAGZWEMnAAAAAElFTkSuQmCC')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 4.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAADElEQVQYlWNgIAoAAAAnAAGZWEMnAAAAAElFTkSuQmCC')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports adding a data URL representation for a scale factor', () => {
|
||||||
|
const image = nativeImage.createEmpty()
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 1.0,
|
||||||
|
dataURL: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '1x1.png')).toDataURL()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 2.0,
|
||||||
|
dataURL: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '2x2.jpg')).toDataURL()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 3.0,
|
||||||
|
dataURL: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '3x3.png')).toDataURL()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 4.0,
|
||||||
|
dataURL: 'invalid'
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(image.isEmpty(), false)
|
||||||
|
assert.deepEqual(image.getSize(), {width: 1, height: 1})
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 1.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYlWNgAAIAAAUAAdafFs0AAAAASUVORK5CYII=')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 2.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFUlEQVQYlWP8////fwYGBgYmBigAAD34BABBrq9BAAAAAElFTkSuQmCC')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 3.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAADElEQVQYlWNgIAoAAAAnAAGZWEMnAAAAAElFTkSuQmCC')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 4.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAADElEQVQYlWNgIAoAAAAnAAGZWEMnAAAAAElFTkSuQmCC')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports adding a representation to an existing image', () => {
|
||||||
|
const image = nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '1x1.png'))
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 2.0,
|
||||||
|
dataURL: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '2x2.jpg')).toDataURL()
|
||||||
|
})
|
||||||
|
image.addRepresentation({
|
||||||
|
scaleFactor: 2.0,
|
||||||
|
dataURL: nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', '3x3.png')).toDataURL()
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 1.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYlWNgAAIAAAUAAdafFs0AAAAASUVORK5CYII=')
|
||||||
|
assert.equal(image.toDataURL({scaleFactor: 2.0}), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFUlEQVQYlWP8////fwYGBgYmBigAAD34BABBrq9BAAAAAElFTkSuQmCC')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
BIN
spec/fixtures/assets/2x2.jpg
vendored
Normal file
BIN
spec/fixtures/assets/2x2.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
spec/fixtures/assets/3x3.png
vendored
Normal file
BIN
spec/fixtures/assets/3x3.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 507 B |
Loading…
Reference in a new issue