Threshold image colors - Base64 - javascript

I would like to use threshold filter on base64 string (data:image/png;base64,iVBOR...) using javaScript like this:
function threshold(base64) {
some action whith base64 string...
return base64; //base64 is updated by threshold filter
}
Is it possible and if it is, how can I do this?

var base64string = "data:image/png;base64,iVBOR..........",
threshold = 180, // 0..255
ctx = document.createElement("canvas").getContext("2d"),
image = new Image();
image.onload = function() {
var w = ctx.canvas.width = image.width,
h = ctx.canvas.height = image.height;
ctx.drawImage(image, 0, 0, w, h); // Set image to Canvas context
var d = ctx.getImageData(0, 0, w, h); // Get image Data from Canvas context
for (var i=0; i<d.data.length; i+=4) { // 4 is for RGBA channels
// R=G=B=R>T?255:0
d.data[i] = d.data[i+1] = d.data[i+2] = d.data[i+1] > threshold ? 255 : 0;
}
ctx.putImageData(d, 0, 0); // Apply threshold conversion
document.body.appendChild(ctx.canvas); // Show result
};
image.src = base64string;
MDN - putImageData
MDN - getImageData

Related

Get pixel RGB in Javascript

I have a function to get pixel data from a 14x14px png. I tested to see if img.src was valid, which it is. Any pixel coordinate I use returns an array filled with 0's.
var RGB = getPixel('spectrum2D.png', 5, 5)
console.log(RGB) // Uint8ClampedArray(4) [0, 0, 0, 0]
function getPixel(url, x, y) {
var img = new Image();
img.src = url;
var canvas = document.createElement('canvas');
canvas.width = 14
canvas.height = 14
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
return context.getImageData(x, y, 1, 1).data;
}

On loading Image, getImageData delivers some zeros

I'm loading a PNG and try to check, whether it is fully opaque, meaning alpha channel is near 100% over the whole image. Therefore, I use the canvas and 2D-Context to get the pixel data and loop through it checking the alpha value.
To my surprise i get whole areas of zeros (RGBA = [0000]) where it obviously shouldn't.
Browser in focus: chrome 50.0.2661.87
Here is my code, it is embedded in a ThreeJS environment:
var imageData = zipHandler.zip.file(src); // binary image data
var texture = new THREE.Texture();
var img = new Image();
img.addEventListener( 'load', function ( event ) {
texture.imageHasTransparency = false; // extend THREEJS Texture by a flag
if (img.src.substring(imgSrc.length-4).toLowerCase().indexOf("png") > -1
|| img.src.substring(0, 15).toLowerCase().indexOf("image/png") > -1) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, img.width, img.height );
var pixDataContainer = context.getImageData(0, 0, img.width, img.height);
var pixData = pixDataContainer.data;
// search for pixel.alpha < 250
for (var pix = 0, pixDataLen = pixData.length; pix < pixDataLen; pix += 4) {
if (pixData[pix+3] < 250) {
texture.imageHasTransparency = true;
break;
}
}
}
texture.image = img;
texture.needsUpdate = true;
this.removeEventListener('load', arguments.callee, false);
}, false );
var fileExtension = src.substr(src.lastIndexOf(".") + 1);
img.src = "data:image/"+fileExtension+";base64,"+ btoa(imageData.asBinary());
The order is correct: first define new Image(), then the onload function and then the source.
Solved. The image was larger than the canvas, so when context.drawImage() was started, only parts of the area was filled. I've set the canvas dimensions according to the image size, so now it works and we have
// ...
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width; // !!!!!
canvas.height = img.height; // !!!!
context.drawImage(img, 0, 0, img.width, img.height );
var pixDataContainer = context.getImageData(0, 0, img.width, img.height);
var pixData = pixDataContainer.data;
// ...

Merge a png overlay and image into single file

