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.crossOrigin = "Anonymous"; 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.crossOrigin = "Anonymous"; 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 {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 * @returns {Blob} returns the resized image as a new blob. */ static async resizeImage(image, newWidth, sharpen = 0.5) { var canvas = document.createElement('canvas'); var ctx = canvas.getContext("2d"); var oc = document.createElement('canvas'); var octx = oc.getContext('2d'); 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.crossOrigin = "Anonymous"; img.src = image; await promise; } canvas.width = newWidth; // destination canvas size canvas.height = canvas.width * img.height / img.width; var currWidth = Math.floor(img.width * 0.5); var currHeight = Math.floor(img.height * 0.5); oc.width = currWidth; 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. octx.drawImage(img, 0, 0, currWidth, currHeight); while (currWidth * 0.5 > newWidth) { currWidth = Math.floor(currWidth * 0.5); currHeight = Math.floor(currHeight * 0.5); octx.drawImage(oc, 0, 0, currWidth * 2, currHeight * 2, 0, 0, currWidth, currHeight); } //Put the final resized image onto the dest canvas. ctx.drawImage(oc, 0, 0, currWidth, currHeight, 0, 0, canvas.width, canvas.height); //Now sharpen the resized image var w = canvas.width, h = canvas.height; var x, sx, sy, r, g, b, a, dstOff, srcOff, wt, cx, cy, scy, scx, weights = [0, -1, 0, -1, 5, -1, 0, -1, 0], katet = Math.round(Math.sqrt(weights.length)), half = (katet * 0.5) | 0, dstData = ctx.createImageData(w, h), dstBuff = dstData.data, srcBuff = ctx.getImageData(0, 0, w, h).data, y = h; while (y--) { x = w; while (x--) { sy = y; sx = x; dstOff = (y * w + x) * 4; r = 0; g = 0; b = 0; a = 0; for (cy = 0; cy < katet; cy++) { for (cx = 0; cx < katet; cx++) { scy = sy + cy - half; scx = sx + cx - half; if (scy >= 0 && scy < h && scx >= 0 && scx < w) { srcOff = (scy * w + scx) * 4; wt = weights[cy * katet + cx]; r += srcBuff[srcOff] * wt; g += srcBuff[srcOff + 1] * wt; b += srcBuff[srcOff + 2] * wt; a += srcBuff[srcOff + 3] * wt; } } } dstBuff[dstOff] = r * sharpen + srcBuff[dstOff] * (1 - sharpen); dstBuff[dstOff + 1] = g * sharpen + srcBuff[dstOff + 1] * (1 - sharpen); dstBuff[dstOff + 2] = b * sharpen + srcBuff[dstOff + 2] * (1 - sharpen); dstBuff[dstOff + 3] = srcBuff[dstOff + 3]; } } //Put the sharpened image back onto the canvas. ctx.putImageData(dstData, 0, 0); //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; } } window.Aperture = Aperture; export { Aperture }