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
// 纯 MoonBit PNM 16-bit 解码器
// 支持 P5(PGM 16-bit 灰度)和 P6(PPM 16-bit RGB)
// maxval ≥ 256 时为 16-bit(big-endian uint16 per sample)
///|
/// 解码 PNM 字节流为 Image16
/// 支持 P5(PGM 16-bit 灰度,channels=1)和 P6(PPM 16-bit RGB,channels=3)
/// maxval ≥ 256 时为 16-bit(big-endian),maxval < 256 时上采样为 16-bit
pub fn decode_pnm_16_pure(
data : Bytes,
) -> @types.Image16 raise @types.LoadError {
let len = data.length()
if len < 2 {
raise @types.LoadError::DecodeFailed("PNM 数据过短")
}
let magic0 = data[0].to_int()
let magic1 = data[1].to_int()
if !(magic0 == 0x50 && (magic1 == 0x35 || magic1 == 0x36)) {
raise @types.LoadError::DecodeFailed(
"不支持的 PNM magic,仅支持 P5 和 P6",
)
}
let channels = if magic1 == 0x36 { 3 } else { 1 }
let pos = Ref(2)
pnm_skip_ws_and_comments(data, pos, len)
let width = pnm_read_ascii_int(data, pos, len)
pnm_skip_ws_and_comments(data, pos, len)
let height = pnm_read_ascii_int(data, pos, len)
pnm_skip_ws_and_comments(data, pos, len)
let maxval = pnm_read_ascii_int(data, pos, len)
if maxval <= 0 {
raise @types.LoadError::DecodeFailed("PNM maxval 无效")
}
if width <= 0 || height <= 0 {
raise @types.LoadError::DecodeFailed("PNM 尺寸无效")
}
if pos.val >= len {
raise @types.LoadError::DecodeFailed(
"PNM 像素数据起始 whitespace 缺失",
)
}
let sep = data[pos.val].to_int()
if !pnm_is_whitespace(sep) {
raise @types.LoadError::DecodeFailed("PNM maxval 后分隔符无效")
}
pos.val += 1
@types.check_dims(width, height, channels)
let pixel_count = width * height
let is_16bit = maxval >= 256
let out_data : Array[Byte] = Array::make(pixel_count * channels * 2, b'\x00')
if is_16bit {
let pixel_bytes = pixel_count * channels * 2
if pos.val + pixel_bytes > len {
raise @types.LoadError::DecodeFailed("PNM 16-bit 像素数据不足")
}
// big-endian → little-endian
for i in 0..<(pixel_count * channels) {
let hi = data[pos.val + i * 2].to_int()
let lo = data[pos.val + i * 2 + 1].to_int()
out_data[i * 2] = lo.to_byte()
out_data[i * 2 + 1] = hi.to_byte()
}
} else {
let pixel_bytes = pixel_count * channels
if pos.val + pixel_bytes > len {
raise @types.LoadError::DecodeFailed("PNM 像素数据不足")
}
// 8-bit → upscale: v * 257
for i in 0..<pixel_bytes {
let v = data[pos.val + i].to_int() * 257
out_data[i * 2] = (v & 0xFF).to_byte()
out_data[i * 2 + 1] = ((v >> 8) & 0xFF).to_byte()
}
}
@types.Image16::{ width, height, channels, data: Bytes::from_array(out_data) }
}