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'});
},
Related
I got an image, it could be of every size but I need to take the center area of 86x86. Also I've to do that in javascript when a new image is loaded, replacing the old one.
At the end of the code I need to have my 's src updated with the new image.
function loadedImage(elem,gCount){
var crop = { //just messing with numbers
top : 10,
left : 10,
right : 20,
bottom : 20,
};
var file = elem.files[0]; //I take the loaded image
var img = document.getElementsByName('imag')[gCount]; //I take the interessed <img>
var canvas = document.createElement("canvas"); //create canvas
canvas.width = crop.right - crop.left; //set dimensions
canvas.height = crop.bottom - crop.top;
var ctx = canvas.getContext("2d"); // so we can draw
var image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
image.width = img.width;
image.height = img.height;
image.src = window.URL.createObjectURL(file);
ctx.drawImage(image, -crop.left, -crop.top);
image.src = canvas.toDataURL("image/png");
img.src = image.src;
}
No image is shown
Use a load event listener to wait for your image to load. Once it's ready, you can then start drawing.
To draw the center part of your image, the source x-coordinate should be half the width of your image, minus half the width of the crop. (The source y-coordinate can be calculated in a similar way.)
var input = document.getElementsByName('input')[0];
input.addEventListener('change', function (e) {
var file = e.target.files[0];
drawCroppedImage(file, 86, 86);
});
function drawCroppedImage(file, w, h) {
var canvas = document.getElementById('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
var image = new Image();
image.addEventListener('load', function (e) {
var sx = (image.width / 2) - (w / 2), // Source X
sy = (image.height / 2) - (h / 2), // Source Y
dx = 0, // Destination X
dy = 0; // Destination Y
ctx.drawImage(image, sx, sy, w, h, dx, dy, w, h);
});
image.src = URL.createObjectURL(file);
}
<input type="file" name="input">
<br><br>
<canvas id="canvas" width="86" height="86"></canvas>
I want to stretch the image to the size of the canvas. But the image takes its original size instead of taking the canvas size.Any help is appreciated.
var canvas = document.createElement("canvas");
canvas.setAttribute("width", "100px");
canvas.setAttribute("height", "180px");
//alert(canvas.height);
myImg.width = canvas.width;
myImg.height = canvas.height;
var ctx44 = canvas.getContext("2d");
ctx44.drawImage(myImg, 0, 0, canvas.width, canvas.height,0,0,canvas.width,canvas.height);
// image gets displayed in its original size instead of taking the size of the canvas
The 2nd ~ 4th parameters of drawImage represent the source rectangle. That is, a rectangle from where your image will be cropped, before being applied to the destination, resized by the rectangle defined in the following rectangle.
Here is a simple demo:
var img = new Image();
img.onload = e => {
const source = document.getElementById('source');
const destination = document.getElementById('destination');
const imgWIDTH = source.width = destination.width = 300;
const imgHEIGHT = source.height = destination.height = 300;
const src_x = source.getContext('2d');
const dest_x = destination.getContext('2d');
src_x.drawImage(img, 0, 0, imgWIDTH, imgHEIGHT); // simple copy to source canvas
const source_rect = {
x: 20,
y: 20,
w: 150,
h: 150
};
const dest_rect = {
x: 0,
y: 0,
w: 300,
h: 300
};
destination.getContext('2d')
.drawImage(source,
source_rect.x,
source_rect.y,
source_rect.w,
source_rect.h,
dest_rect.x,
dest_rect.y,
dest_rect.w,
dest_rect.h
);
// show the source rectangle on the 'source' canvas
src_x.strokeRect(
source_rect.x,
source_rect.y,
source_rect.w,
source_rect.h,
);
};
img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
<canvas id="source"></canvas>
<canvas id="destination"></canvas>
So in your case, if your original image is smaller than the 100x180px of your canvas, you are defining the source rectangle to be outside of the source image, this will then result in no apparent changes from the original image.
What you probably wanted was
ctx44.drawImage(myImg, 0, 0, myImg.naturalWidth, myImg.naturalHeight,0,0,canvas.width,canvas.height);
which is the same as the 5 param version
ctx44.drawImage(myImg,0,0,canvas.width,canvas.height);
var myImg = new Image();
myImg.onload = function(e) {
var canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 180;
var ctx44 = canvas.getContext("2d");
ctx44.drawImage(myImg, 0,0,canvas.width,canvas.height);
document.body.appendChild(myImg);
document.body.appendChild(canvas);
};
myImg.src = "https://i.stack.imgur.com/LbM0l.jpg?s=32&g=1"
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
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;
// ...
I am trying to draw an image from binary string on to the canvas.
var reader = new FileReader();
//reader.readAsDataURL(file);
reader.readAsBinaryString(file);
reader.onload = function(event){
var d = $(thisObj.CreateIndoorFormDivControlName).dialog();
var canvas =document.getElementById('canvasfloorLayout');
var cxt=canvas.getContext("2d");
var img=new Image();
img.onload = function() {
cxt.drawImage(img, 0, 0,canvas.width,canvas.height);
}
img.src = "data:image/jpeg;base64,"+window.btoa(reader.result);
I am using the above code but the problem is the image size is getting reduced to the canvas size and quality is dropping like anything. I have been tried with
cxt.drawImage(img, 0, 0,img.width,img.height);
But the image gets cropped.
I donot want to use reader.readAsDataURL as I need to post the binary to the server. My requirement is to show the full image and draw lines on it .
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
...if you draw the image at the canvas' native resolution, then when the image gets scaled, it's obviously going to lose quality.
...if you draw the image at the image's native resolution, but the canvas hasn't changed size, then you're going to end up with a partial image, or a partially-filled canvas.
So if you want neither of those, then set the dimensions of the canvas to match the dimensions of the image, and you'll have a canvas-drawn image which matches the resolution of the data-image.
EDIT
Adding an example of a proxy, between the two.
var img = new Image(),
canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
// ......etc
dimensions = {
max_height : 800,
max_width : 600,
width : 800, // this will change
height : 600, // this will change
largest_property : function () {
return this.height > this.width ? "height" : "width";
},
read_dimensions : function (img) {
this.width = img.width;
this.height = img.height;
return this;
},
scaling_factor : function (original, computed) {
return computed / original;
},
scale_to_fit : function () {
var x_factor = this.scaling_factor(this.width, this.max_width),
y_factor = this.scaling_factor(this.height, this.max_height),
largest_factor = Math.min(x_factor, y_factor);
this.width *= largest_factor;
this.height *= largest_factor;
}
};
dimensions.read_dimensions(img).scale_to_fit();
canvas.width = dimensions.width;
canvas.height = dimensions.height;
context.drawImage(img, 0, 0, dimensions.width, dimensions.height);