From ca609a0fa5edbbeb31da90b37535bc6c09eb45a1 Mon Sep 17 00:00:00 2001 From: Lu Wilson Date: Tue, 17 Oct 2023 13:54:40 +0100 Subject: [PATCH] Fix not being able to upload massive images (#2095) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes a case where you couldn't upload images that are bigger than the browser's max canvas size. It does this by resizing them down if they're too big. ### Change Type - [x] `patch` — Bug fix ### Test Plan Easiest to test on one of our iPads. 1. Take a photo with the iPad camera. (they're big photos) 2. Insert the photo to the canvas with the 'insert media' tool. 3. It should appear on the canvas! (You might want to double check that your photo *doesn't* successfully upload on staging, to make sure it's big enough) - [ ] Unit Tests - [ ] End to end tests ### Release Notes - Fixed big images being too big to get added to the canvas. --- packages/tldraw/src/lib/utils/assets.ts | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/tldraw/src/lib/utils/assets.ts b/packages/tldraw/src/lib/utils/assets.ts index 0e905dda9..3c5ef99f6 100644 --- a/packages/tldraw/src/lib/utils/assets.ts +++ b/packages/tldraw/src/lib/utils/assets.ts @@ -1,3 +1,4 @@ +import { getBrowserCanvasMaxSize } from '../shapes/shared/getBrowserCanvasMaxSize' import { isAnimated } from './is-gif-animated' type BoxWidthHeight = { @@ -50,16 +51,37 @@ export async function getResizedImageDataUrl( ): Promise { return await new Promise((resolve) => { const img = new Image() - img.onload = () => { + img.onload = async () => { // Initialize the canvas and it's size const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') if (!ctx) return - // Set width and height - canvas.width = width * 2 - canvas.height = height * 2 + const canvasSizes = await getBrowserCanvasMaxSize() + + let desiredWidth = width * 2 + let desiredHeight = height * 2 + const aspectRatio = img.width / img.height + + if (desiredWidth > canvasSizes.maxWidth) { + desiredWidth = canvasSizes.maxWidth + desiredHeight = desiredWidth / aspectRatio + } + + if (desiredHeight > canvasSizes.maxHeight) { + desiredHeight = canvasSizes.maxHeight + desiredWidth = desiredHeight * aspectRatio + } + + if (desiredWidth * desiredHeight > canvasSizes.maxArea) { + const ratio = Math.sqrt(canvasSizes.maxArea / (desiredWidth * desiredHeight)) + desiredWidth *= ratio + desiredHeight *= ratio + } + + canvas.width = desiredWidth + canvas.height = desiredHeight // Draw image and export to a data-uri ctx.drawImage(img, 0, 0, canvas.width, canvas.height)