mirror of
https://github.com/zserge/fenster.git
synced 2025-07-17 09:16:12 +03:00
28
.github/workflows/go.yml
vendored
Normal file
28
.github/workflows/go.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# This workflow will build a golang project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
|
||||
|
||||
name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.x
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
@ -1,3 +1,5 @@
|
||||
//go:build example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -20,11 +22,11 @@ func main() {
|
||||
// Fill screen with random noise
|
||||
for i := 0; i < 240; i++ {
|
||||
for j := 0; j < 320; j++ {
|
||||
f.SetPixel(j, i, rand.Uint32())
|
||||
f.Set(j, i, fenster.RGB(rand.Uint32()))
|
||||
}
|
||||
}
|
||||
// Wait for FPS rate
|
||||
sleep := 16*time.Millisecond - time.Now().Sub(lastFrame)
|
||||
sleep := 16*time.Millisecond - time.Since(lastFrame)
|
||||
if sleep > 0 {
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
|
BIN
examples/testdata/Testbild.png
vendored
Normal file
BIN
examples/testdata/Testbild.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
58
examples/testimage.go
Normal file
58
examples/testimage.go
Normal file
@ -0,0 +1,58 @@
|
||||
//go:build example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color/palette"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/zserge/fenster"
|
||||
)
|
||||
|
||||
func openImage(fname string) (image.Image, error) {
|
||||
fd, err := os.Open(fname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return png.Decode(fd)
|
||||
}
|
||||
|
||||
func main() {
|
||||
f := fenster.New()
|
||||
f.Open(320, 240, "Hello")
|
||||
defer f.Close()
|
||||
lastFrame := time.Now()
|
||||
|
||||
img, err := openImage("testdata/Testbild.png")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// convert to paletted image
|
||||
pimg := image.NewPaletted(img.Bounds(), palette.Plan9)
|
||||
draw.Draw(pimg, pimg.Bounds(), img, image.Point{}, draw.Src)
|
||||
|
||||
for f.Loop() {
|
||||
// If escape is pressed - exit
|
||||
if f.Key(27) {
|
||||
break
|
||||
}
|
||||
|
||||
// rotate palette
|
||||
pimg.Palette = append(pimg.Palette[1:], pimg.Palette[0])
|
||||
draw.Draw(f, f.Bounds(), pimg, image.Point{}, draw.Src)
|
||||
|
||||
// Wait for FPS rate
|
||||
sleep := 16*time.Millisecond - time.Since(lastFrame)
|
||||
if sleep > 0 {
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
lastFrame = time.Now()
|
||||
}
|
||||
}
|
41
fenster.go
41
fenster.go
@ -9,6 +9,9 @@ package fenster
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
@ -22,10 +25,33 @@ type Fenster interface {
|
||||
Open(w, h int, title string) error
|
||||
Loop() bool
|
||||
Close()
|
||||
Pixel(x int, y int) uint32
|
||||
SetPixel(x int, y int, rgb uint32)
|
||||
Key(byte) bool
|
||||
Mod() Mods
|
||||
draw.Image
|
||||
}
|
||||
|
||||
// RGB Color 00RRGGBB
|
||||
type RGB uint32
|
||||
|
||||
func (c RGB) RGBA() (r uint32, g uint32, b uint32, a uint32) {
|
||||
r = uint32(c>>16) & 0xff
|
||||
r |= r << 8
|
||||
g = uint32(c>>8) & 0xff
|
||||
g |= g << 8
|
||||
b = uint32(c) & 0xff
|
||||
b |= b << 8
|
||||
a = 0xffff
|
||||
return r, g, b, a
|
||||
}
|
||||
|
||||
var RGBModel = color.ModelFunc(rgbModel)
|
||||
|
||||
func rgbModel(c color.Color) color.Color {
|
||||
if _, ok := c.(RGB); ok {
|
||||
return c
|
||||
}
|
||||
r, g, b, _ := c.RGBA()
|
||||
return RGB((r>>8)<<16 | (g>>8)<<8 | (b >> 8))
|
||||
}
|
||||
|
||||
type Mods int
|
||||
@ -35,6 +61,11 @@ type fenster struct {
|
||||
buf []uint32
|
||||
}
|
||||
|
||||
func (f *fenster) ColorModel() color.Model { return RGBModel }
|
||||
func (f *fenster) Bounds() image.Rectangle {
|
||||
return image.Rect(0, 0, int(f.f.width), int(f.f.height))
|
||||
}
|
||||
|
||||
func New() Fenster { return &fenster{} }
|
||||
func (f *fenster) Open(w, h int, title string) error {
|
||||
f.f.title = C.CString(title)
|
||||
@ -54,5 +85,7 @@ func (f *fenster) Close() { C.fenster_close(&f.f) }
|
||||
func (f *fenster) Key(code byte) bool { return f.f.keys[code] != 0 }
|
||||
func (f *fenster) Mod() Mods { return Mods(f.f.mod) }
|
||||
|
||||
func (f *fenster) Pixel(x, y int) uint32 { return f.buf[y*int(f.f.width)+x] }
|
||||
func (f *fenster) SetPixel(x, y int, color uint32) { f.buf[y*int(f.f.width)+x] = color }
|
||||
func (f *fenster) At(x, y int) color.Color { return RGB(f.buf[y*int(f.f.width)+x]) }
|
||||
func (f *fenster) Set(x, y int, c color.Color) {
|
||||
f.buf[y*int(f.f.width)+x] = uint32(f.ColorModel().Convert(c).(RGB))
|
||||
}
|
||||
|
Reference in New Issue
Block a user