diff --git a/app/assets/javascripts/discourse/app/lib/media-optimization-utils.js b/app/assets/javascripts/discourse/app/lib/media-optimization-utils.js index b67424f4c46..2d18cbf98fe 100644 --- a/app/assets/javascripts/discourse/app/lib/media-optimization-utils.js +++ b/app/assets/javascripts/discourse/app/lib/media-optimization-utils.js @@ -1,12 +1,10 @@ import { Promise } from "rsvp"; -export async function fileToImageData(file) { - let drawable, err; - - // Chrome and Firefox use a native method to do Image -> Bitmap Array (it happens of the main thread!) - // Safari uses the `` element due to https://bugs.webkit.org/show_bug.cgi?id=182424 +// Chrome and Firefox use a native method to do Image -> Bitmap Array (it happens of the main thread!) +// Safari uses the `` element due to https://bugs.webkit.org/show_bug.cgi?id=182424 +async function fileToDrawable(file) { if ("createImageBitmap" in self) { - drawable = await createImageBitmap(file); + return await createImageBitmap(file); } else { const url = URL.createObjectURL(file); const img = new Image(); @@ -26,38 +24,55 @@ export async function fileToImageData(file) { // Always await loaded, as we may have bailed due to the Safari bug above. await loaded; - - drawable = img; + return img; } +} +function drawableToimageData(drawable) { const width = drawable.width, height = drawable.height, sx = 0, sy = 0, sw = width, sh = height; + // Make canvas same size as image const canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; + // Draw image onto canvas const ctx = canvas.getContext("2d"); if (!ctx) { - err = "Could not create canvas context"; + throw "Could not create canvas context"; } ctx.drawImage(drawable, sx, sy, sw, sh, 0, 0, width, height); const imageData = ctx.getImageData(0, 0, width, height); canvas.remove(); + return imageData; +} - // potentially transparent - if (/(\.|\/)(png|webp)$/i.test(file.type)) { - for (let i = 0; i < imageData.data.length; i += 4) { - if (imageData.data[i + 3] < 255) { - err = "Image has transparent pixels, won't convert to JPEG!"; - break; - } +function isTransparent(type, imageData) { + if (!/(\.|\/)(png|webp)$/i.test(type)) { + return false; + } + + for (let i = 0; i < imageData.data.length; i += 4) { + if (imageData.data[i + 3] < 255) { + return true; } } - return { imageData, width, height, err }; + return false; +} + +export async function fileToImageData(file) { + const drawable = await fileToDrawable(file); + const imageData = drawableToimageData(drawable); + + if (isTransparent(file.type, imageData)) { + throw "Image has transparent pixels, won't convert to JPEG!"; + } + + return imageData; } diff --git a/app/assets/javascripts/discourse/app/services/media-optimization-worker.js b/app/assets/javascripts/discourse/app/services/media-optimization-worker.js index 24069246fab..f108061ad7b 100644 --- a/app/assets/javascripts/discourse/app/services/media-optimization-worker.js +++ b/app/assets/javascripts/discourse/app/services/media-optimization-worker.js @@ -54,10 +54,11 @@ export default class MediaOptimizationWorkerService extends Service { this.currentComposerUploadData = data; this.currentPromiseResolver = resolve; - const { imageData, width, height, err } = await fileToImageData(file); - - if (err) { - this.logIfDebug(err); + let imageData; + try { + imageData = await fileToImageData(file); + } catch (error) { + this.logIfDebug(error); return resolve(data); } @@ -66,8 +67,8 @@ export default class MediaOptimizationWorkerService extends Service { type: "compress", file: imageData.data.buffer, fileName: file.name, - width: width, - height: height, + width: imageData.width, + height: imageData.height, settings: { mozjpeg_script: getURLWithCDN( "/javascripts/squoosh/mozjpeg_enc.js" @@ -102,8 +103,6 @@ export default class MediaOptimizationWorkerService extends Service { registerMessageHandler() { this.worker.onmessage = (e) => { - this.logIfDebug("Main: Message received from worker script"); - this.logIfDebug(e); switch (e.data.type) { case "file": let optimizedFile = new File([e.data.file], `${e.data.fileName}`, { diff --git a/public/javascripts/media-optimization-worker.js b/public/javascripts/media-optimization-worker.js index 7bbdf137bd5..7bd196854c2 100644 --- a/public/javascripts/media-optimization-worker.js +++ b/public/javascripts/media-optimization-worker.js @@ -81,6 +81,7 @@ async function optimize(imageData, fileName, width, height, settings) { ).data; width = target_dimensions.width; height = target_dimensions.height; + logIfDebug(`Worker post resizing file: ${maybeResized.byteLength}`); } catch (error) { console.error(`Resize failed: ${error}`); maybeResized = imageData;