diff --git a/cmd/httputil/handler.go b/cmd/httputil/handler.go new file mode 100644 index 0000000..b4c0ec4 --- /dev/null +++ b/cmd/httputil/handler.go @@ -0,0 +1,25 @@ +package main + +type FileWithOptions struct { + Options map[string]string + io.Reader +} + +func mapToStruct[T any](m map[string]string, a T) T { + t := reflect.TypeOf(a) + for _, v := range reflect.VisibleFields(t) { + v. + } +} + +func Handle(img image.Image) http.Handler { + func(w http.ResponseWriter, + r *http.Request) { + err := png.Encode(w, img) + if err != nil { + log.Fatal(err) + w.WriteHeader(500) + return + } + } +} diff --git a/cmd/httputil/readme b/cmd/httputil/readme new file mode 100644 index 0000000..9d84e0e --- /dev/null +++ b/cmd/httputil/readme @@ -0,0 +1,2 @@ +input: image with modifier options + output: png image diff --git a/cmd/httputil/type.go b/cmd/httputil/type.go new file mode 100644 index 0000000..b418d7a --- /dev/null +++ b/cmd/httputil/type.go @@ -0,0 +1,3 @@ +package main + +} diff --git a/cmd/repalette/repalette.go b/cmd/repalette/repalette.go new file mode 100644 index 0000000..e89b1b9 --- /dev/null +++ b/cmd/repalette/repalette.go @@ -0,0 +1,91 @@ +package main + +func parseMap(fields []string) (map[string]string, error) { + m := map[string]string{} + var k, v string + + for i, v := range fields { + if v == "=" { + return nil, errors.New("bad field") + } + if len(v) > 1 { + // check if "=" is the last or first character + if "=" == v[0] { + return nil, errors.New("no key") + } + if "=" == v[len(v)-1] { + return nil, errors.New("no value") + } + } + if strings.Contains(v, "=") { + splitted := strings.Split(v, "=") + k, v = splitted[0], splitted[1] + m[k] = v + if i == len(fields)-1 { + return m, nil + } + continue + } + return nil, errors.New("no equality sign in field") + } + return nil, errors.New("everything is wrong!") +} + +type Map map[color.Color]color.Color +type repalette struct { + image.Image + Map +} + +func (r repalette) ColorModel() color.Model { + return r.Image.ColorModel() +} +func (r repalette) Bounds() image.Rectangle { + return r.Image.Bounds() +} +func (r repalette) At(x, y int) color.Color { + v := r.Image.At(x, y) + newColor, ok := r.Map[v] + if !ok { + return v + } + return newColor +} + +func main() { + fields := os.Args[1:] + m, err := parseMap(fields) + if err != nil { + panic("parseMap:", err) + } + + errParseHexColor := errors.New("parse hex color:") + newPalette, err := + func(m map[string]string) (newMap map[color.Color]color.Color, err error) { + for k, v := range m { + newKey, err := util.ParseHexColor(k) + if err != nil { + return nil, errors.Join( + errors.New("bad key hex value."), + errors.Join(errParseHexColor, err), + ) + } + newValue, err := util.ParseHexColor(v) + if err != nil { + return nil, errors.Join( + errors.New("bad value hex value."), + errors.Join(errParseHexColor, err), + ) + } + newMap[newKey] = newValue + } + return + }(fields) + if err != nil { + panic(errors.Join(errors.New("palette parsing:"), err)) + } + err = util.ProcessStdio(func(img image.Image) image.Image { return repalette{img, newPalette} }) + if err != nil { + panic(errors.Join(errors.New("process stdio:"), err)) + } +} diff --git a/go.mod b/go.mod index e139c9f..c7abb5b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.nkpl.cc/twocookedfaggots/imageutils -go 1.25.5 +go 1.26.4 require ( github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 diff --git a/http/actions_collection.go b/http/actions_collection.go new file mode 100644 index 0000000..bcdeea8 --- /dev/null +++ b/http/actions_collection.go @@ -0,0 +1,7 @@ +package http + +type Modifyer interface { + image.Image +} + +type Actions map[string]Modifyer diff --git a/pkg/dithering/grid.go b/pkg/dithering/grid.go index 3ff03d0..a007856 100644 --- a/pkg/dithering/grid.go +++ b/pkg/dithering/grid.go @@ -7,10 +7,14 @@ import ( const side = 16 +type Options struct { + Factor float64 +} + // tile type grid struct { color.Gray - Factor float64 + Options } func (_ grid) ColorModel() color.Model { @@ -22,7 +26,7 @@ func (_ grid) Bounds() image.Rectangle { } func (g grid) At(x, y int) color.Color { - n := uint8(float64(g.Gray.Y) * g.Factor) + n := uint8(float64(g.Gray.Y) * g.Options.Factor) if n == 0 { return color.Black @@ -54,13 +58,13 @@ func (g uniformGrid) At(x, y int) color.Color { type Dithering struct { image.Image - Factor float64 + Options } func (d Dithering) ColorModel() color.Model { return color.GrayModel } func (d Dithering) Bounds() image.Rectangle { return d.Image.Bounds() } func (d Dithering) At(x, y int) color.Color { c := color.GrayModel.Convert(d.Image.At(x, y)) - return uniformGrid{grid{c.(color.Gray), d.Factor}}. + return uniformGrid{grid{c.(color.Gray), d.Options.Factor}}. At(x, y) } diff --git a/pkg/dithering/grid_test.go b/pkg/dithering/grid_test.go index 8e300cd..fe044f0 100644 --- a/pkg/dithering/grid_test.go +++ b/pkg/dithering/grid_test.go @@ -9,6 +9,7 @@ import ( "os/exec" "testing" "time" + "reflect" "git.nkpl.cc/twocookedfaggots/imageutils" ) @@ -17,6 +18,8 @@ func init() { rand.Seed(time.Now().UnixNano()) } +const factor = 0.75 + func callImage(img image.Image) { for y := 0; y < img.Bounds().Dy(); y++ { for x := 0; x < img.Bounds().Dx(); x++ { @@ -38,14 +41,14 @@ func TestGrid(t *testing.T) { n := uint8(rand.Int() % 256) t.Log(n) - img := imageutils.Scale(1<<6, grid{color.Gray{n}}) + img := imageutils.Scale(grid{color.Gray{n}, factor}, 1<<6) err = png.Encode(w, img) if err != nil { t.Fatal(err) } - callImage(grid{color.Gray{4}}) - callImage(grid{color.Gray{0}}) + callImage(grid{color.Gray{4}, factor}) + callImage(grid{color.Gray{0}, factor}) } func TestDithering(t *testing.T) { @@ -66,8 +69,48 @@ func TestDithering(t *testing.T) { t.Fatal(err) } - err = png.Encode(w, Dithering{img}) + err = png.Encode(w, Dithering{img, factor}) if err != nil { t.Fatal(err) } } + +func TestRangeStruct(t *testing.T){ + s := Dithering{image.Rectangle{},0} + value := reflect.ValueOf(s) + if value.Kind() == reflect.Ptr { + value = value.Elem() + } + if value.Kind() != reflect.Struct { + t.Log("Provided value is not a struct") + } + tp := value.Type() + for i := 0; i < value.NumField(); i++ { + fieldName := tp.Field(i).Name + fieldValue := value.Field(i) + + if !fieldValue.CanInterface() { + t.Logf("Field %s is unexported\n", fieldName) + continue + } + if fieldValue.Kind() == reflect.Ptr { + fieldValue = fieldValue.Elem() + } + /* + if fieldValue.Kind() == reflect.Interface { + fieldValue = fieldValue.Elem() + } + */ + + + actualValue := fieldValue.Interface() + switch v := actualValue.(type) { + case float64: + t.Logf("Field '%s' is a float64.\n", fieldName) + case image.Image: + t.Logf("Field '%s' is a image.Image. Value: %q\n", fieldName, v) + default: + t.Logf("Field '%s' has an unhandled type: %T\n", fieldName, v) + } + } +} diff --git a/pkg/dithering/http.go b/pkg/dithering/http.go new file mode 100644 index 0000000..fb55b92 --- /dev/null +++ b/pkg/dithering/http.go @@ -0,0 +1,20 @@ +//go:build ignore +package dithering + +func valueOfType(a any) reflect.Value { + return reflect.TypeOf(a).Elem() +} + +func ServeHTTP(w http.ResponseWriter, req* http.Request) { + instance := new(Dithering{}) + value := reflect.ValueOf(instance).Elem() + imageType := valueOfType(new(image.Image)) + floatType := valueOfType + + for i := 0; i < value.NumField(); i++ { + v := value.Field(i) + switch v.Type() { + case imageType + } + } +} diff --git a/pkg/dithering/sample.png b/pkg/dithering/sample.png index bcc389e..4fc366e 100644 Binary files a/pkg/dithering/sample.png and b/pkg/dithering/sample.png differ diff --git a/pkg/mirror/cmd/.interface.md.swp b/pkg/mirror/cmd/.interface.md.swp new file mode 100644 index 0000000..f7cb4df Binary files /dev/null and b/pkg/mirror/cmd/.interface.md.swp differ diff --git a/pkg/mirror/cmd/http_form.go b/pkg/mirror/cmd/http_form.go new file mode 100644 index 0000000..7edcaec --- /dev/null +++ b/pkg/mirror/cmd/http_form.go @@ -0,0 +1,20 @@ +package main + +import ( + "reflect" + + "git.nkpl.cc/twocookedfaggots/imageutils/pkg/mirror" +) + +func main() { + cmp := func(v reflect.Value) { + switch v := reflect.f { + case + } + } + instance := &mirror.Mirror{} + value := reflect.ValueOf(instance).Elem() + for i := 0; i < value.NumField(); i++ { + value.Type().Field(i) + } +} diff --git a/pkg/mirror/cmd/httpformtest.go b/pkg/mirror/cmd/httpformtest.go new file mode 100644 index 0000000..4b3c72b --- /dev/null +++ b/pkg/mirror/cmd/httpformtest.go @@ -0,0 +1,16 @@ +package main + +import ( + "log" + "net/http" +) + +func main() { + addr := ":8080" + http.HandleFunc("/", + func(w http.ResponseWriter, req *http.Request) { + log.Println(req.URL.Query()) + }) + log.Println("listening on", addr) + log.Fatal(http.ListenAndServe(addr, nil)) +} diff --git a/pkg/mirror/cmd/interface.md b/pkg/mirror/cmd/interface.md new file mode 100644 index 0000000..620554f --- /dev/null +++ b/pkg/mirror/cmd/interface.md @@ -0,0 +1,5 @@ +image modifyer consists of: + input image + options + output (modifyed image) + usually Encoder diff --git a/pkg/mirror/mirror.go b/pkg/mirror/mirror.go new file mode 100644 index 0000000..d6a9d20 --- /dev/null +++ b/pkg/mirror/mirror.go @@ -0,0 +1,22 @@ +package mirror + +import ( + "image" + "image/color" +) + +type Mirror struct { + image.Image +} + +func (m Mirror) ColorModel() color.Model { + return m.Image.ColorModel() +} + +func (m Mirror) Bounds() image.Rectangle { + return m.Image.Bounds() +} + +func (m Mirror) At(x, y int) color.Color { + return m.Image.At(m.Bounds().Dx()-x, y) +} diff --git a/transform.go b/transform.go index 14ae62b..b94cb9b 100644 --- a/transform.go +++ b/transform.go @@ -1,5 +1 @@ package imageutils - -type Transformer interface { - Transform(image.Image) image.Image -}