class Foto {
constructor() {
var root = this;
this.operationOrgCanvas = document.createElement("canvas");
this.operationOrgCtx = this.operationOrgCanvas.getContext("2d");
this.operationEditedCanvas = document.createElement("canvas");
this.operationEditedCtx = this.operationEditedCanvas.getContext("2d");
this.fileInput = document.getElementById("foto-file");
this.fileInput.addEventListener("change", function(event){
root.loadImage();
})
this.image = null;
this.imageData = null;
this.imageWidth = 0;
this.imageHeight = 0;
this.convertedToGrayScale = false;
this.previewImageElement = null;
this.redPixelMatrix = [];
this.greenPixelMatrix = [];
this.bluePixelMatrix = [];
this.alphaPixelMatrix = [];
this.pickedR = "";
this.pickedG = "";
this.pickedB = "";
this.selectedFileName = "";
this.selectStart = false;
this.startX = "";
this.startY = "";
this.endX = "";
this.endY = "";
this.excludeArea = false;
this.relativeStartX = "";
this.relativeStartY = "";
this.relativeEndX = "";
this.relativeEndY = "";
this.pickedR = null;
this.pickedG = null;
this.pickedB = null;
this.selectRect = document.createElement("div");
document.body.appendChild(this.selectRect);
this.oldSelectedColorForColorize = null;
this.ctrlPressed = false;
//attach few events
var root = this;
document.addEventListener("keydown", function(event){
if(event.keyCode == 17) {
root.ctrlPressed = true;
}
})
document.addEventListener("keyup", function(event){
root.ctrlPressed = true;
})
}
loadImage() {
var input = document.getElementById("foto-file");
this.selectedFileName = input.files.item(0).name
var reader = new FileReader();
var root = this;
reader.onload = function (e) {
root.image = new Image();
root.image.onload = function() {
root.imageWidth = root.image.width;
root.imageHeight = root.image.height;
root.operationOrgCanvas.width = root.imageWidth;
root.operationOrgCanvas.height = root.imageHeight;
//edited
root.operationEditedCanvas.width = root.imageWidth;
root.operationEditedCanvas.height = root.imageHeight;
//resetting
root.imageData = [];
root.operationOrgCtx.clearRect(0,0,root.operationOrgCanvas.width, root.operationOrgCanvas.height);
root.operationEditedCtx.clearRect(0,0,root.operationEditedCanvas.width, root.operationEditedCanvas.height);
root.operationOrgCtx.drawImage(root.image, 0, 0);
root.operationEditedCtx.drawImage(root.image, 0, 0);
//for viewing purpose
root.previewImage(root.operationOrgCanvas, 0);
//root.previewImage(); //put data on edited canvas also
root.imageData = root.operationOrgCtx.getImageData(0, 0, root.operationOrgCanvas.width, root.operationOrgCanvas.height);
//generate pixel matrix
root.generatePixelMatrix();
console.log("Pixel Data Loaded");
}
root.image.src = e.target.result
}
reader.readAsDataURL(input.files[0]);
}
generatePixelMatrix() {
var r = [], g = [], b = [], a = [];
this.redPixelMatrix = [];
this.greenPixelMatrix = [];
this.bluePixelMatrix = [];
this.alphaPixelMatrix = [];
for(var i=0; i < this.imageData.data.length; i = i + 4) {
if((i/4) % this.imageWidth == 0) {
if(i != 0) {
this.redPixelMatrix.push(r);
this.greenPixelMatrix.push(g);
this.bluePixelMatrix.push(b);
this.alphaPixelMatrix.push(a);
}
r = [];
g = [];
b = [];
a = [];
}
r.push(this.imageData.data[i]);
g.push(this.imageData.data[i + 1]);
b.push(this.imageData.data[i + 2]);
a.push(this.imageData.data[i + 3]);
}
}
grayscale() {
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
var red = modifiedImageData.data[i];
var green = modifiedImageData.data[i + 1];
var blue = modifiedImageData.data[i + 2];
var alpha = modifiedImageData.data[i + 3];
modifiedImageData.data[i] = (red + green + blue) /3;
modifiedImageData.data[i + 1] = (red + green + blue) /3;
modifiedImageData.data[i + 2] = (red + green + blue) /3 ;
}
//this.editedCtx.putImageData(modifiedImageData, 0, 0);
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.operationOrgCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
this.convertedToGrayScale = !this.convertedToGrayScale;
}
/**
* Bright
*/
makeBright() {
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
var pixel = [];
var red = modifiedImageData.data[i];
var green = modifiedImageData.data[i + 1];
var blue = modifiedImageData.data[i + 2];
var alpha = modifiedImageData.data[i + 3];
modifiedImageData.data[i] = red + 10;
modifiedImageData.data[i + 1] = green + 10;
modifiedImageData.data[i + 2] = blue + 10;
modifiedImageData.data[i + 3] = alpha;
}
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
}
/**
* Dark
*/
makeDark() {
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
modifiedImageData.data[i] -= 10;
modifiedImageData.data[i + 1] -= 10;
modifiedImageData.data[i + 2] -= 10;
modifiedImageData.data[i + 3] -= 10;
}
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
}
/**
* Transparent
*/
makeTransparent() {
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
if(Math.abs(modifiedImageData.data[i] - this.pickedR) < 30
&& Math.abs(modifiedImageData.data[i + 1] - this.pickedG) < 30
&& Math.abs(modifiedImageData.data[i + 2] - this.pickedB) < 30)
modifiedImageData.data[i + 3] = 0;
}
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
}
/**
* Apply filter
* @param {*} filter 3x3 Matrix
*/
applyFilter(filter) {
var count = 0;
for(var i=0; i < this.imageData.data.length; i = i + 4) {
var finalR, finalG, finalB;
var row = parseInt((i/4) / this.imageWidth);
var col = (i/4) % this.imageWidth;
if(row == 0 || col == 0 ||
row == this.imageHeight - 1 || col == this.imageWidth - 1)
continue;
var finalR = 0, finalG = 0, finalB = 0, finalA = 0;
for(var x=0; x<3; x++) {
for(var y=0; y<3; y++) {
if(this.redPixelMatrix[row + (x - 1)] == undefined){continue;}
if(this.redPixelMatrix[row + (x - 1)][col + (y - 1)] == undefined){continue;}
finalR += filter[x][y] * this.redPixelMatrix[row + (x - 1)][col + (y - 1)];
finalG += filter[x][y] * this.greenPixelMatrix[row + (x - 1)][col + (y - 1)];
finalB += filter[x][y] * this.bluePixelMatrix[row + (x - 1)][col + (y - 1)];
finalA += filter[x][y] * this.alphaPixelMatrix[row + (x - 1)][col + (y - 1)];
}
}
if(this.convertedToGrayScale) {
this.imageData.data[i] = (finalR + finalG + finalB) / 3;
this.imageData.data[i + 1] = (finalR + finalG + finalB) / 3;
this.imageData.data[i + 2] = (finalR + finalG + finalB) / 3;
this.imageData.data[i + 3] = finalA;
} else {
this.imageData.data[i] = finalR;
this.imageData.data[i + 1] = finalG;
this.imageData.data[i + 2] = finalB;
this.imageData.data[i + 3] = finalA;
}
}
//console.log(this.imageData);
this.operationEditedCtx.putImageData(this.imageData, 0, 0);
this.previewImage();
}
/**
* Make Blur
*/
applyBlurFilter() {
/*this.applyFilter([
[.0625, .125, .0625],
[.125, .25, .125],
[.0625, .125, .0625]
])*/
this.applyFilter([
[1/9, 1/9, 1/9],
[1/9, 1/9, 1/9],
[1/9, 1/9, 1/9]
])
}
/**
* Make Emboss
*/
applyEmbossFilter() {
this.applyFilter([
[-2, -1, 0],
[-1, 1, 1],
[0, 1, 2]
])
}
/**
* Make Sharp
*/
applySharpFilter() {
this.applyFilter([
[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]
])
}
/**
* Unused for now
*/
applyVintageFilter() {
this.colorFilter("#0000ff");
this.colorFilter("#0000ff");
this.colorFilter("#ec8900");
}
applyCustom() {
this.applyFilter([
[-1, -1, -1],
[2, 2, 2],
[-1, -1, -1]
])
}
flipVertically() {
//this.recreateImageObject();
this.operationEditedCtx.translate(this.imageWidth, 0);
this.operationEditedCtx.scale(-1, 1);
this.operationEditedCtx.drawImage(this.image, 0, 0);
this.operationOrgCtx.translate(this.imageWidth, 0);
this.operationOrgCtx.scale(-1, 1);
this.operationOrgCtx.drawImage(this.image, 0, 0);
this.imageData = this.operationOrgCtx.getImageData(0, 0, this.operationOrgCanvas.width, this.operationOrgCanvas.height);
this.generatePixelMatrix();
this.previewImage();
}
flipHorizontally() {
//this.recreateImageObject();
this.operationEditedCtx.translate(0, this.imageHeight);
this.operationEditedCtx.scale(1, -1);
this.operationEditedCtx.drawImage(this.image, 0, 0);
this.operationOrgCtx.translate(0, this.imageHeight);
this.operationOrgCtx.scale(1, -1);
this.operationOrgCtx.drawImage(this.image, 0, 0);
this.imageData = this.operationOrgCtx.getImageData(0, 0, this.operationOrgCanvas.width, this.operationOrgCanvas.height);
this.generatePixelMatrix();
this.previewImage();
}
rotate(degrees){
this.operationEditedCtx.clearRect(0,0,this.operationEditedCanvas.width,this.operationEditedCanvas.height);
this.operationEditedCtx.save();
this.operationEditedCtx.translate(this.imageWidth/2,this.imageHeight/2);
this.operationEditedCtx.rotate(degrees * Math.PI/180);
this.operationEditedCtx.drawImage(this.image, -this.image.width/2, -this.image.width/2);
this.operationEditedCtx.restore();
this.operationOrgCtx.clearRect(0,0,this.operationOrgCanvas.width,this.operationOrgCanvas.height);
this.operationOrgCtx.save();
this.operationOrgCtx.translate(this.imageWidth/2,this.imageHeight/2);
this.operationOrgCtx.rotate(degrees * Math.PI/180);
this.operationOrgCtx.drawImage(this.image, -this.image.width/2, -this.image.width/2);
this.operationOrgCtx.restore();
this.imageData = this.operationOrgCtx.getImageData(0, 0, this.operationOrgCanvas.width, this.operationOrgCanvas.height);
this.generatePixelMatrix();
this.previewImage();
}
/**
* Download ImagepreviewImage
*/
export() {
var link = document.createElement('a');
link.download = this.selectedFileName + '-edited.png';
link.href = this.operationEditedCanvas.toDataURL()
link.click();
}
previewImage(canvas, firstLoad, recreateImageFlag) {
var root = this;
this.previewImageElement = document.getElementById("foto-image");
this.previewImageElement.setAttribute('draggable', false);
var root = this;
if(firstLoad != undefined && firstLoad == 0) {
this.previewImageElement.addEventListener("mouseover", function(event){
this.style.cursor = "crosshair"
})
this.previewImageElement.addEventListener("click", function(event){
root.relativeStartX = event.offsetX;
root.relativeStartY = event.offsetY;
if(root.ctrlPressed) {
root.pickColorPixel(root.relativeStartX, root.relativeStartY);
}
root.selectStart = false;
})
this.previewImageElement.addEventListener("mousedown", function(event){
root.selectStart = true;
root.startX = event.clientX;
root.startY = event.clientY;
root.relativeStartX = event.offsetX;
root.relativeStartY = event.offsetY;
})
this.previewImageElement.addEventListener("mousemove", function(event){
root.endX = event.clientX;
root.endY = event.clientY;
if(root.selectStart) {
root.selectRect.style.position = "fixed";
root.selectRect.style.display = "initial";
root.selectRect.style.border = "2px dashed black";
root.selectRect.style.top = root.startY + "px";
root.selectRect.style.left = root.startX + "px";
root.selectRect.style.height = (root.endY - root.startY) + "px";
root.selectRect.style.width = (root.endX - root.startX) + "px";
}
})
this.previewImageElement.addEventListener("mouseup", function(event){
root.relativeEndX = event.layerX;
root.relativeEndY = event.layerY;
root.selectStart = false;
root.selectRect.style.height = "0px";
root.selectRect.style.width = "0px";
root.selectRect.style.display = "none";
})
this.selectRect.addEventListener("mouseup", function(event){
root.selectStart = false;
})
}
if(canvas == undefined)
this.previewImageElement.src = root.operationEditedCanvas.toDataURL();
else {
this.previewImageElement.src = canvas.toDataURL();
}
//this.recreateImageObject();
}
recreateImageObject() {
this.image = new Image();
this.image.src = this.operationOrgCanvas.toDataURL();
}
pickColorPixel(x, y) {
var imgW = this.previewImageElement.width;
var imgH = this.previewImageElement.height;
var imgWFactor = this.imageWidth / imgW;
var imageHFactor = this.imageHeight / imgH;
var actualX = parseInt(x * imgWFactor);
var actualY = parseInt(y * imageHFactor);
var pixelData = this.operationOrgCtx.getImageData(actualX, actualY, 1, 1).data;
this.pickedR = pixelData[0];
this.pickedG = pixelData[1];
this.pickedB = pixelData[2];
this.pickedA = pixelData[3];
document.getElementById("color-preview").style.background = "rgb(" + this.pickedR + ", " + this.pickedG + ", " + this.pickedB + ")"
}
applyColorFilter(color) {
var r = parseInt(color.substr(1,2), 16) * .5;
var g = parseInt(color.substr(3,2), 16) * .5;
var b = parseInt(color.substr(5,2), 16) * .5;
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
if(modifiedImageData.data[i] <= r)modifiedImageData.data[i] = r;
if(modifiedImageData.data[i + 1] <= g)modifiedImageData.data[i+1] = g;
if(modifiedImageData.data[i + 2] <= b)modifiedImageData.data[i+2] = b;
}
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.operationOrgCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
}
colorize(color) {
var r = parseInt(color.substr(1,2), 16) * .5;
var g = parseInt(color.substr(3,2), 16) * .5;
var b = parseInt(color.substr(5,2), 16) * .5;
if(this.oldSelectedColorForColorize != undefined) {
r = - parseInt(this.oldSelectedColorForColorize.substr(1,2), 16) + r;
g = - parseInt(this.oldSelectedColorForColorize.substr(3,2), 16) + g;
b = - parseInt(this.oldSelectedColorForColorize.substr(3,2), 16) + b;
}
this.oldSelectedColorForColorize = color;
var modifiedImageData = this.imageData;
for(var i=0; i < modifiedImageData.data.length; i = i + 4) {
modifiedImageData.data[i] += r;
modifiedImageData.data[i + 1] += g;
modifiedImageData.data[i + 2] += b;
}
this.operationEditedCtx.putImageData(modifiedImageData, 0, 0);
this.operationOrgCtx.putImageData(modifiedImageData, 0, 0);
this.previewImage();
}
cropSelected() {
var imgW = this.previewImageElement.width;
var imgH = this.previewImageElement.height;
var imgWFactor = this.imageWidth / imgW;
var imageHFactor = this.imageHeight / imgH;
var actualStartX = this.relativeStartX * imgWFactor;
var actualStartY = this.relativeStartY * imageHFactor;
var croppedWidth = parseInt(parseInt(this.selectRect.style.width.replace(/\D/g,'')) * imgWFactor);
var croppedHeight = parseInt(parseInt(this.selectRect.style.height.replace(/\D/g,'')) * imageHFactor);
var editedCroppedImageData = this.operationEditedCtx.getImageData(actualStartX, actualStartY, croppedWidth, croppedHeight);
var orgCroppedImageData = this.operationOrgCtx.getImageData(actualStartX, actualStartY, croppedWidth, croppedHeight);
this.operationEditedCtx.clearRect(0, 0, this.operationEditedCanvas.width, this.operationEditedCanvas.height);
this.operationOrgCtx.clearRect(0, 0, this.operationOrgCtx.width, this.operationOrgCtx.height);
this.operationEditedCanvas.width = croppedWidth;
this.operationEditedCanvas.height = croppedHeight;
this.operationOrgCanvas.width = croppedWidth;
this.operationOrgCanvas.height = croppedHeight;
this.operationEditedCtx.putImageData(editedCroppedImageData, 0, 0);
this.operationOrgCtx.putImageData(orgCroppedImageData, 0, 0);
this.imageWidth = croppedWidth;
this.imageHeight = croppedHeight;
this.imageData = this.operationOrgCtx.getImageData(0, 0, this.operationOrgCanvas.width, this.operationOrgCanvas.height);
this.generatePixelMatrix();
this.selectRect.style.display = "none";
this.previewImage()
}
}