14. October 2015

Smartcrop.js

Smartcrop (GitHub: jwagner/smartcrop.js, License: MIT, npm: smartcrop, bower: smartcrop)

Smartcrop.js is not just another image cropping library. It detects the primary region of an image such as faces. It does this using the following algorithm.

  1. Find edges using Laplace method
  2. Find regions with a color like skin
  3. Find regions high in saturation
  4. Generate a set of candidate crops using a sliding window
  5. Rank them using a importance function to focus the detail in the center and avoid it in the edges.
  6. Output the candidate crop with the highest rank

Using it in a simple example:

SmartCrop.crop(image, {width: 100, height: 100}, result => console.log(result) );
// Which will return
// -> {topCrop: {x: 300, y: 200, height: 200, width: 200}}

When you wanna use it within node.js you would have to do something like this:

import fs from 'fs';
import Canvas from 'canvas';
import SmartCrop from 'smartcrop';

SmartCrop.crop(img, options, result => {
    console.log(JSON.stringify(result, null, 2));
    if(output && options.width && options.height){
        var canvas = new Canvas(options.width, options.height),
            ctx = canvas.getContext('2d'),
            crop = result.topCrop,
            f = fs.createWriteStream(output);
        ctx.patternQuality = 'best';
        ctx.filter = 'best';
        ctx.drawImage(img, crop.x, crop.y, crop.width, crop.height, 0, 0, canvas.width, canvas.height);
        canvas.syncJPEGStream({quality: quality}).pipe(f);
    }
});

Smartcrop.js also offers a command line interface under the npm package name smartcrop-cli. Which based uses node-canvas.

That one you would use like this:

npm i smartcrop-cli -g
smartcrop-cli --width 100 --height 100 photo.jpg square-thumbnail.jpg

Smartcrop-cli does requires node-canvas which requires local libraries to be installed. Refer to the node-canvas wiki installation instructions.

14. October 2015

Chiffon

Chiffon (GitHub: polygonplanet/Chiffon, License: MIT, npm: chiffon, bower: chiffon)

Chiffon is a very small ECMAScript parser, tokenizer and minifier. Sometimes we come across an idea where you will need to parse or tokenize Javascript files for, for instance to do analysis on the code.

When using Chiffon for tokenizing you will get an Array of each “element” of the input code like this:

let tokens = Chiffon.tokenize('var a = 1');

Which would then return:

[ { type: 'Keyword',    value: 'var' },
  { type: 'Identifier', value: 'a' },
  { type: 'Punctuator', value: '=' },
  { type: 'Numeric',    value: '1' } ]

Here is a list of all possible tokens:

  • Comment
  • LineTerminator
  • Template
  • String
  • Punctuator
  • RegularExpression
  • Numeric
  • UnicodeEscapeSequence
  • Identifier
  • Null
  • Boolean
  • Keyword

Sadly JavaScript AST is not currently supported.

When you wish to “untokenize” the Array, you can pass it into the untokenize method like this:

Chiffon.untokenize

When you want to use the minification, you would do something like this:

Chiffon.minify('var a = 1 + 1; // comment');

Which is a simple implementation of untokenize and tokenize together like this:

function minify(code) {
    return untokenize(tokenize(code, { lineTerminator: true }));
}

13. October 2015

t7

t7 (GitHub: trueadm/t7, License: ISC, npm: t7)

While browsing I came across t7, which is a template library that compiles template strings into virtual DOM objects. Because of this functionality it’s used in frameworks such as Inferno, but it can also be used within React.

There are multiple ways to work with t7. You could include the script on your page the old school way like this:

<script src="t7.js"></script>

and you can build it with Browserify or Webpack by installing it via npm and require it like this:

import t7 from 't7';

Now let’s make a page with it.

const items = ['Pizza', 'Kebab', 'Donut'];
const welcome = 'to the wonderful world of t7';

t7`
  <div class="foo">
    <h1>Welcome ${ welcome }</h1>
    <ul>
      ${
        items.map( item => t7`
          <li class="item">
            <span>The item is: ${ item }</span>
          </li>
        `)
      }
    </ul>
  </div>
`;

By default t7 will attempt to check to see if React is available. If it is, t7 will automatically produce React elements as its output. When React is not present, you can use to export it to a Universal format. Universal DOM output should be compatible with most other virtual DOM frameworks out there, like Mercury, Cito and Virtual-dom.

To set the way you want to output you use:

t7.setOutput(t7.Outputs.React);

The supported outputs are:

12. October 2015

React Image Crop

react-image-crop (GitHub: DominicTobias/react-image-crop, License: ISC, npm: react-image-crop)

React-image-crop is a React component for client side cropping of images. This mainly got my interest because I had several moments where I needed to implement something similar. This will take away that work in the future. I used to do the cropping server side which was a hassle. Upload the image, Getting the dimensions, crop with imagemagick then communicate that back to the browser.

In hindsight I now know that there are a lot of different ways to approach this problem.

What I like about react-image-crop is that it’s the basics of what you need to crop images. It gives you an object which can be used to render the cropped image in canvas to get a base64 encoded image. Another way to display this would be via clipping it with CSS.

And you guys can probably come up with a few more ways. Let’s take a look at the setup for this component.

import ReactCrop from 'react-image-crop';

<ReactCrop src='path/to/image.jpg' />

When you already want to add a crop, you just pass it as a prop like this:

var crop = {
    x: 20,
    y: 10,
    width: 30,
    height: 10
}

<ReactCrop src='path/to/image.jpg' crop={crop} />

The crop object also has a property called aspect. With that you can lock the aspect if the cropped area.

If you want to get the dimensions to where to crop you use the onChange or onComplete props.

09. October 2015

Gulp load subtasks

gulp-load-subtasks (GitHub: skorlir/gulp-load-subtasks, License: ISC, npm: gulp-load-subtasks)

gulp-load-subtasks is a gulp “extention” which was long overdue in my opinion. The problem that it solves is that it is reducing the amount of clutter the forms inside a Gulpfile when working on big projects.

This does require a bit of a shift in contrast of how we are used to writing our Gulpfile. Normally you would do something like this:

// gulpfile.js
var gulp = require('gulp');

gulp.task('some-task', function(){
    // Your stuff here
});

After a while you would get stuck with one big spaggetti of tasks. Now you can split that up into different files with their own dependencies.

The file structure would look something like this:

+ gulpfile.js
|
+ tasks/
  + a.tasks.js
  + b.tasks.js

Task A would look like this:

module.exports = function (gulp) {
  gulp.task('subtaskA1', function () {
    // do things... A1
  })
  gulp.task('subtaskA2', function () {
    // do things... A2
  })
}

And task B like this:

module.exports = function (gulp, plugins) {
  gulp.task('subtaskB', function () {
    // do things... B
    // You can use plugins!
  })
}

Then when we get back to the Gulpfile we can do this:

var gulp    = require('gulp'),
    plugins = require('gulp-load-plugins')()

$.loadSubtasks('tasks/**/*.js', gulp, plugins);

// refer tasks in a.tasks.js and b.tasks.js
gulp.task('default', [ 'subtaskA', 'subtaskB' ])