Skip to content

Commit

Permalink
v2.1.0
Browse files Browse the repository at this point in the history
* add support for strings (uri or base64 data-uri) as sources for `vintagejs`
  • Loading branch information
rendro committed Mar 5, 2017
1 parent e8e925b commit e352958
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 156 deletions.
14 changes: 12 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Add a retro/vintage effect to images using the HTML5 canvas element.
vintagejs :: TSourceElement -> $Shape<TEffect> -> Promise<TResult>
```

The `vintagejs` function takes two arguments, a source element (image or canvas) and an effect object and returns a promise that resolves to a result object with the following methods:
The `vintagejs` function takes two arguments, a source (url, base64 data uri, image element or canvas element) and an effect object and returns a promise that resolves to a result object with the following methods:

```javascript
// returns the data url of the updated image. Use it to update the source of an existing image
Expand Down Expand Up @@ -37,6 +37,13 @@ vintagejs(srcEl, { brightness: 0.2 })
.then(res => {
ctx.drawImage(res.getCanvas(), 0, 0, srcEl.width, srcEl.height);
});

// use a url (file path or data-uri) as source and insert result image into DOM
vintagejs('./path/to/image.jpg', { brightness: 0.2 })
.then(res => res.genImage())
.then(img => {
document.body.appendChild(img);
});
```

## Effect options
Expand Down Expand Up @@ -107,7 +114,10 @@ Higher performance when canvas blend modes are supported [caniuse.com/#feat=canv

## Changelog

### Version 2.0.0 - <small>Mar, 2017</small>
### Version 2.1.0 - <small>Mar 5, 2017</small>
* Add support for strings (URI or base64 encoded data-uri) as a source

### Version 2.0.0 - <small>Mar 4, 2017</small>
* Rewrite from ground up
* Functional API

Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "vintageJS",
"version": "2.0.0",
"version": "2.1.0",
"main": "dist/vintage.js"
}
141 changes: 73 additions & 68 deletions dist/vintage.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ Object.defineProperty(exports, "__esModule", {
value: true
});

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _utils = require('./utils.js');

var defaultEffect = {
Expand Down Expand Up @@ -104,77 +104,73 @@ var getLUT = function getLUT(effect) {
return [idArr.map(rMod), idArr.map(gMod), idArr.map(bMod)];
};

// ApplyEffect :: SourceElement -> $Shape<Effect> -> Promise<TResult>
var applyEffect = function applyEffect(effect) {
var LUT = getLUT(effect);
return function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
canvas = _ref2[0],
ctx = _ref2[1];

return new Promise(function (resolve, reject) {
var width = canvas.width,
height = canvas.height;

ctx.globalCompositeOperation = 'multiply';
var supportsBlendModes = ctx.globalCompositeOperation === 'multiply';
var data = ctx.getImageData(0, 0, width, height);
var id = data.data.slice(0);
var sepia = effect.sepia,
saturation = effect.saturation;


for (var i = id.length / 4; i >= 0; --i) {
var ri = i << 2;
var gi = ri + 1;
var bi = ri + 2;

var r = LUT[0][id[ri]];
var g = LUT[1][id[gi]];
var b = LUT[2][id[bi]];

if (sepia) {
var _ref3 = [r * 0.393 + g * 0.769 + b * 0.189, r * 0.349 + g * 0.686 + b * 0.168, r * 0.272 + g * 0.534 + b * 0.131];
r = _ref3[0];
g = _ref3[1];
b = _ref3[2];
}

exports.default = function (srcEl, partialEffect) {
return new Promise(function (resolve, reject) {
var effect = _extends({}, defaultEffect, partialEffect);
var LUT = getLUT(effect);

var _getCanvasAndCtx = (0, _utils.getCanvasAndCtx)(srcEl),
_getCanvasAndCtx2 = _slicedToArray(_getCanvasAndCtx, 2),
canvas = _getCanvasAndCtx2[0],
ctx = _getCanvasAndCtx2[1];

var width = canvas.width,
height = canvas.height;

ctx.globalCompositeOperation = 'multiply';
var supportsBlendModes = ctx.globalCompositeOperation === 'multiply';
var data = ctx.getImageData(0, 0, width, height);
var id = data.data.slice(0);
var sepia = effect.sepia,
saturation = effect.saturation,
viewfinder = effect.viewfinder;


for (var i = id.length / 4; i >= 0; --i) {
var ri = i << 2;
var gi = ri + 1;
var bi = ri + 2;

var r = LUT[0][id[ri]];
var g = LUT[1][id[gi]];
var b = LUT[2][id[bi]];

if (sepia) {
var _ref = [r * 0.393 + g * 0.769 + b * 0.189, r * 0.349 + g * 0.686 + b * 0.168, r * 0.272 + g * 0.534 + b * 0.131];
r = _ref[0];
g = _ref[1];
b = _ref[2];
}
if (saturation < 1) {
var avg = (r + g + b) / 3;
r += (avg - r) * (1 - saturation);
g += (avg - g) * (1 - saturation);
b += (avg - b) * (1 - saturation);
}

if (saturation < 1) {
var avg = (r + g + b) / 3;
r += (avg - r) * (1 - saturation);
g += (avg - g) * (1 - saturation);
b += (avg - b) * (1 - saturation);
id[ri] = r;
id[gi] = g;
id[bi] = b;
}

id[ri] = r;
id[gi] = g;
id[bi] = b;
}
data.data.set(id);
ctx.putImageData(data, 0, 0);

data.data.set(id);
ctx.putImageData(data, 0, 0);
if (effect.vignette) {
ctx.globalCompositeOperation = supportsBlendModes ? 'multiply' : 'source-over';
ctx.fillStyle = (0, _utils.getGradient)(ctx, width, height, ['rgba(0,0,0,0)', 'rgba(0,0,0,0)', 'rgba(0,0,0,' + effect.vignette + ')']);
ctx.fillRect(0, 0, width, height);
}

if (effect.vignette) {
ctx.globalCompositeOperation = supportsBlendModes ? 'multiply' : 'source-over';
ctx.fillStyle = (0, _utils.getGradient)(ctx, width, height, ['rgba(0,0,0,0)', 'rgba(0,0,0,0)', 'rgba(0,0,0,' + effect.vignette + ')']);
ctx.fillRect(0, 0, width, height);
}
if (effect.lighten) {
ctx.globalCompositeOperation = supportsBlendModes ? 'screen' : 'lighter';
ctx.fillStyle = (0, _utils.getGradient)(ctx, width, height, ['rgba(255,255,255,' + effect.lighten + ')', 'rgba(255,255,255,0)', 'rgba(0,0,0,0)']);
ctx.fillRect(0, 0, width, height);
}

if (effect.lighten) {
ctx.globalCompositeOperation = supportsBlendModes ? 'screen' : 'lighter';
ctx.fillStyle = (0, _utils.getGradient)(ctx, width, height, ['rgba(255,255,255,' + effect.lighten + ')', 'rgba(255,255,255,0)', 'rgba(0,0,0,0)']);
ctx.fillRect(0, 0, width, height);
}
if (!effect.viewfinder) {
return resolve((0, _utils.getResult)(canvas));
}

if (!viewfinder) {
resolve((0, _utils.getResult)(canvas));
} else {
return (0, _utils.loadImageWithCache)(viewfinder).then(function (img) {
return (0, _utils.loadImageWithCache)(effect.viewfinder).then(function (img) {
if (supportsBlendModes) {
ctx.globalCompositeOperation = 'multiply';
ctx.drawImage(img, 0, 0, width, height);
Expand All @@ -193,10 +189,19 @@ exports.default = function (srcEl, partialEffect) {
}));
ctx.putImageData(imageData, 0, 0);
}
resolve((0, _utils.getResult)(canvas));

return resolve((0, _utils.getResult)(canvas));
});
}
});
});
};
};

// vintagejs :: TSource -> $Shape<TEffect> -> Promise<TResult>

exports.default = function (src, partialEffect) {
var genSource = typeof src === 'string' ? (0, _utils.loadImage)(src).then(_utils.getCanvasAndCtx) : Promise.resolve((0, _utils.getCanvasAndCtx)(src));

return genSource.then(applyEffect(_extends({}, defaultEffect, partialEffect)));
};

module.exports = exports['default'];
Expand Down
2 changes: 1 addition & 1 deletion dist/vintage.min.js

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions examples/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,20 @@ const effect = {
brightness: -0.1,
contrast: 0.15,
curves: curves2,
saturation: 0.7,
saturation: 0.8,
viewfinder: './film-1.jpg',
screen: {
r: 227,
g: 12,
b: 169,
a: 0.15,
},
sepia: true,
};

vintagejs('./dude.jpg', effect).then(res => res.genImage()).then(img => {
document.body.appendChild(img);
});

const img = document.getElementById('picture');
vintagejs(img, effect).then(res => {
img.src = res.getDataURL();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vintagejs",
"description": "Add a retro/vintage effect to images using the HTML5 canvas element",
"license": "MIT",
"version": "2.0.0",
"version": "2.1.0",
"author": {
"name": "Robert Fleischmann",
"email": "[email protected]",
Expand Down
Loading

0 comments on commit e352958

Please sign in to comment.