img2gif
This commit is contained in:
+2
-1
@@ -3,5 +3,6 @@ imageutils.test
|
|||||||
cpu.out
|
cpu.out
|
||||||
profile.out
|
profile.out
|
||||||
*.png
|
*.png
|
||||||
|
*.gif
|
||||||
*.jpg
|
*.jpg
|
||||||
*.jpeg
|
*.jpeg
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
}
|
import (
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Options any
|
||||||
|
|
||||||
|
type Modifunc func(image.Image) image.Image
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/gif"
|
||||||
|
_ "image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r, w := os.Stdin, os.Stdout
|
||||||
|
img, format, err := image.Decode(r)
|
||||||
|
println("registered format:", format)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = gif.Encode(w, img, &gif.Options{256, nil, nil})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package url_values
|
||||||
|
|
||||||
|
func UnmarshalURLValues(values url.Values) map[string]any {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var noSuchField = errors.New("no such field")
|
||||||
|
|
||||||
|
func Pull(V any, m map[string]any) error {
|
||||||
|
v := reflect.ValueOf(V).Elem()
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
value, ok := m[strings.ToLower(v.Field(i).Name)]
|
||||||
|
if !ok {
|
||||||
|
return noSuchField
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Push(V any, m map[string]any) error {
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//go:build gist
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/gif"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Circle struct {
|
||||||
|
X, Y, R float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Circle) Brightness(x, y float64) uint8 {
|
||||||
|
var dx, dy float64 = c.X - x, c.Y - y
|
||||||
|
d := math.Sqrt(dx*dx+dy*dy) / c.R
|
||||||
|
if d > 1 {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return 255
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var w, h int = 240, 240
|
||||||
|
|
||||||
|
var palette = []color.Color{
|
||||||
|
color.RGBA{0x00, 0x00, 0x00, 0xff}, color.RGBA{0x00, 0x00, 0xff, 0xff},
|
||||||
|
color.RGBA{0x00, 0xff, 0x00, 0xff}, color.RGBA{0x00, 0xff, 0xff, 0xff},
|
||||||
|
color.RGBA{0xff, 0x00, 0x00, 0xff}, color.RGBA{0xff, 0x00, 0xff, 0xff},
|
||||||
|
color.RGBA{0xff, 0xff, 0x00, 0xff}, color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
var images []*image.Paletted
|
||||||
|
var delays []int
|
||||||
|
|
||||||
|
var hw, hh float64 = float64(w / 2), float64(h / 2)
|
||||||
|
circles := []*Circle{&Circle{}, &Circle{}, &Circle{}}
|
||||||
|
steps := 20
|
||||||
|
for step := 0; step < steps; step++ {
|
||||||
|
img := image.NewPaletted(image.Rect(0, 0, w, h), palette)
|
||||||
|
images = append(images, img)
|
||||||
|
delays = append(delays, 0)
|
||||||
|
|
||||||
|
θ := 2.0 * math.Pi / float64(steps) * float64(step)
|
||||||
|
for i, circle := range circles {
|
||||||
|
θ0 := 2 * math.Pi / 3 * float64(i)
|
||||||
|
println(θ0)
|
||||||
|
circle.X = hw - math.Sin(θ0) - math.Sin(θ0+θ)
|
||||||
|
circle.Y = hh - math.Cos(θ0) - math.Cos(θ0+θ)
|
||||||
|
circle.R = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
for y := 0; y < h; y++ {
|
||||||
|
img.Set(x, y, color.RGBA{
|
||||||
|
circles[0].Brightness(float64(x), float64(y)),
|
||||||
|
circles[1].Brightness(float64(x), float64(y)),
|
||||||
|
circles[2].Brightness(float64(x), float64(y)),
|
||||||
|
255,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile("rgb.gif", os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
gif.EncodeAll(f, &gif.GIF{
|
||||||
|
Image: images,
|
||||||
|
Delay: delays,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
//go:build pull
|
||||||
|
package rotate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Rotate struct {
|
||||||
|
image.Image
|
||||||
|
Angle float64 // math.Pi * n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rot Rotate) Bounds() image.Rectangle { return rot.Image.Bounds() }
|
||||||
|
func (rot Rotate) ColorModel() color.Model { return rot.Image.ColorModel() }
|
||||||
|
|
||||||
|
func (rot Rotate) At(x, y int) color.Color {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package rotate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Rotate(img image.Image, angle float64) image.Image {
|
||||||
|
newImg := image.NewRGBA(img.Bounds())
|
||||||
|
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
hh, hw := float64(h/2), float64(w/2)
|
||||||
|
|
||||||
|
for y := 0; y < w; y++ {
|
||||||
|
for x := 0; x < h; x++ {
|
||||||
|
newImg.Set(
|
||||||
|
int(hh-math.Cos(angle)),
|
||||||
|
int(hw-math.Sin(angle)),
|
||||||
|
img.At(x, y),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newImg
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package rotate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/png"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRender(t *testing.T) {
|
||||||
|
gopherImg, err := func() (image.Image, error) {
|
||||||
|
r, err := http.Get("https://go.dev/images/favicon-gopher.png")
|
||||||
|
defer r.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
img, err := png.Decode(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return img, nil
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("img.png")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
err = png.Encode(f, Rotate(gopherImg, math.Pi/6))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
type Set map[color.Color]struct{}
|
||||||
|
|
||||||
|
func PaletteFromImage(img image.Image) color.Palette {
|
||||||
|
m := Set{}
|
||||||
|
for y := 0; y < img.Bounds().Dy(); y++ {
|
||||||
|
for x := 0; x < img.Bounds().Dx(); x++ {
|
||||||
|
m[img.At] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(m Set)(p color.Palette){
|
||||||
|
for k := range m {
|
||||||
|
p = append(p, k)
|
||||||
|
}
|
||||||
|
}(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageToPaletted(img image.Image) (image.Paletted) {
|
||||||
|
p := image.NewPaletted(img.Bounds(), PaletteFromImage(img))
|
||||||
|
|
||||||
|
for y := 0; y < img.Bounds().Dy(); y++ {
|
||||||
|
for x := 0; x < img.Bounds().Dx(); x++ {
|
||||||
|
p.Set(x, y, img.At(x,y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user