JavaScript - Take Center of Image - javascript

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>

Related

Createjs: How to pixelate bitmaps?

I have a very specific project I'm working on and after 2 weeks the best option seems to be using a bitmap within an empty movie clip. It's perfect apart from one issue - I can't figure out how to pixelate the image.
Here is my code so far:
init_image = () => {
props.image = null
_.holder_grid.bitmap = null
props.image = new Image()
props.image.src = "images/myImage.jpg"
props.image.onload = function() {
stage.holder_grid.bitmap = new createjs.Bitmap(props.image)
stage.holder_grid.bitmap.scale = props.image_scale
stage.holder_grid.addChild(_.holder_grid.bitmap);
const coords = redraw.get_centre()
stage.holder_grid.bitmap.x = coords.x
stage.holder_grid.bitmap.y = coords.y
settings.update()
}
}
init_image()
Its all working as I want but I can't figure out how to pixelate the image.
I found one solution where I draw the image using canvas.context.drawImage() but due to the parameters of the project it's not adequate. That worked like so:
const canvas = document.getElementById("canvas2")
const base = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const image = new Image()
props.image = image
image.src = "images/myImage.jpg"
image.onload = function() {
const width = base.clientWidth
const height = base.clientHeight
canvas.width= width
canvas.height= height
const scale= props.image_scale
const x = (ctx.canvas.width - image.width * scale) / 2
const y = (ctx.canvas.height - image.height * scale) / 2
//draws tiny
const size = props.pixelate/1
const w = canvas.width * size
const h = canvas.height * size
ctx.drawImage(image, 0, 0, w, h);
// turn off image aliasing
ctx.msImageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
// enlarge the minimized image to full size
ctx.drawImage(canvas, 0, 0, w, h, x, y, image.width * scale, image.height * scale);
}
So basically you draw it small then use that small instance as the image source to draw it bigger and viola, it's pixelated.... but due to other issues I've encountered doing this I cannot use this method.
Can anyone help me with this issue please?
The pixelation in your example is accomplished by drawing the original image at a lower resolution to an html <canvas> element. With createJS however you don't have built-in support for manipulating the sources of it's own Bitmap object.
There's hope though. Besides URL's to images, the constructor to a Bitmap also accepts a <canvas> element. So the trick here is loading the image, preparing - thus pixelating it - using a temporary <canvas> and once it's done, pass this element to the Bitmap constructor.
For example:
let stage = new createjs.Stage("canvas");
function pixelate(src) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let image = new Image();
image.crossOrigin = "anonymous";
image.onload = (e) => {
canvas.width = e.target.width;
canvas.height = e.target.height;
const width = e.target.width;
const height = e.target.height;
canvas.width = width;
canvas.height = height;
const scale = 1;
const x = (ctx.canvas.width - image.width * scale) / 2;
const y = (ctx.canvas.height - image.height * scale) / 2;
const size = 0.125 / 1;
const w = canvas.width * size;
const h = canvas.height * size;
ctx.drawImage(e.target, 0, 0, w, h);
ctx.msImageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
ctx.drawImage(canvas, 0, 0, w, h, x, y, e.target.width * scale, e.target.height * scale);
let bitmap = new createjs.Bitmap(canvas);
stage.addChild(bitmap);
stage.update();
}
image.src = src;
}
pixelate("https://api.codetabs.com/v1/proxy?quest=https://picsum.photos/id/237/400/300");
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<canvas id="canvas" width="400" height="300"></canvas>

drawing a cropped version of an image onto a canvas

I have the following html file which draws an image on the canvas.
<canvas id="canvas"width="800"height="800"></canvas>
<script>
var canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let img = new Image()
img.src = 'https://clipartspub.com/images/circle-clipart-blue-1.jpg'
img.onload = function(){
ctx.drawImage(img,300,300,300,300)
}
</script>
It works fine, however I would like to instead draw a cropped version of this image, for example, the bottom right quarter of the image. Is this possible?
You have to use the below implementation of drawImage to achieve that
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Check the docs here
var canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = "https://clipartspub.com/images/circle-clipart-blue-1.jpg";
img.onload = function () {
const width = img.width;
const height = img.height;
ctx.drawImage(
img, // Source image
width / 2, // Start at this x of image
height / 2, // Start at this y of image
width / 2, // Till this width of image
height / 2, // Till this height of image
0, // Start at this x of canvas
0, // Start at this y of image
300, // Till this width of canvas
300 // // Till this height of canvas
);
};
<canvas id="canvas"width="800"height="800"></canvas>
You can also use canvas.width and canvas.height in the canvas values used above for a better scaled result.

