forked from www/www-new
Compare commits
30 Commits
main
...
amy-image-
Author | SHA1 | Date |
---|---|---|
|
b6cd0d3f35 | 1 year ago |
|
06123e8adb | 1 year ago |
|
a9ef29c193 | 1 year ago |
|
f831e96048 | 1 year ago |
|
5b6a3e98ab | 1 year ago |
|
7408cf421a | 1 year ago |
|
b933635e6e | 1 year ago |
|
fa6fe454a9 | 1 year ago |
|
388bf799ab | 1 year ago |
|
72cd1ee06c | 1 year ago |
|
fbbfaf9fff | 1 year ago |
|
6e73bb3eb8 | 1 year ago |
|
a7bf6f56a3 | 1 year ago |
|
ecfbb721a5 | 1 year ago |
|
370452f246 | 1 year ago |
|
c031147aad | 1 year ago |
|
609d10732c | 1 year ago |
|
5bead562f9 | 1 year ago |
|
f5adb69bdd | 1 year ago |
|
92eec34fa7 | 1 year ago |
|
aa32e20c6e | 1 year ago |
|
8cd3a7747b | 1 year ago |
|
3519e87e42 | 1 year ago |
|
60fee0618e | 1 year ago |
|
9cde6e563e | 1 year ago |
|
16cdbe9db4 | 1 year ago |
|
e8988e0e4c | 1 year ago |
|
4ffad01bbe | 1 year ago |
|
c37a714c32 | 1 year ago |
|
bdd65d2e22 | 1 year ago |
@ -0,0 +1,98 @@ |
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ |
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */ |
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ |
||||
|
||||
// TODO: upgrade libsquoosh once types are available: https://github.com/GoogleChromeLabs/squoosh/issues/1077
|
||||
|
||||
import { cpus } from "os"; |
||||
import path from "path"; |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { ImagePool } from "@squoosh/lib"; |
||||
import fse from "fs-extra"; |
||||
import { default as getImageDimensions } from "image-size"; |
||||
|
||||
const IMAGES_SOURCE_DIRECTORY = "images"; |
||||
const IMAGES_DESTINATION_DIRECTORY = "public/images"; |
||||
|
||||
void optimizeImages(); |
||||
|
||||
const IMAGE_MINIMUM_SIZE = 300; |
||||
|
||||
const IMAGE_ENCODE_OPTIONS = { mozjpeg: {} }; |
||||
const GET_CODEC_FROM_EXTENSION: { [imageExtension: string]: string } = { |
||||
jpg: "mozjpeg", |
||||
jpeg: "mozjpeg", |
||||
}; |
||||
|
||||
export async function optimizeImages() { |
||||
const imagePaths = await getFilePathsInDirectory(IMAGES_SOURCE_DIRECTORY); |
||||
await fse.emptyDir(IMAGES_DESTINATION_DIRECTORY); |
||||
|
||||
const numberOfWorkers = cpus().length; |
||||
const imagePool = new ImagePool(numberOfWorkers); |
||||
|
||||
await Promise.all( |
||||
imagePaths.map(async (imagePath) => { |
||||
const sourcePath = path.join(IMAGES_SOURCE_DIRECTORY, imagePath); |
||||
const destinationPath = path.join( |
||||
IMAGES_DESTINATION_DIRECTORY, |
||||
imagePath |
||||
); |
||||
const fileExtension = imagePath.split(".").pop() ?? ""; |
||||
|
||||
if (!GET_CODEC_FROM_EXTENSION[fileExtension]) { |
||||
await fse.copy(sourcePath, destinationPath); |
||||
return; |
||||
} |
||||
|
||||
const rawImageFile = await fse.readFile(sourcePath); |
||||
const ingestedImage = imagePool.ingestImage(rawImageFile); |
||||
const { width, height } = getImageDimensions(rawImageFile); |
||||
|
||||
await ingestedImage.decoded; |
||||
|
||||
if (width && height) { |
||||
const resizeEnabled = |
||||
width > IMAGE_MINIMUM_SIZE && height > IMAGE_MINIMUM_SIZE; |
||||
const smallerDimension = width < height ? "width" : "height"; |
||||
|
||||
// specifying only one dimension maintains the aspect ratio
|
||||
const preprocessOptions = { |
||||
resize: { |
||||
enabled: resizeEnabled, |
||||
[smallerDimension]: IMAGE_MINIMUM_SIZE, |
||||
}, |
||||
}; |
||||
|
||||
await ingestedImage.preprocess(preprocessOptions); |
||||
} |
||||
|
||||
await ingestedImage.encode(IMAGE_ENCODE_OPTIONS); |
||||
|
||||
const encodedImage = await ingestedImage.encodedWith[ |
||||
GET_CODEC_FROM_EXTENSION[fileExtension] |
||||
]; |
||||
await fse.outputFile(destinationPath, encodedImage.binary); |
||||
}) |
||||
); |
||||
|
||||
await imagePool.close(); |
||||
} |
||||
|
||||
async function getFilePathsInDirectory(directory: string): Promise<string[]> { |
||||
const entries = await fse.readdir(directory, { withFileTypes: true }); |
||||
return ( |
||||
await Promise.all( |
||||
entries.map(async (entry) => { |
||||
if (entry.isDirectory()) { |
||||
const subdirectory = path.join(directory, entry.name); |
||||
const subentries = await getFilePathsInDirectory(subdirectory); |
||||
return subentries.map((subentry) => path.join(entry.name, subentry)); |
||||
} |
||||
return entry.name; |
||||
}) |
||||
) |
||||
).flat(); |
||||
} |
Loading…
Reference in new issue