-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsquoosh.js
113 lines (92 loc) · 2.74 KB
/
squoosh.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import module from 'node:module'
import * as path from 'node:path'
import url from 'node:url'
import os from 'node:os'
import fs from 'node:fs/promises'
import {Buffer} from 'node:buffer'
import isJpeg from 'is-jpg'
import isWebp from 'is-webp'
import isPng from 'is-png'
const LIB_SQUOOSH_HACK_CODE = 'var fetch;'
async function importLibrarySquoosh() {
const libsquooshEntry = module
.createRequire(import.meta.url)
.resolve('@frostoven/libsquoosh')
const content = await fs.readFile(libsquooshEntry, 'utf8')
if (!content.startsWith(LIB_SQUOOSH_HACK_CODE)) {
await fs.writeFile(libsquooshEntry, LIB_SQUOOSH_HACK_CODE + content)
}
return import(url.pathToFileURL(libsquooshEntry).href)
}
const encoders = new Map([
['.jpg', {id: 'mozjpeg', test: isJpeg}],
['.jpeg', {id: 'mozjpeg', test: isJpeg}],
['.webp', {id: 'webp', test: isWebp}],
// ['.avif', {id: 'avif'}],
// [
// '.jxl',
// {
// id: 'jxl',
// options: {effort: 7, photonNoiseIso: 0, lossyModular: false},
// },
// ],
// ['.wp2', {id:'wp2'}],
['.png', {id: 'oxipng', test: isPng}],
])
function getEncoder(filename) {
return encoders.get(path.extname(filename).toLowerCase())
}
/**
* @param {{content: Buffer, name: string}[]} files
* @returns {Uint8Array[]}
*/
async function squooshImages(files, {cache, onFileExtensionError}) {
if (files.length === 0) {
return []
}
let imagePoolLoadPromise
let imagePool
function getImagePool() {
imagePoolLoadPromise ??= (async () => {
const {ImagePool} = await importLibrarySquoosh()
imagePool = new ImagePool(os.cpus().length)
return imagePool
})()
return imagePoolLoadPromise
}
let result
try {
result = await Promise.all(
files.map(async (file) => {
const encoder = file.path
? getEncoder(file.path)
: getEncoder(file.name)
if (!encoder) {
return file.content
}
const cached = cache.getCachedData(file)
if (cached) {
return cached
}
const original = file.content
if (onFileExtensionError && !encoder.test(original)) {
onFileExtensionError(file)
}
const imagePool = await getImagePool()
const image = imagePool.ingestImage(original)
await image.encode({
[encoder.id]: encoder.options,
})
const result = await image.encodedWith[encoder.id]
const compressed = result.binary
const data = compressed.length < original.length ? compressed : original
return Buffer.from(data)
}),
)
} finally {
await imagePool?.close()
}
return result
}
const isSupportedImage = (filename) => Boolean(getEncoder(filename))
export {squooshImages, isSupportedImage}