diff --git a/web/vue-app/src/components/ImagePicker.vue b/web/vue-app/src/components/ImagePicker.vue index 4202318..4f5b86f 100644 --- a/web/vue-app/src/components/ImagePicker.vue +++ b/web/vue-app/src/components/ImagePicker.vue @@ -34,20 +34,24 @@ const addFromLocal = () => { fileInput.value?.click() } -const onFileChange = (event: Event) => { +const onFileChange = async (event: Event) => { const files = (event.target as HTMLInputElement).files if (files && files.length > 0) { const file = files[0] if (localImageUrl.value) URL.revokeObjectURL(localImageUrl.value) - const url = URL.createObjectURL(file) + const { blob, url } = await resizeImageFile(file, 512) localImageUrl.value = url const idx = availableImages.value.findIndex((img) => img.id === 'local-upload') if (idx === -1) { - availableImages.value.unshift({ id: 'local-upload', url }) // <-- use unshift + availableImages.value.unshift({ id: 'local-upload', url }) } else { availableImages.value[idx].url = url } - emit('add-image', { id: 'local-upload', url, file }) + emit('add-image', { + id: 'local-upload', + url, + file: new File([blob], file.name, { type: 'image/png' }), + }) emit('update:modelValue', 'local-upload') } } @@ -90,36 +94,15 @@ const takePhoto = async () => { const confirmPhoto = async () => { if (capturedImageUrl.value) { if (localImageUrl.value) URL.revokeObjectURL(localImageUrl.value) - const img = new window.Image() - img.src = capturedImageUrl.value - await new Promise((resolve) => { - img.onload = resolve - }) - let { width, height } = img - const maxDim = 512 - if (width > maxDim || height > maxDim) { - if (width > height) { - height = Math.round((height * maxDim) / width) - width = maxDim - } else { - width = Math.round((width * maxDim) / height) - height = maxDim - } - } - const canvas = document.createElement('canvas') - canvas.width = width - canvas.height = height - const ctx = canvas.getContext('2d') - ctx?.drawImage(img, 0, 0, width, height) - const blob: Blob = await new Promise((resolve) => - canvas.toBlob((b) => resolve(b!), 'image/png'), - ) - const url = URL.createObjectURL(blob) + // Convert dataURL to Blob + const res = await fetch(capturedImageUrl.value) + const originalBlob = await res.blob() + const { blob, url } = await resizeImageFile(originalBlob, 512) localImageUrl.value = url cameraFile.value = new File([blob], 'camera.png', { type: 'image/png' }) const idx = availableImages.value.findIndex((img) => img.id === 'local-upload') if (idx === -1) { - availableImages.value.unshift({ id: 'local-upload', url }) // <-- use unshift + availableImages.value.unshift({ id: 'local-upload', url }) } else { availableImages.value[idx].url = url } @@ -190,6 +173,37 @@ onMounted(async () => { loadingImages.value = false } }) + +async function resizeImageFile( + file: File | Blob, + maxDim = 512, +): Promise<{ blob: Blob; url: string }> { + const img = new window.Image() + const url = URL.createObjectURL(file) + img.src = url + await new Promise((resolve) => { + img.onload = resolve + }) + + let { width, height } = img + if (width > maxDim || height > maxDim) { + if (width > height) { + height = Math.round((height * maxDim) / width) + width = maxDim + } else { + width = Math.round((width * maxDim) / height) + height = maxDim + } + } + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + const ctx = canvas.getContext('2d') + ctx?.drawImage(img, 0, 0, width, height) + const blob: Blob = await new Promise((resolve) => canvas.toBlob((b) => resolve(b!), 'image/png')) + URL.revokeObjectURL(url) + return { blob, url: URL.createObjectURL(blob) } +}