From abffd98e29e18a97dfccf9a11e62731badb69bde Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 5 Oct 2016 09:15:06 -0700 Subject: [PATCH] Resize images with preserve aspect ratio --- atom/common/api/atom_api_native_image.cc | 26 ++++++++++++++++++++---- atom/common/api/atom_api_native_image.h | 1 + docs/api/native-image.md | 7 +++++++ spec/api-native-image-spec.js | 7 +++++-- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 4e843343305..77ce3660619 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -284,15 +284,32 @@ gfx::Size NativeImage::GetSize() { return image_.Size(); } +float NativeImage::GetAspectRatio() { + gfx::Size size = GetSize(); + if (size.IsEmpty()) + return 1.f; + else + return static_cast(size.width()) / static_cast(size.height()); +} + mate::Handle NativeImage::Resize( v8::Isolate* isolate, const base::DictionaryValue& options) { gfx::Size size = GetSize(); int width = size.width(); int height = size.height(); - options.GetInteger("width", &width); - options.GetInteger("height", &height); - size.set_width(width); - size.set_height(height); + bool width_set = options.GetInteger("width", &width); + bool height_set = options.GetInteger("height", &height); + size.SetSize(width, height); + + if (width_set && !height_set) { + // Scale height to preserve original aspect ratio + size.set_height(width); + size = gfx::ScaleToRoundedSize(size, 1.f, 1.f / GetAspectRatio()); + } else if (height_set && !width_set) { + // Scale width to preserve original aspect ratio + size.set_width(height); + size = gfx::ScaleToRoundedSize(size, GetAspectRatio(), 1.f); + } skia::ImageOperations::ResizeMethod method = skia::ImageOperations::ResizeMethod::RESIZE_BEST; @@ -420,6 +437,7 @@ void NativeImage::BuildPrototype( .SetMethod("isTemplateImage", &NativeImage::IsTemplateImage) .SetMethod("resize", &NativeImage::Resize) .SetMethod("crop", &NativeImage::Crop) + .SetMethod("getAspectRatio", &NativeImage::GetAspectRatio) // TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings .SetMethod("toPng", &NativeImage::ToPNG) .SetMethod("toJpeg", &NativeImage::ToJPEG); diff --git a/atom/common/api/atom_api_native_image.h b/atom/common/api/atom_api_native_image.h index 979bcfd6dc5..ee1b5f5d4b8 100644 --- a/atom/common/api/atom_api_native_image.h +++ b/atom/common/api/atom_api_native_image.h @@ -84,6 +84,7 @@ class NativeImage : public mate::Wrappable { std::string ToDataURL(); bool IsEmpty(); gfx::Size GetSize(); + float GetAspectRatio(); // Mark the image as template image. void SetTemplateImage(bool setAsTemplate); diff --git a/docs/api/native-image.md b/docs/api/native-image.md index 0a0d8e69447..4c797cae61c 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -239,4 +239,11 @@ Returns `NativeImage` - The cropped image. Returns `NativeImage` - The resized image. +If only the `height` or the `width` are specified then the current aspect ratio +will be preserved in the resized image. + +#### `image.getAspectRatio()` + +Returns `Float` - The image's aspect ratio. + [buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer diff --git a/spec/api-native-image-spec.js b/spec/api-native-image-spec.js index 3e03aff099a..de96217dd1d 100644 --- a/spec/api-native-image-spec.js +++ b/spec/api-native-image-spec.js @@ -98,9 +98,12 @@ describe('nativeImage module', () => { it('returns a resized image', () => { const image = nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', 'logo.png')) assert.deepEqual(image.resize({}).getSize(), {width: 538, height: 190}) - assert.deepEqual(image.resize({width: 400}).getSize(), {width: 400, height: 190}) - assert.deepEqual(image.resize({height: 123}).getSize(), {width: 538, height: 123}) + assert.deepEqual(image.resize({width: 269}).getSize(), {width: 269, height: 95}) + assert.deepEqual(image.resize({width: 600}).getSize(), {width: 600, height: 212}) + assert.deepEqual(image.resize({height: 95}).getSize(), {width: 269, height: 95}) + assert.deepEqual(image.resize({height: 200}).getSize(), {width: 566, height: 200}) assert.deepEqual(image.resize({width: 80, height: 65}).getSize(), {width: 80, height: 65}) + assert.deepEqual(image.resize({width: 600, height: 200}).getSize(), {width: 600, height: 200}) assert.deepEqual(image.resize({width: 0, height: 0}).getSize(), {width: 0, height: 0}) assert.deepEqual(image.resize({width: -1, height: -1}).getSize(), {width: 0, height: 0}) })