imagejs
Advanced tools
Comparing version 0.0.8 to 0.0.9
@@ -35,2 +35,3 @@ /** | ||
var Resize = require("./resize"); | ||
//var Graphics = require("./graphics"); | ||
@@ -76,2 +77,8 @@ // default pad colour | ||
}, | ||
//get graphics() { | ||
// if (!this._graphics) { | ||
// this._graphics = new Graphics(this); | ||
// } | ||
// return this._graphics; | ||
//}, | ||
@@ -294,4 +301,4 @@ attach: function(data) { | ||
wMargin = (that.width - w2) / 2; | ||
that._fill(padColor, {left: 0, top: 0, width: Math.floor(wMargin), height: that.height}); | ||
that._fill(padColor, {left: that.width - Math.ceil(wMargin), top: 0, width: Math.ceil(wMargin), height: that.height}); | ||
that._fill(padColor, 0, 0, Math.floor(wMargin), that.height); | ||
that._fill(padColor, that.width - Math.ceil(wMargin), 0, Math.ceil(wMargin), that.height); | ||
@@ -304,4 +311,4 @@ Resize[options.algorithm](this, temp, options); | ||
hMargin = (that.height - h2) / 2; | ||
that._fill(padColor, {left: 0, top: 0, width: that.width, height: Math.floor(hMargin)}); | ||
that._fill(padColor, {left: 0, top: that.height - Math.ceil(hMargin), width: that.width, height: Math.ceil(hMargin)}); | ||
that._fill(padColor, 0, 0, that.width, Math.floor(hMargin)); | ||
that._fill(padColor, 0, that.height - Math.ceil(hMargin), that.width, Math.ceil(hMargin)); | ||
@@ -342,2 +349,141 @@ Resize[options.algorithm](this, temp, options); | ||
rotate: function(options) { | ||
// TODO: crop, user supplied dst width, height | ||
// options.degrees || options.radians; | ||
// options.fit = ['pad','crop','same'] | ||
// options.padColor | ||
var radians = options.radians !== undefined ? options.radians : 3.141592653589793 * options.degrees / 180; | ||
if (radians < 0.000000001) { | ||
return new Bitmap(this); | ||
} | ||
//console.log("radians=" + radians); | ||
var rotators = { | ||
forward: { | ||
cos: Math.cos(radians), | ||
sin: Math.sin(radians) | ||
}, | ||
backward: { | ||
cos: Math.cos(-radians), | ||
sin: Math.sin(-radians) | ||
} | ||
} | ||
//console.log("cos=" + cos + ", sin=" + sin) | ||
var srcWidth = this.width; | ||
var srcHeight = this.height; | ||
var srcWidthHalf = srcWidth / 2; | ||
var srcHeightHalf = srcHeight / 2; | ||
var padColor = options.padColor || transparentBlack; | ||
var padArray = [padColor.r, padColor.g, padColor.b, padColor.a]; | ||
var rotate = function(point, rotator) { | ||
// in-place rotation of point | ||
var x = rotator.cos * point.x - rotator.sin * point.y; | ||
var y = rotator.sin * point.x + rotator.cos * point.y; | ||
point.x = x; | ||
point.y = y; | ||
return point; | ||
}; | ||
var cropToSource = function(point) { | ||
var m = Math.abs(point.x/srcWidthHalf); | ||
var n = Math.abs(point.y/srcHeightHalf); | ||
return Math.max(m,n); | ||
}; | ||
var dstWidth, dstHeight; | ||
switch (options.fit) { | ||
case 'custom': | ||
dstWidth = options.width; | ||
dstHeight = options.height; | ||
break; | ||
case 'pad': | ||
// entire src fits in dst | ||
var tl = rotate({x:-srcWidthHalf,y:srcHeightHalf}, rotators.forward); | ||
var tr = rotate({x:srcWidthHalf,y:srcHeightHalf}, rotators.forward); | ||
var bl = rotate({x:-srcWidthHalf,y:-srcHeightHalf}, rotators.forward); | ||
var br = rotate({x:srcWidthHalf,y:-srcHeightHalf}, rotators.forward); | ||
dstWidth = Math.round(Math.max(tl.x,tr.x,bl.x,br.x) - Math.min(tl.x,tr.x,bl.x,br.x)); | ||
dstHeight = Math.round(Math.max(tl.y,tr.y,bl.y,br.y) - Math.min(tl.y,tr.y,bl.y,br.y)); | ||
break; | ||
case 'crop': | ||
var tl = rotate({x:-srcWidthHalf,y:srcHeightHalf}, rotators.forward); | ||
var tr = rotate({x:srcWidthHalf,y:srcHeightHalf}, rotators.forward); | ||
var bl = rotate({x:-srcWidthHalf,y:-srcHeightHalf}, rotators.forward); | ||
var br = rotate({x:srcWidthHalf,y:-srcHeightHalf}, rotators.forward); | ||
var d = Math.max(cropToSource(tl), cropToSource(tr), cropToSource(bl), cropToSource(br)); | ||
dstWidth = Math.floor(srcWidth / d); | ||
dstHeight = Math.floor(srcHeight / d); | ||
break; | ||
case 'same': | ||
default: | ||
// dst is same size as src | ||
dstWidth = srcWidth; | ||
dstHeight = srcHeight; | ||
break; | ||
} | ||
var that = new Bitmap({width: dstWidth, height: dstHeight}); | ||
var srcBuf = this._data.data; | ||
var dstBuf = that._data.data; | ||
// we will rotate the destination pixels back to the source and interpolate the colour | ||
var srcCoord = {}; | ||
var dstWidthHalf = dstWidth / 2; | ||
var dstHeightHalf = dstHeight / 2; | ||
var dstWidth4 = dstWidth * 4; | ||
var srcWidth4 = srcWidth * 4; | ||
//console.log("src=[" + srcWidth + "," + srcHeight + "]") | ||
//console.log("dst=[" + dstWidth + "," + dstHeight + "]") | ||
for (var i = 0; i < dstHeight; i++) { | ||
for (var j = 0; j < dstWidth; j++) { | ||
// calculate src coords | ||
srcCoord.x = j - dstWidthHalf; | ||
srcCoord.y = dstHeightHalf - i; | ||
//console.log("x=" + srcCoord.x + ", y=" + srcCoord.y); | ||
rotate(srcCoord, rotators.backward); | ||
//console.log(" ==> x=" + srcCoord.x + ", y=" + srcCoord.y); | ||
// srcX and SrcY are in src coords | ||
var srcX = srcCoord.x + srcWidthHalf; | ||
var srcY = srcHeightHalf - srcCoord.y; | ||
//console.log("srcX=" + srcX + ", srcY=" + srcY); | ||
// now interpolate (bilinear! | ||
var dstPos = (i * dstWidth + j) * 4; | ||
//console.log("dstPos=" + dstPos) | ||
if ((srcX > -1) && (srcX < srcWidth) && (srcY > -1) && (srcY < srcHeight)) { | ||
var srcPosX = Math.floor(srcX); | ||
var srcPosY = Math.floor(srcY); | ||
var srcPos = (srcPosY * srcWidth + srcPosX) * 4; | ||
for (var k = 0; k < 4; k++) { | ||
var kSrcPos = srcPos + k; | ||
var kPad = padArray[k]; | ||
var tl = ((srcX >= 0) && (srcY >= 0)) ? srcBuf[kSrcPos] : kPad; | ||
var tr = ((srcX < srcWidth-1) && (srcY >= 0)) ? srcBuf[kSrcPos+4] : kPad; | ||
var bl = ((srcX >= 0) && (srcY < srcHeight-1)) ? srcBuf[kSrcPos + srcWidth4] : kPad; | ||
var br = ((srcX < srcWidth-1) && (srcY < srcHeight-1)) ? srcBuf[kSrcPos + srcWidth4 + 4] : kPad; | ||
var tx = srcX - srcPosX; | ||
var ty = srcY - srcPosY; | ||
var t = (1-tx) * tl + tx * tr; | ||
var b = (1-tx) * bl + tx * br; | ||
dstBuf[dstPos++] = (1-ty) * t + ty * b; | ||
} | ||
} else { | ||
dstBuf[dstPos++] = padColor.r; | ||
dstBuf[dstPos++] = padColor.g; | ||
dstBuf[dstPos++] = padColor.b; | ||
dstBuf[dstPos++] = padColor.a; | ||
} | ||
} | ||
} | ||
return that; | ||
}, | ||
crop: function(options) { | ||
@@ -384,11 +530,11 @@ var t = options.top; | ||
src[pos -(i>0?V:0) + (j<W?4:0)] * 1 + // 1/16 | ||
src[pos - (j>0?4:0)] * 2 + // 2/16 | ||
src[pos ] * 4 + // 4/16 | ||
src[pos + (j<W?4:0)] * 2 + // 2/16 | ||
src[pos +(i<H?V:0) - (j>0?4:0)] * 1 + // 1/16 | ||
src[pos +(i<H?V:0) ] * 2 + // 2/16 | ||
src[pos +(i<H?V:0) + (j<W?4:0)] * 1; // 1/16 | ||
dst[pos] = Math.round(t/16); | ||
@@ -401,8 +547,7 @@ } | ||
_fill: function(color, options) { | ||
options = options || {}; | ||
var t = options.top || 0; | ||
var l = options.left || 0; | ||
var w = options.width || this.width - l; | ||
var h = options.height || this.height - t; | ||
_fill: function(color, l,t,w,h) { | ||
l = l || 0; | ||
t = t || 0; | ||
w = w || this.width - l; | ||
h = h || this.height - t; | ||
//console.log("Fill: l="+l + ", t="+t + ", w="+w + ", h="+h); | ||
@@ -409,0 +554,0 @@ |
{ | ||
"name": "imagejs", | ||
"version": "0.0.8", | ||
"version": "0.0.9", | ||
"description": "Image Processor", | ||
@@ -17,3 +17,3 @@ "private": false, | ||
"keywords": [ | ||
"pure", "javascript", "image", "bitmap", "jpg", "jpeg", "resize", "negative", "crop", | ||
"pure", "javascript", "image", "bitmap", "jpg", "jpeg", "resize", "rotate", "negative", "crop", | ||
"bilinear", "bicubic", "hermite", "bezier" | ||
@@ -20,0 +20,0 @@ ], |
# ImageJS | ||
Read, manipulate and write Images | ||
A Pure JavaScript Image manipulation library. | ||
Read and write JPG and PNG image files or streams and perform a number of operations on them. | ||
Due to a lack of pure JavaScript Image manipulation libraries available, I decided to implement one. | ||
This is an early release supporting only jpeg and png files and only the simplest resize algorithms | ||
but there will be more to come. | ||
# Installation | ||
@@ -17,15 +14,11 @@ | ||
<ul> | ||
<li>Internal Restructuring</li> | ||
<li>Corrected Documentation</li> | ||
<li>Better Bitmap Construction</li> | ||
<li>Performance Improvements</li> | ||
<li> | ||
Bug Fixes | ||
<ul> | ||
<li>readFile this bug</li> | ||
<li>resize same aspect ratio fix</li> | ||
</ul> | ||
</li> | ||
<li><a href="#rotate">Rotate</a></li> | ||
</ul> | ||
# Backlog | ||
<ul> | ||
<li>Graphics Object (draw and fill lines and shapes)</li> | ||
</ul> | ||
# Contents | ||
@@ -41,7 +34,8 @@ | ||
<ul> | ||
<li><a href="set-pixel">Set Pixel</a></li> | ||
<li><a href="negative">Negative</a></li> | ||
<li><a href="blur">Blur</a></li> | ||
<li><a href="crop">Crop</a></li> | ||
<li><a href="resize">Resize</a></li> | ||
<li><a href="#set-pixel">Set Pixel</a></li> | ||
<li><a href="#negative">Negative</a></li> | ||
<li><a href="#blur">Blur</a></li> | ||
<li><a href="#crop">Crop</a></li> | ||
<li><a href="#resize">Resize</a></li> | ||
<li><a href="#rotate">Rotate</a></li> | ||
</ul> | ||
@@ -56,2 +50,4 @@ </li> | ||
# Interface | ||
@@ -165,2 +161,22 @@ | ||
### Rotate | ||
```javascript | ||
// rotate image 0.5 radians counterclockwise, keeping the dimensions the same and padding with red | ||
// Note: default fit is "same" so including it in options is optional | ||
var red = {r: 255, g: 0, b: 0, a: 255}; | ||
var rotated = bitmap.rotate({radians: 0.5, fit: "same", padColor: red}); | ||
// rotate image 10 degrees clockwise, preserving entire image and padding with transparent white | ||
var transparentWhite = {r: 255, g: 255, b: 255, a: 0}; | ||
var rotated = bitmap.rotate({degrees: -10, fit: "pad", padColor: transparentWhite}); | ||
// rotate image 45 degress counterclockwise, cropping so all of the result image comes from the source. | ||
var rotated = bitmap.rotate({degrees: 45, fit: "crop"}); | ||
// rotate image 30 degrees counterclockwise, selecting custom dimensions. Note: image will not be scaled. | ||
// default padColor (if required) is transparentBlack. | ||
var rotated = bitmap.rotate({degrees: 30, fit: "custom", width: 100, height: 150}); | ||
``` | ||
## Reading Images | ||
@@ -213,2 +229,3 @@ | ||
| 0.0.6 | <ul><li>Internal Restructuring</li><li>Corrected Documentation</li><li>Better Bitmap Construction</li><li>Performance Improvements</li></ul> | | ||
| 0.0.8 | <ul><li>Bug Fixes<ul><li>readFile this bug</li><li>resize same aspect ratio fix</li></ul></li></ul> | | ||
| 0.0.9 | <ul><li><a href="#rotate">Rotate</a></li></ul> |
58121
10
1134
227