Generating an image based on other images

Asked

Viewed 1,346 times

2

I have two HTML fields. In each of them, there will be a list of teams. When the user selects the two teams that will play (against each other), he would like to generate an image with the logos of the two teams in PNG.

Field 1 X Field 2 = PNG image with Logo 1 + Logo 2

It is possible to do this only with Javascript?

Edited: It really has to be with PHP, because the user will have to download the image, thanks for the other alternatives...

  • With the canvas, it is possible to mount using only client side code, display the result in a <canvas> or in a tag <img>, and still download the result. I updated my answer, anything :D

3 answers

4

Possible, yes, with the Canvas API (HTML5).

However, for security reasons, it is not possible to display the result of gluing to a tag <img>, also do not download, case at least one of the input images comes from a different domain (server) page.

The most important steps are described below. I provided an example*; just pay close attention to the security details; this code can be used to both display the result on the canvas and on <img>, just choosing the right lines for the desired purpose.


Canvas creation

It is essential, because the images will be pasted to each other inside the canvas. Therefore, in this step, it is important to also set the size of the canvas (see Example jsfiddle*). If you don’t want to display the result on the canvas, but on a <img>, simply remove the line from the appendChild().

var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
output.appendChild(canvas); // opcional

Creation of elements for input images

Needed to be able to request server input image files.

var img_in1 = document.createElement("img");
var img_in2 = document.createElement("img");

Listener of the first input image

Once the first image is loaded, add your pixels to the canvas and request the second image. (To know where to paste the second image into the canvas, it is necessary that we already have the width of the first image.)

img_in1.addEventListener("load", function(){
    context.drawImage(img_in1
                     , 0, 0, img_in1.width, img_in1.height
                     , 0, 0, img_in1.width, img_in1.height
                     );
    img_in2.src = "/imagens/img2.png";
});

Listener of the second input image

When the second image is loaded, this code positions it next to the first image on the canvas. If both images are of the same domain of the page, you have the option to display the result of the collage in a <img> instead of canvas.

img_in2.addEventListener("load", function(){
    context.drawImage( img_in2
                     , 0, 0, img_in2.width, img_in2.height
                     , img_in1.width, 0, img_in2.width, img_in2.height
                     );
    // Se as imagens vierem do mesmo domínio da página:
    img_out.src = canvas.toDataURL("image/png");
    botao.href = canvas.toDataURL("image/png");
});

Request the first input image

Trigger the whole process; if the first image is not loaded, none of the listeners will be warned and nothing will happen.

img_in1.src = "/imagens/img1.png";

I hope I’ve helped!

Example jsfiddle: updated to work with Jsfiddle’s own images, thus escaping the security constraint.

Edit: I have two observations to make:

  • This method is robust. You can make very complex transformations with the images, thanks to the canvas, and also make available the resulting montage for download, at the end of the process.

  • The @Jader method may end up being easier. If the goal is a simple setup, intended only for "static" viewing on the page itself, the CSS method uses far less script (JS).

  • 2

    The code documentation is full professional. When you finally install the Stack Snippets here, remember to bring your fiddles here. ++ 1++

  • Thanks, @brasofilo, and I didn’t know about Stack Snippets... Great, SO is getting better and better! : D You can let me migrate, yes!

3

In general, it is not possible to generate Javascript files when it runs in the browser. If this were possible, we would have a security breach.

You can generate the file in PHP and go up to the browser. In this case I hope that someone more expert in PHP will leave an answer on how to do this (you will have my upvote guaranteed).

Or you can charge two PNG’s with the transparent background, each with a team’s coat of arms/shield/logo. This saves processing as you can have all the images already stored on the server. The only effort is to hit the CSS.

As a variation of this second alternative you can play with the Canvas of HTML 5, but many people think that this is not a good idea because then your application will not work for a number of people (more or less the population of Antarctica) who cannot or do not know how to update Internet Explorer, that already supports this even in obsolete versions.

3

I didn’t quite understand the real need to generate an image, my suggestion is to build the frame with CSS superimposing the images, something like that:

HTML:

<div class="campo" style="background-image:url(ENDEREÇO DA IMAGEM DE FUNDO)">
    <div class="time1" style="background-image:url(ENDEREÇO DA IMAGEM DO TIME 1)"></div>
    <div class="time2" style="background-image:url(ENDEREÇO DA IMAGEM DO TIME 2)"></div>
</div>

CSS:

.campo {
    position: relative;
    width: 660px;
    height: 495px;
    background-size:cover;
}
.time1, .time2 {
    position: absolute;
    width: 128px;
    height: 128px;
    top: 230px;
}
.time1 {
    left: 150px;
}
.time2 {
    right: 150px;
}

Obs.: I chose to put the background-image in the style parameter, as it is easier to work with dynamic images, because to put in the CSS rules would require at least one class for each team...

See working on Jsfiddle

  • 1

    If I could give two upvotes i would. One for the independent Javascript solution that overrides obstructivity and one for the "times" images to play. D

  • On second thought, the CSS solution is really quite good, if the setup is simple. It’s easy to implement and works in more browsers compared to the canvas technique I suggested. Good idea! The only justification for canvas is the new OP specification, which is the download of the result, and also because more complex montages can only be done via script. Rotation effects in CSS, for example, in the same way as canvas, are only supported in newer browsers... Anyway, a good suggestion! :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.