How to improve the quality of the saved image?

Asked

Viewed 3,318 times

3

I use the tool html2canvas in a project to print a certain area of my code and save it as an image.

I tried saving in the following formats, JPEG and PNG, but both are of the same quality, I would like to know, of someone who uses this tool as well, if there is any way to determine the quality of the image to be saved.

[EDIT]

Answering the requested questions:

  1. The screen is not retina
  2. The Operating System is Ubuntu 15.04 x64
  3. The browser is Google Chrome x64

This is the call code to html2canvas, very simple, practically transforms the image into url saved in a input Hidden to save her with the PHP (I don’t know exactly if this shipment to save with the PHP has something to do with this bug, If there is, let me know, please):

html2canvas($("#result"), {
    onrendered: function(canvas) {
        img = canvas.toDataURL("image/jpeg");

        $("#screenshot").val(img);

        $("#form").submit();
    }
});

In this system in which I work, one of its functions is to create images for posting on Facebook.

The HTML used consists of:

Testing Test subtitle

The reason I don’t use a background image on <div id="backgroud"> was a decision related to other system functionalities.

The CSS consists of:

div#template {
  width: 500px;
  height: 450px;
  position: relative;  
  background: rgba(0, 0, 0, 0.1);
}
div#background {
  width: 500px;
  height: 450px;
  position: absolute;
  z-index: 1;
}
img#bg-image {
  display: none;
}
div#content {
  width: 500px;
  height: 125px;
  background: rgba(0, 0, 0, 0.3);
  position: absolute;
  top: 25%;
  color: #fff;
  display: table;
  z-index: 2;
}
div#content-bar {
  width: 500px;
  height: 40px;
  position: absolute;
  backgrund:#000;
}
h1.title {
  color: inherit;
  width: 400px;
  margin: 15px auto;
  font-size: 30px;
  font-weight: bold;
}
h2.subtitle {
  color: inherit;
  font-size: 20px;
  margin: 75px auto;
  font-weight: bold;
}

It’s pretty basic, because in this case, it only makes the positioning Absolute of Divs and positions them one on the other, leaving the <div id="background"> behind, having background function.

An example image

I don’t know if I can see very well, but I’m sending a print I took of a picture posted after ready.

If you notice, the image is a little "blurred", during the construction of the image this does not occur.

Imagem postada

I didn’t post the image related HTML and CSS, as I don’t have them at my disposal at the moment.

  • In this case, to maintain quality, it would not be better to try to convert the print into svg?

  • I thought about it too, but I haven’t tried yet, I’ll try.

  • If you have the image in Canvas, you can convert it to SVG using this plug-in: https://github.com/gliffy/canvas2svg

  • @Marcelobonifazio the problem is that there was already generated with low quality.

  • So @bigown, I was commenting on this, the ideal would be to convert straight from HTML to SVG, only I never had to do something like, I’ll do a search, if I find a solution, put here

  • @Marcelobonifazio If you mean foreignObject, think it is blocked in Chrome by "security".

  • Post html and css too, if possible post an image of the problem.

  • @Guillhermenascimento posted :)

  • @Thomersonroncally I didn’t understand the facebook part in the photo. Do so, without wanting to ask too much rs, post a full example in jsfiddle please.

  • @Guilhermenascimento Ok rsrs

  • @Guilhermenascimento Edited rsrs Jsfiddle + PHP + Image

  • The test I did was no loss of quality, see the result: http://i.stack.Imgur.com/u2EzW.jpg - for me it looks "perfect". Then I tested with more reddish colors (http://www.socwall.com/images/wallpapers/26794-1920x1200.jpg) and the result was: http://i.stack.Imgur.com/5uQ5s.jpg - With warmer colors it is possible to observe more details, however it seems normal. Maybe the problem occurs at another time, at the time you share on facebook for example (facebook compresses the images I think)

  • @Guilhermenascimento Um, got it! Yes, in local tests, it also seemed normal to me, but there were several complaints about this, so I thought the mistake was with html2canvas, but I will try your solution, to see if it changes something and I will look for possible causes in other parts of code! Thanks for the great help :) If I solve, I will share here, changing the question :)

Show 8 more comments

1 answer

2


There may be two more known problems (I believe there is another problem with similar sources, but it does not seem to be the case):

Problem with retinal screen

Retinal screen or Retinal screen (european portuguese) or Retina Display (english) are used LCD (Apple) screens that feature sufficient pixel density for the human eye not to be able to perceive pixelation at a standard distance, used in Apple products like iPhone and Mac.

Usually the content displayed on the screen has on average the "double" size that appears, that is and we usually have to use high-quality images so that they do not present the blurred effect ("blurry").

The moment you use the html2canvas on the retina screen, what is presented to you is an image that would be only noticeable to the pixels. This seems to be a problem of Canvas API trying to adjust the image when exporting it.

Chrome/Safari bug with background images on Windows 64bit

Note: Apparently this bug has been fixed in the latest versions of Chromium

I don’t remember if the problem occurs in Safari, but in Chrome and Opera (Chromium/Blink technology) this occurs. It’s a bug in Canvas API also, which usually occurs when the image has different element size (for example a DIV).

Let’s assume we have a 100x100 image call test png. one <div> thus:

