Last active
March 10, 2022 09:11
-
-
Save turbotobias/b4c30eb117a3778677a454ba79fbb33c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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<HTMLImageElement>() | |
| const imageUpload = ref<HTMLInputElement>() | |
| 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<File | void>((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!) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment