-
Notifications
You must be signed in to change notification settings - Fork 1
/
image_manipulation.ts
135 lines (106 loc) · 3.94 KB
/
image_manipulation.ts
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import fs from "fs";
import sharp from "sharp";
import path from "path";
import exifReader from "exif-reader";
/*
We use NuxtImage in the site, which will generate multiple size images, for the various devices. A smartphone will be served a lighter image than a computer.
If the image is small, in the mosaic, it will be lighter that a full screen image.
If we use this optimisation techniques, we can not upload 3 Go of pictures to GitHub each year, which will never be viewed at full resolution.
We use this script to optimize these images by reducing their size.
The algorithm will also sort pictures, give them a correct filename and put them in the correct folder.
Usage:
```bash
npx tsx image_manipulation.ts directory/containing/all/images
```
*/
const args = process.argv.slice(2);
if (args.length !== 1) {
console.log();
console.log();
console.log(
"Usage: `npx tsx image_manipulation.ts directory/containing/all/images`"
);
console.log();
console.log();
throw new Error("Invalid usage");
}
const dir = args[0];
console.log(`Starting to prepare pictures from folder ${dir}`);
// We search the latest year already used for the website
let currentYear = 0;
fs.readdirSync("public/images/galeries/").forEach((filename) => {
const name = Number(path.parse(filename).name);
if (name > currentYear) {
currentYear = name;
}
});
const outputFolder = `public/images/galeries/${currentYear + 1}/`;
console.log(`Images will be added to folder ${outputFolder}`);
// We use two structures to store images
// `imagesWithoutTimestamp` will contains all images that don't have a date. We will add them at the end of the folder
const imagesWithoutTimestamp: sharp.Sharp[] = [];
// `imagesWithTimestamp` will contains other images, add will be sorted
const imagesWithTimestamp: {
dateTimeOriginal: Date;
image: sharp.Sharp;
}[] = [];
const files = await fs.promises.readdir(dir);
for (const filename of files) {
const name = path.parse(filename).name;
const ext = path.parse(filename).ext;
if (name[0] === ".") {
// This is a system file
continue;
}
if (ext !== ".jpg" && ext !== ".jpeg") {
throw new Error(
"Warning: you need to implement export for non jpg files, current extension: " +
ext +
"for file " +
filename
);
}
const filepath = path.resolve(dir, filename);
const image = sharp(filepath);
const metadata = await image.metadata();
// Images should have exif data containing the date and hour they where taken
// As we may have multiples images sources (ex: Pixels and Declic), we will use these timestamps to sorts images
const exif =
metadata.exif !== undefined ? exifReader(metadata.exif) : undefined;
const dateTimeOriginal = exif?.Photo?.DateTimeOriginal;
if (dateTimeOriginal !== undefined) {
imagesWithTimestamp.push({
dateTimeOriginal,
image,
});
} else {
console.log(`Warning: ${name} does not have a dateTimeOriginal`);
imagesWithoutTimestamp.push(image);
}
}
// We want to store found images by date
imagesWithTimestamp.sort(
(a, b) => a.dateTimeOriginal.getTime() - b.dateTimeOriginal.getTime()
);
const images: sharp.Sharp[] = [];
imagesWithTimestamp.forEach((image) => images.push(image.image));
imagesWithoutTimestamp.forEach((image) => images.push(image));
console.log(`Found ${images.length} images, starting to export`);
await fs.promises.mkdir(outputFolder);
let imageIndex = 1;
// We will export images after changing their quality
for (const image of images) {
console.log(`${imageIndex}/${images.length}`);
// https://stackoverflow.com/questions/51291678/compress-image-using-sharp-in-node-js
await image
.resize({ width: 2048 })
.jpeg({ progressive: true, force: false, quality: 100 })
//.png({ progressive: true, force: false, quality: 80 })
.toFile(outputFolder + imageIndex + ".jpg");
imageIndex += 1;
}
// const image = sharp("_4_.jpg");
// const meta = await image.metadata();
// const { format } = meta;
//
//