Skip to content

Instantly share code, notes, and snippets.

@gekowa
Created November 4, 2014 00:34
Show Gist options
  • Save gekowa/d515bb4c3941f6123a53 to your computer and use it in GitHub Desktop.
Save gekowa/d515bb4c3941f6123a53 to your computer and use it in GitHub Desktop.
var blockSize = 2;
function Montage(canvas) {
document._MontageObj = this;
IsBlack=function(c){
var white=(c.R==0 && c.G==0 && c.B==0 && c.A==0) || (c.R>250 && c.G>250 && c.B>250);
return !white;
};
this.OnProgress = null;
this.OnFinish = null;
this.Direction=0;
this.MaxFont=60;
this.MinFont = 8;
this.Canvas = canvas;
this.PathLayer = document.createElement("canvas");
this.Progress = 0;
this.Ctx = this.Canvas.getContext("2d");
this.PathCtx = this.PathLayer.getContext("2d");
this.PathCtx.fillStyle="black";
this.Image = new Image();
this.Image.Montage = this;
this.ImageUrl = "";
this.Angles = [0, 90];
this.Fonts = ["Chiller", "CopperplateGothicStd-32AB", "ITCEDSCR"];
this.Colors = ["#003E5F", "#025D8C", "#107FDB", "#23B0DB", "#1693A5"];
this.Text = "Everybody Google News Web";
this.Words=[];
this.Image.onload = function () {
this.Montage.PathLayer.width = this.Montage.Canvas.width = this.width;
this.Montage.PathLayer.height = this.Montage.Canvas.height = this.height;
this.Montage.PathCtx.drawImage(this, 0, 0);
//this.Montage.Ctx.drawImage(this, 0, 0);
this.Montage.GetPath();
this.Montage.PathReady = true;
if (this.CallBack != undefined && this.CallBack != null) {
this.CallBack();
}
};
this.Words = [];
this.DrawText = function (textBlock, x, y) {
var l, t;
var p;
this.Words[this.Words.length] = {Text:textBlock,X:x*blockSize,Y:y *blockSize};
for (var i = 0; i < textBlock.PotWidth; i++) {
l = x + i;
for (var j = 0; j < textBlock.PotHeight; j++) {
t = y + j;
if (textBlock.Pots[i][j].Black) {
try {
this.Pots[l][t].Blank = false;
this.Pots[l][t].Black = true;
}
catch (e) {
var m = e;
}
}
}
}
};
this.Rend = function () {
this.Ctx.clearRect(0, 0, this.Canvas.width, this.Canvas.height);
for (var i = 0; i < this.Words.length; i++) {
var word = this.Words[i];
this.Ctx.drawImage(word.Text.Image, word.X , word.Y );
}
if (this.OnFinish != undefined && this.OnFinish != null) {
this.OnFinish();
}
}
this.ExportIndex = 0;
this.GetPrintImageEX = function (callback) {
var ratio = 4;
if (this.ExportIndex == 0) {
this.ExportCallback = callback;
document.Canvas = null;
this.ExportCanvas = document.createElement("canvas");
this.ExportCanvas.width = this.Image.width * ratio;
this.ExportCanvas.height = this.Image.height * ratio;
this.ExportCtx = this.ExportCanvas.getContext("2d");
}
var word = this.Words[this.ExportIndex];
var biger = this.GetText(word.Text.Word, word.Text.FontSize, word.Text.FontFamily, word.Text.Color, word.Text.Angle, ratio);
this.ExportCtx.drawImage(biger.Image, word.X * ratio, word.Y * ratio);
this.ExportIndex++;
if (this.ExportIndex < this.Words.length) {
if (this.OnProgress != undefined && this.OnProgress != null) {
var p = this.ExportIndex * 100 / this.Words.length;
this.Progress = p;
setTimeout(this.OnProgress, 0);
}
setTimeout(function () { document._MontageObj.GetPrintImageEX(); }, 0);
}
else {
if (this.OnProgress != undefined && this.OnProgress != null) {
this.Progress = 100;
setTimeout(this.OnProgress, 0);
}
var data = this.ExportCanvas.toDataURL("image/png");
this.ExportCallback(data);
this.ExportCtx = 0;
}
};
this.GetPrintImage = function (ratio) {
document.Canvas = null;
var canvas = document.createElement("canvas");
canvas.width = this.Image.width * ratio;
canvas.height = this.Image.height * ratio;
var ctx = canvas.getContext("2d");
for (var i = 0; i < this.Words.length; i++) {
var word = this.Words[i];
var biger = this.GetText(word.Text.Word, word.Text.FontSize, word.Text.FontFamily, word.Text.Color, word.Text.Angle, ratio);
ctx.drawImage(biger.Image, word.X * ratio, word.Y * ratio);
}
var data = canvas.toDataURL("image/png");
// var img = document.createElement("img");
// img.src = data;
return data;
};
this.ChangeColor = function (colors) {
this.Colors = colors;
document.Canvas = null;
this.Ctx.clearRect(0, 0, this.Canvas.width, this.Canvas.height);
for (var i = 0; i < this.Words.length; i++) {
var word = this.Words[i];
word.Text = this.GetText(word.Text.Word, word.Text.FontSize, word.Text.FontFamily, colors[parseInt(Math.random()*colors.length)], word.Text.Angle);
this.Ctx.drawImage(word.Text.Image, word.X, word.Y);
}
if (this.OnFinish != undefined && this.OnFinish != null) {
this.OnFinish();
}
}
this.GetPath = function () {
var imageData = this.PathCtx.getImageData(0, 0, this.Image.width, this.Image.height);
var Colors = [];
this.Words = [];
this.PotWidth = this.Image.width / blockSize;
if (this.Image.width % blockSize > 0) this.PotWidth++;
this.PotHeight = this.Image.height / blockSize;
if (this.Image.height % blockSize > 0) this.PotHeight++;
var l = this.PotWidth, t = this.PotHeight, r = 0, b = 0;
this.Pots = [];
for (var i = 0; i < this.PotWidth; i++) {
var col = [];
for (var j = 0; j < this.PotHeight; j++) {
var blank = true;
for (var x = i * blockSize; x < i * blockSize + blockSize; x++) {
if (x >= this.Image.width) {
continue;
}
for (var y = j * blockSize; y < j * blockSize + blockSize; y++) {
if (y > this.Image.height) continue;
var pos = x + y * this.Image.width;
var color = {
R: imageData.data[pos * 4],
G: imageData.data[pos * 4 + 1],
B: imageData.data[pos * 4 + 2],
A: imageData.data[pos * 4 + 3],
X: x,
Y: y
};
color.Black = IsBlack(color);
if (color.Black == false) {
blank = false;
break;
}
else {
color.Blank == true;
}
}
if (!blank) break;
}
var p = { Blank: blank, X: i, Y: j, Black: !blank };
col[j] = p;
if (p.Blank) {
if (i < l) {
l = i;
}
if (i > r) {
r = i;
}
if (j < t) {
t = j;
}
if (j > b) {
b = j;
}
}
}
this.Pots[i] = col;
}
this.L = l;
this.T = t;
this.B = b;
this.R = r;
};
this.Refresh = function () {
this.GetPath();
this.AddText();
};
this.fontsize = 48;
this.AddTextEx = function () {
var fonts = this.Fonts;
var words = this.Text.split(" ");
var angles = this.Angles;
var colors = this.Colors;
if (this.fontsize >= this.MinFont) {
for (var k in words) {
var word = words[k];
if (word == "") continue;
var c = colors[parseInt(Math.random() * colors.length)];
var degree = angles[parseInt(Math.random() * angles.length)];
var font = fonts[parseInt(Math.random() * fonts.length )];
var txt = this.GetText(word, this.fontsize, font, c, degree); // this.GetText(word, fontsize, font, c, degree);
var l = this.L + parseInt(Math.random() * (this.R - this.L + 1));
var t = this.T + parseInt(Math.random() * (this.B - this.T + 1));
var pos = this.FindPlace(txt, l, t);
var times = this.MaxFont / this.fontsize;
while (pos != null) {
this.DrawText(txt, pos.X, pos.Y);
if (times-- > 0) {
l = this.L + parseInt(Math.random() * (this.R - this.L + 1));
t = this.T + parseInt(Math.random() * (this.B - this.T + 1));
pos = this.FindPlace(txt, l, t);
}
else {
break;
}
}
}
if (this.OnProgress != undefined && this.OnProgress != null) {
var p = (this.MaxFont - this.fontsize + 1) * 100 / (this.MaxFont - this.MinFont + 1);
setTimeout(this.OnProgress, 0);
this.Progress = p;
}
this.fontsize -= 2;
setTimeout(function () { document._MontageObj.AddTextEx(); }, 0);
}
else {
this.Rend();
this.fontsize = this.MaxFont;
}
}
this.AddText = function (word) {
this.Words = [];
document.Canvas = null;
if (this.OnProgress != undefined && this.OnProgress != null) {
this.fontsize = this.MaxFont;
this.AddTextEx();
return;
}
var fontsize = 48;
var fonts = this.Fonts;
var words = this.Text.split(" ");
var angles = this.Angles;
var colors = this.Colors;
for (fontsize = this.MaxFont; fontsize >= this.MinFont; fontsize -= 2) {
for (var k in words) {
var word = words[k];
var c = colors[parseInt(Math.random() * colors.length)];
var degree = angles[parseInt(Math.random() * angles.length)];
var font = fonts[parseInt(Math.random() * fonts.length)];
var txt = this.GetText(word, fontsize, font, c, degree); // this.GetText(word, fontsize, font, c, degree);
var l = this.L + parseInt(Math.random() * (this.R - this.L + 1));
var t = this.T + parseInt(Math.random() * (this.B - this.T + 1));
var pos = this.FindPlace(txt, l, t);
var times = this.MaxFont / this.fontsize;
while (pos != null) {
this.DrawText(txt, pos.X, pos.Y);
if (times-- > 0) {
l = this.L + parseInt(Math.random() * (this.R - this.L + 1));
t = this.T + parseInt(Math.random() * (this.B - this.T + 1));
pos = this.FindPlace(txt, l, t);
}
else {
break;
}
}
}
if (this.OnProgress != undefined && this.OnProgress != null) {
this.Progress = p;
}
}
this.Rend();
};
this.FindPlace=function(text,x,y){
if (this.Direction == 0)
{
//find to left
for (var i = x ; i >= this.L; i -= 2)
{
if (this.Canput(text, i, y))
{
return { X : i, Y : y };
}
}
}
this.Direction = 1;
//find to right
if (this.Direction == 1)
{
for (var i = x +1; i <= this.R - text.PotWidth; i++)
{
if (this.Canput(text, i, y))
{
return { X : i, Y : y };
}
}
}
this.Direction = 2;
//find to top
if (this.Direction == 2)
{
for (var j = y - 1; j >= this.T; j--)
{
for (var i = x - 1; i >= this.L; i--)
{
if (this.Canput(text, i, j))
{
return { X : i, Y :j };
}
}
for (var i = x + 1; i <= this.R - text.PotWidth; i++)
{
if (this.Canput(text, i, j))
{
return { X : i, Y :j };
}
}
}
}
this.Direction = 3;
//find to bottom
if (this.Direction == 3)
{
for (var j = y + 1; j <= this.B - text.PotHeight; j++)
{
for (var i = x - 1; i >= this.L; i--)
{
if (this.Canput(text, i, j))
{
return { X : i, Y :j };
}
}
for (var i = x + 1; i <= this.R - text.PotWidth; i++)
{
if (this.Canput(text, i, j))
{
return { X: i, Y: j };
}
}
}
}
this.Direction = 0;
return null;
}
this.LoadPath = function (url,callBack) {
this.ImageReady = false;
this.Image.src = url;
this.Image.CallBack=callBack;
}
this.Canput = function (textBlock, left, top) {
for (var i = 0; i < textBlock.PotWidth; i++) {
for (var j = 0; j < textBlock.PotHeight; j++) {
if (textBlock.Pots[i][j].Black) {
if (left + i > this.R) return false;
if (top + j > this.B) return false;
if (this.Pots[left + i][top + j].Black) {
return false;
}
//check blank
if (i <= textBlock.PotWidth / 2) {
if (left + i > this.L) {
if (this.Pots[left + i - 1][top + j].Black) {
return false;
}
}
}
else if (i > textBlock.PotWidth / 2) {
if (left + i < this.R) {
if (this.Pots[left + i + 1][top + j].Black) {
return false;
}
}
}
if (j < textBlock.PotHeight / 2) {
if (top + j > this.T) {
if (this.Pots[left + i][top + j - 1].Black) {
return false;
}
}
}
else if (top + j < this.B) {
if (this.Pots[left + i][top + j + 1].Black) {
return false;
}
}
}
}
}
return true;
}
this.GetImage = function (imageData) {
var temp = document.createElement("canvas");
temp.width = imageData.width;
temp.height = imageData.height;
var ctx = temp.getContext("2d");
ctx.putImageData(imageData, 0, 0);
var data = temp.toDataURL("image/png");
var img = document.createElement("img");
img.src = data;
img.width = 266;
return img;
};
this.GetText = function (word, size, font, color, angle, ratio) {
if (ratio == null || ratio == undefined) ratio = 1;
if (document.Canvas == undefined || document.Canvas == null) {
var canvas = document.createElement("canvas");
canvas.width = 1000 * ratio;
canvas.height = 1000 * ratio;
document.Canvas = canvas.getContext("2d");
document.Canvas.imageSmoothingEnabled = true;
document.Canvas.translate(500 * ratio, 500 * ratio);
document.Canvas.textBaseline = "top";
}
var Canvas = document.Canvas;
var s = parseInt(size * ratio);
Canvas.font = s + "px " + font;
Canvas.fillStyle = color;
var pos = Canvas.measureText(word);
pos.height = s;
var d = pos.width + pos.height;
Canvas.save();
if (angle != 0) {
Canvas.rotate(angle * Math.PI / 180);
}
Canvas.fillText(word, 0, 0);
Canvas.restore();
var imageData = Canvas.getImageData(500 * ratio - d, 500 * ratio - d, 2 * d, 2 * d);
var l = imageData.width, r = 0, b = 0, t = imageData.height;
for (var i = 0; i < imageData.width; i++) {
for (var j = 0; j < imageData.height; j++) {
var pos = (j * imageData.width + i) * 4;
if (imageData.data[pos + 3] > 0) {
if (i < l) {
l = i;
}
if (r < i) {
r = i;
}
if (b < j) {
b = j;
}
if (t > j) {
t = j;
}
}
}
}
var bl = parseInt(2 * ratio);
l -= bl;
r += bl;
t -= bl;
b += bl;
imageData = Canvas.getImageData(500 * ratio - d + l, 500 * ratio - d + t, r + 1 - l, b + 1 - t);
Canvas.clearRect(-d, -d, 2 * d, 2 * d);
var Text = {};
Text.Image = this.GetImage(imageData);
Text.Word = word;
Text.FontSize = size;
Text.FontFamily = font;
Text.Width = imageData.width;
Text.Height = imageData.height;
Text.Color = color;
Text.Angle = angle;
Text.Pots = [];
Text.PotWidth = 0;
Text.PotHeight = 0;
Text.PotWidth = parseInt(Text.Width / blockSize);
if (Text.Width % blockSize > 0) Text.PotWidth++;
Text.PotHeight = parseInt(Text.Height / blockSize);
if (Text.Height % blockSize > 0) Text.PotHeight++;
//get pots
Text.Pots = [];
for (var i = 0; i < Text.PotWidth; i++) {
var col = [];
for (var j = 0; j < Text.PotHeight; j++) {
var blank = true;
for (var x = i * blockSize; x < i * blockSize + blockSize; x++) {
if (x >= this.Width) {
continue;
}
for (var y = j * blockSize; y < j * blockSize + blockSize; y++) {
if (y >= this.Height) continue;
var pos = y * Text.Width + x;
if (imageData.data[pos * 4 + 3] > 0) {
blank = false;
break;
}
}
if (!blank) break;
}
var p = { Blank: blank, X: i, Y: j, Black: !blank };
col[j] = p;
}
Text.Pots[i] = col;
}
return Text;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment