-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecompress_IDAT.py
More file actions
59 lines (45 loc) · 1.58 KB
/
Copy pathdecompress_IDAT.py
File metadata and controls
59 lines (45 loc) · 1.58 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
from pathlib import Path
import struct, zlib, math
b = Path("msi_full/US8yBGmyj").read_bytes()
pos = b.find(b"IDAT") - 4
idat_parts = []
chunks = []
while pos + 8 <= len(b):
length = struct.unpack(">I", b[pos:pos+4])[0]
ctype = b[pos+4:pos+8]
data = b[pos+8:pos+8+length]
crc = b[pos+8+length:pos+8+length+4]
chunks.append((pos, length, ctype, crc.hex()))
if ctype == b"IDAT":
idat_parts.append(data)
elif ctype == b"IEND":
break
pos += 8 + length + 4
print("chunks:", len(chunks))
print("first chunk:", chunks[0])
print("last chunk:", chunks[-1])
print("total IDAT compressed bytes:", sum(len(x) for x in idat_parts))
compressed = b"".join(idat_parts)
for mode in ["normal", "raw-deflate"]:
try:
if mode == "normal":
raw = zlib.decompress(compressed)
else:
raw = zlib.decompress(compressed, -15)
print("\nDECOMPRESS OK:", mode)
print("raw bytes:", len(raw))
# Try common PNG pixel formats:
# grayscale=1, RGB=3, RGBA=4 bytes/pixel
for bpp, name in [(1, "gray8"), (3, "rgb8"), (4, "rgba8")]:
print("\nFormat", name)
hits = []
for w in range(1, 5000):
row = 1 + w * bpp # PNG filter byte + pixels
if len(raw) % row == 0:
h = len(raw) // row
if 1 <= h <= 5000:
hits.append((w, h))
print("candidates:", hits[:50])
print("count:", len(hits))
except Exception as e:
print("\nDECOMPRESS FAIL:", mode, e)