我需要一种在不使用HTML元素的情况下使用JavaScript调整图片大小的方法。
我的移动端HTML应用程序捕获照片,然后将它们转换为base64字符串。最后,在将它们发送到API之前,我想要调整它们的大小。
我正在寻找一种不同且更合适的调整大小方法,而不是使用canvas元素,有什么方法吗?
我需要一种在不使用HTML元素的情况下使用JavaScript调整图片大小的方法。
我的移动端HTML应用程序捕获照片,然后将它们转换为base64字符串。最后,在将它们发送到API之前,我想要调整它们的大小。
我正在寻找一种不同且更合适的调整大小方法,而不是使用canvas元素,有什么方法吗?
避免主要的HTML受到影响的方法是创建一个不在DOM树中的离屏画布。
这将提供一个位图缓冲区和本地编译代码来编码图像数据。这很容易实现:
function imageToDataUri(img, width, height) {
// create an off-screen canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
// encode image to data-uri with base64 version of compressed image
return canvas.toDataURL();
}
return canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
toDataURL()
。var img = new Image;
img.onload = resizeImage;
img.src = originalDataUriHere;
function resizeImage() {
var newDataUri = imageToDataUri(this, targetWidth, targetHeight);
// continue from here...
}
如果源码是纯base-64字符串,只需添加一个头部即可将其转换为数据URI:
function base64ToDataUri(base64) {
return 'data:image/png;base64,' + base64;
}
只需替换image/png
部分为base64字符串所代表的类型(即将其作为可选参数)。
Ken的答案是正确的,但他的代码无法运行。我对其进行了一些调整,现在它可以完美地工作了。要调整 Data URI 的大小:
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight)
{
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
/////////////////////////////////////////
// Use and treat your Data URI here !! //
/////////////////////////////////////////
};
// We put the Data URI in the image's src attribute
img.src = datas;
}
// Use it like that : resizedataURL('yourDataURIHere', 50, 50);
var newDataUri = await resizedataURL(datas,600,600);
这将在进行下一步之前等待函数的结果。这是编写代码的更清晰的方式。这是来自Pierrick的函数,稍作修改:
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight){
return new Promise(async function(resolve,reject){
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
// This is the return of the Promise
resolve(dataURI);
};
// We put the Data URI in the image's src attribute
img.src = datas;
})
}// Use it like : var newDataURI = await resizedataURL('yourDataURIHere', 50, 50);
如需更多详细信息,请查看 MDN 文档: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise
img.onerror = reject;
以在所有情况下都履行承诺。 - Thomas KekeisenJpg-js和Pica完全不使用DOM元素。这些库仅使用图像数据,而不使用DOM元素(画布和图像)。
这种方法适用于浏览器端和Node.js。我只在浏览器端使用它,它是一个能够调整高分辨率图片(6000x6000像素及以上)大小的上传工具。我的上一个建议(作为Chris)被认为没有回答问题,因为它使用了canvas。因为canvas太明显了。
如果不将图像加载到内存中进行操作,就无法完成此操作。为什么不使用类似jimp的库呢?
import Jimp from "jimp";
async function resizeBase64Image(base64: string, targetWidth: number, targetHeight: number): Promise<string> {
// Decode the base64 image data and save it to a buffer
const imageBuffer = Buffer.from(base64, "base64");
// Use Jimp to load the image from the buffer and resize it
const image = await Jimp.read(imageBuffer);
image.resize(targetWidth, targetHeight);
// Convert the image back to a base64 data URI
const resizedImageBase64 = await image.getBase64Async(Jimp.MIME_PNG);
return resizedImageBase64;
}
function base64Resize(sourceBase64, scale , callBack) {
const _scale = scale;
var img = document.createElement('img');
img.setAttribute("src", sourceBase64);
img.onload = () => {
var canvas = document.createElement('canvas');
canvas.width = img.width * _scale;
canvas.height = img.height * _scale;
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var maxW = img.width * _scale;
var maxH = img.height * _scale;
var iw = img.width;
var ih = img.height;
var scl = Math.min((maxW / iw), (maxH / ih));
var iwScaled = iw * scl;
var ihScaled = ih * scl;
canvas.width = iwScaled;
canvas.height = ihScaled;
ctx.drawImage(img, 0, 0, iwScaled, ihScaled);
const newBase64 = canvas.toDataURL("image/jpeg", scl);
callBack(newBase64);
}
}
重要的一点是你应该使用img.onload
事件。
base64Resize("data:image/png;base64,iVBO...", 0.5, function(resizedImage){ // resizedImage 是调整大小后的 base64 图像变量 });
。但这不是必需的。如果你不想要它,从参数列表中删除 callBack
并删除 callBack(newBase64);
行 :) - Pridconst resizeBase64Image = (base64: string, width: number, height: number): Promise<string> => {
// Create a canvas element
const canvas = document.createElement('canvas') as HTMLCanvasElement;
// Create an image element from the base64 string
const image = new Image();
image.src = base64;
// Return a Promise that resolves when the image has loaded
return new Promise((resolve, reject) => {
image.onload = () => {
// Calculate the aspect ratio of the image
const aspectRatio = image.width / image.height;
// Calculate the best fit dimensions for the canvas
if (width / height > aspectRatio) {
canvas.width = height * aspectRatio;
canvas.height = height;
} else {
canvas.width = width;
canvas.height = width / aspectRatio;
}
// Draw the image to the canvas
canvas.getContext('2d')!.drawImage(image, 0, 0, canvas.width, canvas.height);
// Resolve the Promise with the resized image as a base64 string
resolve(canvas.toDataURL());
};
image.onerror = reject;
});
};
然后就像这样简单地等待它:
const resizedImage: string = await resizeBase64Image(base64, 100, 100);
function resizeImage(base64Str) {
var img = new Image();
img.src = base64Str;
var canvas = document.createElement('canvas');
var MAX_WIDTH = 400;
var MAX_HEIGHT = 350;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL();
}
https://gist.github.com/ORESoftware/ba5d03f3e1826dc15d5ad2bcec37f7bf