canvas not drawing complete image from uri - javascript

i am using ionic and trying to draw selected image on canvas and convert it into base64 string. when i select image of low quality/size it appear perfectly fine but when image of high quality is selected, it only shows the upper part of image like image gets cropped.
$scope.getImages = function() {
$scope.modal.hide();
// Image picker will load images according to these settings
var options = {
maximumImagesCount: 1, // Max number of selected images, I'm using only one for this example
width: 800,
height: 800,
quality: 80 // Higher is better
};
$cordovaImagePicker.getPictures(options).then(function (results) {
// Loop through acquired images
for (var i = 0; i < results.length; i++) {
$scope.selectedImage = results[i];
}
}, function(error) {
console.log('Error: ' + JSON.stringify(error)); // In case of error
});
}
this is how image is being selected. the question is how can i draw complete selected image on canvas or in other words how can i get the image width and height in the loop, coz results[i] get only the uri of image.

This will help
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function()
{
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.src = imagePath

Related

Some trouble with PDFJS during creating extension(chromeAPI)

I have tried to create simple chrome extension to help myself download manga to ebook.
How it works - i get img sources as a string separated by space from website to extension side and split that into the table.
And now my function attached below should check every single image(page) of manga, redraw it to canvas, and recreate it again to raw img(cause its should be like that for pdfjs).
My problem:
console show its skips to last file
my for loop ends faster than recreate process lasts - it saves 3kb pdf (propably empty
manual saving PDF file from console still not works (file is bigger - +-size of image, but wont starts - shows errors).
function preparedownloadPDF(imagelist){
var page = 0;
console.log(imagelist);
var doc = new jsPDF();
var imageArray = imagelist.split(" ");
console.log(imageArray);
for(var i = 0; i < imageArray.length; i++)
{
if(imageArray[i] != "")
{
pdf.getImgFromUrl(imageArray[i]);
//pdf.generatePDF();
}
}
pdf.saveFile("123.pdf")
}
var pdf = {
page: 0,
img: null,
options: {orientation: 'p', unit: 'mm', format: "custom"},
doc: new jsPDF(this.options),
getImgFromUrl: function(base_url){
this.img = new Image();
this.img.src = base_url;
console.log(this.img.src + " baseurl: "+ base_url)
this.img.onload = function () {
pdf.generatePDF();
};
},
generatePDF: function(){
//redrawing image to canvas, to later recreate this as a BASE64 string(RAW data)
var canvas = document.createElement("canvas");
canvas.width = this.img.width;
canvas.height = this.img.height;
console.log("canvas")
console.log(canvas.width + "x" + canvas.height)
canvas.getContext("2d").drawImage(this.img, 0, 0);
var image = document.createElement("img");
image.src = canvas.toDataURL();
document.body.appendChild(image);
if(this.page++ != 0)
pdf.doc.addPage();
pdf.doc.addImage(this.img, 10, 10);
},
saveFile: function(name){
this.doc.save(name)
this.page = 0;
}
}
Any tips?
#
I not attach code of validation URL,etc. I use as valid phoenix-scans pl website.

Take full screenshot in Chrome

I developed a little chrome extension, which takes a screenshot from the current page. The Problem is, when a part of the current area is covered by e.g. the inspector or not in view the screenshot gets cropped.
Is there a way to get the full screen?
Here my Code (stripped down):
function createScreenshot() {
chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
chrome.tabs.captureVisibleTab({ format: "png" }, function (screenshotUrl) {
cropImage(screenshotUrl, "Screenshot");
});
});
}
function cropImage(url, fileName) {
var img = new Image();
img.onload = function () {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
chrome.storage.sync.get(null, function(data) {
downloadImage(canvas, fileName + ".png");
});
};
img.src = url;
}
for example, this is the page i want to shot in a 4k res:
source
as you can see, it doesn't fit to the actual screen resolution but the result is only the active area (even smaller):
result
is there a way to get the "not visible" part?
Regrads,
Martin
There is minor correction in your code
you have to pass canvas width, height in drawImage
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
You will need to get the base64 string
let image = canvas.toDataURL("image/png");
Finally, you will get the result you want
Hope this solution will help you

