Compare commits

..

6 Commits

Author SHA1 Message Date
Surma
41f085438b Create my own memory 2019-01-24 16:33:03 -05:00
Surma
fdbc0932e4 Code review 2019-01-24 16:16:18 -05:00
Surma
2412e925ba Load wasm module 2019-01-24 15:21:34 -05:00
Surma
a676e1a2e9 Workaround asc build 2019-01-24 15:14:18 -05:00
Surma
a8265d5350 AssemblyScript version works 2019-01-24 15:12:48 -05:00
Surma
8f5c03e05b Add AssemblyScript implementation 2019-01-24 15:12:02 -05:00
28 changed files with 455 additions and 1466 deletions

1
.nvmrc
View File

@@ -1 +0,0 @@
v10.15.1

View File

@@ -1,4 +1,7 @@
language: node_js
node_js:
- node
- 10
- 8
cache: npm
script: npm run build
after_success: npm run sizereport

View File

@@ -1,2 +0,0 @@
target
Cargo.lock

View File

@@ -1,14 +0,0 @@
[package]
name = "rotate"
version = "0.1.0"
authors = ["Surma <surma@google.com>"]
edition = "2018"
[lib]
name = "rotate"
path = "rotate.rs"
crate-type = ["cdylib", "rlib"]
[profile.release]
lto = true
opt-level = "s"

View File

@@ -1,17 +0,0 @@
FROM ubuntu
RUN apt-get update && \
apt-get install -qqy git build-essential cmake python2.7
RUN git clone --recursive https://github.com/WebAssembly/wabt /usr/src/wabt
RUN mkdir -p /usr/src/wabt/build
WORKDIR /usr/src/wabt/build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=/opt/wabt && \
make && \
make install
FROM rust
RUN rustup install nightly && \
rustup target add --toolchain nightly wasm32-unknown-unknown
COPY --from=0 /opt/wabt /opt/wabt
ENV PATH="/opt/wabt/bin:${PATH}"
WORKDIR /src

View File

@@ -1,25 +0,0 @@
#!/bin/bash
set -e
echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
rustup run nightly \
cargo build \
--target wasm32-unknown-unknown \
--release
cp target/wasm32-unknown-unknown/release/rotate.wasm .
wasm-strip rotate.wasm
)
echo "============================================="
echo "Compiling wasm done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull ubuntu\`"
echo "Run \`docker pull rust\`"
echo "Run \`docker build -t squoosh-rotate .\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

124
codecs/rotate/package-lock.json generated Normal file
View File

@@ -0,0 +1,124 @@
{
"name": "rotate",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
"dev": true
},
"assemblyscript": {
"version": "github:AssemblyScript/assemblyscript#54b02c287c4d42092e4b01cc5d11bce1a53e9fb2",
"from": "github:AssemblyScript/assemblyscript",
"dev": true,
"requires": {
"@protobufjs/utf8": "^1.1.0",
"binaryen": "63.0.0-nightly.20190107",
"glob": "^7.1.3",
"long": "^4.0.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"binaryen": {
"version": "63.0.0-nightly.20190107",
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-63.0.0-nightly.20190107.tgz",
"integrity": "sha512-vck6ZESU9q6DeEK9v/Fk2O8d2jBsSrNlia8jpmdLZv5eqmNWpkNli+QMRa9Ezfb4wi3c+NVMuxT3Ck0g9GYe8A==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
},
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
}
}

View File

@@ -1,7 +1,9 @@
{
"name": "rotate",
"scripts": {
"build:image": "docker build -t squoosh-rotate .",
"build": "docker run --rm -v $(pwd):/src squoosh-rotate ./build.sh"
"build": "mv rotate.{as,ts} && asc rotate.ts -b rotate.wasm --validate -O3 --importMemory && mv rotate.{ts,as}"
},
"devDependencies": {
"assemblyscript": "github:AssemblyScript/assemblyscript"
}
}

64
codecs/rotate/rotate.as Normal file
View File