I got it working using crop as recommended. Here is how I got it with the plugin. The if statement is only because I have multiple crop sizes, the circular crop is only for square images.
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
if (width==height){
context.globalCompositeOperation='destination-in';
context.beginPath();
context.arc(width/2,height/2,height/2,0,Math.PI*2);
context.closePath();
context.fill();
}
var imageData = canvas.toDataURL('image/png');
return imageData;
},
-- Original Question --
I'm using a jQuery plugin called CropBox which I have set up to export a 300x300 image. I am trying to take the square image and add an overlay that will make the image appear round, adding white corners or subtracting the overlay and have transparent corners.
What I'm going for.
The plugin uses a portion of the canvas to create the image. Once the image is captured I'm looking to add the overlay.
Adding my image and trying to draw the image.
var overlay = new Image();
overlay.src = 'MyOverlay.png';
context.drawImage(overlay, 0, 0);
Then I get lost on how to add this to imageData. It should start at 0, 0 too, any input would be appreciated.
Part of the plugin:
(function ($) {
var cropbox = function(options, el){
var el = el || $(options.imageBox),
obj =
{
state : {},
ratio : 1,
options : options,
imageBox : el,
thumbBox : el.find(options.thumbBox),
spinner : el.find(options.spinner),
image : new Image(),
getDataURL: function ()
{
var width = this.thumbBox.width(),
height = this.thumbBox.height(),
canvas = document.createElement("canvas"),
dim = el.css('background-position').split(' '),
size = el.css('background-size').split(' '),
dx = parseInt(dim[0]) - el.width()/2 + width/2,
dy = parseInt(dim[1]) - el.height()/2 + height/2,
dw = parseInt(size[0]),
dh = parseInt(size[1]),
sh = parseInt(this.image.height),
sw = parseInt(this.image.width);
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
var imageData = canvas.toDataURL('image/png');
return imageData;
},
getBlob: function()
{
var imageData = this.getDataURL();
var b64 = imageData.replace('data:image/png;base64,','');
var binary = atob(b64);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: 'image/png'});
},

canvas imageData manipulation

I am playing with canvases imageData and I am having some issues with speed. What I am doing is
$(document).ready(function(){
loadCanvas();
myImageData();
});
function loadCanvas(){
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d')
image = new Image();
image.src = '/static/images/teeth1.jpg';
image.onload = function (){
imageWidth = image.width;
imageHeight = image.height;
context.drawImage(image, 0, 0, image.width, image.height);
imageData = myImageData(context, image);
pixels = imageData.data;
console.log(pixels);
console.log(pixels.length);
console.log(imageData);
//Changing the value of each pixel
for (var y=0; y<=imageHeight; ++y){
for (var x=0; x<=imageWidth; ++x){
index = (y*imageWidth + x) * 4;
pixels[index] += 30;
pixels[++index] += 30;
pixels[++index] += 30;
}
}
}
}
function myImageData(context){
console.log("width: "+image.width+", height:"+image.height)
return context.getImageData(0, 0, image.width, image.height);
}
When I execute the above code outside the onload function from chrome's console it works very fast. But when executing the double for's inside the onload function (as it is right now) it hangs. Why is that? Is it because it is inside the onload? How can I make sure the image was fully loaded before executing the double fors(so to put them seperatelly outside the onload function)?
// Define functions before using them (Good to)
function loadCanvas(){
var canvas = document.getElementById('myCanvas'); // Define variables!
var context = canvas.getContext('2d');
var image = new Image();
image.onload = function (){
var imageWidth = image.width; // Variables again!
var imageHeight = image.height;
context.drawImage(image, 0, 0, imageWidth, imageHeight );
var imageData = myImageData(context, image); // Variables!
var pixels = imageData.data;
console.log(pixels);
console.log(pixels.length);
console.log(imageData);
//Changing the value of each pixel
for (var y=0; y<=imageHeight; ++y){
for (var x=0; x<=imageWidth; ++x){
var index = (y*imageWidth + x) * 4;
pixels[index] += 30;
pixels[++index] += 30;
pixels[++index] += 30;
}
}
};
image.src = '/static/images/teeth1.jpg'; // Set src here
}
function myImageData(ctx, img){ // Pass the actual image as argument
console.log("width: "+img.width+", height:"+img.height);
return ctx.getImageData(0, 0, img.width, img.height);
}
$(document).ready(function(){
loadCanvas(); // has myImageData() so...
//myImageData(); // why??
});

HTML5 video frame capture to bitmap

I got this script:
function capture(video, scaleFactor) {
if(scaleFactor == null){
scaleFactor = 1;
}
var w = video.videoWidth * scaleFactor;
var h = video.videoHeight * scaleFactor;
var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, w, h);
return canvas;
}
function shoot(){
var video = document.getElementById(videoId);
var output = document.getElementById('output');
var canvas = capture(video, scaleFactor);
canvas.onclick = function(){
window.open(this.toDataURL());
};
snapshots.unshift(canvas);
output.innerHTML = '';
for(var i=0; i<1; i++){
output.appendChild(snapshots[i]);
}
}
What I want to do is export the snapshot to a bitmap image. I read that I could use this line:
canvas.toDataURL('image/jpeg');
But I don't know where to add it.
Any ideas?
ctx.drawImage(video, 0, 0, w, h);
canvas.toDataURL(...)
toDataURL will return you a string which is usually base64 encoded image (file) content. You can display it in image tag by < img src="the string"/>. Or you can use javascript to do whatever you want...
Pass it to window.open
canvas.onclick = function () {
window.open(canvas.toDataURL('image/png'));
};
Full Example : http://www.nihilogic.dk/labs/canvas2image/

Categories