From 192ff0757d649df552c988674ddb2e175da4c951 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Sat, 9 Oct 2021 16:32:34 -0500 Subject: [PATCH] Allow selecting webp images --- src/components/sprite-selector/sprite-selector.jsx | 2 +- src/components/stage-selector/stage-selector.jsx | 2 +- src/containers/costume-tab.jsx | 2 +- src/lib/bmp-converter.js | 8 ++++---- src/lib/file-uploader.js | 9 +++++++++ 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/components/sprite-selector/sprite-selector.jsx b/src/components/sprite-selector/sprite-selector.jsx index 7daecde55..a3d3c2477 100644 --- a/src/components/sprite-selector/sprite-selector.jsx +++ b/src/components/sprite-selector/sprite-selector.jsx @@ -120,7 +120,7 @@ const SpriteSelectorComponent = function (props) { title: intl.formatMessage(messages.addSpriteFromFile), img: fileUploadIcon, onClick: onFileUploadClick, - fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .sprite2, .sprite3, .gif', + fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .webp, .sprite2, .sprite3, .gif', fileChange: onSpriteUpload, fileInput: spriteFileInput, fileMultiple: true diff --git a/src/components/stage-selector/stage-selector.jsx b/src/components/stage-selector/stage-selector.jsx index fdc9f28b9..62652259c 100644 --- a/src/components/stage-selector/stage-selector.jsx +++ b/src/components/stage-selector/stage-selector.jsx @@ -102,7 +102,7 @@ const StageSelector = props => { title: intl.formatMessage(messages.addBackdropFromFile), img: fileUploadIcon, onClick: onBackdropFileUploadClick, - fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .gif', + fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .webp, .gif', fileChange: onBackdropFileUpload, fileInput: fileInputRef, fileMultiple: true diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 12fa047c5..fdfd32e8b 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -283,7 +283,7 @@ class CostumeTab extends React.Component { title: intl.formatMessage(addFileMessage), img: fileUploadIcon, onClick: this.handleFileUploadClick, - fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .gif', + fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .jfif, .webp, .gif', fileChange: this.handleCostumeUpload, fileInput: this.setFileInput, fileMultiple: true diff --git a/src/lib/bmp-converter.js b/src/lib/bmp-converter.js index fc33666b5..43e2434ad 100644 --- a/src/lib/bmp-converter.js +++ b/src/lib/bmp-converter.js @@ -1,10 +1,10 @@ -export default bmpImage => new Promise(resolve => { +export default (bmpImage, type = 'image/bmp') => new Promise(resolve => { // If the input is an ArrayBuffer, we need to convert it to a `Blob` and give it a URL so we can use it as an // `src`. If it's a data URI, we can use it as-is. const imageUrl = bmpImage instanceof String ? bmpImage : - window.URL.createObjectURL(new Blob([bmpImage], {type: 'image/bmp'})); - + window.URL.createObjectURL(new Blob([bmpImage], {type})); + const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); @@ -16,7 +16,7 @@ export default bmpImage => new Promise(resolve => { ctx.drawImage(image, 0, 0); const dataUrl = canvas.toDataURL('image/png'); - + // Revoke URL. If a blob URL was generated earlier, this allows the blob to be GC'd and prevents a memory leak. window.URL.revokeObjectURL(imageUrl); diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index 9299323fa..7aba5b585 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -127,6 +127,14 @@ const costumeUpload = function (fileData, fileType, storage, handleCostume, hand assetType = storage.AssetType.ImageBitmap; break; } + case 'image/webp': { + // Scratch does not natively support webp, so convert to png + // see image/bmp logic above + bmpConverter(fileData, 'image/webp').then(dataUrl => { + costumeUpload(dataUrl, 'image/png', storage, handleCostume); + }); + return; + } case 'image/gif': { let costumes = []; gifDecoder(fileData, (frameNumber, dataUrl, numFrames) => { @@ -222,6 +230,7 @@ const spriteUpload = function (fileData, fileType, spriteName, storage, handleSp case 'image/png': case 'image/bmp': case 'image/jpeg': + case 'image/webp': case 'image/gif': { // Make a sprite from an image by making it a costume first costumeUpload(fileData, fileType, storage, vmCostumes => {