@@ -0,0 +1,64 @@
export function rotate(inputWidth: i32, inputHeight: i32, rotate: i32): void {
const bpp = 4;
let offset = inputWidth * inputHeight * bpp;
let i = 0;
// In the straight-copy case, d1 is x, d2 is y.
// x starts at 0 and increases.
// y starts at 0 and increases.
let d1Start = 0;
let d1Limit = inputWidth;
let d1Advance = 1;
let d1Multiplier = 1;
let d2Start = 0;
let d2Limit = inputHeight;
let d2Advance = 1;
let d2Multiplier = inputWidth;
if (rotate === 90) {
// d1 is y, d2 is x.
// y starts at its max value and decreases.
// x starts at 0 and increases.
d1Start = inputHeight - 1;
d1Limit = inputHeight;
d1Advance = -1;
d1Multiplier = inputWidth;
d2Start = 0;
d2Limit = inputWidth;
d2Advance = 1;
d2Multiplier = 1;
} else if (rotate === 180) {
// d1 is x, d2 is y.
// x starts at its max and decreases.
// y starts at its max and decreases.
d1Start = inputWidth - 1;
d1Limit = inputWidth;
d1Advance = -1;
d1Multiplier = 1;
d2Start = inputHeight - 1;
d2Limit = inputHeight;
d2Advance = -1;
d2Multiplier = inputWidth;
} else if (rotate === 270) {
// d1 is y, d2 is x.
// y starts at 0 and increases.
// x starts at its max and decreases.
d1Start = 0;
d1Limit = inputHeight;
d1Advance = 1;
d1Multiplier = inputWidth;
d2Start = inputWidth - 1;
d2Limit = inputWidth;
d2Advance = -1;
d2Multiplier = 1;
}
for (let d2 = d2Start; d2 >= 0 && d2 < d2Limit; d2 += d2Advance) {
let d2offset = d2 * d2Multiplier;
for (let d1 = d1Start; d1 >= 0 && d1 < d1Limit; d1 += d1Advance) {
let start = ((d1 * d1Multiplier) + d2offset);
store<u32>(offset + i * 4, load<u32>(start * 4));
i += 1;
}
}
}

View File

@@ -1,90 +0,0 @@
use std::slice::from_raw_parts_mut;
// This function is taken from
// https://rustwasm.github.io/book/reference/code-size.html
#[cfg(not(debug_assertions))]
#[inline]
pub fn unwrap_abort<T>(o: Option<T>) -> T {
use std::process;
match o {
Some(t) => t,
None => process::abort(),
}
}
// Normal panic-y behavior for debug builds
#[cfg(debug_assertions)]
unsafe fn unchecked_unwrap<T>(o: Option<T>) -> T {
o.unwrap()
}
#[no_mangle]
fn rotate(input_width: isize, input_height: isize, rotate: isize) {
let mut i = 0isize;
// In the straight-copy case, d1 is x, d2 is y.
// x starts at 0 and increases.
// y starts at 0 and increases.
let mut d1_start: isize = 0;
let mut d1_limit: isize = input_width;
let mut d1_advance: isize = 1;
let mut d1_multiplier: isize = 1;
let mut d2_start: isize = 0;
let mut d2_limit: isize = input_height;
let mut d2_advance: isize = 1;
let mut d2_multiplier: isize = input_width;
if rotate == 90 {
// d1 is y, d2 is x.
// y starts at its max value and decreases.
// x starts at 0 and increases.
d1_start = input_height - 1;
d1_limit = input_height;
d1_advance = -1;
d1_multiplier = input_width;
d2_start = 0;
d2_limit = input_width;
d2_advance = 1;
d2_multiplier = 1;
} else if rotate == 180 {
// d1 is x, d2 is y.
// x starts at its max and decreases.
// y starts at its max and decreases.
d1_start = input_width - 1;
d1_limit = input_width;
d1_advance = -1;
d1_multiplier = 1;
d2_start = input_height - 1;
d2_limit = input_height;
d2_advance = -1;
d2_multiplier = input_width;
} else if rotate == 270 {
// d1 is y, d2 is x.
// y starts at 0 and increases.
// x starts at its max and decreases.
d1_start = 0;
d1_limit = input_height;
d1_advance = 1;
d1_multiplier = input_width;
d2_start = input_width - 1;
d2_limit = input_width;
d2_advance = -1;
d2_multiplier = 1;
}
let num_pixels = (input_width * input_height) as usize;
let in_b: &mut [u32];
let out_b: &mut [u32];
unsafe {
in_b = from_raw_parts_mut::<u32>(4 as *mut u32, num_pixels);
out_b = from_raw_parts_mut::<u32>((input_width * input_height * 4 + 4) as *mut u32, num_pixels);
}
for d2 in 0..d2_limit {
for d1 in 0..d1_limit {
let in_idx = (d1_start + d1 * d1_advance) * d1_multiplier + (d2_start + d2 * d2_advance) * d2_multiplier;
*unwrap_abort(out_b.get_mut(i as usize)) = *unwrap_abort(in_b.get(in_idx as usize));
i += 1;
}
}
}

