// you might have to do something in webpack to enable wasm/photon import initPhoton, { resize as photon__resize, open_image as photon__open_image, putImageData as photon__put_image_data, } from "photon-web" const image = ref() const imageUpload = ref() const storageImageUrl = ref("") const lqip = ref("") const allowedMimeTypes = ["image/png", "image/jpg", "image/webp", "image/jpeg", "image/gif", "image/svg"] const resize = async (file: File, maxSize: number = 1200) => { return new Promise((resolve, reject) => { try { // prepare File that is an image for being drawn onto canvas const reader = new FileReader() reader.readAsDataURL(file) // get the image from FileReader reader.onloadend = (e) => { const imageFromFileReader = e.target?.result if (typeof imageFromFileReader !== "string" || !imageFromFileReader) { return console.trace( "could not get image (string) from file reader when drawing image onto canvas", imageFromFileReader, ) } // put the FileReader image in an Image const image = new Image() image.src = imageFromFileReader // load the image onto a canvas image.onload = (ev) => { // create the canvas const canvasElement = document.createElement("canvas") if (!canvasElement) { throw Error("could not get canvas element") } // set original dimensions () canvasElement.width = image.width canvasElement.height = image.height // draw image onto canvas const canvasContext = canvasElement.getContext("2d") canvasContext?.drawImage(image, 0, 0) // @todo use as backup // get image (as base64 string) in jpeg format // const imageBase64Jpeg = canvasElement.toDataURL("image/jpg", 100) // shouldLog && console.log("image base 64 from canvas element", imageBase64Jpeg) shouldLog && console.log("will photon.open_image canvasElement", canvasElement) shouldLog && console.log("will photon.open_image canvasContext", canvasContext) if (!canvasContext) throw Error("could not create canvas context for photon") initPhoton() .then((photon) => { // set max image size (after compression) let imageSizeReducedByPercentage: number = 0 // 0.1 = 10% let imageNewWidth = image.width let imageNewHeight = image.height // image is large, reduce max size while maintaining aspect ratio if (image.width > maxSize || image.height > maxSize) { // image width is the basis for resize if (image.width > image.height) { imageSizeReducedByPercentage = Number((maxSize / image.width).toFixed(2)) console.log(`image width will be reduced to ${imageSizeReducedByPercentage}%`) } // image height is the basis for resize else if (image.height > image.width) { imageSizeReducedByPercentage = Number((maxSize / image.height).toFixed(2)) console.log(`image height will be reduced to ${imageSizeReducedByPercentage}%`) } // set reduced image size imageNewWidth = image.height * imageSizeReducedByPercentage imageNewHeight = image.height * imageSizeReducedByPercentage } // Convert the ImageData found in the canvas to a PhotonImage (so that it can communicate with the core Rust library) let image_photon = photon__open_image(canvasElement, canvasContext) // resize the image using rust over wasm ⚡ console.log(`should resize image to ${imageNewWidth}`) const image_resized = photon__resize(image_photon, imageNewWidth, imageNewHeight, 1) const { height, width } = image_resized.get_image_data() canvasElement.height = height canvasElement.width = width console.log(`new image size ${imageNewWidth}`) // place the smaller image back on the smaller canvas photon__put_image_data(canvasElement, canvasContext, image_resized) canvasElement.toBlob(async (blob) => { if (!blob) throw Error("could not convert canvas to blob") const fileImage = new File([blob], file.name, { type: "image/jpeg" }) resolve(fileImage) }, "image/jpeg") }) .catch((error) => { console.trace("could not resize image with photon", error) reject(error) }) } } } catch (error) { console.trace("could not reduce file image size with wasm+photon") reject(error) } }) } const dropHandler = (ev: DragEvent) => { shouldLog && console.log("drop handler dataTransfer.items.length: ", ev.dataTransfer?.items?.length) if (props.field?.disabled) return let file: File | null = null const dataTransfer = ev.dataTransfer as DataTransfer if (dataTransfer.items) { const dataTransferItemList = dataTransfer.items as DataTransferItemList for (let i = 0; i < dataTransferItemList.length; i++) { // If dropped items aren't files, reject them if (dataTransferItemList[i].kind === "file") { file = dataTransferItemList[i].getAsFile() shouldLog && console.log("... file[" + i + "].name = " + file?.name) } } } else { const dataTransferItemList = dataTransfer.files as FileList for (let i = 0; i < dataTransferItemList.length; i++) { shouldLog && console.log("... file[" + i + "].name = " + dataTransferItemList[i].name) file = dataTransferItemList[i] } } dropToUpload.value = false const imageFormatIsAccepted = (type: string) => { const isValidType = allowedMimeTypes.includes(type) return isValidType } if (!imageFormatIsAccepted(file?.type || "")) return uploadImage(file!) }