wip
This commit is contained in:
parent
d41eba2a2b
commit
bfbd0a63cc
@ -2,4 +2,11 @@ module git.neet.dev/zuckerberg/dynamic-frame/server
|
|||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require github.com/go-chi/chi/v5 v5.0.8
|
require (
|
||||||
|
github.com/go-chi/chi/v5 v5.0.8
|
||||||
|
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3
|
||||||
|
github.com/muesli/smartcrop v0.3.0
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/image v0.7.0 // indirect
|
||||||
|
@ -1,2 +1,41 @@
|
|||||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 h1:BXxTozrOU8zgC5dkpn3J6NTRdoP+hjok/e+ACr4Hibk=
|
||||||
|
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3/go.mod h1:x1uk6vxTiVuNt6S5R2UYgdhpj3oKojXvOXauHZ7dEnI=
|
||||||
|
github.com/muesli/smartcrop v0.3.0 h1:JTlSkmxWg/oQ1TcLDoypuirdE8Y/jzNirQeLkxpA6Oc=
|
||||||
|
github.com/muesli/smartcrop v0.3.0/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78RwcQLUkocpI=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
|
||||||
|
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
168
server/main.go
168
server/main.go
@ -3,10 +3,26 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
_ "image/gif"
|
||||||
|
"image/jpeg"
|
||||||
|
_ "image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
|
||||||
|
"github.com/mattn/go-ciede2000"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
|
||||||
|
"github.com/muesli/smartcrop"
|
||||||
|
"github.com/muesli/smartcrop/nfnt"
|
||||||
|
"github.com/nfnt/resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define a function to handle incoming requests
|
// Define a function to handle incoming requests
|
||||||
@ -23,18 +39,149 @@ func requestHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintf(w, "Hello, %s!\n", name)
|
fmt.Fprintf(w, "Hello, %s!\n", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EInkColor uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EPD_7IN3F_BLACK = 0x0
|
EPD_7IN3F_BLACK EInkColor = 0x0
|
||||||
EPD_7IN3F_WHITE = 0x1
|
EPD_7IN3F_WHITE EInkColor = 0x1
|
||||||
EPD_7IN3F_GREEN = 0x2
|
EPD_7IN3F_GREEN EInkColor = 0x2
|
||||||
EPD_7IN3F_BLUE = 0x3
|
EPD_7IN3F_BLUE EInkColor = 0x3
|
||||||
EPD_7IN3F_RED = 0x4
|
EPD_7IN3F_RED EInkColor = 0x4
|
||||||
EPD_7IN3F_YELLOW = 0x5
|
EPD_7IN3F_YELLOW EInkColor = 0x5
|
||||||
EPD_7IN3F_ORANGE = 0x6
|
EPD_7IN3F_ORANGE EInkColor = 0x6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ColorDefinition struct {
|
||||||
|
Color color.RGBA
|
||||||
|
Code EInkColor
|
||||||
|
}
|
||||||
|
|
||||||
|
// var Colors = []ColorDefinition{
|
||||||
|
// {color.RGBA{0, 0, 0, 255}, EPD_7IN3F_BLACK},
|
||||||
|
// {color.RGBA{255, 255, 255, 255}, EPD_7IN3F_WHITE},
|
||||||
|
// {color.RGBA{0, 255, 0, 255}, EPD_7IN3F_GREEN},
|
||||||
|
// {color.RGBA{0, 0, 255, 255}, EPD_7IN3F_BLUE},
|
||||||
|
// {color.RGBA{255, 0, 0, 255}, EPD_7IN3F_RED},
|
||||||
|
// {color.RGBA{255, 255, 0, 255}, EPD_7IN3F_YELLOW},
|
||||||
|
// {color.RGBA{255, 165, 0, 255}, EPD_7IN3F_ORANGE},
|
||||||
|
// }
|
||||||
|
|
||||||
|
var Colors = []ColorDefinition{
|
||||||
|
{color.RGBA{0, 0, 0, 255}, EPD_7IN3F_BLACK},
|
||||||
|
{color.RGBA{255, 255, 255, 255}, EPD_7IN3F_WHITE},
|
||||||
|
{color.RGBA{16, 84, 31, 255}, EPD_7IN3F_GREEN},
|
||||||
|
{color.RGBA{16, 38, 86, 255}, EPD_7IN3F_BLUE},
|
||||||
|
{color.RGBA{147, 17, 3, 255}, EPD_7IN3F_RED},
|
||||||
|
{color.RGBA{251, 193, 2, 255}, EPD_7IN3F_YELLOW},
|
||||||
|
{color.RGBA{203, 66, 5, 255}, EPD_7IN3F_ORANGE},
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertToEInkColor(c color.RGBA) EInkColor {
|
||||||
|
minDist := math.MaxFloat64
|
||||||
|
minCode := EInkColor(0)
|
||||||
|
for _, def := range Colors {
|
||||||
|
dist := colorDistance(c, def.Color)
|
||||||
|
if dist < minDist {
|
||||||
|
minDist = dist
|
||||||
|
minCode = def.Code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func colorDistance(a, b color.RGBA) float64 {
|
||||||
|
// r := float64(a.R) - float64(b.R)
|
||||||
|
// g := float64(a.G) - float64(b.G)
|
||||||
|
// bb := float64(a.B) - float64(b.B)
|
||||||
|
// return math.Sqrt(r*r + g*g + bb*bb)
|
||||||
|
return ciede2000.Diff(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func imageToRGBA(src image.Image) *image.RGBA {
|
||||||
|
// No conversion needed if image is an *image.RGBA.
|
||||||
|
if dst, ok := src.(*image.RGBA); ok {
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the image/draw package to convert to *image.RGBA.
|
||||||
|
b := src.Bounds()
|
||||||
|
dst := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||||
|
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertToEInkImage(src image.Image) []byte {
|
||||||
|
rgbImage := imageToRGBA(src)
|
||||||
|
|
||||||
|
var image []byte
|
||||||
|
|
||||||
|
for y := 0; y < src.Bounds().Max.Y; y++ {
|
||||||
|
for x := 0; x < src.Bounds().Max.X; x++ {
|
||||||
|
image = append(image, byte(ConvertToEInkColor(rgbImage.RGBAAt(x, y))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image = packBytesIntoNibbles(image)
|
||||||
|
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
|
||||||
|
func packBytesIntoNibbles(input []byte) []byte {
|
||||||
|
// input must divisible by 2
|
||||||
|
|
||||||
|
var output []byte
|
||||||
|
|
||||||
|
for x := 0; x < len(input); x += 2 {
|
||||||
|
output = append(output, (input[x]<<4)|input[x+1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
func getImage(w http.ResponseWriter, r *http.Request) {
|
func getImage(w http.ResponseWriter, r *http.Request) {
|
||||||
colors := []byte{
|
// Open the file
|
||||||
|
// file, err := os.Open("image.jpg")
|
||||||
|
// file, err := os.Open("image-out.jpg")
|
||||||
|
file, err := os.Open("dahlia-out.jpg")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: File could not be opened")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
img, _, _ := image.Decode(file)
|
||||||
|
|
||||||
|
analyzer := smartcrop.NewAnalyzer(nfnt.NewDefaultResizer())
|
||||||
|
topCrop, _ := analyzer.FindBestCrop(img, 800, 480)
|
||||||
|
|
||||||
|
fmt.Printf("Top crop: %+v\n", topCrop)
|
||||||
|
|
||||||
|
type SubImager interface {
|
||||||
|
SubImage(r image.Rectangle) image.Image
|
||||||
|
}
|
||||||
|
croppedImg := img.(SubImager).SubImage(topCrop)
|
||||||
|
|
||||||
|
resizedImg := resize.Resize(800, 480, croppedImg, resize.Lanczos3)
|
||||||
|
|
||||||
|
// Now you can save the cropped image
|
||||||
|
outFile, err := os.Create("cropped_image.jpg")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: File could not be created")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
err = jpeg.Encode(outFile, resizedImg, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: Image could not be encoded")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Cropped image saved successfully")
|
||||||
|
|
||||||
|
// data := ConvertToEInkImage(resizedImg)
|
||||||
|
|
||||||
|
colors := []EInkColor{
|
||||||
EPD_7IN3F_BLACK, EPD_7IN3F_BLUE, EPD_7IN3F_GREEN, EPD_7IN3F_ORANGE,
|
EPD_7IN3F_BLACK, EPD_7IN3F_BLUE, EPD_7IN3F_GREEN, EPD_7IN3F_ORANGE,
|
||||||
EPD_7IN3F_RED, EPD_7IN3F_YELLOW, EPD_7IN3F_WHITE, EPD_7IN3F_WHITE,
|
EPD_7IN3F_RED, EPD_7IN3F_YELLOW, EPD_7IN3F_WHITE, EPD_7IN3F_WHITE,
|
||||||
}
|
}
|
||||||
@ -44,7 +191,7 @@ func getImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
for i := 0; i < 240; i++ {
|
for i := 0; i < 240; i++ {
|
||||||
for k := 0; k < 4; k++ {
|
for k := 0; k < 4; k++ {
|
||||||
for j := 0; j < 100; j++ {
|
for j := 0; j < 100; j++ {
|
||||||
data = append(data, (colors[k]<<4)|colors[k])
|
data = append(data, (byte(colors[k]<<4))|byte(colors[k]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +199,7 @@ func getImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
for i := 0; i < 240; i++ {
|
for i := 0; i < 240; i++ {
|
||||||
for k := 4; k < 8; k++ {
|
for k := 4; k < 8; k++ {
|
||||||
for j := 0; j < 100; j++ {
|
for j := 0; j < 100; j++ {
|
||||||
data = append(data, (colors[k]<<4)|colors[k])
|
data = append(data, (byte(colors[k]<<4))|byte(colors[k]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,6 +210,7 @@ func getImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
|
||||||
|
fmt.Printf("Bytes to send: %+v\n", len(data))
|
||||||
|
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user