BIN
codecs/rotate/rotate.wasm Executable file → Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
{
"extends": "./node_modules/assemblyscript/std/assembly.json",
"include": [
"./**/*.ts"
]
}

View File

@@ -1,7 +1,7 @@
# WebP decoder
- Source: <https://github.com/webmproject/libwebp>
- Version: v1.0.2
- Version: v0.6.1
## Example

View File

@@ -6,33 +6,7 @@ export OPTIMIZE="-Os"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
apt-get update
apt-get install -qqy autoconf libtool libpng-dev pkg-config
echo "============================================="
echo "Compiling libwebp"
echo "============================================="
test -n "$SKIP_LIBWEBP" || (
cd node_modules/libwebp
autoreconf -fiv
rm -rf build || true
mkdir -p build && cd build
emconfigure ../configure \
--disable-libwebpdemux \
--disable-wic \
--disable-gif \
--disable-tiff \
--disable-jpeg \
--disable-png \
--disable-sdl \
--disable-gl \
--disable-threading \
--disable-neon-rtcd \
--disable-neon \
--disable-sse2 \
--disable-sse4.1
emmake make
)
echo "============================================="
echo "Compiling wasm bindings"
echo "============================================="
@@ -46,9 +20,9 @@ echo "============================================="
--std=c++11 \
-I node_modules/libwebp \
-o ./webp_dec.js \
node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c \
-x c++ \
webp_dec.cpp \
node_modules/libwebp/build/src/.libs/libwebp.a
webp_dec.cpp
)
echo "============================================="
echo "Compiling wasm bindings done"

View File

@@ -5,7 +5,7 @@
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"libwebp": "webmproject/libwebp#v1.0.2"
"libwebp": "webmproject/libwebp#v1.0.0"
},
"devDependencies": {
"napa": "3.0.0"

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,7 +1,7 @@
# WebP encoder
- Source: <https://github.com/webmproject/libwebp>
- Version: v1.0.2
- Version: v0.6.1
## Dependencies

View File

@@ -7,33 +7,6 @@ export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
apt-get update
apt-get install -qqy autoconf libtool libpng-dev pkg-config
echo "============================================="
echo "Compiling libwebp"
echo "============================================="
test -n "$SKIP_LIBWEBP" || (
cd node_modules/libwebp
autoreconf -fiv
rm -rf build || true
mkdir -p build && cd build
emconfigure ../configure \
--disable-libwebpdemux \
--disable-wic \
--disable-gif \
--disable-tiff \
--disable-jpeg \
--disable-png \
--disable-sdl \
--disable-gl \
--disable-threading \
--disable-neon-rtcd \
--disable-neon \
--disable-sse2 \
--disable-sse4.1
emmake make
)
echo "============================================="
echo "Compiling wasm bindings"
echo "============================================="
@@ -47,9 +20,9 @@ echo "============================================="
--std=c++11 \
-I node_modules/libwebp \
-o ./webp_enc.js \
node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c \
-x c++ \
webp_enc.cpp \
node_modules/libwebp/build/src/.libs/libwebp.a
webp_enc.cpp
)
echo "============================================="
echo "Compiling wasm bindings done"

View File

