mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-11 16:26:20 +00:00
Use all the codecs
This commit is contained in:
191
cli/index.js
191
cli/index.js
@@ -1,16 +1,108 @@
|
||||
const mozjpeg_dec = require("../codecs/mozjpeg/dec/mozjpeg_dec.js");
|
||||
const mozjpeg_enc = require("../codecs/mozjpeg/enc/mozjpeg_enc.js");
|
||||
const webp_enc = require("../codecs/webp/enc/webp_enc.js");
|
||||
const { program } = require("commander");
|
||||
const JSON5 = require("json5");
|
||||
//const { Worker, isMainThread, parentPort } = require('worker_threads');
|
||||
//const {cpus} = require("os");
|
||||
const path = require("path");
|
||||
const fsp = require("fs").promises;
|
||||
|
||||
const visdifModule = require("../codecs/visdif/visdif.js");
|
||||
|
||||
// Our decoders currently rely on this.
|
||||
globalThis.ImageData = require("./image_data.js");
|
||||
|
||||
const fsp = require("fs").promises;
|
||||
|
||||
const supportedFormats = {
|
||||
mozjpeg: {
|
||||
name: "MozJPEG",
|
||||
extension: "jpg",
|
||||
detectors: [/^\xFF\xD8\xFF/],
|
||||
dec: require("../codecs/mozjpeg/dec/mozjpeg_dec.js"),
|
||||
enc: require("../codecs/mozjpeg/enc/mozjpeg_enc.js"),
|
||||
defaultEncoderOptions: {
|
||||
quality: 75,
|
||||
baseline: false,
|
||||
arithmetic: false,
|
||||
progressive: true,
|
||||
optimize_coding: true,
|
||||
smoothing: 0,
|
||||
color_space: 3 /*YCbCr*/,
|
||||
quant_table: 3,
|
||||
trellis_multipass: false,
|
||||
trellis_opt_zero: false,
|
||||
trellis_opt_table: false,
|
||||
trellis_loops: 1,
|
||||
auto_subsample: true,
|
||||
chroma_subsample: 2,
|
||||
separate_chroma_quality: false,
|
||||
chroma_quality: 75
|
||||
}
|
||||
},
|
||||
webp: {
|
||||
name: "WebP",
|
||||
extension: "webp",
|
||||
detectors: [/^RIFF....WEBPVP8[LX ]/],
|
||||
dec: require("../codecs/webp/dec/webp_dec.js"),
|
||||
enc: require("../codecs/webp/enc/webp_enc.js"),
|
||||
defaultEncoderOptions: {
|
||||
quality: 75,
|
||||
target_size: 0,
|
||||
target_PSNR: 0,
|
||||
method: 4,
|
||||
sns_strength: 50,
|
||||
filter_strength: 60,
|
||||
filter_sharpness: 0,
|
||||
filter_type: 1,
|
||||
partitions: 0,
|
||||
segments: 4,
|
||||
pass: 1,
|
||||
show_compressed: 0,
|
||||
preprocessing: 0,
|
||||
autofilter: 0,
|
||||
partition_limit: 0,
|
||||
alpha_compression: 1,
|
||||
alpha_filtering: 1,
|
||||
alpha_quality: 100,
|
||||
lossless: 0,
|
||||
exact: 0,
|
||||
image_hint: 0,
|
||||
emulate_jpeg_size: 0,
|
||||
thread_level: 0,
|
||||
low_memory: 0,
|
||||
near_lossless: 100,
|
||||
use_delta_palette: 0,
|
||||
use_sharp_yuv: 0
|
||||
}
|
||||
},
|
||||
avif: {
|
||||
name: "AVIF",
|
||||
extension: "avif",
|
||||
detectors: [/^\x00\x00\x00 ftypavif\x00\x00\x00\x00/],
|
||||
dec: require("../codecs/avif/dec/avif_dec.js"),
|
||||
enc: require("../codecs/avif/enc/avif_enc.js"),
|
||||
defaultEncoderOptions: {
|
||||
minQuantizer: 16,
|
||||
maxQuantizer: 16,
|
||||
tileColsLog2: 0,
|
||||
tileRowsLog2: 0,
|
||||
speed: 10,
|
||||
subsample: 0
|
||||
}
|
||||
}
|
||||
};
|
||||
async function decodeFile(file) {
|
||||
const buffer = await fsp.readFile(file);
|
||||
const rgba = (await mozjpeg_dec()).decode(new Uint8Array(buffer));
|
||||
const firstChunk = buffer.slice(0, 16);
|
||||
const firstChunkString = Array.from(firstChunk)
|
||||
.map(v => String.fromCodePoint(v))
|
||||
.join("");
|
||||
const key = Object.entries(supportedFormats).find(([name, { detectors }]) =>
|
||||
detectors.some(detector => detector.exec(firstChunkString))
|
||||
)?.[0];
|
||||
if (!key) {
|
||||
throw Error(`${file} has an unsupported format`);
|
||||
}
|
||||
const rgba = (await supportedFormats[key].dec()).decode(
|
||||
new Uint8Array(buffer)
|
||||
);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
@@ -63,40 +155,61 @@ async function optimize(bitmapIn, encode, decode) {
|
||||
};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [, , inFile, outFile] = process.argv;
|
||||
const bitmapIn = await decodeFile(inFile);
|
||||
//if(isMainThread) {
|
||||
program
|
||||
.version(require("./package.json").version)
|
||||
.arguments("<files...>")
|
||||
.option("-d, --output-dir <dir>", "Output directory", ".");
|
||||
|
||||
const jpegEncModule = await mozjpeg_enc();
|
||||
const jpegEnc = async (bitmap, quality) =>
|
||||
jpegEncModule.encode(bitmap.data.buffer, bitmap.width, bitmap.height, {
|
||||
quality,
|
||||
baseline: false,
|
||||
arithmetic: false,
|
||||
progressive: true,
|
||||
optimize_coding: true,
|
||||
smoothing: 0,
|
||||
color_space: 3 /*YCbCr*/,
|
||||
quant_table: 3,
|
||||
trellis_multipass: false,
|
||||
trellis_opt_zero: false,
|
||||
trellis_opt_table: false,
|
||||
trellis_loops: 1,
|
||||
auto_subsample: true,
|
||||
chroma_subsample: 2,
|
||||
separate_chroma_quality: false,
|
||||
chroma_quality: 75
|
||||
});
|
||||
const jpegDecModule = await mozjpeg_dec();
|
||||
const jpegDec = async binary => jpegDecModule.decode(binary);
|
||||
const jpegOut = await optimize(bitmapIn, jpegEnc, jpegDec);
|
||||
await fsp.writeFile("out.jpg", jpegOut.binary);
|
||||
//await webp_enc();
|
||||
//console.log(bitmapIn);
|
||||
// Create a CLI option for each supported encoder
|
||||
for (const [key, value] of Object.entries(supportedFormats)) {
|
||||
program.option(
|
||||
`--${key} [config]`,
|
||||
`Use ${value.name} to generate a .${value.extension} file with the given configuration`
|
||||
);
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error("Something went wrong");
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
program.action(async files => {
|
||||
// Create output directory
|
||||
await fsp.mkdir(program.outputDir, { recursive: true });
|
||||
//const pool = Array.from({length: cpus().length}, () => new Worker(process.argv[1]));
|
||||
let i = 0;
|
||||
for (const file of files) {
|
||||
const ext = path.extname(file);
|
||||
const base = path.basename(file, ext);
|
||||
const bitmapIn = await decodeFile(file);
|
||||
|
||||
for (const [key, value] of Object.entries(supportedFormats)) {
|
||||
if (!program[key]) {
|
||||
continue;
|
||||
}
|
||||
const encConfig = Object.assign(
|
||||
{},
|
||||
value.defaultEncoderOptions,
|
||||
JSON5.parse(program[key])
|
||||
);
|
||||
const encoder = await value.enc();
|
||||
const out = encoder.encode(
|
||||
bitmapIn.data.buffer,
|
||||
bitmapIn.width,
|
||||
bitmapIn.height,
|
||||
encConfig
|
||||
);
|
||||
const outputFile = path.join(
|
||||
program.outputDir,
|
||||
`${base}.${value.extension}`
|
||||
);
|
||||
await fsp.writeFile(outputFile, out);
|
||||
}
|
||||
// pool[i].postMessage({
|
||||
// inFile: file,
|
||||
// outFile: path.join(program.outputDir, base,kkkkk
|
||||
// })
|
||||
}
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
//} else {
|
||||
// parentPort.on("message", async ({inFile, outFile, encoder, config}) => {
|
||||
// });
|
||||
//}
|
||||
|
||||
13
cli/package-lock.json
generated
13
cli/package-lock.json
generated
@@ -8,6 +8,19 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-6.0.0.tgz",
|
||||
"integrity": "sha512-s7EA+hDtTYNhuXkTlhqew4txMZVdszBmKWSPEMxGr8ru8JXR7bLUFIAtPhcSuFdJQ0ILMxnJi8GkQL0yvDy/YA=="
|
||||
},
|
||||
"json5": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
||||
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"author": "Surma <surma@surma.dev>",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"commander": "^6.0.0"
|
||||
"commander": "^6.0.0",
|
||||
"json5": "^2.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user