image-clipper
Advanced tools
Comparing version 0.3.1 to 0.4.0
418
lib/index.js
@@ -1,383 +0,75 @@ | ||
var fs = require('fs'); | ||
var Clipper = require('./clipper'); | ||
var utils = require('./utils'); | ||
var polyfills = require('./polyfills'); | ||
// whether is Electron | ||
var isElectron = utils.isElectron(); | ||
// Clipper factory | ||
function imageClipper(source, options, callback) { | ||
var clipper; | ||
// whether is NW.js (Node-webkit) | ||
var isNW = utils.isNW(); | ||
switch (arguments.length) { | ||
// imageClipper() | ||
case 0: | ||
clipper = new Clipper(); | ||
break; | ||
// whether is Browser | ||
var isBrowser = utils.isBrowser(); | ||
// imageClipper(Image) || imageClipper({...}) | ||
case 1: | ||
var sourceType = utils.type(source); | ||
// whether support canvas | ||
var isSupportCanvas = isBrowser || isElectron || isNW; | ||
// imageClipper({...}) | ||
if (sourceType === 'Object') { | ||
clipper = new Clipper(source); | ||
} | ||
else { | ||
clipper = new Clipper(); | ||
clipper.image(source); | ||
} | ||
// constructor | ||
function ImageClipper(options) { | ||
options = options || {}; | ||
break; | ||
this.originalOptions = options; | ||
this.maxQualityLevel = options.maxQualityLevel || 92; | ||
this.minQualityLevel = options.minQualityLevel || 1; | ||
this.qualityLevel = options.quality || this.maxQualityLevel; | ||
this.quality(this.qualityLevel); | ||
// imageClipper('path/to/image.jpg', callback) | ||
case 2: | ||
callback = options; | ||
options = null; | ||
return this; | ||
} | ||
clipper = new Clipper(); | ||
/** | ||
* load image from the memory. | ||
* | ||
* @param {Object} image, anything ctx.drawImage() accepts, usually HTMLImageElement | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.loadImageFromMemory = function(image) { | ||
image = image || this.originalImage; | ||
clipper.image(source, function () { | ||
callback.call(this); | ||
}); | ||
break; | ||
var width = image.width; | ||
var height = image.height; | ||
// imageClipper('path/to/image.jpg', {...}, callback) | ||
default: | ||
if (utils.type(options) !== 'Object') { | ||
throw new Error('invalid arguments'); | ||
} | ||
var canvas = this.__createCanvas(width, height); | ||
var ctx = canvas.getContext('2d'); | ||
clipper = new Clipper(options); | ||
ctx.drawImage(image, 0, 0, width, height); | ||
this.canvas = canvas; | ||
this.imageFormat = this.imageFormat || utils.getImageFormat(image.src) || 'image/jpeg'; | ||
if (!this.originalImage) { | ||
this.originalImage = image; | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Load image from the given url. | ||
* | ||
* @param {String} url, image url | ||
* @param {Function} callback, fired when image completely loaded | ||
* */ | ||
ImageClipper.prototype.loadImageFromUrl = function(url, callback) { | ||
var self = this; | ||
var image = this.__createImage(); | ||
this.imageFormat = utils.getImageFormat(url) || 'image/jpeg'; | ||
image.onload = function() { | ||
self.loadImageFromMemory(image); | ||
callback.call(self); | ||
}; | ||
image.src = url; | ||
}; | ||
/** | ||
* Crops the resultant image to the given width and height at the given x and y position. | ||
* | ||
* @param {Number} x, The x axis of the coordinate for the rectangle starting point | ||
* @param {Number} y, The y axis of the coordinate for the rectangle starting point | ||
* @param {Number} width, The rectangle's width | ||
* @param {Number} height, The rectangle's height | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.crop = function(x, y, width, height) { | ||
var canvas = this.canvas; | ||
var ctx = canvas.getContext('2d'); | ||
// Get cropped pixel data | ||
var imageData = ctx.getImageData(x, y, width, height); | ||
// Create a temporary canvas to place cropped pixel data | ||
var tempcanvas = this.__createCanvas(width, height); | ||
var tempctx = tempcanvas.getContext('2d'); | ||
tempctx.rect(0, 0, width, height); | ||
tempctx.fillStyle = 'white'; | ||
tempctx.fill(); | ||
tempctx.putImageData(imageData, 0, 0); | ||
// change context canvas | ||
this.canvas = tempcanvas; | ||
return this; | ||
}; | ||
/** | ||
* Write the resultant image to file. | ||
* | ||
* Note: in the Browser (not contain Electron & NW.js), | ||
* this method is equivalent to toDataURL, callback will still be executed. | ||
* | ||
* @param {String} the path where the resultant image will be saved | ||
* @param {Function} a function to be executed when saving is complete | ||
* */ | ||
ImageClipper.prototype.toFile = function(path, callback) { | ||
var self = this; | ||
var imageFormat = self.imageFormat; | ||
this.toDataURL(function(dataUrl) { | ||
// return data URI when using in browser | ||
if (isBrowser) { | ||
callback.call(self, dataUrl); | ||
} | ||
// Electron & NW.js & server-side Node.js | ||
else { | ||
this.dataUrlToFile(path, dataUrl, imageFormat, function() { | ||
callback.call(self); | ||
clipper.image(source, function () { | ||
callback.call(this); | ||
}); | ||
} | ||
}); | ||
return this; | ||
}; | ||
ImageClipper.prototype.dataUrlToFile = function(path, dataUrl, imageFormat, callback) { | ||
var self = this; | ||
var base64 = dataUrl.replace('data:'+ imageFormat +';base64,', ''); | ||
var dataBuffer = new Buffer(base64, 'base64'); | ||
// create image binary file | ||
polyfills.writeFile(path, dataBuffer, function() { | ||
callback.call(self); | ||
}); | ||
}; | ||
/** | ||
* Resize the resultant image to the given width and height | ||
* | ||
* @param {Number} width, Number of pixels wide | ||
* @param {Number} height, Number of pixels high | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.resize = function(width, height) { | ||
var originalCanvas = this.canvas; | ||
var scaleX, scaleY; | ||
if (!arguments.length) throw new Error('resize() must be specified at least one parameter'); | ||
// proportional scale when resize(width) | ||
if (arguments.length === 1) { | ||
// resize(null) | ||
if (!width) throw new Error('resize() inappropriate parameter'); | ||
scaleX = width / originalCanvas.width; | ||
height = originalCanvas.height * scaleX; | ||
} else { | ||
// proportional scale when resize(null, height) | ||
if (!width && height) { | ||
scaleY = height / originalCanvas.height; | ||
width = originalCanvas.width * scaleY; | ||
} | ||
} | ||
var canvas = this.__createCanvas(width, height); | ||
var ctx = canvas.getContext('2d'); | ||
return clipper; | ||
} | ||
ctx.drawImage(originalCanvas, 0, 0, width, height); | ||
// change context canvas | ||
this.canvas = canvas; | ||
return this; | ||
}; | ||
/** | ||
* Removes rectangular pixels from the given width and height at the given x and y position. | ||
* | ||
* @param {Number} x, The x axis of the coordinate for the rectangle starting point | ||
* @param {Number} y, The y axis of the coordinate for the rectangle starting point | ||
* @param {Number} width, Number of pixels wide will be removed | ||
* @param {Number} height, Number of pixels high will be removed | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.clear = function(x, y, width, height) { | ||
var canvas = this.canvas; | ||
// get target canvas's context | ||
var ctx = canvas.getContext('2d'); | ||
// clear rect pixel | ||
ctx.clearRect(x, y, width, height); | ||
// fill the cleared area with a white background | ||
ctx.fillStyle = '#fff'; | ||
ctx.fillRect(x, y, width, height); | ||
return this; | ||
}; | ||
/** | ||
* Adjusts the jpeg and webp compression level. | ||
* | ||
* @param {Number | String} level, a Number between 1 and 100 indicating image quality | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.quality = function(level) { | ||
level = parseFloat(level); | ||
// this will always be between 'min' and 'max' | ||
level = utils.rangeNumber(level, this.minQualityLevel, this.maxQualityLevel); | ||
this.qualityLevel = level; | ||
return this; | ||
}; | ||
/** | ||
* Return a string containing the data URI of current resultant canvas. | ||
* | ||
* @param {Number} quality | ||
* @param {Function} callback, optional in the Browser & Electron & NW.js, neccessary on the server-side Node.js | ||
* @return ImageClipper instance | ||
* */ | ||
ImageClipper.prototype.toDataURL = function(quality, callback) { | ||
var self = this; | ||
// toDataURL('68', function() {...}) | ||
if (typeof quality === 'string') { | ||
quality = parseFloat(quality); | ||
} | ||
// toDataURL() | ||
if (arguments.length == 0) { | ||
quality = this.qualityLevel; | ||
} | ||
else if (arguments.length == 1) { | ||
// toDataURL(quality) | ||
if (typeof quality === 'number') { | ||
quality = utils.rangeNumber(quality, this.minQualityLevel, this.maxQualityLevel); | ||
} | ||
// toDataURL(callback) | ||
else if (typeof quality === 'function') { | ||
callback = quality; | ||
quality = this.qualityLevel; | ||
} | ||
} | ||
// toDataURL(quality, callback) | ||
else if (arguments.length == 2) { | ||
quality = utils.rangeNumber(quality, this.minQualityLevel, this.maxQualityLevel); | ||
} | ||
var canvas = this.canvas; | ||
var imageFormat = this.imageFormat; | ||
// Browsers & Electron & NW.js | ||
if (isSupportCanvas) { | ||
var dataUrl = canvas.toDataURL(imageFormat, quality); | ||
callback && callback.call(self, dataUrl); | ||
return dataUrl; | ||
} | ||
// server-side Node.js | ||
else { | ||
if (!callback) throw new Error('toDataURL(): callback must be specified'); | ||
polyfills.toDataURL({ | ||
canvas: canvas, | ||
imageFormat: imageFormat, | ||
quality: quality, | ||
bufsize: this.originalOptions.bufsize || 4096 | ||
}, function(dataUrl) { | ||
callback.call(self, dataUrl); | ||
}); | ||
} | ||
return this; | ||
}; | ||
// get canvas | ||
ImageClipper.prototype.getCanvas = function() { | ||
return this.canvas; | ||
}; | ||
// destroy canvas | ||
ImageClipper.prototype.destroy = function() { | ||
this.canvas = null; | ||
return this; | ||
}; | ||
// reset canvas | ||
ImageClipper.prototype.reset = function() { | ||
return this.destroy().loadImageFromMemory(); | ||
}; | ||
// inject node-canvas | ||
ImageClipper.prototype.injectNodeCanvas = function(Canvas) { | ||
this.originalOptions.canvas = Canvas; | ||
}; | ||
// create Canvas object | ||
ImageClipper.prototype.__createCanvas = function(width, height) { | ||
var canvas, c; | ||
if (isSupportCanvas) { | ||
var document = window.document; | ||
c = document.createElement('canvas'); | ||
c.width = width; | ||
c.height = height; | ||
} else { | ||
// Node.js | ||
canvas = this.originalOptions.canvas; | ||
if (canvas && canvas.Image) { | ||
c = new canvas(width, height); | ||
} else { | ||
throw new Error('Require node-canvas on the server-side Node.js'); | ||
} | ||
} | ||
return c; | ||
}; | ||
// create Image object | ||
ImageClipper.prototype.__createImage = function() { | ||
var Image, img, canvas; | ||
if (isSupportCanvas) { | ||
Image = window.Image; | ||
} else { | ||
// Node.js | ||
canvas = this.originalOptions.canvas; | ||
if (canvas && canvas.Image) { | ||
Image = canvas.Image; | ||
} else { | ||
throw new Error('Require node-canvas on the server-side Node.js'); | ||
} | ||
} | ||
img = new Image; | ||
return img; | ||
}; | ||
// initialize setter | ||
function initSetter(construct) { | ||
var keys = ['imageFormat', 'maxQualityLevel', 'minQualityLevel']; | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
var key = keys[i]; | ||
(function(k) { | ||
construct.prototype['set' + utils.upperCaseFirstLetter(k)] = function(v) { | ||
this[k] = v; | ||
}; | ||
})(key); | ||
} | ||
// Configure default properties | ||
imageClipper.configure = function (name, value) { | ||
Clipper.__configure(name, value); | ||
} | ||
// init attribute setter | ||
initSetter(ImageClipper); | ||
// Export the imageClipper object for Node.js, with | ||
// backwards-compatibility for their old module API. | ||
exports = module.exports = imageClipper; | ||
exports.imageClipper = imageClipper; | ||
// use via AMD loader | ||
if(typeof define === 'function' && define.amd){ | ||
define(function(){ | ||
return ImageClipper; | ||
// If we're in the browser, | ||
// define it if we're using AMD, otherwise leak a global. | ||
if (typeof define == 'function' && define.amd) { | ||
define(function () { | ||
return imageClipper; | ||
}); | ||
} | ||
// use in browser | ||
else if(typeof window !== 'undefined'){ | ||
window.ImageClipper = ImageClipper; | ||
} | ||
module.exports = ImageClipper; | ||
} else if (typeof window != 'undefined' || typeof navigator != 'undefined') { | ||
window.imageClipper = imageClipper; | ||
} |
@@ -6,14 +6,2 @@ | ||
// whether is Electron | ||
var isElectron = utils.isElectron(); | ||
// whether is NW.js (Node-webkit) | ||
var isNW = utils.isNW(); | ||
// whether is Browser | ||
var isBrowser = utils.isBrowser(); | ||
// whether support canvas | ||
var isSupportCanvas = isBrowser || isElectron || isNW; | ||
// write an image to file | ||
@@ -34,25 +22,18 @@ polyfills.writeFile = function(path, dataBuffer, callback) { | ||
if (isSupportCanvas) { | ||
var dataUrl = canvas.toDataURL(imageFormat, quality / 100); | ||
callback(dataUrl); | ||
if (imageFormat === 'image/jpeg') { | ||
// JPEG quality number support 1 ~ 100 | ||
canvas.toDataURL(imageFormat, {quality: quality, bufsize: bufsize}, function(err, str) { | ||
if (err) throw err; | ||
callback(str); | ||
}); | ||
} else { | ||
if (imageFormat === 'image/jpeg') { | ||
// JPEG quality number support 1 ~ 100 | ||
canvas.toDataURL(imageFormat, {quality: quality, bufsize: bufsize}, function(err, str) { | ||
if (err) throw err; | ||
callback(str); | ||
}); | ||
} else { | ||
// PNG doesn't support quality setting | ||
canvas.toDataURL(imageFormat, function(err, str) { | ||
if (err) throw err; | ||
callback(str); | ||
}); | ||
} | ||
// PNG doesn't support quality setting | ||
canvas.toDataURL(imageFormat, function(err, str) { | ||
if (err) throw err; | ||
callback(str); | ||
}); | ||
} | ||
}; | ||
module.exports = polyfills; |
@@ -28,2 +28,7 @@ | ||
// detect object type | ||
utils.type = function(obj) { | ||
return Object.prototype.toString.call(obj).split(' ')[1].replace(']', ''); | ||
}; | ||
// return a number between 'min' and 'max' | ||
@@ -34,2 +39,64 @@ utils.rangeNumber = function(num, min, max) { | ||
utils.each = function(stack, handler) { | ||
var len = stack.length; | ||
// Array | ||
if (len) { | ||
for(var i = 0; i < len; i++) { | ||
if (handler.call(stack[i], stack[i], i) === false) break; | ||
} | ||
} | ||
// Object | ||
else if (typeof len === 'undefined') { | ||
for(var name in stack) { | ||
if (handler.call(stack[name], stack[name], name) === false) break; | ||
} | ||
} | ||
}; | ||
// shallow copy | ||
// utils.extend(target, obj1, obj2, ...) | ||
utils.extend = function(target) { | ||
utils.each(arguments, function(source, index) { | ||
if (index > 0) { | ||
utils.each(source, function(value, key) { | ||
if (typeof value !== 'undefined') { | ||
target[key] = value; | ||
} | ||
}); | ||
} | ||
}); | ||
}; | ||
// setter | ||
utils.setter = function(target, name, value) { | ||
var nameType = utils.type(name); | ||
// setter(name, value) | ||
if (nameType === 'String') { | ||
if (typeof target[name] === 'undefined') { | ||
throw new Error('Invalid configuration name.'); | ||
} | ||
if (typeof value === 'undefined') { | ||
throw new Error('Lack of a value corresponding to the name'); | ||
} | ||
if (utils.type(value) === 'Object' && utils.type(target[name]) === 'Object') { | ||
utils.extend(target[name], value); | ||
} else { | ||
target[name] = value; | ||
} | ||
} | ||
// setter({...}) | ||
else if (nameType === 'Object') { | ||
value = name; | ||
utils.extend(target, value); | ||
} | ||
// otherwise throws | ||
else { | ||
throw new Error('Invalid arguments'); | ||
} | ||
}; | ||
// get image format | ||
@@ -36,0 +103,0 @@ utils.getImageFormat = function(str) { |
{ | ||
"name": "image-clipper", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "Node.js module for clip & crop JPEG, PNG, WebP images purely using the native Canvas APIs, excellent compatibility with the Browser & Electron & NW.js (Node-webkit), itself doesn't relies on any image processing libraries.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
245
README.md
@@ -21,14 +21,9 @@ # image-clipper | ||
```js | ||
var ImageClipper = require('image-clipper'); | ||
var clipper = new ImageClipper(); | ||
var Clipper = require('image-clipper'); | ||
var x = 20; | ||
var y = 20; | ||
var width = 100; | ||
var height = 100; | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
this.crop(x, y, width, height) | ||
Clipper('/path/to/image.jpg', function() { | ||
this.crop(20, 20, 100, 100) | ||
.resize(50, 50) | ||
.toFile('/path/to/image-cropped.jpg', function() { | ||
.quality(80) | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
@@ -43,3 +38,3 @@ }); | ||
1. Since server-side Node.js doesn't natively support Canvas, therefore you must to specify a Canvas implementation library, such as [node-canvas](https://github.com/Automattic/node-canvas). [See usage](#clipperinjectnodecanvascanvas) | ||
1. On the server-side Node.js, since it doesn't natively support Canvas, therefore you should specify a Canvas implementation library, such as [node-canvas](https://github.com/Automattic/node-canvas). [See injectNodeCanvas() API](#clipperinjectnodecanvascanvas) | ||
2. `toFile()` not support to write the resultant image to file in the truly Browsers (not contain Electron & NW.js) | ||
@@ -66,4 +61,4 @@ | ||
var preview = document.getElementById('preview'); | ||
var clipper = new ImageClipper(); | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
imageClipper('/path/to/image.jpg', function() { | ||
this.crop(x, y, width, height) | ||
@@ -77,3 +72,3 @@ .toDataURL(function(dataUrl) { | ||
Also usable [via require.js](https://github.com/superRaytin/image-clipper/wiki/use-with-require.js) | ||
Also usable [via AMD or CMD](https://github.com/superRaytin/image-clipper/wiki/use-via-AMD-or-CMD) | ||
@@ -86,39 +81,98 @@ ### Supported browsers | ||
You can see all possible usages of APIs in the [Test Suite (server-side Node.js)](test/server.test.js) and [Test Suite (client-side Browser & Electron & NW.js)](test/jasmine/browser.test.js), or [run them](#testing) to verify. | ||
Listed below are commonly used APIs, you can see all of the possible usages of APIs in the [Test Suite (server-side Node.js)](test/tests.js) and [Test Suite (client-side Browser & Electron & NW.js)](test/browser/tests.js), or [run them](#testing) to verify. | ||
### clipper.loadImageFromUrl(url, callback) | ||
Just start with `Clipper()`, chain-capable styles provided. | ||
Load image from the given url. callback will be executed when loading is complete. | ||
### Clipper(path [, options], callback) | ||
- **url:** the path where the source image | ||
- **callback:** function() | ||
Load image from the given path with some optional parameters. This process will be performed asynchronously. | ||
- **path:** the path where the source image | ||
- **options:** properties configurable in the list of available values, reference [configure()](#clipperconfigureoptions) | ||
- **callback:** a function will be executed when loading is complete. | ||
> Note: in all callbacks, allow using `this` to call instance methods | ||
### clipper.loadImageFromMemory(image) | ||
```js | ||
Clipper('/path/to/image.jpg', function() { | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
}); | ||
}); | ||
Load image from the memory. | ||
Clipper('/path/to/image.jpg', {quality: 50}, function() { | ||
// ... | ||
}); | ||
``` | ||
- **image:** anything ctx.drawImage() accepts, usually HTMLImageElement, HTMLCanvasElement, HTMLVideoElement or [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap). Keep in mind that [origin policies](https://en.wikipedia.org/wiki/Same-origin_policy) apply to the image source, and you may not use cross-domain images without [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). | ||
### Clipper(source [, options]) | ||
`clipper.loadImageFromUrl` will eventually using this method to load image. | ||
Load image from memory. | ||
Below is an example: | ||
- **source:** anything ctx.drawImage() accepts, usually HTMLImageElement, HTMLCanvasElement, HTMLVideoElement or [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap). Keep in mind that [origin policies](https://en.wikipedia.org/wiki/Same-origin_policy) apply to the image source, and you may not use cross-domain images without [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). | ||
```js | ||
clipper.loadImageFromMemory(image) | ||
.crop(x, y, width, height) | ||
Clipper(source) | ||
.toDataURL(function(dataUrl) { | ||
console.log('cropped!'); | ||
}); | ||
Clipper(source, {quality: 50}) | ||
.toDataURL(function(dataUrl) { | ||
console.log('cropped!'); | ||
}); | ||
``` | ||
In this case, the best practice is to place the code in `onload` callback: | ||
In this case, the best practice is to place the code in `onload`: | ||
```js | ||
var image = new Image; | ||
image.onload(function(){ clipper.loadImageFromMemory(...) }); | ||
image.src = '/path/to/image.jpg'; | ||
var source = new Image; | ||
source.onload(function(){ Clipper(source).resize(...) }); | ||
source.src = '/path/to/image.jpg'; | ||
``` | ||
### Clipper(options) | ||
Create an image-clipper instance with some optional parameters. | ||
```js | ||
var clipper = Clipper({quality: 68, maxQuality: 92}); | ||
clipper.image(source) | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
}); | ||
``` | ||
### clipper.image(path, callback) | ||
Load source image from the memory after initialized. Functionality is identical to `Clipper(path, callback)`. | ||
```js | ||
clipper.image('/path/to/image.jpg', function() { | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
}); | ||
}); | ||
``` | ||
### clipper.image(source) | ||
Load source image from the memory after initialized. This process will be performed synchronously; functionality is identical to `Clipper(source)`. | ||
```js | ||
clipper.image(source) | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
}); | ||
``` | ||
In this case, the best practice is to place the code in `onload`: | ||
```js | ||
var source = new Image; | ||
source.onload(function(){ clipper.image(source).toFile(...) }); | ||
source.src = '/path/to/image.jpg'; | ||
``` | ||
### clipper.crop(x, y, width, height) | ||
@@ -133,2 +187,10 @@ | ||
```js | ||
Clipper(source) | ||
.crop(x, y, width, height) | ||
.toDataURL(function(dataUrl) { | ||
console.log('cropped!'); | ||
}); | ||
``` | ||
### clipper.toFile(path, callback) | ||
@@ -138,3 +200,3 @@ | ||
> Note: in the Browser (not contain Electron & NW.js), this method is the equivalent of **toDataURL**, callback will still be executed and will be passed the result data URI. | ||
> Note: in the Browser (not contain Electron & NW.js), this method is identical to **toDataURL()**, and callback will still be executed and will be passed the result data URI. | ||
@@ -147,5 +209,4 @@ - **path:** the path where the resultant image will be saved | ||
```js | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
this.crop(x, y, width, height) | ||
.toFile('/path/to/image-cropped.jpg', function() { | ||
Clipper('/path/to/image.jpg', function() { | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
@@ -158,10 +219,13 @@ }); | ||
Return a string containing the data URI of current resultant canvas. | ||
Return a string containing the data URI of current resultant canvas by optional compression level. | ||
- **quality:** a Number between 1 and 100 indicating image quality. | ||
- **callback:** function(dataUrl), a function to be executed when converting is complete, callback will be passed the result data URI. | ||
> Note: the quality (if provided) will only affect current `toDataURL()` | ||
- **quality:** a Number between 1 and 100 indicating image quality. If not provided, this will be get from `quality()` | ||
- **callback:** a function to be executed when converting is complete, callback will be passed the result data URI. | ||
Using on the server-side Node.js: | ||
```js | ||
var clipper = Clipper(source); | ||
clipper.toDataURL(function(dataUrl) {...}); | ||
@@ -182,3 +246,3 @@ clipper.toDataURL(quality, function(dataUrl) {...}); | ||
Adjusts the jpeg and webp compression level. Level ranges from 0 to 100. Only supported if the requested type is `image/jpeg` or `image/webp`. | ||
Adjusts the jpeg and webp compression level. Level ranges from 1 to 100. Only be supported if the requested type is `image/jpeg` or `image/webp`. | ||
@@ -190,6 +254,6 @@ - **quality:** a Number between 1 and 100 indicating image quality. | ||
```js | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
Clipper('/path/to/image.jpg', function() { | ||
this.quality(68) | ||
.crop(x, y, width, height).toDataURL(function(dataUrl) { | ||
console.log('cropped!'); | ||
.toFile('/path/to/result.jpg', function() { | ||
console.log('saved!'); | ||
}); | ||
@@ -206,2 +270,10 @@ }); | ||
```js | ||
var clipper = Clipper(); | ||
clipper.image('/path/to/image.jpg', function() { | ||
this.resize(100); | ||
}); | ||
``` | ||
To resize the resultant image to a width of 50px while maintaining aspect ratio: | ||
@@ -237,5 +309,6 @@ | ||
```js | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
Clipper('/path/to/image.jpg', function() { | ||
this.clear(50, 50, 100, 100) | ||
.crop(0, 0, 300, 300).toDataURL(function(dataUrl) { | ||
.crop(0, 0, 300, 300) | ||
.toDataURL(function(dataUrl) { | ||
preview.src = dataUrl; | ||
@@ -248,8 +321,10 @@ }); | ||
Used to restore the canvas, useful after `clear()`, `crop()`, `resize()` called. | ||
Restore the resultant image to its original. | ||
Useful if you want to clip & crop the original image after `clear()`, `crop()`, `resize()` happened. | ||
Below is an example: | ||
```js | ||
clipper.loadImageFromUrl('/path/to/image.jpg', function() { | ||
clipper('/path/to/image.jpg', function() { | ||
this.clear(50, 50, 100, 100) | ||
@@ -259,3 +334,2 @@ .crop(0, 0, 300, 300) | ||
console.log('cropped, part of data has been cleared'); | ||
this.reset() | ||
@@ -270,5 +344,7 @@ .crop(50, 50, 100, 100) | ||
Or you can also create a new instance to do that. | ||
### clipper.injectNodeCanvas(Canvas) | ||
Inject canvas implementation library into the context of instance. Can be used only on the sever-side Node.js. | ||
Inject canvas implementation library into the instance context. You should use this only on the sever-side Node.js. | ||
@@ -278,5 +354,5 @@ Usage: | ||
```js | ||
var ImageClipper = require('image-clipper'); | ||
var Clipper = require('image-clipper'); | ||
var Canvas = require('canvas'); | ||
var clipper = new ImageClipper(); | ||
var clipper = Clipper(); | ||
@@ -286,8 +362,7 @@ clipper.injectNodeCanvas(Canvas); | ||
Be equivalent to: | ||
The above is identical to: | ||
```js | ||
var ImageClipper = require('image-clipper'); | ||
var Canvas = require('canvas'); | ||
var clipper = new ImageClipper({ | ||
var Clipper = require('image-clipper'); | ||
var clipper = Clipper({ | ||
canvas: Canvas | ||
@@ -297,5 +372,11 @@ }); | ||
and: | ||
```js | ||
clipper.configure('canvas', Canvas); | ||
``` | ||
### clipper.getCanvas() | ||
Return current Canvas object. | ||
Return the current Canvas object. | ||
@@ -308,5 +389,51 @@ ```js | ||
### clipper.configure(options) | ||
Configure global properties. Properties changed by this method (same properties configurable through the constructor) will take effect for every instance created after the change. | ||
```js | ||
var Clipper = require('image-clipper'); | ||
Clipper.configure({ | ||
canvas: require('canvas') | ||
}); | ||
``` | ||
Or configure instance properties, this will only take effect for current instance and will override the global settings. | ||
```js | ||
var Clipper = require('image-clipper'); | ||
var clipper = Clipper(); | ||
clipper.configure({ | ||
canvas: require('canvas') | ||
}); | ||
``` | ||
Available properties: | ||
- **canvas** canvas implementation library, default: null | ||
- **quality** compression level, default: 92 | ||
- **maxQuality** maximum compression level, default: 100 | ||
- **minQuality** minimum compression level, default: 1 | ||
- **bufsize** output buffer size in bytes for JPEG while using node-canvas, default: 4096 | ||
Another usage for modifying single property: | ||
```js | ||
clipper.configure('bufsize', 2048); | ||
``` | ||
**Happy Clipping!** | ||
# Contributing | ||
``` | ||
$ git clone https://github.com/superRaytin/image-clipper.git | ||
$ cd image-clipper && npm install | ||
``` | ||
Please keep your local edits to `lib/*.js`, `dist/*.js` will be built upon releases. Patches for features, bug fixes, documentation, examples and others are certainly welcome. | ||
# Testing | ||
### Testing on the server-side Node.js (with node-canvas) | ||
### Node.js (with node-canvas) | ||
@@ -317,11 +444,9 @@ ``` | ||
### Testing on the client-side (Browser & Electron & NW.js) | ||
### Browser & Electron & NW.js | ||
First install jasmine: | ||
``` | ||
cd test/jasmine && bower install jasmine | ||
npm start | ||
``` | ||
Then you can run the tests using `npm start` and open http://localhost:9100/test/jasmine/runner.html | ||
Then open http://localhost:9100/test/browser/index.html | ||
@@ -328,0 +453,0 @@ # License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
33829
8
573
434