fix (i hope) all bugs

This commit is contained in:
olcxja 2026-09-26 11:40:04 +02:00
commit 201f9d7a7e
11 changed files with 195 additions and 37 deletions

View file

@ -120,6 +120,36 @@ function pngSize(img) {
return null
}
// Raw RT_ICON payloads are BITMAPINFOHEADER-based bitmaps: biSize, biWidth,
// biHeight (2x the visible height - XOR + AND mask), biPlanes, biBitCount,
// ..., biClrUsed. Read the real dimensions from there instead of treating the
// first bytes as an ICONDIRENTRY (which yielded garbage like h=0, planes=48
// and made Chromium decode an empty image).
function bmpDims(img) {
if (img.length < 12) return null
const biSize = img.readUInt32LE(0)
if (biSize === 12) {
// BITMAPCOREHEADER (Win 2.x/3.x era icons): DWORD size, then WORD width,
// height, planes, bitcount
const w = img.readUInt16LE(4)
const h = Math.floor(img.readUInt16LE(6) / 2)
const planes = img.readUInt16LE(8) || 1
const bpp = img.readUInt16LE(10) || 32
const colors = bpp <= 8 ? 1 << bpp : 0
if (w > 0 && h > 0 && w <= 1024 && h <= 1024) return { w, h, planes, bpp, colors }
return null
}
if (biSize >= 40 && biSize <= 124 && img.length > 40) {
const w = img.readUInt32LE(4)
const h = Math.floor(img.readUInt32LE(8) / 2)
const planes = img.readUInt16LE(12) || 1
const bpp = img.readUInt16LE(14) || 32
const colors = img.readUInt32LE(32) || (bpp <= 8 ? 1 << bpp : 0)
if (w > 0 && h > 0 && w <= 1024 && h <= 1024) return { w, h, planes, bpp, colors }
}
return null
}
function buildIco(images) {
const header = Buffer.alloc(6)
header.writeUInt16LE(0, 0)
@ -135,16 +165,27 @@ function buildIco(images) {
w = dim.w
h = dim.h
} else {
w = img.readUInt8(0) || 256
h = img.readUInt8(1) || 256
colors = img.readUInt8(2)
planes = img.length > 4 ? img.readUInt16LE(4) || 1 : 1
bpp = img.length > 6 ? img.readUInt16LE(6) || 32 : 32
const dims = bmpDims(img)
if (dims) {
w = dims.w
h = dims.h
colors = dims.colors
planes = dims.planes
bpp = dims.bpp
} else {
// legacy fallback: ICONDIRENTRY-style first bytes (PNG-era heuristic)
w = img.readUInt8(0) || 256
h = img.readUInt8(1) || 256
colors = img.readUInt8(2)
planes = img.length > 4 ? img.readUInt16LE(4) || 1 : 1
bpp = img.length > 6 ? img.readUInt16LE(6) || 32 : 32
}
}
const meta = Buffer.alloc(16)
meta.writeUInt8(w >= 256 ? 0 : w, 0)
meta.writeUInt8(h >= 256 ? 0 : h, 1)
meta.writeUInt8(colors, 2)
// 0 in the ICO dir entry means "256+ colors" (palette implied by bpp)
meta.writeUInt8(colors >= 256 ? 0 : colors, 2)
meta.writeUInt8(0, 3)
meta.writeUInt16LE(planes, 4)
meta.writeUInt16LE(bpp, 6)