-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
119 lines (105 loc) · 3.64 KB
/
Copy pathindex.js
File metadata and controls
119 lines (105 loc) · 3.64 KB
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
import fs from 'fs/promises';
import { createWriteStream } from 'fs';
import Jimp from 'jimp';
import { getNearbyColor, createColor, isSameColor } from './color-util';
import GIFEncoder from 'gifencoder';
import pngFileStream from 'png-file-stream';
function pad(n) {
if (n < 10) {
return `0${n}`;
}
return `${n}`;
}
const FPS = 8;
const DELAY = 1000 / FPS;
const FRAME_COUNT = FPS;
const SCALE = 4;
const ignoreColor = createColor(33, 33, 33);
function paintRect(image, color, x, y, w, h) {
for (let i = x; i < x + w; i += 1) {
for (let j = y; j < y + h; j += 1) {
image.setPixelColor(color, i, j);
}
}
}
async function createVariation(srcImage, scale) {
const dstImage = await new Jimp(srcImage.bitmap.width * scale, srcImage.bitmap.height * scale);
for (let y = 0; y < srcImage.bitmap.height; y += 1) {
for (let x = 0; x < srcImage.bitmap.width; x += 1) {
const colorHex = srcImage.getPixelColor(x, y);
const color = Jimp.intToRGBA(colorHex);
if (!isSameColor(ignoreColor, color)) {
const nearbyColor = getNearbyColor(color, 32);
const nearbyHex = Jimp.rgbaToInt(
nearbyColor.r, nearbyColor.g, nearbyColor.b, 255,
);
paintRect(dstImage, nearbyHex, x * scale, y * scale, scale, scale);
} else {
paintRect(dstImage, colorHex, x * scale, y * scale, scale, scale);
}
}
}
return dstImage;
}
function createFrames(srcImage, count, outputDir) {
return Promise.all(
new Array(count).fill(true).map(async (_, i) => {
const dstImage = await createVariation(srcImage, SCALE);
const filename = `${outputDir}/${pad(i)}.png`;
console.log('Creating frame', filename);
return new Promise((resolve, reject) =>
dstImage.write(filename, err =>
err ? reject(err) : resolve()
)
);
})
);
}
async function createAnimatedGif(inputFilename, name, outputDir) {
console.log('Loading source for', name);
const srcImage = await Jimp.read(inputFilename);
const frameDirpath = `${outputDir}/${name}`;
console.log('Creating frames for', name);
try {
await fs.access(frameDirpath);
} catch (e) {
await fs.mkdir(frameDirpath);
}
await createFrames(srcImage, FRAME_COUNT, frameDirpath);
console.log('Creating GIF for', name);
const encoder = new GIFEncoder(srcImage.bitmap.width * SCALE, srcImage.bitmap.height * SCALE);
return new Promise((resolve, reject) => {
try {
pngFileStream(`${frameDirpath}/*.png`)
.pipe(encoder.createWriteStream({ repeat: 0, delay: DELAY, quality: 10 }))
.pipe(createWriteStream(`gallery/${name}.gif`))
.on('finish', resolve)
.on('error', reject);
} catch (err) {
reject(err);
}
});
}
async function createFlatPic(inputFilename, name) {
const srcImage = await Jimp.read(inputFilename);
const outputFilename = `${name}-big.png`;
const dstImage = await createVariation(srcImage, 10);
dstImage.write(outputFilename);
}
async function main() {
const files = await fs.readdir('resources');
const html = [];
await Promise.all(files.map(async file => {
const pngIndex = file.indexOf('.png');
if (pngIndex >= 0) {
const stem = file.substring(0, pngIndex);
const name = stem.split('-').join(' ');
html.push(` <div><img src="gallery/${stem}.gif" title="${name}" />${name}</div>`);
await createAnimatedGif(`resources/${stem}.png`, stem, '.output');
// await createFlatPic(`resources/${stem}.png`, stem);
}
}));
const htmlTemplate = await fs.readFile('template.html', 'utf-8');
await fs.writeFile('index.html', htmlTemplate.replace('$$$', html.join('\n')));
}
main().catch(console.error);