0

I'm trying generate an image and save it as PNG, so when printed it's size would be exactly as supposed to: i.e. a rectangle 2x1 inches.

For starters I'm using imperial units (inches) and assume the default printer settings is 300dpi.

This works fine if I manually set the image dimensions in my printer's software. Is there a way make the printer recognize the image true size? I do aware there are different software, so perhaps there is a "universal" method to do so?

Would adding pHYs chunk help and if so how would I do that?

const canvas = document.getElementById("preview"),
      ctx = canvas.getContext("2d"),
      width = document.getElementById("width"),
      height = document.getElementById("height"),
      link = document.getElementById("download"),
      dpi = 300,
      offset = 0.5; //make lines true 1px wide by shifting it 0.5 pixels

function generate()
{
  const w = width.value * dpi,
        h = height.value * dpi,
        text = width.value + "x" + height.value;

  canvas.width = w + offset * 2;
  canvas.height = h + offset * 2;
  ctx.strokeStyle = "black";
  ctx.fillStyle = "white";
  ctx.lineWidth = 1;
  ctx.fillRect(0, 0, canvas.width, canvas.height); //fill background
  ctx.rect(offset, offset, w, h);
  // diagonal lines
  ctx.moveTo(offset, offset);
  ctx.lineTo(w, h);
  ctx.moveTo(w + offset, offset);
  ctx.lineTo(offset, h);
  // vertical line
  ctx.moveTo(w / 2 + offset, offset + offset);
  ctx.lineTo(w / 2, h);
  // horizontal line
  ctx.moveTo(offset, h / 2 + offset);
  ctx.lineTo(w, h / 2);
  // circle
  ctx.moveTo(w / 2 + Math.min(w, h) / 2 + offset, h / 2 + offset);
  ctx.arc(w / 2 + offset, h / 2 + offset, Math.min(w, h) / 2, 0, Math.PI * 2);
  // text
  ctx.font = Math.min(w, h) / (text.length / 1.5) + "px monospace";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.strokeText(text, w / 2 + offset, h / 2 + offset);
  ctx.stroke();
  //generate download link
  canvas.toBlob(data =>
  {
    link.setAttribute("download", `${text}_(${dpi}dpi).png`);
    link.href = URL.createObjectURL(data);
  });
}

generate();
input
{
  width: 3em;
}
div
{
  padding: 1em;
  background-color: pink;
  display: inline-block;
}

div:first-of-type
{
  padding-bottom: 0;
}
<div>
  Size (in inches): <input id="width" type="number" oninput="generate()" value="2"> x <input id="height" type="number" oninput="generate()" value="1">
</div>

<a id="download">download PNG</a>
<br>
<div>
  <canvas id="preview"></canvas>
</div>
vanowm
  • 9,466
  • 2
  • 21
  • 37
  • The proposed "answer" covers only changing information in the image in node.js, I'm not using node.js – vanowm Nov 09 '21 at 11:57
  • The **questions** are duplicate. And if you only took the time to read below the accepted answer you would have seen https://stackoverflow.com/a/50913701/3702797 which also works in browser environments. – Kaiido Nov 10 '21 at 03:12

0 Answers0