canvas toDataURL not returning a complete image

I'm building a jQuery plugin which watermarks images (and yes, i'm well aware of the multitudinal drawbacks of a javascript/html5 watermarking system but just ignore that for now.) The basic method for each image is:
paste the image to the background of a canvas
add the data for a watermark image over that,
replace the src of the original image with that of the canvas (which now contains the watermark.)
Now it appears to work fine if I replace the image element with the canvas itself.. all of the elements appear on the canvas. But when I get the dataURL of the canvas, everything but the last image drawn onto it appears. I wouldn't even mind except this plugin also needs to replace the links to images as well, and so replace the hrefs with data urls (with the watermark.)
This is the current code:
(function($){
$.fn.extend({
cmark: function(options) {
var defaults = {
type: 'image',
content: 'watermark.png',
filter: 'darker',
scale:300,
box: {
top : 0.5,
left : 0.5,
width : 0.75,
height : 0.75,
bgcolor : '#000000',
bgopacity : 0.5,
fgopacity : 1
},
callback_unsupported: function(obj){
return obj;
}
}
var getScale = function(w, h, scale){
ratio = Math.min(scale/w, scale/h);
scalew = Math.round(ratio*w);
scaleh = Math.round(ratio*h);
return [scalew,scaleh];
}
var options = $.extend(defaults, options);
return this.each(function() {
obj = $(this);
canvas = document.createElement('canvas');
if(!window.HTMLCanvasElement){
return options.callback_unsupported(obj);
}
/* if selecting for images, reset the images. Otherwise,
we're replacing link hrefs with data urls. */
if(obj.attr('src')){
target_img = obj.attr('src');
}
else if (obj.attr('href')){
target_img = obj.attr('href');
}
// get the filetype, make sure it's an image. If it is, get a mimetype. If not, return.
ftype = target_img.substring(target_img.lastIndexOf(".")+1).toLowerCase();
canvasbg = new Image();
canvasbg.onload = function(){
iw = canvasbg.width;
ih = canvasbg.height;
scale = getScale(iw, ih, options.scale);
iw = scale[0];
ih = scale[1];
canvas.setAttribute('width', iw);
canvas.setAttribute('height', ih);
ctx = canvas.getContext('2d');
/* define the box as a set of dimensions relative to the size of the image (percentages) */
bw = Math.round(iw * options.box.width);
bh = Math.round(ih * options.box.height);
// for now the box will only ever be centered.
bx = Math.round((iw * options.box.top) - (bw/2));
by = Math.round(ih * options.box.left - (bh/2));
/* draw the box unless the opacity is 0 */
if(options.box.bgopacity > 0){
ctx.fillStyle = options.box.bgcolor;
ctx.globalAlpha = options.box.bgopacity;
ctx.fillRect(bx, by, bw, bh);
}
wm = new Image();
wm.onload = function(){
ww = wm.width;
wh = wm.height;
scalar = Math.max(bw, bh); // scale to within the box dimensions
scale = getScale(ww, wh, scalar);
ww = scale[0];
wh = scale[1];
ctx.globalCompositeOperation = options.filter;
ctx.drawImage(wm, bx, by, ww, wh);
}
wm.src = options.content;
ctx.drawImage(canvasbg, 0, 0, iw, ih);
obj.replaceWith(canvas);
$('body').append('<img src="'+canvas.toDataURL()+'">');
//obj.attr('src', canvas.toDataURL());
}
canvasbg.src = target_img;
});
}
})
})(jQuery);
I added a line which dumps an image with the data url directly onto the page for testing and this is what I see... on the left is the canvas element, on the right is the image with the data url:
So yeah, this has had me stumped for a couple of days now. I'm probably missing something horribly obvious but I can't see it.
... edited because the example is no longer online. sorry.
First of all, don't build a string buffer that big for a tag.
var img = new Image();
img.src = canvas.toDataURL();
$('body').append(img);
Or if you prefer:
$('body').append($('<img>').attr('src', canvas.toDataURL()))
Second, you are getting there dataURL of the canvas before you draw the watermark. The drawing happens in the wm.onload callback function, which happens when the watermark loads. That may not fire until way after canvasbg.onload fires off, which is where you get the dataURL.
So move the image append into code at the end of the wm.onload callback and you should be good.