@@ -5,7 +5,7 @@
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"libwebp": "webmproject/libwebp#v1.0.2"
"libwebp": "webmproject/libwebp#v1.0.0"
},
"devDependencies": {
"napa": "3.0.0"

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,204 +0,0 @@
const path = require('path');
const { URL } = require('url');
const gzipSize = require('gzip-size');
const fetch = require('node-fetch');
const prettyBytes = require('pretty-bytes');
const escapeRE = require('escape-string-regexp');
const readdirp = require('readdirp');
const chalk = new require('chalk').constructor({ level: 4 });
function fetchTravis(path, options = {}) {
const url = new URL(path, 'https://api.travis-ci.org');
url.search = new URLSearchParams(options);
return fetch(url, {
headers: { 'Travis-API-Version': '3' },
});
}
function fetchTravisBuildInfo(user, repo, branch) {
return fetchTravis(`/repo/${encodeURIComponent(`${user}/${repo}`)}/builds`, {
'branch.name': branch,
state: 'passed',
limit: 1,
}).then(r => r.json());
}
function fetchTravisText(path) {
return fetchTravis(path).then(r => r.text());
}
/**
* Recursively-read a directory and turn it into an array of { name, size, gzipSize }
*/
async function dirToInfoArray(startPath, {
namePrefix = '',
} = {}) {
const results = await new Promise((resolve, reject) => {
readdirp({ root: startPath }, (err, results) => {
if (err) reject(err); else resolve(results);
});
});
return Promise.all(
results.files.map(async (entry) => ({
name: entry.path,
gzipSize: await gzipSize.file(entry.fullPath),
size: entry.stat.size,
})),
);
}
/**
* Try to treat two entries with different file name hashes as the same file.
*/
function findHashedMatch(name, buildInfo) {
const nameParts = /^(.+\.)[a-f0-9]+(\..+)$/.exec(name);
if (!nameParts) return;
const matchRe = new RegExp(`^${escapeRE(nameParts[1])}[a-f0-9]+${escapeRE(nameParts[2])}$`);
const matchingEntry = buildInfo.find(entry => matchRe.test(entry.name));
return matchingEntry;
}
const buildSizePrefix = '=== BUILD SIZES: ';
const buildSizePrefixRe = new RegExp(`^${escapeRE(buildSizePrefix)}(.+)$`, 'm');
async function getPreviousBuildInfo() {
const buildData = await fetchTravisBuildInfo('GoogleChromeLabs', 'squoosh', 'master');
const jobUrl = buildData.builds[0].jobs[0]['@href'];
const log = await fetchTravisText(jobUrl + '/log.txt');
const reResult = buildSizePrefixRe.exec(log);
if (!reResult) return;
return JSON.parse(reResult[1]);
}
/**
* Generate an array that represents the difference between builds.
* Returns an array of { beforeName, afterName, beforeSize, afterSize }.
* Sizes are gzipped size.
* Before/after properties are missing if resource isn't in the previous/new build.
*/
function getChanges(previousBuildInfo, buildInfo) {
const buildChanges = [];
const alsoInPreviousBuild = new Set();
for (const oldEntry of previousBuildInfo) {
const newEntry = buildInfo.find(entry => entry.name === oldEntry.name) ||
findHashedMatch(oldEntry.name, buildInfo);
// Entry is in previous build, but not the new build.
if (!newEntry) {
buildChanges.push({
beforeName: oldEntry.name,
beforeSize: oldEntry.gzipSize,
});
continue;
}
// Mark this entry so we know we've dealt with it.
alsoInPreviousBuild.add(newEntry);
// If they're the same, just ignore.
// Using size rather than gzip size. I've seen different platforms produce different zipped
// sizes.
if (
oldEntry.size === newEntry.size &&
oldEntry.name === newEntry.name
) continue;
// Entry is in both builds (maybe renamed).
buildChanges.push({
beforeName: oldEntry.name,
afterName: newEntry.name,
beforeSize: oldEntry.gzipSize,
afterSize: newEntry.gzipSize,
});
}
// Look for entries that are only in the new build.
for (const newEntry of buildInfo) {
if (alsoInPreviousBuild.has(newEntry)) continue;
buildChanges.push({
afterName: newEntry.name,
afterSize: newEntry.gzipSize,
});
}
return buildChanges;
}
async function main() {
// Output the current build sizes for later retrieval.
const buildInfo = await dirToInfoArray(__dirname + '/../build');
console.log(buildSizePrefix + JSON.stringify(buildInfo));
console.log('\nBuild change report:');
let previousBuildInfo;
try {
previousBuildInfo = await getPreviousBuildInfo();
} catch (err) {
console.log(` Couldn't parse previous build info`);
return;
}
if (!previousBuildInfo) {
console.log(` Couldn't find previous build info`);
return;
}
const buildChanges = getChanges(previousBuildInfo, buildInfo);
if (buildChanges.length === 0) {
console.log(' No changes');
return;
}
// One letter references, so it's easier to get the spacing right.
const y = chalk.yellow;
const g = chalk.green;
const r = chalk.red;
for (const change of buildChanges) {
// New file.
if (!change.beforeSize) {
console.log(` ${g('ADDED')} ${change.afterName} - ${prettyBytes(change.afterSize)}`);
continue;
}
// Removed file.
if (!change.afterSize) {
console.log(` ${r('REMOVED')} ${change.beforeName} - was ${prettyBytes(change.beforeSize)}`);
continue;
}
// Changed file.
let size;
if (change.beforeSize === change.afterSize) {
// Just renamed.
size = `${prettyBytes(change.afterSize)} -> no change`;
} else {
const color = change.afterSize > change.beforeSize ? r : g;
const sizeDiff = prettyBytes(change.afterSize - change.beforeSize, { signed: true });
const relativeDiff = Math.round((change.afterSize / change.beforeSize) * 1000) / 1000;
size = `${prettyBytes(change.beforeSize)} -> ${prettyBytes(change.afterSize)}` +
' (' +
color(`${sizeDiff}, ${relativeDiff}x`) +
')';
}
console.log(` ${y('CHANGED')} ${change.afterName} - ${size}`);
if (change.beforeName !== change.afterName) {
console.log(` Renamed from: ${change.beforeName}`);
}
}
}
main();

1224
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,13 @@
{
"private": true,
"name": "squoosh",
"version": "1.3.3",
"version": "1.3.1",
"license": "apache-2.0",
"scripts": {
"start": "webpack-dev-server --host 0.0.0.0 --hot",
"build": "webpack -p",
"lint": "tslint -c tslint.json -p tsconfig.json -t verbose 'src/**/*.{ts,tsx,js,jsx}'",
"lintfix": "tslint -c tslint.json -p tsconfig.json -t verbose --fix 'src/**/*.{ts,tsx,js,jsx}'",
"sizereport": "node config/size-report.js"
"lintfix": "tslint -c tslint.json -p tsconfig.json -t verbose --fix 'src/**/*.{ts,tsx,js,jsx}'"
},
"husky": {
"hooks": {
@@ -16,14 +15,13 @@
}
},
"devDependencies": {
"@types/node": "10.12.26",
"@types/node": "10.12.18",
"@types/pretty-bytes": "5.1.0",
"@types/webassembly-js-api": "0.0.2",
"@webcomponents/custom-elements": "1.2.1",
"@webpack-cli/serve": "0.1.3",
"assets-webpack-plugin": "3.9.7",
"chokidar": "2.1.1",
"chalk": "2.4.2",
"chokidar": "2.0.4",
"classnames": "2.2.6",
"clean-webpack-plugin": "1.0.1",
"comlink": "3.1.1",
@@ -31,33 +29,29 @@
"critters-webpack-plugin": "2.2.0",
"css-loader": "1.0.1",
"ejs": "2.6.1",
"escape-string-regexp": "1.0.5",
"exports-loader": "0.7.0",
"file-drop-element": "0.0.9",
"file-loader": "3.0.1",
"gzip-size": "5.0.0",
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"idb-keyval": "3.1.0",
"linkstate": "1.1.1",
"loader-utils": "1.2.3",
"loader-utils": "1.2.0",
"mini-css-extract-plugin": "0.5.0",
"minimatch": "3.0.4",
"node-fetch": "2.3.0",
"node-sass": "4.11.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pointer-tracker": "2.0.3",
"preact": "8.4.2",
"prerender-loader": "1.2.0",
"pretty-bytes": "5.1.0",
"progress-bar-webpack-plugin": "1.12.1",
"progress-bar-webpack-plugin": "1.12.0",
"raw-loader": "1.0.0",
"readdirp": "2.2.1",
"sass-loader": "7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"source-map-loader": "0.2.4",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.2.2",
"terser-webpack-plugin": "1.2.1",
"ts-loader": "5.3.3",
"tslint": "5.12.1",
"tslint-config-airbnb": "5.11.1",
@@ -67,8 +61,8 @@
"typescript": "3.2.4",
"url-loader": "1.1.2",
"webpack": "4.28.0",
"webpack-bundle-analyzer": "3.0.4",
"webpack-cli": "3.2.3",
"webpack-bundle-analyzer": "3.0.3",
"webpack-cli": "3.2.1",
"webpack-dev-server": "3.1.14",
"worker-plugin": "3.0.0"
}

View File

@@ -1,32 +1,29 @@
import wasmUrl from '../../../codecs/rotate/rotate.wasm';
import { RotateOptions, RotateModuleInstance } from './processor-meta';
const instancePromise = (WebAssembly as any).instantiateStreaming(fetch(wasmUrl));
export async function rotate(
data: ImageData,
opts: RotateOptions,
): Promise<ImageData> {
const { instance } = (await instancePromise) as {instance: RotateModuleInstance};
const flipDimensions = opts.rotate % 180 !== 0;
// 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 + 4) / (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;
const numPagesNeeded = Math.ceil(bytesPerImage * 2 / (64 * 1024));
const { instance } = (await (WebAssembly as any).instantiateStreaming(
fetch(wasmUrl),
{
env: {
memory: new WebAssembly.Memory({ initial: numPagesNeeded }),
},
},
)) as { instance: RotateModuleInstance };
if (additionalPagesToAllocate > 0) {
instance.exports.memory.grow(additionalPagesToAllocate);
}
const view = new Uint8ClampedArray(instance.exports.memory.buffer);
view.set(data.data, 4);
view.set(data.data);
instance.exports.rotate(data.width, data.height, opts.rotate);
const flipDimensions = opts.rotate % 180 !== 0;
return new ImageData(
view.slice(bytesPerImage + 4, bytesPerImage * 2 + 4),
view.slice(bytesPerImage, bytesPerImage * 2),
flipDimensions ? data.height : data.width,
flipDimensions ? data.width : data.height,
);

View File

@@ -40,7 +40,6 @@
position: relative;
display: flex;
flex-flow: column;
overflow: hidden;
// Reorder so headings appear after content:
& > :nth-child(1) {

View File

@@ -17,8 +17,6 @@ const CrittersPlugin = require('critters-webpack-plugin');
const AssetTemplatePlugin = require('./config/asset-template-plugin');
const addCssTypes = require('./config/add-css-types');
const regexpPathSep = path.sep === '\\' ? '\\\\' : '/';
function readJson (filename) {
return JSON.parse(fs.readFileSync(filename));
}
@@ -40,7 +38,7 @@ module.exports = async function (_, env) {
return {
mode: isProd ? 'production' : 'development',
entry: {
'first-interaction': path.join('.', 'src', 'index'),
'first-interaction': './src/index'
},
devtool: isProd ? 'source-map' : 'inline-source-map',
stats: 'minimal',
@@ -54,13 +52,13 @@ module.exports = async function (_, env) {
resolve: {
extensions: ['.ts', '.tsx', '.mjs', '.js', '.scss', '.css'],
alias: {
style: path.join(__dirname, 'src', 'style')
style: path.join(__dirname, 'src/style')
}
},
resolveLoader: {
alias: {
// async-component-loader returns a wrapper component that waits for the import to load before rendering:
async: path.join(__dirname, 'config', 'async-component-loader')
async: path.join(__dirname, 'config/async-component-loader')
}
},
module: {
@@ -149,11 +147,11 @@ module.exports = async function (_, env) {
},
{
// All the codec files define a global with the same name as their file name. `exports-loader` attaches those to `module.exports`.
test: new RegExp(`${regexpPathSep}codecs${regexpPathSep}.*\.js`),
test: /\/codecs\/.*\.js$/,
loader: 'exports-loader'
},
{
test: new RegExp(`${regexpPathSep}codecs${regexpPathSep}.*\.wasm`),
test: /\/codecs\/.*\.wasm$/,
// This is needed to make webpack NOT process wasm files.
// See https://github.com/webpack/webpack/issues/6725
type: 'javascript/auto',
@@ -174,7 +172,7 @@ module.exports = async function (_, env) {
plugins: [
new webpack.IgnorePlugin(
/(fs|crypto|path)/,
new RegExp(`${regexpPathSep}codecs${regexpPathSep}`)
new RegExp(`${path.sep}codecs${path.sep}`)
),
// Pretty progressbar showing build progress: