fn save_png(path : String, png_data : Bytes) -> Bool raise @fs.IOError {
match (try? @fs.write_bytes_to_file(path, png_data)) {
Ok(_) => true
Err(e) => {
raise e
false
}
}
}
// 渐变色映射工具
// 将 H, S, L 映射为 RGB(输入:h ∈ [0,360], s ∈ [0,1], l ∈ [0,1])
fn hsl_to_rgb(h : Float, s : Float, l : Float) -> (Byte, Byte, Byte) {
let c = (1.0 - (2.0 * l.to_double() - 1.0).abs()) * s.to_double()
let h_ = h / 60.0
let x = c * (1.0 - (h_.to_double() % 2.0 - 1.0).abs())
let (r1, g1, b1) = if h_ < 1.0 {
(c, x, 0.0)
} else if h_ < 2.0 {
(x, c, 0.0)
} else if h_ < 3.0 {
(0.0, c, x)
} else if h_ < 4.0 {
(0.0, x, c)
} else if h_ < 5.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
}
let m = l - c.to_float() * 0.5
fn to_byte_safe(v : Float) -> Byte {
let p = 0
let q = 255
let i = (v * 255.0).to_int()
if i < 0 {
p.to_byte()
} else if i > 255 {
q.to_byte()
} else {
i.to_byte()
}
}
let r = to_byte_safe(r1.to_float() + m)
let g = to_byte_safe(g1.to_float() + m)
let b = to_byte_safe(b1.to_float() + m)
(r, g, b)
}
fn noise_to_color(val : Float) -> @color.RGBA {
let hue = val * 360.0 % 360.0 // 色相映射(让噪声值对应颜色环)
let sat : Float = 0.6
let light : Float = 0.5
let c = 255
let (r, g, b) = hsl_to_rgb(hue, sat, light)
@color.RGBA::new(r, g, b, c.to_byte())
}
// 生成指定尺寸的 2D Simplex Noise图像
fn generate_noise_png_buffer(
width : Int,
height : Int,
scale : Float,
seed : Int,
grads : Array[Array[Float]],
useWarp : Bool, // 添加 useWarp 参数来控制是否使用 warp2d
isGrayScale : Bool, // 是否生成灰度图
strength : Float // 扰动强度
) -> Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0.. Bytes raise @image.SizeError {
let buf = @io.Buffer::new(size_hint=1024)
let perm_table = init_noise(seed)
let bounds = @image.rect(0, 0, width, height)
if isGrayScale {
let img = @image.Gray::new(bounds)
for y in 0.. 255.0 {
255
} else {
raw_val.to_int()
}
img.set_gray(x, y, @color.Gray::new(gray_val.to_byte()))
}
}
ignore(@png.encode(buf, img))
} else {
let img = @image.RGBA::new(bounds)
for y in 0..