<style>
.foo {
   width: 200px;
   height: 200px;
   background: url(test.png) no-repeat;
}
</style>

If your Chrome is 32bit running on a 64bit system there is a blur effect, see an example (as I mentioned here #206):

function putImage()
{
    //Funciona-----------------------
    var canvas=document.getElementById("myCanvas1");
    var ctx=canvas.getContext("2d");

    ctx.webkitImageSmoothingEnabled = false; //Corrige o problema

    var pat=ctx.createPattern(img, "repeat");
    ctx.rect(0,0, 64, 64);
    ctx.fillStyle=pat;
    ctx.fill();

    ctx.restore();
    //Funciona-----------------------

    //Causa o bug-----------------------
    var canvas2=document.getElementById("myCanvas2");
    var ctx2=canvas2.getContext("2d");

    var pat=ctx2.createPattern(img, "repeat");
    ctx2.rect(0,0, 64, 64);
    ctx2.fillStyle=pat;
    ctx2.fill();

    ctx2.restore();
    //Causa o bug-----------------------
}

var img = document.getElementById("lamp");

img.onload = function() {
     setTimeout(putImage, 100);
};
<div>
    <p>Imagem usada:</p>
    <img src="http://i.stack.imgur.com/IvOeo.png" id="lamp">
</div>

<div style="float: left; width: 40%;">
    <p>Funciona (com ctx.webkitImageSmoothingEnabled = false):</p>
    <canvas id="myCanvas1" width="300" height="318"></canvas>
</div>

<div style="float: right; width: 40%;">
    <p>Falha (se não falhar é porque está usando um navegador que já teve o bug corrigido):</p>
    <canvas id="myCanvas2" width="300" height="318"></canvas>
</div>

Possible solution 1

This solution may work with Retina monitors, but her focus is to solve the problem with the background-size. The solution seems to cause some other problem, but I do not know for sure what it is (maybe with images resized by background-size or width="" and height="", I’m not sure, but it seems that the canvas loses the "precision" of the resized images), however if your page is simpler it is quite possible that it works.

In the "context" of the Canvas API we have the properties:

var ctx = canvas.getContext("2d");
ctx.webkitImageSmoothingEnabled = false; //Webkit/Safari/Chrome
ctx.mozImageSmoothingEnabled = false;    //Firefox/Gecko
ctx.imageSmoothingEnabled = false;       //Outros navegadores

These properties disable image smoothing, but you need to "mess" with the source code of html2canvas to be able to apply this.

Possible solution 2

The second possible solution is addressed to the problem with the retinal screens, the idea is that you can create an image twice the size and reduce it later, the process would be something like:

Note: Very large canvas images cannot be exported with .toDataURI, because there is a size limit.

CSS:

.escala-x2 {
    -webkit-transform: scale(2);
       -moz-transform: scale(2);
            transform: scale(2);
}

Javascript:

var elemento = document.getElementById("foo");

elemento.className += " escala-x2";

html2canvas(elemento).then(function(canvas) {

    elemento.className = elemento.className.replace(/\sescala\-x2/g, "");

    var new_canvas = document.createElement("canvas");

    //Copia canvas para new_canvas e redimenciona pela metade
    new_canvas.width = canvas.width / 2;
    new_canvas.height = canvas.height / 2;

    var ctx = new_canvas.getContext('2d');

    ctx.drawImage(canvas, 0, 0, new_canvas.width, new_canvas.height);
    ctx.webkitImageSmoothingEnabled = false; //Webkit/Safari/Chrome
    ctx.mozImageSmoothingEnabled = false;    //Firefox/Gecko
    ctx.imageSmoothingEnabled = false;       //Outros navegadores

    canvas = null;

    document.body.appendChild(new_canvas);//Adiciona o canvas redimensionado ao body
});

This way you can use the imageSmoothingEnabled quietly, as the original images have already been converted to canvas, so it is likely that no problem will occur.

Size limit of canvas

Each browser has an image limit that can work with Canvas, usually when it exceeds this limit is launched an Exception, according to the answer of Soen (these limits are improved as the browser receives updates):

Note: I will update the data as I find more sources

Data of 10/13/2014:

  • Chrome:

    • Maximum width and height: 32,767 pixels
    • Maximum area: 268,435,456 pixels (for example 16,384 x 16,384)
  • Firefox:

    • Maximum width and height: 32,767 pixels
    • Maximum area: 472,907,776 pixels (for example 22,528 x 20,992)
  • Internet Explorer:

    • Maximum width and height: 8,192 pixels
  • IE Mobile:

    • Maximum width and height: 4,096 pixels
  • I answered the questions you requested in the post, about my operating system, etc... I will try the second solution you proposed, but first I would like to know what the size limit for the use of . toDataURI you quoted, because the images I try to save are in size: 500x450 or 851x315. Thank you

  • @Thomersonroncally the limitation varies from browser to browser, however in Internetexplorer is approximately 8,192 pixels (width and height), I will update the answer, note that these limits are always improved with each update :) - Fortunately.

  • I added the code I call html2canvas, it’s very simple.

  • Could you show me a "picture" of the problem? @Thomersonroncally This may be the problem with the background (however it may be a new problem) or with the fonts.

  • can yes, I will update my question, trying to expose a little more my problem

Browser other questions tagged

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