How can i load an array of images in html5 canvas and swap one of the images on button click

i'm trying to build a bike configurator. This is my problem.
How can i load and array of images to construct the bike and another array with parts on the right from which when the user click i take the part and load it on the left where is the bike without preloading the entire canvas again. the new image will be the same width and height and should be on the same x/y position. This is how i load and array of images, but then i don't know how to swap them. I know that i can't clear the image that is loaded on the canvas and i have to draw the new one on top but i don't know how.
<script type="text/javascript" charset="utf-8">
function loadImages(sources, callback){
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for (var src in sources) {
numImages++;
}
for (var src in sources) {
images[src] = new Image();
images[src].onload = function(){
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
window.onload = function(images){
var canvas = document.getElementById("config");
var context = canvas.getContext("2d");
var sources = {
one: "one.jpg",
two: "two.jpg"
};
loadImages(sources, function(images){
context.drawImage(images.one, 100, 100, 180, 200);
context.drawImage(images.two, 280, 100, 180, 200);
});
};
</script>
How can i change image two.jpg on button click. The button should be outside the canvas.
button.addEventListener('click', function () {
canvas.width = canvas.width; // redraws canvas
sources.two = 'three.jpg';
// fyi, you are drawing the images as many times as there are sources.
loadImages(sources, function(images){
context.drawImage(images.one, 100, 100, 180, 200);
context.drawImage(images.two, 280, 100, 180, 200);
});
}, false);

canvas shown on IE but not chrome and firefox

I want to use canvas to make an image to grayscale. There are a number of examples. But it has problem with my latest Chrome and Firefox. Surprisingly, IE9 is good. Is it the problem of my code?
And here is my code:
function draw() {
canvas = document.getElementById('canvas')
ctx = canvas.getContext('2d');
image = new Image();
image.src = 'ichiro.jpg';
ctx.drawImage(image, 0, 0);
imgd = ctx.getImageData(0, 0, 480, 400);
for (i=0; i<imgd.data.length; i+=4) {
grays = imgd.data[i]*.3 + imgd.data[i+1]*.6 + imgd.data[i+2]*.1;
imgd.data[i ] = grays; // red
imgd.data[i+1] = grays; // green
imgd.data[i+2] = grays; // blue
}
ctx.putImageData(imgd, 0, 0);
imggray = new Image();
imggray.src = canvas.toDataURL();
imggray.onload = function() {
ctx.drawImage(imggray, 0, 0);
}
}
I am new to HTML5 and javascript. So any help will be appreciated.
EDIT:
Sorry, I misread your question. It is almost certainly because of a security error. You are not allowed to use getImageData if you have drawn an image to the canvas that is from a different "origin" (a different domain or from your local file system). In Chrome locally you can get around it if you do:
C:\Users\root\AppData\Local\Google\Chrome\Application\chrome.exe --allow-file-access-from-files
There's something called the origin-clean flag and it is removed once you drawImage from a different origin. All files are of a different origin for (good) security reasons.
Original answer:
You need to wait for image to load:
working example: http://jsfiddle.net/SYLW2/1107/
...
// this now happens only after the image is loaded:
image.onload = function() {
ctx.drawImage(image, 0, 0);
imgd = ctx.getImageData(0, 0, 480, 400);
for (i=0; i<imgd.data.length; i+=4) {
grays = imgd.data[i]*.3 + imgd.data[i+1]*.6 + imgd.data[i+2]*.1;
imgd.data[i ] = grays; // red
imgd.data[i+1] = grays; // green
imgd.data[i+2] = grays; // blue
}
ctx.putImageData(imgd, 0, 0);
imggray = new Image();
imggray.src = canvas.toDataURL();
imggray.onload = function() {
ctx.drawImage(imggray, 0, 0);
}
}
image.src = 'http://placekitten.com/400/400';

Categories