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>