Fetch Urls and merge into single high quality image (Javascript) - javascript

I've currently got a piece of JS that allows me to fetch all the IMG urls inside a certain DIV (vpc-preview). I'm now looking for a solution to take these Urls and merge them into one image that pops up for the user to download.
I'm using this method rather than something like the "HTMLCanvasElement.toDataURL" method as I want a high quality image output. I found the Html2canvas method generates a blurry image especially on retina. The original URL's are high quality images which would be ideal if just merged.
Note: The images will not have consistent names and there can be anywhere between 5-30 images stacked on top of eachother. Which is why I'm collecting them from the container they reside in as that and the height/width are the only constants.
Below is a Fiddle I've put together to show what I have so far, the only difference is the images will be stacked on top of each other rather than side by side.
Demo Fiddle
function img_find() {
var imgs = document.querySelectorAll('#vpc-preview img');
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
return alert(imgSrcs);
}
UPDATE: The following fiddle lets users upload images and then merges them into a single photo for download. Unfortunately my coding skills aren't good enough to manipulate this into using the SRC urls of images within certain DIV and to Merge all the photos on top of each other. Click here to see thread this came from.
Fiddle
function addToCanvas(img) {
// resize canvas to fit the image
// height should be the max width of the images added, since we rotate -90 degree
// width is just a sum of all images' height
canvas.height = max(lastHeight, img.width);
canvas.width = lastWidth + img.height;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (lastImage) {
ctx.drawImage(lastImage, 0, canvas.height - lastImage.height);
}
ctx.rotate(270 * Math.PI / 180); // rotate the canvas to the specified degrees
ctx.drawImage(img, -canvas.height, lastWidth);
lastImage = new Image();
lastImage.src = canvas.toDataURL();
lastWidth += img.height;
lastHeight = canvas.height;
imagesLoaded += 1;
}

Related

Fabricjs: Sprite sheet to horizontal continuous video thumbnail on canvas

I have multiple sprite sheets, one for each minute of the video. For example if video is 3 min long I have sprite.0.jpg, sprite.1.jpg, sprite.2.jpg which mean 3 sprite sheets each having 60 images for every 1 sec.
That means sprite sheet with 10 columns and 6 rows having single image size as 142x80 whereas total sprite sheet as 1420x 480 (see below)
I want to design component to show preview of continous video thumbnail on canvas. (see below)
How to convert Sprite sheets to horizontal continuous video thumbnail on fabricjs canvas?
I tried drawing the first frame of the sprite sheet on canvas but not sure how to put every sprite sheets in continous manner so that canvas is horizontally scrollable.
// Get the canvas and canvas context
var canvas = document.getElementById("timeline");
var ctx = canvas.getContext("2d");
// Create an image object
var image = new Image();
image.src = "path/to/spritesheet.jpg";
// Wait for the image to load
image.onload = function() {
// Set the canvas size
canvas.width = 1420;
canvas.height = 480;
// Draw the first frame of the sprite sheet
ctx.drawImage(image, 0, 0, 1420, 480, 0, 0, canvas.width, canvas.height);
};
I'm just going to focus on the part of your question where you split the sprite sheet into a horizontal continuous thumbnail, there are other concerns that I address after the code sample.
To do what you ask we need a loop on the sample sprite sheet you provide there are 6 rows so we loop on that and draw the rows into one.
You are using drawImage with all the parameters, I'm assuming you have the basics clear, if not see more about that in the documentation:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#parameters
Here is a working sample:
var canvas = document.getElementById("timeline");
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = "https://i.stack.imgur.com/gOk5s.jpg";
image.onload = function() {
for (let i = 0; i < 6; i++)
ctx.drawImage(
image,
0, 80 * i, 1420, 80,
710 * i, 0, 710, 40
);
};
canvas {
border: dashed 5px red
}
<canvas id="timeline" width=4260 height=40></canvas>
I do see in your comments you added:
... what about when I want see preview of 1 hour long video? This doesn't seems right as there is limit on canvas width I guess.
Yes there is a limit and is per browser:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
But That is a much more complex issue that deserves a separate question...
one of the options could be combining the sprite tiles, instead of showing thumbnails every 1 second show every 5 or 10 to better accommodate for the large videos
another option could be to use multiple canvases

