-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathgenerate-ico.js
More file actions
74 lines (64 loc) · 2.4 KB
/
Copy pathgenerate-ico.js
File metadata and controls
74 lines (64 loc) · 2.4 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
/* eslint-env node */
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const inputPng = path.join(__dirname, '../assets/icon.png');
const outputIco = path.join(__dirname, '../assets/icon.ico');
const tempPng = path.join(__dirname, '../assets/icon-256.png');
try {
console.log('Resizing icon to 256x256 using PowerShell...');
// Use PowerShell to resize the image because we don't want to add sharp/jimp dependencies just for this one-off
const psCommand = `
Add-Type -AssemblyName System.Drawing;
$img = [System.Drawing.Image]::FromFile('${inputPng}');
$newImg = new-object System.Drawing.Bitmap(256, 256);
$graph = [System.Drawing.Graphics]::FromImage($newImg);
$graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic;
$graph.DrawImage($img, 0, 0, 256, 256);
$newImg.Save('${tempPng}', [System.Drawing.Imaging.ImageFormat]::Png);
$img.Dispose();
$newImg.Dispose();
$graph.Dispose();
`;
execSync(`powershell -Command "${psCommand.replace(/\n/g, ' ')}"`, { stdio: 'inherit' });
if (!fs.existsSync(tempPng)) {
throw new Error('Failed to create resized PNG');
}
console.log('Generating ICO file...');
const pngBuffer = fs.readFileSync(tempPng);
// size variable removed as it was unused
// ICO Header
// 0-1: Reserved (0)
// 2-3: Type (1 for ICO)
// 4-5: Number of images (1)
const header = Buffer.alloc(6);
header.writeUInt16LE(0, 0);
header.writeUInt16LE(1, 2);
header.writeUInt16LE(1, 4);
// Icon Directory Entry
// 0: Width (0 for 256)
// 1: Height (0 for 256)
// 2: Color count (0 for >= 256 colors)
// 3: Reserved (0)
// 4-5: Color planes (1)
// 6-7: Bits per pixel (32)
// 8-11: Size of image data
// 12-15: Offset of image data
const entry = Buffer.alloc(16);
entry.writeUInt8(0, 0); // 256 width -> 0
entry.writeUInt8(0, 1); // 256 height -> 0
entry.writeUInt8(0, 2);
entry.writeUInt8(0, 3);
entry.writeUInt16LE(1, 4);
entry.writeUInt16LE(32, 6);
entry.writeUInt32LE(pngBuffer.length, 8);
entry.writeUInt32LE(6 + 16, 12); // Header (6) + 1 Entry (16)
const icoBuffer = Buffer.concat([header, entry, pngBuffer]);
fs.writeFileSync(outputIco, icoBuffer);
// Clean up
fs.unlinkSync(tempPng);
console.log(`Successfully created ${outputIco}`);
} catch (error) {
console.error('Error generating ICO:', error);
process.exit(1);
}