From 812e727de0e282d7a329586c6ac07f869d3620a8 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 22 Sep 2020 14:40:27 +0100 Subject: [PATCH] Integrate rotate --- codecs/rotate/rotate.wasm | Bin 1377 -> 1370 bytes src/client/index.tsx | 9 +-- .../rotate/worker/missing-types.d.ts | 13 ++++ .../preprocessors/rotate/worker/rotate.ts | 63 ++++++++++++++++++ .../preprocessors/rotate/worker/tsconfig.json | 7 ++ 5 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 src/features/preprocessors/rotate/worker/missing-types.d.ts create mode 100644 src/features/preprocessors/rotate/worker/rotate.ts create mode 100644 src/features/preprocessors/rotate/worker/tsconfig.json diff --git a/codecs/rotate/rotate.wasm b/codecs/rotate/rotate.wasm index a03bb89d57a2eb2e40ff8b350c008882e7ce47bb..f5d66ec428409514d1e7352ad8cb609791cbe41b 100755 GIT binary patch literal 1370 zcmaiz&2G~`5XWbC?e)jTN!o-{gf#0D99o4^RXxUswu)#~1P>5QV?b{Dm86GCNbVEx z5WE6B0B^t@@hPYYm~D3pjlM*g9Y z6%&hDO4$$m)K#jyQ5IUkl*wflmX_4WMLd$UBQa)PxpHD4mYFD1$!eUCG3Kih{R$Cs zY1itcEtdn4>uMyMhrLW(?Rg_sERGZGMG70Xgu$#+CriUbuw*e#{XNVCJl&GR0cQTd zhAgczjTOZa_-tSk1XT;$<8@5r^3?V-vOeB+U7Fjjrq47^L?*1)(gqTJm)NiC`r|Yh zz$Othz*Yot;8w@;#CQ7qR64D`fvXMq$#Ft19y!tuCY|vBm9ci^A8-#6<*c*;_uULz zXYiCZVrApioyN0Nvn*53sUX%RBh7dKqc`Rj>+w8M?6E$8au0i5Hw-_pngiSA$a=`q zLT=RW9wk0PP17Zh*GkAY?(Pli?0uPP*CGzG$|;Iqfslk_*TDDyz7~-o)4|K3RrTtn z5S3hY-$}>u!xEf?`}Mg?mxOS|0y=QQee{aZ{;+IR&?>++2s%>Xsu=TKi5`%1I=Yz) zceiyH7aa0`xJ37HiT;L5)Zh~R1DBeU()Joobi;{m@ca)dpz%H`!1C{?=s!?tV`KX+ zDt-4UxNN7OC0udSb&C}(F=#QkUt%*$f#Yvlf|8L5v;;LRK|@P$mln-^bUU;ijvHD! zEKbu-O^d!yi*~etEk{e>dIiokhpX=spuib}7+A~H{6S3giVB$6)RX$frT!?ANiko@aF(CHz0Thj!h3PO ySW*kFlVY(brW>zsgg=Mv}SAO8gA-^j)Q literal 1377 zcmaKr!EPHj5QfPixmszp(%N!PLV+Pq>A{8^1aXhvgKaFDz(M-}iehh5tmQb7)5VdPR;azlSbLIC+U25MOCK)V} zBqrI{F;&4#5p&Q?u@oXUGCE)7PW(}D;*~N?jbJ}N&z0zrBaG1*S5xeav26c{Ct?>1 zmccZ>&wFez(f9#dpT#T9mLXx+1S2LCCk-P@HAT==JmjQWe(Qj8uy@&)&O z!UJ!R#hi%p1sp=zyQ>j$L1B2O@rX(RdR&yhHKC9?aldTE(Et(H!Eu_9aV|9+DwU~h zjE_@qyV1{Dw-gar!bBk004(WgJUlg$MB$z_+@NZwD3}5RX|pw>qClzyA3>i*Qob5J z0e9k~C`B$;_K+DI^}m=g9W&;h8PhRi9x!7&X5y_zW^Bid5oRR%fSKKGQ6@Nm#YbCM z=$_GUd5IuKP7~pjgqI}p0*rCVB%?cCY)HhX6<+X0?s!SW!UzjT9WO~dJn(?Mf|ILd zAgRs-Tz0&ee|d4JEGiIraSbC2coB3#fs4ElJK;svcD(HQF?ey{1&3o2UR>mb?s;*n zub?2|1<{U|vG6jMYDN2fIf^g?nEr-9L9Kf7j2&(Fq diff --git a/src/features/preprocessors/rotate/worker/rotate.ts b/src/features/preprocessors/rotate/worker/rotate.ts new file mode 100644 index 00000000..a4491819 --- /dev/null +++ b/src/features/preprocessors/rotate/worker/rotate.ts @@ -0,0 +1,63 @@ +/** + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import wasmUrl from 'url:codecs/rotate/rotate.wasm'; + +export interface RotateOptions { + rotate: 0 | 90 | 180 | 270; +} + +export interface RotateModuleInstance { + exports: { + memory: WebAssembly.Memory; + rotate(width: number, height: number, rotate: 0 | 90 | 180 | 270): void; + }; +} + +// We are loading a 500B module here. Loading the code to feature-detect +// `instantiateStreaming` probably takes longer to load than the time we save by +// using `instantiateStreaming` in the first place. So let’s just use +// `ArrayBuffer`s here. +const instancePromise = fetch(wasmUrl) + .then((r) => r.arrayBuffer()) + .then((buf) => WebAssembly.instantiate(buf)); + +export default async function rotate( + data: ImageData, + opts: RotateOptions, +): Promise { + const instance = (await instancePromise).instance as RotateModuleInstance; + + // Number of wasm memory pages (á 64KiB) needed to store the image twice. + const bytesPerImage = data.width * data.height * 4; + const numPagesNeeded = Math.ceil((bytesPerImage * 2 + 8) / (64 * 1024)); + // Only count full pages, just to be safe. + const numPagesAvailable = Math.floor( + instance.exports.memory.buffer.byteLength / (64 * 1024), + ); + const additionalPagesToAllocate = numPagesNeeded - numPagesAvailable; + + if (additionalPagesToAllocate > 0) { + instance.exports.memory.grow(additionalPagesToAllocate); + } + const view = new Uint8ClampedArray(instance.exports.memory.buffer); + view.set(data.data, 8); + + instance.exports.rotate(data.width, data.height, opts.rotate); + + const flipDimensions = opts.rotate % 180 !== 0; + return new ImageData( + view.slice(bytesPerImage + 8, bytesPerImage * 2 + 8), + flipDimensions ? data.height : data.width, + flipDimensions ? data.width : data.height, + ); +} diff --git a/src/features/preprocessors/rotate/worker/tsconfig.json b/src/features/preprocessors/rotate/worker/tsconfig.json new file mode 100644 index 00000000..bea39d16 --- /dev/null +++ b/src/features/preprocessors/rotate/worker/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../../../generic-tsconfig.json", + "compilerOptions": { + "lib": ["webworker", "esnext"] + }, + "references": [{ "path": "../../../" }] +}