Error in export PNG canvas all div content

In localhost, it's works exported div to image, include image over another image. I need create dynamic ID card.
But, the local project its work perfect, but the project online, not worked
I used guillotine for only zoom image and move
My first image template is svg inside div as background image
The name, job, number employee its show
var test = $(".test").get(0);
$('.toCanvas').click(function(e) {
html2canvas(test).then(function(canvas) {
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var img = Canvas2Image.convertToImage(canvas, canvasWidth, canvasHeight);
$('#save').click(function(e) {
let type = 'png'; // image type
w = canvasWidth;
h = canvasHeight;
Canvas2Image.saveAsImage(canvas, w, h, type, 'credencial');
});
});
});
i tried different options, for example, generated image to php, save it, and after download, but the problem its same, locally its work perfectly, but online not working
thanks

How to scale my canvas in reason, with the zoom scale?

I am working on a multiple web game using JavaScript. My canvas is currently set to the width and the height of my screen.
html
<canvas id = "canvas"></canvas>
javascript
var c=document.getElementById("canvas");
var ctx = c.getContext("2d");
//Making canvas scale;
c.width = window.innerWidth;
c.height = window.innerHeight;
function resize(){
//Add some code
}
My problem is, I do not want my players to zoom out, well not by default. It will make the game look bad and give the players an edge over everyone else. So I need to add some code to go into the resize method, that regardless of scale, the canvas will not be zoomed out. If the end result is something blurry at 300%+ that is fine.
IMPORTANT: the resize function cannot remove or reset the canvas back to default.
There are various ways to scale a canvas.
First off, there are 2 main parameters for the canvas size:
-Canvas Pixel Count. Set via canvas.width = 1000
-Canvas Display Pixel Size. Set via canvas.style.width = '1000px'
If you want all players to see a 1000x1000 region but displaying it fullscreen:
canvas.width = 1000;
canvas.height = 1000;
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
There is also another option with canvas.style.transform = 'scale(2,2)'.
This method is the closest thing to the browser zoom done via Ctrl+ or Ctrl-.
The big advantage of transform is that the scaling is applied to all DOM children elements. If your game is using HTML for its interface, then this is the way to go. (By applying the scaling on the div containing the canvas + HTML interface.

Big image drawn on small canvas become blurrier

In my project i have a canvas (200*150) and i want to draw an image of size (800*600) . The result is that image become bluer (not smooth and clear) , but if we put that image on img tag it look well. So how can we deal with this? thanks.
<img src="http://www.drivingkids.com/wp-content/uploads/2010/07/preschool-math-game-for-kids-math-racing-equatations.jpg"
width="200" heigh="150" />
<canvas id="my_canvas" width="200" height="150"></canvas>
<script type="text/javascript">
window.onload = function () {
var context = document.getElementById("my_canvas").getContext("2d");
var image = new Image();
image.src = "http://www.drivingkids.com/wp-content/uploads/2010/07/preschool-math-game-for-kids-math-racing-equatations.jpg";
image.onload = function () {
context.drawImage(image, 0, 0, context.canvas.width, context.canvas.height); //dx-30, GY-28, GW+50, GH+35
}
}
</script>
Cause
Browsers can prioritize quality or performance depending on the current scenario.
For images quality is typically prioritized over performance for most pages. But for canvas performance is not as good as with for instance direct browser rendering and CSS so the interpolation with canvas may have performance prioritized before quality. Depending on browser implementation.
Solution
Luckily there is a way to work around this by sort of splitting the burden with the resizing and interpolation by doing it in two (or more) steps, or one intermediate step if you like.
The intermediate step will first scale the image 50% to an off-screen canvas. Then use that canvas to draw to the final size. For larger images more steps will perhaps be needed.
The time spent in sum is about the same due to the sum of the operations to get the new sizes (more simply put: less to interpolate with intermediate step x2, versus more to interpolate x1) so you won't notice much performance reduction.
But most importantly: the result will be better than with just a single step.
Implementation
This is how you can implement an intermediate step:
image.onload = function () {
/// create an extra step for re-sizing image
var tmpCanvas = document.createElement('canvas'),
tmpContext = c.getContext('2d');
/// set this canvas to 50% of image
tmpCanvas.width = image.width * 0.5;
tmpCanvas.height = image.height * 0.5;
/// draw image step 1
tmpContext.drawImage(image, 0, 0, image.width * 0.5, image.height * 0.5);
/// draw image step 2
context.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
}
Demo (proof-of-concept)
ONLINE DEMO HERE
The result will be:
Left image: IMG element. Right image: canvas two steps (rendered in Firefox)
As you can see there is now no noticeable difference between image and canvas element.

Tricky screen sizing and scaling (on Javascript)

I have a tricky question that might just have a simple solution, although I trully don't see it now.
So, I've been working around HTML5 element and, obviously, doing the interaction methodology in JavaScript.
One of the objectives of this work is to be able to use a mobile device [MD] (iOS or Android, phone or tablet) as a remote controller for an application that will be served by another machine (eg. a laptop or external display) and both will be showing the same thing on each of the screens on different scales.
So, I wanna have an event occur when the canvas is 80% filled (or in this case, "erased" (which I already have by calculating the total number of [initial] pixels) and each device has a different count since the screen sizes/resolutions are different.
This is the tricky part: How will I be able to "scale" the MD pixel count and mirror that to the bigger screen?
For concrete measures, how will I be able to implement the following example:
I draw a line on the MD that goes for 300px wide, and for simplicity, let's say that this represents 10% of the MD canvas (which on both the screens is in fullscreen).
I want the external monitor (which has a higher resolution) to mirror this event but on an appropriate scale so that those 10% on the MD represent the same (scaled) 10% of "canvas real estate"
Just in case the text is too confusing, I'll leave the code bellow:
function totalPix(x, y) {
var total = x * y;
var objective = (total * 80) / 100;
}
function canvasApp() {
//prevent from scrolling (no bouncing)
document.body.addEventListener('touchmove', function(event){
event.preventDefault();
}, false);
if(!canvasSupport()) {
alert("No canvas support on this device!");
return;
} else if(!socketSupport) {
alert("No websocket support on this device!");
} else {
//create canvas on every load (//TODO)
var elemDiv = document.getElementById("content");
var newElem = document.createElement("canvas");
newElem.setAttribute("id", "frontscreen");
elemDiv.appendChild(newElem);
drawScreen();
function drawScreen() {
//Setup canvas
var canvas = document.getElementById("frontscreen");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
totalPix(canvas.width, canvas.height);
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
//Foreach touchmove event, send position to server
canvas.addEventListener('touchmove', function(event) {
for (var i = 0; i<event.touches.length; i++) {
var touch = event.touches[i];
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(touch.pageX, touch.pageY, 30, 0, 2*Math.PI, false);
ctx.fill();
ctx.stroke();
}
}, false);
window.onresize = function resizeCanvas() {drawScreen();};
}
}
}
If I understand you correctly, it's as simple as changing the size property on the HTML style property of your <canvas> element. For example, let's say you fill in a 300 by 300 px. square on Monitor A, which occupies 10% of the screen real estate (I know, big monitor). Then you load the same page on Monitor B, which is twice the size of Monitor A. (Really really big monitor, just bear with me here. It's an example.) Naturally, it will only occupy 5% of the screen's real estate.
If you want that 300px to always occupy the same percentage of size on all screens (but still be 300px on the canvas), you can do something like this:
var canvas = document.getElementById("mycanvas");
var heightAsPercent = 10;
var widthAsPercent = 10;
canvas.style.height = (heightAsPercent / 100) * screen.height;
canvas.style.width = (widthAsPercent / 100) * screen.width;
That way, the canvas will always occupy 10% of the screen, whether the monitor width is 3000px or 6000px. I've obviously chosen very verbose variable names for clarity, so feel free to modify them as needed.
The reason this works is that you're only modifying the CSS properties of the canvas, which affect only how it's rendered, not the actual <canvas> data. I came across this little trick by accident, and it drove me nuts until I figured out why it was doing this. Now it actually comes in handy. :)

Categories

Resources