├── .versions ├── README.md ├── image-resize-client.js └── package.js /.versions: -------------------------------------------------------------------------------- 1 | blueimp:javascript-load-image@1.13.1 2 | jquery@1.11.3_2 3 | meteor@1.1.6 4 | thinksoftware:image-resize-client@1.0.0 5 | underscore@1.0.3 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Meteor Icon](http://icon.meteor.com/package/thinksoftware:image-resize-client)](https://atmospherejs.com/thinksoftware/image-resize-client) 2 | 3 | Client Side Image Resize 4 | ------------------------ 5 | 6 | After trialling lots of different S3 and file uploading tools for images, I found that the one thing missing was 7 | image resizing and cropping square on the client side before uploading the large file. 8 | 9 | This package solves that issue by allowing you to set a width, height and wether the image is cropped to a square. 10 | 11 | ## Getting started 12 | 13 | `meteor add thinksoftware:image-resize-client` 14 | 15 | 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: 16 | 17 | ``` 18 | var options = { 19 | width: 300, 20 | height: 300, 21 | cropSquare: true 22 | }; 23 | ``` 24 | 25 | 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: 26 | 27 | ``` 28 | Blob {type: "image/jpeg", size: 38898, name: "test.jpg", slice: function} 29 | name: "test.jpg" 30 | size: 38898 31 | type: "image/jpeg" 32 | __proto__: Blob 33 | ``` 34 | 35 | A bug with Safari on iOS 8, FileReader doesn't have permission to access the file input data it seems since v8. 36 | There is no way around it AFAIK, so this package will not work on iOS8 Safari, Chrome works fine however on the device. 37 | 38 | ### Usage Example 39 | 40 | An example of this package with `edgee:slingshot` package for direct S3 uploads: 41 | 42 | #### Server Side 43 | 44 | ``` 45 | Slingshot.createDirective("myFileUploads", Slingshot.S3Storage, { 46 | bucket: "###", 47 | region: "###", 48 | AWSAccessKeyId: "###", 49 | AWSSecretAccessKey: "###", 50 | 51 | acl: "public-read", 52 | 53 | authorize: function () { 54 | //Deny uploads if user is not logged in. 55 | return true; 56 | }, 57 | 58 | key: function (file) { 59 | //Store file into a directory by the user's username. 60 | return new Date().getTime() + "_" + file.name; 61 | } 62 | }); 63 | ``` 64 | 65 | ### Both Sides 66 | 67 | ``` 68 | Slingshot.fileRestrictions("myFileUploads", { 69 | allowedFileTypes: ["image/png", "image/jpeg", "image/gif"], 70 | maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited) 71 | }); 72 | ``` 73 | 74 | ### Client Side 75 | 76 | Template layout 77 | ``` 78 | 81 | ``` 82 | 83 | Template event code 84 | ``` 85 | Template.hello.events({ 86 | 'change input[type=file]': function(e, t) { 87 | var files = e.currentTarget.files; 88 | 89 | Resizer.resize(files[0], {width: 300, height: 300, cropSquare: true}, function(err, file) { 90 | 91 | var uploader = new Slingshot.Upload("myFileUploads"); 92 | 93 | uploader.send(file, function (err, downloadUrl) { 94 | if (err) 95 | console.log(err); 96 | 97 | console.log(downloadUrl); 98 | 99 | }); 100 | 101 | }); 102 | 103 | } 104 | }); 105 | ``` 106 | -------------------------------------------------------------------------------- /image-resize-client.js: -------------------------------------------------------------------------------- 1 | Resizer = { 2 | resize: function(file, options, callback) { 3 | 4 | check(options, Match.ObjectIncluding({ 5 | width: Number, 6 | height: Number, 7 | cropSquare: Boolean 8 | })); 9 | 10 | // Convert to LoadImage style options. 11 | options.maxWidth = options.width; 12 | options.maxHeight = options.width; 13 | options.crop = options.cropSquare; 14 | options.canvas = true; 15 | 16 | var fileData = { 17 | name: file.name, 18 | size: file.size, 19 | type: file.type 20 | }; 21 | 22 | // Get image metadata. 23 | LoadImage.parseMetaData(file, function(data) { 24 | var orientation = 1; 25 | if (data.exif) { 26 | orientation = data.exif.get('Orientation'); 27 | if (orientation) { 28 | options.orientation = orientation; 29 | } 30 | } 31 | 32 | // Resize image with orientation metadata. 33 | LoadImage(file, function(canvas) { 34 | var resize_dataUrl = canvas.toDataURL(fileData.type); 35 | 36 | var binaryImg = atob(resize_dataUrl.slice(resize_dataUrl.indexOf('base64') + 7, resize_dataUrl.length)); 37 | var length = binaryImg.length; 38 | var ab = new ArrayBuffer(length); 39 | var ua = new Uint8Array(ab); 40 | for (var i = 0; i < length; i++) { 41 | ua[i] = binaryImg.charCodeAt(i); 42 | } 43 | 44 | fileData.data = new Blob([ua], {type: file.type, name: file.name}); 45 | 46 | fileData.data.type = file.type; 47 | 48 | fileData.size = ua.length; 49 | 50 | callback(null, _.extend(fileData.data, {name: fileData.name}, data.exif ? data.exif.getAll() : {})); 51 | 52 | }, options); 53 | 54 | }, { maxMetaDataSize: 262144, disableImageHead: false }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'thinksoftware:image-resize-client', 3 | version: '1.0.0', 4 | // Brief, one-line summary of the package. 5 | summary: 'Client-side image resize and crop for file object', 6 | // URL to the Git repository containing the source code for this package. 7 | git: 'https://github.com/thinksoftware/meteor-image-resize-client', 8 | // By default, Meteor will default to using README.md for documentation. 9 | // To avoid submitting documentation, set this field to null. 10 | documentation: 'README.md' 11 | }); 12 | 13 | Package.onUse(function(api) { 14 | api.versionsFrom('1.0.3.2'); 15 | api.use(["underscore", "jquery"]); 16 | 17 | api.use('blueimp:javascript-load-image@1.13.1', 'client'); 18 | 19 | api.addFiles('image-resize-client.js', 'client'); 20 | if (api.export) { api.export('Resizer', 'client'); } 21 | }); 22 | --------------------------------------------------------------------------------