Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add top/bottom/left/right/width/height options #87

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ And that would update the `img` element to show this image:

### Positioning

Those source png images were already the right dimensions to be overlaid on top of each other. You can also supply an array of objects with x/y co-ords to manually position each image:
Those source png images were already the right dimensions to be overlaid on top of each other. You can also supply an array of objects with top/right/bottom/left/x/y co-ords to manually position each image:

```js
mergeImages([
{ src: 'body.png', x: 0, y: 0 },
{ src: 'body.png', left: 0, top: 0 },
{ src: 'eyes.png', x: 32, y: 0 },
{ src: 'mouth.png', x: 16, y: 0 }
{ src: 'mouth.png', right: -16, bottom: 0 }
])
.then(b64 => ...);
// data:image/png;base64,iVBORw0KGgoAA...
Expand All @@ -63,6 +63,24 @@ Using the same source images as above would output this:

<img src="/test/fixtures/face-custom-positions.png" width="128">

### Resize

Those source png images were already the right dimensions to be overlaid on top of each other. You can also supply an array of objects with width/height to manually resize each image:

```js
mergeImages([
{ src: 'body.png', left: 0, top: 0 },
{ src: 'eyes.png', x: 32, y: 64, height: 180 },
{ src: 'mouth.png', right: 32, bottom: 0, width: 128, height: 180 }
])
.then(b64 => ...);
// data:image/png;base64,iVBORw0KGgoAA...
```

Using the same source images as above would output this:

<img src="/test/fixtures/face-custom-height-width.png" width="128">

### Opacity

The opacity can also be tweaked on each image.
Expand Down
16 changes: 15 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ const defaultOptions = {
crossOrigin: undefined
};

const getX = (image, width) => {
if (image.right !== undefined) {
return width - (image.right + (image.width || image.img.width));
}
return image.left || image.x || 0;
};

const getY = (image, height) => {
if (image.bottom !== undefined) {
return height - (image.bottom + (image.height || image.img.height));
}
return image.top || image.y || 0;
};

// Return Promise
const mergeImages = (sources = [], options = {}) => new Promise(resolve => {
options = Object.assign({}, defaultOptions, options);
Expand Down Expand Up @@ -45,7 +59,7 @@ const mergeImages = (sources = [], options = {}) => new Promise(resolve => {
// Draw images to canvas
images.forEach(image => {
ctx.globalAlpha = image.opacity ? image.opacity : 1;
return ctx.drawImage(image.img, image.x || 0, image.y || 0);
return ctx.drawImage(image.img, getX(image, canvas.width), getY(image, canvas.height), image.width || image.img.width, image.height || image.img.height);
});

if (options.Canvas && options.format === 'image/jpeg') {
Expand Down
2 changes: 1 addition & 1 deletion test/errors.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mergeImages from '../';
import test from 'ava';
import { Canvas, Image } from 'canvas';
import mergeImages from '../';

test('mergeImages rejects Promise if node-canvas instance isn\'t passed in', async t => {
t.plan(1);
Expand Down
Binary file added test/fixtures/face-custom-height-width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/types.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mergeImages from '../';
import test from 'ava';
import { Canvas, Image } from 'canvas';
import mergeImages from '../';

test('mergeImages is a function', t => {
t.is(typeof mergeImages, 'function');
Expand Down
25 changes: 21 additions & 4 deletions test/unit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import test from 'ava';
import { Canvas, Image } from 'canvas';
import mergeImages from '../';
import fixtures from './fixtures';
import { Canvas, Image } from 'canvas';
import test from 'ava';

test('mergeImages returns empty b64 string if nothing is passed in', async t => {
t.plan(1);
Expand Down Expand Up @@ -62,9 +62,9 @@ test('mergeImages uses custom dimensions', async t => {
test('mergeImages uses custom positions', async t => {
t.plan(1);
const images = await Promise.all([
{ src: 'body.png', x: 0, y: 0 },
{ src: 'body.png', left: 0, top: 0 },
{ src: 'eyes.png', x: 32, y: 0 },
{ src: 'mouth.png', x: 16, y: 0 }
{ src: 'mouth.png', right: -16, bottom: 0 }
].map(image => fixtures.getImage(image.src).then(src => {
image.src = src;
return image;
Expand All @@ -76,6 +76,23 @@ test('mergeImages uses custom positions', async t => {
t.true(b64 === expectedB64);
});

test('mergeImages uses custom sizing', async t => {
t.plan(1);
const images = await Promise.all([
{ src: 'body.png', left: 0, top: 0 },
{ src: 'eyes.png', x: 32, y: 64, height: 180 },
{ src: 'mouth.png', right: 32, bottom: 0, width: 128, height: 180 }
].map(image => fixtures.getImage(image.src).then(src => {
image.src = src;
return image;
})));
const b64 = await mergeImages(images, { Canvas, Image });

const expectedB64 = await fixtures.getDataURI('face-custom-height-width.png');

t.true(b64 === expectedB64);
});

test('mergeImages uses custom jpeg quality', async t => {
t.plan(1);
const image = await fixtures.getImage('face.png');
Expand Down