Skip to content

Commit

Permalink
Merge branch 'liviutudor-liv_add_color'
Browse files Browse the repository at this point in the history
  • Loading branch information
bostrom committed Nov 13, 2016
2 parents 62a5868 + 31e043e commit 21349e2
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ jspm_packages

# Optional REPL history
.node_repl_history

# IntelliJ
.idea
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ The ```generate``` function takes an optional second parameter containing config
| lineHeight | 28 | The line height for the generated text. |
| margin | 10 | The margin (all sides) between the text and the border of the image. |
| debug | false | Set to true to turn on debug mode (see below). |
| bgColor | `"#FFFFFF"` | Sets the background color of the image. |
| textColor | `"#000000"` | Sets the text color. |

Example:

Expand All @@ -53,7 +55,9 @@ Example:
maxWidth: 720,
fontSize: 18,
lineHeight: 30,
margin: 5
margin: 5,
bgColor: "blue",
textColor: "red"
}).then(function (dataUri) {
console.log(dataUri);
});
Expand Down
17 changes: 9 additions & 8 deletions lib/text-to-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ var fs = require('fs'),
maxWidth: 400,
fontSize: 18,
lineHeight: 28,
margin: 10
margin: 10,
bgColor: '#fff',
textColor: '#000'
};

function generateImage(content, config) {
var conf = _.defaults(config, defaults);

var textData = createTextData(content, conf.maxWidth - conf.margin, conf.fontSize, conf.lineHeight);
var textData = createTextData(content, conf.maxWidth - conf.margin, conf.fontSize, conf.lineHeight, conf.bgColor, conf.textColor);

var canvas = new Canvas(conf.maxWidth, textData.height + conf.margin * 2),
ctx = canvas.getContext('2d');

ctx.globalAlpha = 1;
// make background
ctx.fillStyle = "#fff";
ctx.fillStyle = conf.bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.putImageData(textData, conf.margin, conf.margin);
Expand All @@ -44,19 +45,19 @@ function generateImage(content, config) {
return Promise.resolve(dataUrl);
}

function createTextData(text, maxWidth, fontSize, lineHeight) {
function createTextData(text, maxWidth, fontSize, lineHeight, bgColor, textColor) {
// create a tall context so we definitely can fit all text
var textCanvas = new Canvas(maxWidth, 1000),
textContext = textCanvas.getContext('2d'),
textX = 0,
textY = 0;

// make background white
textContext.fillStyle = "#fff";
// make background the color passed in
textContext.fillStyle = bgColor;
textContext.fillRect(0, 0, textCanvas.width, textCanvas.height);

// make text
textContext.fillStyle = "#000";
textContext.fillStyle = textColor;
textContext.font = 'normal ' + fontSize + 'px Helvetica';
textContext.textBaseline = 'top';

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"image-size": "^0.5.0",
"istanbul": "^0.4.4",
"mocha": "^3.0.0",
"readimage": "^1.1.1",
"sinon": "^1.17.4",
"sinon-chai": "^2.8.0"
}
Expand Down
34 changes: 34 additions & 0 deletions test/helpers/extractColors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";

module.exports = extractColors;

function extractColors(image) {
var pixels = image.frames[0].data;
var colorMap = {};
for (var i = 0; i < pixels.length; i += 4) {
var r = pixels[i],
g = pixels[i + 1],
b = pixels[i + 2];
// a = pixels[i + 3]

var hexNotation = '#' + paddedHex(r) + paddedHex(g) + paddedHex(b);
var currValue = colorMap[hexNotation];
if (currValue) {
currValue += 1;
} else {
currValue = 1;
}
colorMap[hexNotation] = currValue;
}

return colorMap;
}

function paddedHex(intVal) {
var s = intVal.toString(16);
if (s.length === 1) {
s = "0" + s;
}

return s;
}
132 changes: 131 additions & 1 deletion test/text-to-image.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ describe("the text-to-image generator", function () {
glob = require('glob'),
fs = require('fs'),
path = require('path'),
sizeOf = require('image-size');
sizeOf = require('image-size'),
readimage = require('readimage'),
extractColors = require('./helpers/extractColors');

beforeEach(function () {
imageGenerator = require('../lib/text-to-image');
Expand Down Expand Up @@ -93,4 +95,132 @@ describe("the text-to-image generator", function () {
});
});

it("should default to a white background no transparency", function () {
return Promise.all([
imageGenerator.generate('Lorem ipsum dolor sit amet.', {
debug: true
})
]).then(function () {
var images = glob.sync(path.join(process.cwd(), '*.png'));
var imageData = fs.readFileSync(images[0]);

return new Promise(function (resolve, reject) {
readimage(imageData, function (err, image) {
if (err) {
reject(err);
} else {
resolve(image);
}
});
});
}).then(function (image) {
expect(image.frames.length).to.equal(1);
expect(image.frames[0].data[0]).to.equals(0xff);
expect(image.frames[0].data[1]).to.equals(0xff);
expect(image.frames[0].data[2]).to.equals(0xff);
expect(image.frames[0].data[3]).to.equals(0xff);
});
});

it("should use the background color specified with no transparency", function () {
return Promise.all([
imageGenerator.generate('Lorem ipsum dolor sit amet.', {
debug: true,
bgColor: '#001122'
})
]).then(function () {
var images = glob.sync(path.join(process.cwd(), '*.png'));
var imageData = fs.readFileSync(images[0]);

return new Promise(function (resolve, reject) {
readimage(imageData, function (err, image) {
if (err) {
reject(err);
} else {
resolve(image);
}
});
});
}).then(function (image) {
expect(image.frames.length).to.equal(1);
expect(image.frames[0].data[0]).to.equals(0x00);
expect(image.frames[0].data[1]).to.equals(0x11);
expect(image.frames[0].data[2]).to.equals(0x22);
expect(image.frames[0].data[3]).to.equals(0xff);
});
});

it("should default to a black text color", function () {
var WIDTH = 720;
var HEIGHT = 220;

return Promise.all([
imageGenerator.generate('Lorem ipsum dolor sit amet.', {
debug: true,
maxWidth: WIDTH,
fontSize: 100,
lineHeight: 100
})
]).then(function () {
var images = glob.sync(path.join(process.cwd(), '*.png'));
var dimensions = sizeOf(images[0]);
expect(dimensions.width).to.equals(WIDTH);
expect(dimensions.height).to.equals(HEIGHT);
var imageData = fs.readFileSync(images[0]);

return new Promise(function (resolve, reject) {
readimage(imageData, function (err, image) {
if (err) {
reject(err);
} else {
resolve(image);
}
});
});
}).then(function (image) {
var map = extractColors(image);
// GIMP reports 256 colors on this image
expect(Object.keys(map).length).to.be.within(2, 256);
expect(map['#000000']).to.be.above(10);
expect(map['#ffffff']).to.be.above(100);
});
});

it("should use the text color specified", function () {
var WIDTH = 720;
var HEIGHT = 220;

return Promise.all([
imageGenerator.generate('Lorem ipsum dolor sit amet.', {
debug: true,
maxWidth: WIDTH,
fontSize: 100,
lineHeight: 100,
textColor: "#112233"
})
]).then(function () {
var images = glob.sync(path.join(process.cwd(), '*.png'));
var dimensions = sizeOf(images[0]);
expect(dimensions.width).to.equals(WIDTH);
expect(dimensions.height).to.equals(HEIGHT);
var imageData = fs.readFileSync(images[0]);

return new Promise(function (resolve, reject) {
readimage(imageData, function (err, image) {
if (err) {
reject(err);
} else {
resolve(image);
}
});
});
}).then(function (image) {
var map = extractColors(image);
// GIMP reports 256 colors on this image
expect(Object.keys(map).length).to.be.within(2, 256);
expect(map['#112233']).to.be.above(10);
expect(map['#ffffff']).to.be.above(100);
});
});

});

0 comments on commit 21349e2

Please sign in to comment.