2024-03-23 05:15:23 +01:00
|
|
|
package bloob
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
_ "github.com/askeladdk/aseprite"
|
|
|
|
"image"
|
|
|
|
_ "image/png"
|
|
|
|
"os"
|
|
|
|
"runtime/pprof"
|
|
|
|
"sync"
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Image struct {
|
2024-03-24 01:14:26 +01:00
|
|
|
Data []Color
|
2024-03-23 05:15:23 +01:00
|
|
|
Size Vec2i
|
|
|
|
Alpha bool
|
|
|
|
}
|
|
|
|
|
2024-03-24 01:14:26 +01:00
|
|
|
type Color = uint32
|
|
|
|
|
2024-03-23 05:15:23 +01:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
var threadProfile = pprof.Lookup("threadcreate")
|
|
|
|
|
|
|
|
func NewImage(size Vec2i) *Image {
|
2024-03-24 01:14:26 +01:00
|
|
|
return &Image{Data: make([]Color, size.Size()), Size: Vec2i{X: size.X, Y: size.Y}, Alpha: true}
|
2024-03-23 05:15:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewImageFromPointer(pointer unsafe.Pointer, size Vec2i) *Image {
|
2024-03-24 01:14:26 +01:00
|
|
|
return &Image{Data: unsafe.Slice((*Color)(pointer), size.Size()), Size: Vec2i{X: size.X, Y: size.Y}, Alpha: true}
|
2024-03-23 05:15:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func LoadImage(path string) *Image {
|
|
|
|
data, err := os.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return LoadImageBytes(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func LoadImageBytes(data []byte) *Image {
|
|
|
|
file, _, _ := image.Decode(bytes.NewReader(data))
|
|
|
|
|
|
|
|
width := file.Bounds().Max.X
|
|
|
|
height := file.Bounds().Max.Y
|
|
|
|
img := NewImage(Vec2i{X: width, Y: height})
|
|
|
|
for y := 0; y < height; y += 1 {
|
|
|
|
for x := 0; x < width; x += 1 {
|
|
|
|
r, g, b, a := file.At(x, y).RGBA()
|
|
|
|
r = r >> 8
|
|
|
|
g = g >> 8
|
|
|
|
b = b >> 8
|
|
|
|
a = a >> 8
|
|
|
|
img.Data[x+y*width] = r<<16 | g<<8 | b | a<<24
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return img
|
|
|
|
}
|
|
|
|
|
2024-03-24 01:14:26 +01:00
|
|
|
func (image *Image) Clear(color Color) {
|
2024-03-23 05:15:23 +01:00
|
|
|
for i := 0; i < image.Size.X*image.Size.Y; i += 1 {
|
|
|
|
image.Data[i] = color
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func CropToArea(sizeDst Vec2i, rectSrc Recti, posDst Vec2i) (start, end, dst Vec2i) {
|
|
|
|
if posDst.X+rectSrc.Pos.X < 0 {
|
|
|
|
start.X = -posDst.X
|
|
|
|
} else {
|
|
|
|
start.X = rectSrc.Pos.X
|
|
|
|
}
|
|
|
|
if posDst.X+rectSrc.Size.X-rectSrc.Pos.X >= sizeDst.X {
|
|
|
|
end.X = sizeDst.X - posDst.X
|
|
|
|
} else {
|
|
|
|
end.X = rectSrc.Pos.X + rectSrc.Size.X
|
|
|
|
}
|
|
|
|
|
|
|
|
if posDst.Y+rectSrc.Pos.Y < 0 {
|
|
|
|
start.Y = -posDst.Y
|
|
|
|
} else {
|
|
|
|
start.Y = rectSrc.Pos.Y
|
|
|
|
}
|
|
|
|
if posDst.Y+rectSrc.Size.Y-rectSrc.Pos.Y >= sizeDst.Y {
|
|
|
|
end.Y = sizeDst.Y - posDst.Y
|
|
|
|
} else {
|
|
|
|
end.Y = rectSrc.Pos.Y + rectSrc.Size.Y
|
|
|
|
}
|
|
|
|
dst = Sub(posDst, rectSrc.Pos)
|
|
|
|
//println(dst.X, posDst.X, rectSrc.Pos.X)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-03-25 01:55:14 +01:00
|
|
|
func (image *Image) DrawPixel(pos Vec2i, color Color) {
|
|
|
|
image.Data[pos.X+pos.Y*image.Size.X] = color
|
|
|
|
}
|