Added getImageSize and getImageBlob and resize now draws a white background before resizing to prevent black backgrounds with transparent images.

This commit is contained in:
Matt Mo 2021-02-03 10:06:34 -08:00
parent f73ba6f0c2
commit 9b24fd186c

View File

@ -1,6 +1,73 @@
class Aperture { class Aperture {
/** /**
* * Gets a blob from an image and returns it.
* @param {String|HTMLImageElement} image The image to create a blob from.
* @returns {Blob} returns a blob containing the image data.
*/
static async getImageBlob(image) {
var img = image;
//If the image passed was not an image element then create one.
if (!(img instanceof HTMLImageElement)) {
//Create an image and wait for it to load.
img = new Image();
var promise = new Promise(resolve => {
img.onload = () => resolve();
img.onerror = () => resolve();
});
img.src = image;
await promise;
}
//Setup a canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
//Clear the canvas to white.
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//Draw the image onto the canvas
ctx.drawImage(img, 0, 0, img.width, img.height);
//Get a blob from the canvas.
var promise = new Promise(resolve => {
canvas.toBlob(blob => resolve(blob), 'image/jpeg', 0.95);
});
//Await the creation of the blob and return it.
return await promise;
}
/**
* Gets an images actual size and returns it.
* @param {String|HTMLImageElement} image The image to get the size of.
* @returns {Object} returns an object containing the width and height of the image.
*/
static async getImageSize(image) {
var img = image;
if (!(img instanceof HTMLImageElement)) {
//Create an image and wait for it to load.
img = new Image();
var promise = new Promise(resolve => {
img.onload = () => resolve();
img.onerror = () => resolve();
});
img.src = image;
await promise;
return { width: img.width, height: img.height };
} else {
return { width: img.naturalWidth, height: img.naturalHeight };
}
}
/**
* Resizes an image to a new width and returns the new image as a blob.
* @param {String|HTMLImageElement} image The image to resize, this can be a image element or url, or base64. * @param {String|HTMLImageElement} image The image to resize, this can be a image element or url, or base64.
* @param {Number} newWidth The new width of the image in pixels. * @param {Number} newWidth The new width of the image in pixels.
* @param {Number} sharpen The sharpen level to apply to the result, from 0 to 1.0. Defaults to 0.5 * @param {Number} sharpen The sharpen level to apply to the result, from 0 to 1.0. Defaults to 0.5
@ -15,8 +82,7 @@ class Aperture {
var img = image; var img = image;
//If the image passed was not an image element then create one. //If the image passed was not an image element then create one.
if (!(img instanceof HTMLImageElement)) if (!(img instanceof HTMLImageElement)) {
{
//Create an image and wait for it to load. //Create an image and wait for it to load.
img = new Image(); img = new Image();
var promise = new Promise(resolve => { var promise = new Promise(resolve => {
@ -36,6 +102,12 @@ class Aperture {
oc.width = currWidth; oc.width = currWidth;
oc.height = currHeight; oc.height = currHeight;
//Clear the resize canvas and final canvas to white.
octx.fillStyle = "white";
octx.fillRect(0, 0, oc.width, oc.height);
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//Resize the image. //Resize the image.
octx.drawImage(img, 0, 0, currWidth, currHeight); octx.drawImage(img, 0, 0, currWidth, currHeight);
@ -59,7 +131,7 @@ class Aperture {
dstBuff = dstData.data, dstBuff = dstData.data,
srcBuff = ctx.getImageData(0, 0, w, h).data, srcBuff = ctx.getImageData(0, 0, w, h).data,
y = h; y = h;
while (y--) { while (y--) {
x = w; x = w;
while (x--) { while (x--) {
@ -70,16 +142,16 @@ class Aperture {
g = 0; g = 0;
b = 0; b = 0;
a = 0; a = 0;
for (cy = 0; cy < katet; cy++) { for (cy = 0; cy < katet; cy++) {
for (cx = 0; cx < katet; cx++) { for (cx = 0; cx < katet; cx++) {
scy = sy + cy - half; scy = sy + cy - half;
scx = sx + cx - half; scx = sx + cx - half;
if (scy >= 0 && scy < h && scx >= 0 && scx < w) { if (scy >= 0 && scy < h && scx >= 0 && scx < w) {
srcOff = (scy * w + scx) * 4; srcOff = (scy * w + scx) * 4;
wt = weights[cy * katet + cx]; wt = weights[cy * katet + cx];
r += srcBuff[srcOff] * wt; r += srcBuff[srcOff] * wt;
g += srcBuff[srcOff + 1] * wt; g += srcBuff[srcOff + 1] * wt;
b += srcBuff[srcOff + 2] * wt; b += srcBuff[srcOff + 2] * wt;
@ -87,14 +159,14 @@ class Aperture {
} }
} }
} }
dstBuff[dstOff] = r * sharpen + srcBuff[dstOff] * (1 - sharpen); dstBuff[dstOff] = r * sharpen + srcBuff[dstOff] * (1 - sharpen);
dstBuff[dstOff + 1] = g * sharpen + srcBuff[dstOff + 1] * (1 - sharpen); dstBuff[dstOff + 1] = g * sharpen + srcBuff[dstOff + 1] * (1 - sharpen);
dstBuff[dstOff + 2] = b * sharpen + srcBuff[dstOff + 2] * (1 - sharpen); dstBuff[dstOff + 2] = b * sharpen + srcBuff[dstOff + 2] * (1 - sharpen);
dstBuff[dstOff + 3] = srcBuff[dstOff + 3]; dstBuff[dstOff + 3] = srcBuff[dstOff + 3];
} }
} }
//Put the sharpened image back onto the canvas. //Put the sharpened image back onto the canvas.
ctx.putImageData(dstData, 0, 0); ctx.putImageData(dstData, 0, 0);
@ -110,6 +182,6 @@ class Aperture {
window.Aperture = Aperture; window.Aperture = Aperture;
export { export {
Aperture Aperture
} }