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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// 图像混合与翻转(纯 MoonBit)
///|
/// Alpha 混合两张图像。
/// alpha: 0.0 = 完全显示 img1, 1.0 = 完全显示 img2
/// 要求两张图像尺寸和通道数相同。
pub fn alpha_blend(
img1 : @types.Image,
img2 : @types.Image,
alpha : Float,
) -> @types.Image raise @types.LoadError {
if img1.width != img2.width || img1.height != img2.height {
raise @types.LoadError::DecodeFailed("alpha_blend: 图像尺寸不同")
}
if img1.channels != img2.channels {
raise @types.LoadError::DecodeFailed("alpha_blend: 图像通道数不同")
}
let n = img1.width * img1.height * img1.channels
let result : Array[Byte] = []
let a = alpha.clamp(min=0.0F, max=1.0F)
for i in 0..<n {
let v1 = img1.data[i].to_int()
let v2 = img2.data[i].to_int()
let blended = (Float::from_int(v1) * (1.0F - a) + Float::from_int(v2) * a).to_int()
result.push(blended.clamp(min=0, max=255).to_byte())
}
@types.Image::{
width: img1.width,
height: img1.height,
channels: img1.channels,
data: Bytes::from_array(result),
}
}
///|
/// 使用掩码混合两张图像。
/// 掩码为单通道灰度图,白色(255)显示 img2,黑色(0)显示 img1。
/// 要求掩码与图像尺寸相同。
pub fn mask_blend(
img1 : @types.Image,
img2 : @types.Image,
mask : @types.Image,
) -> @types.Image raise @types.LoadError {
if img1.width != img2.width || img1.height != img2.height {
raise @types.LoadError::DecodeFailed("mask_blend: 图像尺寸不同")
}
if img1.channels != img2.channels {
raise @types.LoadError::DecodeFailed("mask_blend: 图像通道数不同")
}
if mask.channels != 1 {
raise @types.LoadError::DecodeFailed("mask_blend: 掩码必须为单通道")
}
if mask.width != img1.width || mask.height != img1.height {
raise @types.LoadError::DecodeFailed("mask_blend: 掩码尺寸不同")
}
let w = img1.width
let h = img1.height
let ch = img1.channels
let result : Array[Byte] = []
for y in 0..<h {
for x in 0..<w {
let m = Float::from_int(mask.data[y * w + x].to_int()) / 255.0F
for c in 0..<ch {
let idx = (y * w + x) * ch + c
let v1 = img1.data[idx].to_int()
let v2 = img2.data[idx].to_int()
let blended = (Float::from_int(v1) * (1.0F - m) +
Float::from_int(v2) * m).to_int()
result.push(blended.clamp(min=0, max=255).to_byte())
}
}
}
@types.Image::{
width: w,
height: h,
channels: ch,
data: Bytes::from_array(result),
}
}
///|
/// 水平翻转图像。
pub fn flip_horizontal(img : @types.Image) -> @types.Image {
let w = img.width
let h = img.height
let ch = img.channels
let result : Array[Byte] = []
for y in 0..<h {
for x in 0..<w {
let src_x = w - 1 - x
for c in 0..<ch {
result.push(img.data[(y * w + src_x) * ch + c])
}
}
}
@types.Image::{
width: w,
height: h,
channels: ch,
data: Bytes::from_array(result),
}
}
///|
/// 垂直翻转图像。
pub fn flip_vertical(img : @types.Image) -> @types.Image {
let w = img.width
let h = img.height
let ch = img.channels
let result : Array[Byte] = []
for y in 0..<h {
let src_y = h - 1 - y
for x in 0..<w {
for c in 0..<ch {
result.push(img.data[(src_y * w + x) * ch + c])
}
}
}
@types.Image::{
width: w,
height: h,
channels: ch,
data: Bytes::from_array(result),
}
}