noisy pic after drawing big PNG file on cavnas

I have problem with drawing this (1766 * 2880) PNG file on canvas.
But I don't have any problem with JPG format of that size or (1533 * 2500) size of PNG file.
I consider devicePixelRatio for scaling canvas, and ignoring the ratio makes no changes.
var loadImage = function (url) {
var ratio = Math.max(window.devicePixelRatio || 1, 1),
image = new Image();
image.onload = function () {
var paper = '#paper-0',
canvas = $(paper)[0],
ctx = canvas.getContext("2d"),
img = this;
var w = Math.ceil(img.width / ratio), h = Math.ceil(img.height / ratio);
$(paper).css({ width: w + 'px', height: h + 'px' });
canvas.width = w * ratio;
canvas.height = h * ratio;
ctx.scale(ratio, ratio);
ctx.drawImage(img, 0, 0, w, h);
}
image.src = url;
}

canvas.toDataURL() results black image by trying to resize base64 string

I am currently trying to resize base64 images, since the image files are too big to be processed later on with php. I've found a way to achieve this by resizing the image using canvas. Unfortunately the image I get is just a black field which is 300px wide and 150px high. Maybe it has something to do with img.onload and canvas.toDataURL() order, or I am just using the wrong event (img.onload). Any idea where the mistake can be?
function exportImg(val){
var imageData = $('#image-cropper').cropit('export', {originalSize: true});
imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");
var imageDataRes = resize(imageData);
$.post('php/upload.php', { imageDataRes: imageDataRes });
}
function resize(base64){
// Max size for thumbnail
var maxWidth = 900;
var maxHeight = 900;
// Create and initialize two canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
// Create original image
var img = new Image();
img.src = base64;
img.onload = function(){
// Determine new ratio based on max size
var ratio = 1;
if(img.width > maxWidth) {
ratio = maxWidth / img.width;
}
else if(img.height > maxHeight) {
ratio = maxHeight / img.height;
}
// Draw original image in second canvas
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
// Copy and resize second canvas to first canvas
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
}
alert(canvas.toDataURL());
return canvas.toDataURL();
}
EDIT:
What is async in this case and how to solve it? Sorry, but unfortunately I don't see how this could help me further. The $.post works perfectly, I get the images. I just don't get the idea of img.onload and toDataURL() and how I should parse them from one function to another. At first, I got a blank result, with no string at all (just data,), but by adding this img.onload I got finally some base64 string...but it was just black screen.
You will need to wait onload event after that use global variable to save data and call upload function on the end .
Try this :
function exportImg(val){
var imageData = $('#image-cropper').cropit('export', {originalSize: true});
imageData = imageData.replace(/^data:image\/[a-z]+;base64,/, "");
resize(imageData);
}
var SendWhenisReady = function(imageDataRes){
$.post('php/upload.php', { imageDataRes: imageDataRes });
};
function resize(base64){
// Max size for thumbnail
var maxWidth = 900;
var maxHeight = 900;
// Create and initialize two canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
// Create original image
var img = new Image();
img.src = base64;
img.onload = function(){
// Determine new ratio based on max size
var ratio = 1;
if(img.width > maxWidth) {
ratio = maxWidth / img.width;
}
else if(img.height > maxHeight) {
ratio = maxHeight / img.height;
}
// Draw original image in second canvas
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
// Copy and resize second canvas to first canvas
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
alert(canvas.toDataURL());
window['imageDataRes'] = canvas.toDataURL();
SendWhenisReady(window['imageDataRes'])
}
}

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'});
},

Categories