Skip to content
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
46 changes: 39 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,45 @@ This package solves that issue by allowing you to set a width, height and wether

This package allows you to set the size you want to upload to the service, saving space and bandwidth from the client. The package gives you the following options:

```
var options = {
width: 300,
height: 300,
cropSquare: true
};
```
* **maxWidth**: Defines the maximum width of the img/canvas element.
* **maxHeight**: Defines the maximum height of the img/canvas element.
* **minWidth**: Defines the minimum width of the img/canvas element.
* **minHeight**: Defines the minimum height of the img/canvas element.
* **sourceWidth**: The width of the sub-rectangle of the source image to draw
into the destination canvas.
Defaults to the source image width and requires *canvas: true*.
* **sourceHeight**: The height of the sub-rectangle of the source image to draw
into the destination canvas.
Defaults to the source image height and requires *canvas: true*.
* **top**: The top margin of the sub-rectangle of the source image.
Defaults to *0* and requires *canvas: true*.
* **right**: The right margin of the sub-rectangle of the source image.
Defaults to *0* and requires *canvas: true*.
* **bottom**: The bottom margin of the sub-rectangle of the source image.
Defaults to *0* and requires *canvas: true*.
* **left**: The left margin of the sub-rectangle of the source image.
Defaults to *0* and requires *canvas: true*.
* **contain**: Scales the image up/down to contain it in the max dimensions if
set to *true*.
This emulates the CSS feature
[background-image: contain](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#contain).
* **cover**: Scales the image up/down to cover the max dimensions with the image dimensions if set to *true*.
This emulates the CSS feature
[background-image: cover](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#cover).
* **aspectRatio**: Crops the image to the given aspect ratio (e.g. `16/9`).
This feature assumes *crop: true*.
* **crop**: Crops the image to the maxWidth/maxHeight constraints if set to
*true*.
This feature assumes *canvas: true*.
* **orientation**: Allows to transform the canvas coordinates according to the
EXIF orientation specification.
This feature assumes *canvas: true*.
* **crossOrigin**: Sets the crossOrigin property on the img element for loading
[CORS enabled images](https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image).
* **noRevoke**: By default, the
[created object URL](https://developer.mozilla.org/en/DOM/window.URL.createObjectURL)
is revoked after the image has been loaded, except when this option is set to
*true*.

The package returns a Blob file extended with the file name, size and type intact as you can see in a copy of a console log of a resized image from a file upload input:

Expand Down
43 changes: 43 additions & 0 deletions image-resize-client-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Tinytest.addAsync('Image - Resize', function(test, done) {
var originalImg, resizedImg, originalBlob, resizedBlob
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", 'https://scontent-dfw1-1.xx.fbcdn.net/hphotos-xpt1/v/t1.0-9/12346343_871489722946736_5400293110848611387_n.jpg?oh=420c4ce953952c93b6d282898dd1061d&oe=56DBA4F4', true); // true for asynchronous
xmlHttp.responseType = 'blob';
xmlHttp.onload = originalImgRetrieved
xmlHttp.send();

function originalImgRetrieved(error) {
if (this.status == 200) {
originalBlob = new Blob([this.response], {type: 'image/jpg'})
originalBlob.name = 'blob.jpg'

originalImg = document.createElement('img');
// originalImg.style = 'display: none;'
originalImg.src = window.URL.createObjectURL(originalBlob);
originalImg.onload = onOriginalImgLoaded

document.body.appendChild(originalImg)
}
}

function onOriginalImgLoaded() {
Resizer.resize(originalBlob, {maxWidth: 300, maxHeight: 100, crop: true, canvas: false}, function(err, file) {
resizedBlob = file
resizedImg = document.createElement('img');
// resizedImg.style = 'display: none;'
resizedImg.src = window.URL.createObjectURL(resizedBlob);
resizedImg.onload = onResizedImgLoaded

document.body.appendChild(resizedImg)
})
}

function onResizedImgLoaded() {
test.isTrue(originalImg.height > resizedImg.height, "Original height not greater than resized")
test.equal(resizedImg.height, 100, "Resized height incorrect")
test.equal(resizedImg.width, 300, "Resized height incorrect")
test.isTrue(originalBlob.size > resizedBlob.size )

done()
}
})
59 changes: 30 additions & 29 deletions image-resize-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@ Resizer = {
resize: function(file, options, callback) {

check(options, Match.ObjectIncluding({
width: Number,
height: Number,
cropSquare: Boolean
maxWidth: Match.Optional(Number),
maxHeight: Match.Optional(Number),
minWidth: Match.Optional(Number),
minHeight: Match.Optional(Number),
sourceWidth: Match.Optional(Number),
sourceHeight: Match.Optional(Number),
top: Match.Optional(Number),
right: Match.Optional(Number),
bottom: Match.Optional(Number),
left: Match.Optional(Number),
contain: Match.Optional(Boolean),
cover: Match.Optional(Boolean),
aspectRatio: Match.Optional(Number),
crop: Match.Optional(Boolean),
orientation: Match.Optional(Boolean),
canvas: Match.Optional(Boolean),
crossOrigin: Match.Optional(Boolean),
noRevoke: Match.Optional(Boolean)
}));

// Convert to LoadImage style options.
options.maxWidth = options.width;
options.maxHeight = options.width;
options.crop = options.cropSquare;
options.canvas = true;

var fileData = {
name: file.name,
size: file.size,
type: file.type
};

// Get image metadata.
LoadImage.parseMetaData(file, function(data) {
loadImage.parseMetaData(file, function(data) {
var orientation = 1;
if (data.exif) {
orientation = data.exif.get('Orientation');
Expand All @@ -30,27 +38,20 @@ Resizer = {
}

// Resize image with orientation metadata.
LoadImage(file, function(canvas) {
var resize_dataUrl = canvas.toDataURL(fileData.type);

var binaryImg = atob(resize_dataUrl.slice(resize_dataUrl.indexOf('base64') + 7, resize_dataUrl.length));
var length = binaryImg.length;
var ab = new ArrayBuffer(length);
var ua = new Uint8Array(ab);
for (var i = 0; i < length; i++) {
ua[i] = binaryImg.charCodeAt(i);
}

fileData.data = new Blob([ua], {type: file.type, name: file.name});

fileData.data.type = file.type;

fileData.size = ua.length;
loadImage(file, function(canvas) {

callback(null, _.extend(fileData.data, {name: fileData.name}, data.exif ? data.exif.getAll() : {}));
canvas.toBlob(function(blob) {
fileData.data = blob
fileData.data.type = file.type;

callback(null, _.extend(fileData.data, {name: fileData.name}, data.exif ? data.exif.getAll() : {}));
})
}, options);

}, { maxMetaDataSize: 262144, disableImageHead: false });
},
{
maxMetaDataSize: 262144,
disableImageHead: false
});
}
}
20 changes: 18 additions & 2 deletions package.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,26 @@ Package.describe({

Package.onUse(function(api) {
api.versionsFrom('1.0.3.2');
api.use(["underscore", "jquery"]);
api.use(["underscore", "jquery", 'check']);

api.use('blueimp:javascript-load-image@1.13.1', 'client');
api.use('marvin:javascript-load-image@2.1.1', 'client');

api.addFiles('image-resize-client.js', 'client');
if (api.export) { api.export('Resizer', 'client'); }
});

Package.onTest(function(api) {
api.use([
'ecmascript',
'tinytest',
// 'underscore'
]);

api.use([
'thinksoftware:image-resize-client',
]);

api.addFiles([
'image-resize-client-tests.js',
], 'client')
})