使用HTML5画布创建图像时,有没有办法设置自定义DPI / PPI?我知道如何在画布上绘制并将其导出为图像,但如何确保输出图像具有某些DPI / PPI。我想使用SVG元素在画布上绘制是一种方式,但是当我将整个画布作为图像导出时,这不会被弄平吗?或者计算设备DPI然后缩放图像以满足我的DPI要求,但这似乎不是正确的解决方案。
答案 0 :(得分:42)
画布有两种不同的'尺寸':它们的DOM宽度/高度和它们的CSS宽度/高度。您可以通过增加DOM大小来增加画布的分辨率,同时保持CSS大小不变,然后使用.scale()方法将所有未来的绘制扩展到新的更大的大小。这是一个例子:
function changeResolution(canvas, scaleFactor) {
// Set up CSS size.
canvas.style.width = canvas.style.width || canvas.width + 'px';
canvas.style.height = canvas.style.height || canvas.height + 'px';
// Resize canvas and scale future draws.
canvas.width = Math.ceil(canvas.width * scaleFactor);
canvas.height = Math.ceil(canvas.height * scaleFactor);
var ctx = canvas.getContext('2d');
ctx.scale(scaleFactor, scaleFactor);
}
画布默认分辨率为96dpi(CSS英寸,不基于实际屏幕)。因此,scaleFactor为2得到192dpi,3为288dpi等等。事实上,这是一个应该给出你想要的DPI的版本:
function setDPI(canvas, dpi) {
// Set up CSS size.
canvas.style.width = canvas.style.width || canvas.width + 'px';
canvas.style.height = canvas.style.height || canvas.height + 'px';
// Resize canvas and scale future draws.
var scaleFactor = dpi / 96;
canvas.width = Math.ceil(canvas.width * scaleFactor);
canvas.height = Math.ceil(canvas.height * scaleFactor);
var ctx = canvas.getContext('2d');
ctx.scale(scaleFactor, scaleFactor);
}
玩得开心!请注意,这两个代码示例只能在每个画布上使用一次,它们假设当前的DOM大小是原始的(可以调整它们来改变它)。还需要重新缩放之前在画布上进行任何绘制。感谢this post获取方法和信息!
编辑:这是一个更强大的功能,可以扩展未来的绘制和维护现有的画布内容。可以调用此方法多次重新缩放。
function setDPI(canvas, dpi) {
// Set up CSS size.
canvas.style.width = canvas.style.width || canvas.width + 'px';
canvas.style.height = canvas.style.height || canvas.height + 'px';
// Get size information.
var scaleFactor = dpi / 96;
var width = parseFloat(canvas.style.width);
var height = parseFloat(canvas.style.height);
// Backup the canvas contents.
var oldScale = canvas.width / width;
var backupScale = scaleFactor / oldScale;
var backup = canvas.cloneNode(false);
backup.getContext('2d').drawImage(canvas, 0, 0);
// Resize the canvas.
var ctx = canvas.getContext('2d');
canvas.width = Math.ceil(width * scaleFactor);
canvas.height = Math.ceil(height * scaleFactor);
// Redraw the canvas image and scale future draws.
ctx.setTransform(backupScale, 0, 0, backupScale, 0, 0);
ctx.drawImage(backup, 0, 0);
ctx.setTransform(scaleFactor, 0, 0, scaleFactor, 0, 0);
}
答案 1 :(得分:3)
你不能(在任何浏览器中)访问当前网页显示的DPI:
Detecting the system DPI/PPI from JS/CSS?
用于打印:您很可能无法使用浏览器标准功能设置导出的<canvas>
图像(PNG,JPEG)的DPI。但是,如果您使用纯Javascript编码器图像编码器,则可以自由创建任何类型的二进制文件,并手动调整二进制文件中嵌入的DPI值。
答案 2 :(得分:1)
如果您只想设置PNG的dpi(即不增加像素数),那么此库可让您设置 pHYs 块(以及其他内容):
https://github.com/imaya/CanvasTool.PngEncoder
将HTML5画布导出为base64编码的PNG的最小示例:
// convert dots per inch into dots per metre
var pixelsPerM = dpi * 100 / 2.54;
var param = {
bitDepth : 8,
colourType : 2,
filterType : 0,
height : canvas.height,
interlaceMethod : 0,
phys : {
unit : 1,
x : pixelsPerM,
y : pixelsPerM
},
width : canvas.width
};
var array = canvas.getContext('2d').getImageData(0, 0, canvas.width,
canvas.height).data;
var png = new window.CanvasTool.PngEncoder(array, param).convert();
var base64 = 'data:image/png;base64,' + btoa(png);
答案 3 :(得分:0)
使用更改后的库pi:
npm install changedpi --save
也可以看到
示例代码还允许为png或jpg导出调整px大小和分辨率:
Canvas2Image.saveAsImage('fileName.png', canvas, 2000, 3000, 300, 'png');
-
import Url from './url';
import * as ChangeDpi from 'changeDPI';
export default class Canvas2Image {
static saveAsImage(fileName, canvas, width, height, dpi, type) {
type = this._fixType(type);
canvas = this._scaleCanvas(canvas, width, height);
let dataUrl = canvas.toDataURL(type);
let dataUrlWithDpi = ChangeDpi.changeDpiDataUrl(dataUrl, dpi)
dataUrlWithDpi = dataUrlWithDpi.replace(type, 'image/octet-stream');
Url.download(fileName, dataUrlWithDpi);
}
static _fixType(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
const r = type.match(/png|jpeg|bmp|gif/)[0];
return `image/${r}`;
}
static _scaleCanvas(canvas, width, height) {
const w = canvas.width;
const h = canvas.height;
if (width === undefined) {
width = w;
}
if (height === undefined) {
height = h;
}
const retCanvas = document.createElement('canvas');
const retCtx = retCanvas.getContext('2d');
retCanvas.width = width;
retCanvas.height = height;
retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);
return retCanvas;
}
}
-
export default class Url {
static download(fileName, url) {
const element = document.createElement('a');
element.setAttribute('href', url);
element.setAttribute('download', fileName);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
static createUrlForBlob(blob) {
return this._URL.createObjectURL(blob);
}
static clearBlobUrl(blobUrl) {
this._URL.revokeObjectURL(blobUrl);
}
static get _URL() {
return window.URL || window.webkitURL || window;
}
}