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
// 流式解码接口(纯 MoonBit)
// 提供逐行/分块回调式解码接口(当前为全量解码后逐行分发,未来支持增量解码)
///|
/// 流式解码信息
pub(all) struct StreamInfo {
width : Int
height : Int
channels : Int
}
///|
/// 流式解码:逐行回调处理。
/// on_row 回调接收 (行号, 行数据) 参数。
/// 行数据为 w*channels 个字节,按 RGB/RGBA 顺序排列。
pub fn decode_stream(
data : Bytes,
on_row : (Int, Array[Byte]) -> Unit,
) -> StreamInfo raise @types.LoadError {
let img = load_from_bytes_auto(data)
let w = img.width
let h = img.height
let ch = img.channels
let row_data : Array[Byte] = Array::make(w * ch, b'\x00')
for y in 0..<h {
for x in 0..<w {
for c in 0..<ch {
row_data[x * ch + c] = img.data[(y * w + x) * ch + c]
}
}
on_row(y, row_data)
}
StreamInfo::{ width: w, height: h, channels: ch }
}
///|
/// 分块流式解码:每 chunk_height 行回调一次。
/// on_chunk 回调接收 (起始行号, 块图像) 参数。
/// 适用于分块处理大图,减少回调开销。
pub fn decode_stream_chunked(
data : Bytes,
chunk_height : Int,
on_chunk : (Int, @types.Image) -> Unit,
) -> StreamInfo raise @types.LoadError {
let img = load_from_bytes_auto(data)
let w = img.width
let h = img.height
let ch = img.channels
let chunk_h = if chunk_height < 1 { 1 } else { chunk_height }
let mut y = 0
while y < h {
let end_y = if y + chunk_h > h { h } else { y + chunk_h }
let block_h = end_y - y
let block_data : Array[Byte] = Array::make(w * block_h * ch, b'\x00')
for by in 0..<block_h {
for x in 0..<w {
for c in 0..<ch {
block_data[(by * w + x) * ch + c] = img.data[((y + by) * w + x) * ch +
c]
}
}
}
let block_img = @types.Image::{
width: w,
height: block_h,
channels: ch,
data: Bytes::from_array(block_data),
}
on_chunk(y, block_img)
y = end_y
}
StreamInfo::{ width: w, height: h, channels: ch }
}
///|
/// 流式解码(带 req_channels):指定输出通道数。
pub fn decode_stream_channels(
data : Bytes,
req_channels : Int,
on_row : (Int, Array[Byte]) -> Unit,
) -> StreamInfo raise @types.LoadError {
let img = load_from_bytes_auto(data, req_channels=Some(req_channels))
let w = img.width
let h = img.height
let ch = img.channels
let row_data : Array[Byte] = Array::make(w * ch, b'\x00')
for y in 0..<h {
for x in 0..<w {
for c in 0..<ch {
row_data[x * ch + c] = img.data[(y * w + x) * ch + c]
}
}
on_row(y, row_data)
}
StreamInfo::{ width: w, height: h, channels: ch }
}