From a238a0ea6f1b2d20eecdf3e49ba8d07e16c52d1e Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Wed, 9 Nov 2022 20:48:18 -0800 Subject: [PATCH 1/7] gif: faster median cut quantization --- go.mod | 2 +- go.sum | 4 ++-- wrp.go | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ea38319..86d9032 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,6 @@ require ( github.com/MaxHalford/halfgone v0.0.0-20171017091812-482157b86ccb github.com/chromedp/cdproto v0.0.0-20221029224954-108014bf7279 github.com/chromedp/chromedp v0.8.6 - github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 + github.com/soniakeys/quant v1.0.0 golang.org/x/sys v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index 929fae0..f6fb024 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,6 @@ github.com/chromedp/chromedp v0.8.6 h1:KobeeqR2dpfKSG1prS3Y6+FbffMmGC6xmAobRXA9Q github.com/chromedp/chromedp v0.8.6/go.mod h1:nBYHoD6YSNzrr82cIeuOzhw1Jo/s2o0QQ+ifTeoCZ+c= github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= -github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU= -github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -23,6 +21,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/soniakeys/quant v1.0.0 h1:N1um9ktjbkZVcywBVAAYpZYSHxEfJGzshHCxx/DaI0Y= +github.com/soniakeys/quant v1.0.0/go.mod h1:HI1k023QuVbD4H8i9YdfZP2munIHU4QpjsImz6Y6zds= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= diff --git a/wrp.go b/wrp.go index c387dce..49d1931 100644 --- a/wrp.go +++ b/wrp.go @@ -35,7 +35,7 @@ import ( "github.com/chromedp/cdproto/emulation" "github.com/chromedp/cdproto/page" "github.com/chromedp/chromedp" - "github.com/ericpauley/go-quantize/quantize" + "github.com/soniakeys/quant/median" ) var ( @@ -301,7 +301,9 @@ func (rq *wrpReq) capture() { } var gifbuf bytes.Buffer st := time.Now() - err = gif.Encode(&gifbuf, i, &gif.Options{NumColors: int(rq.colors), Quantizer: quantize.MedianCutQuantizer{}}) + q := median.Quantizer(rq.colors) + p := q.Paletted(i) + err = gif.Encode(&gifbuf, p, &gif.Options{}) if err != nil { log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err) fmt.Fprintf(rq.w, "
Unable to encode GIF:
%s
\n", err) @@ -457,7 +459,7 @@ func main() { flag.BoolVar(&headless, "h", true, "Headless mode - hide browser window") flag.BoolVar(&debug, "d", false, "Debug ChromeDP") flag.BoolVar(&noDel, "n", false, "Do not free maps and images after use") - flag.StringVar(&defType, "t", "gif", "Image type: gif|png") + flag.StringVar(&defType, "t", "png", "Image type: fastgif|gif|png") flag.StringVar(&fgeom, "g", "1152x600x256", "Geometry: width x height x colors, height can be 0 for unlimited") flag.StringVar(&tHTML, "ui", "wrp.html", "HTML template file for the UI") flag.Parse() From fec812bc326eea6eda30a57f6feee90728926d05 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Wed, 9 Nov 2022 21:29:58 -0800 Subject: [PATCH 2/7] Add "fastgif" image type that provides much faster (but lower quality) GIF quantization. The default image type is changed to PNG as it is the most "trouble free" choice. --- fastgif_lut.go | 260 +++++++++++++++++++++++++++++++++++++++++++++++++ wrp.go | 26 ++++- wrp.html | 1 + 3 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 fastgif_lut.go diff --git a/fastgif_lut.go b/fastgif_lut.go new file mode 100644 index 0000000..9cd4b11 --- /dev/null +++ b/fastgif_lut.go @@ -0,0 +1,260 @@ +package main + +var FastGifLut = [256]int{ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, + 5, +} diff --git a/wrp.go b/wrp.go index 49d1931..85be069 100644 --- a/wrp.go +++ b/wrp.go @@ -15,6 +15,7 @@ import ( "fmt" "html/template" "image" + "image/color/palette" "image/gif" "image/png" "io/ioutil" @@ -129,7 +130,7 @@ func (rq *wrpReq) parseForm() { rq.keys = rq.r.FormValue("k") rq.buttons = rq.r.FormValue("Fn") rq.imgType = rq.r.FormValue("t") - if rq.imgType != "gif" && rq.imgType != "png" { + if rq.imgType != "fastgif" && rq.imgType != "gif" && rq.imgType != "png" { rq.imgType = defType } log.Printf("%s WrpReq from UI Form: %+v\n", rq.r.RemoteAddr, rq) @@ -288,6 +289,8 @@ func (rq *wrpReq) capture() { var ssize string var iw, ih int switch rq.imgType { + case "fastgif": + fallthrough case "gif": i, err := png.Decode(bytes.NewReader(pngcap)) if err != nil { @@ -301,8 +304,25 @@ func (rq *wrpReq) capture() { } var gifbuf bytes.Buffer st := time.Now() - q := median.Quantizer(rq.colors) - p := q.Paletted(i) + var p *image.Paletted + if rq.imgType == "fastgif" { + r := i.Bounds() + // NOTE: the color index computation below works only for palette.WebSafe! + p = image.NewPaletted(r, palette.WebSafe) + for y := 0; y != r.Dy(); y++ { + for x := 0; x != r.Dx(); x++ { + c := i.At(x, y) + r, g, b, _ := c.RGBA() + r6 := FastGifLut[r&0xff] + g6 := FastGifLut[g&0xff] + b6 := FastGifLut[b&0xff] + p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + } + } + } else { + q := median.Quantizer(rq.colors) + p = q.Paletted(i) + } err = gif.Encode(&gifbuf, p, &gif.Options{}) if err != nil { log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err) diff --git a/wrp.html b/wrp.html index 58b4094..cbd72e3 100644 --- a/wrp.html +++ b/wrp.html @@ -21,6 +21,7 @@ T From bf7e7bfb2cbe879164f80887a2eac022c530e627 Mon Sep 17 00:00:00 2001 From: Hill Ma Date: Thu, 10 Nov 2022 20:39:41 -0800 Subject: [PATCH 3/7] improve fastgif --- wrp.go | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/wrp.go b/wrp.go index 85be069..635f753 100644 --- a/wrp.go +++ b/wrp.go @@ -283,7 +283,7 @@ func (rq *wrpReq) capture() { return } seq := rand.Intn(9999) - imgpath := fmt.Sprintf("/img/%04d.%s", seq, rq.imgType) + var imgpath string mappath := fmt.Sprintf("/map/%04d.map", seq) ismap[mappath] = *rq var ssize string @@ -292,6 +292,7 @@ func (rq *wrpReq) capture() { case "fastgif": fallthrough case "gif": + imgpath = fmt.Sprintf("/img/%04d.gif", seq) i, err := png.Decode(bytes.NewReader(pngcap)) if err != nil { log.Printf("%s Failed to decode screenshot: %s\n", rq.r.RemoteAddr, err) @@ -309,14 +310,26 @@ func (rq *wrpReq) capture() { r := i.Bounds() // NOTE: the color index computation below works only for palette.WebSafe! p = image.NewPaletted(r, palette.WebSafe) - for y := 0; y != r.Dy(); y++ { - for x := 0; x != r.Dx(); x++ { - c := i.At(x, y) - r, g, b, _ := c.RGBA() - r6 := FastGifLut[r&0xff] - g6 := FastGifLut[g&0xff] - b6 := FastGifLut[b&0xff] - p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + if i64, ok := i.(image.RGBA64Image); ok { + for y := r.Min.Y; y < r.Max.Y; y++ { + for x := r.Min.X; x < r.Max.X; x++ { + c := i64.RGBA64At(x, y) + r6 := FastGifLut[c.R>>8] + g6 := FastGifLut[c.G>>8] + b6 := FastGifLut[c.B>>8] + p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + } + } + } else { + for y := r.Min.Y; y < r.Max.Y; y++ { + for x := r.Min.X; x < r.Max.X; x++ { + c := i.At(x, y) + r, g, b, _ := c.RGBA() + r6 := FastGifLut[r&0xff] + g6 := FastGifLut[g&0xff] + b6 := FastGifLut[b&0xff] + p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + } } } } else { @@ -335,6 +348,7 @@ func (rq *wrpReq) capture() { ih = i.Bounds().Max.Y log.Printf("%s Encoded GIF image: %s, Size: %s, Colors: %d, %dx%d, Time: %vms\n", rq.r.RemoteAddr, imgpath, ssize, rq.colors, iw, ih, time.Since(st).Milliseconds()) case "png": + imgpath = fmt.Sprintf("/img/%04d.png", seq) pngbuf := bytes.NewBuffer(pngcap) img[imgpath] = *pngbuf cfg, _, _ := image.DecodeConfig(pngbuf) From 40e081be7717467d91e99e38c406133e6930ac4c Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 29 Nov 2022 05:50:17 -0800 Subject: [PATCH 4/7] refactor fastgif code for readability --- fastgif_lut.go | 260 ------------------------------------------------- wrp.go | 98 +++++++++---------- wrp.html | 2 +- 3 files changed, 50 insertions(+), 310 deletions(-) delete mode 100644 fastgif_lut.go diff --git a/fastgif_lut.go b/fastgif_lut.go deleted file mode 100644 index 9cd4b11..0000000 --- a/fastgif_lut.go +++ /dev/null @@ -1,260 +0,0 @@ -package main - -var FastGifLut = [256]int{ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, -} diff --git a/wrp.go b/wrp.go index 635f753..d9844b4 100644 --- a/wrp.go +++ b/wrp.go @@ -130,7 +130,7 @@ func (rq *wrpReq) parseForm() { rq.keys = rq.r.FormValue("k") rq.buttons = rq.r.FormValue("Fn") rq.imgType = rq.r.FormValue("t") - if rq.imgType != "fastgif" && rq.imgType != "gif" && rq.imgType != "png" { + if rq.imgType != "gif" && rq.imgType != "png" { rq.imgType = defType } log.Printf("%s WrpReq from UI Form: %+v\n", rq.r.RemoteAddr, rq) @@ -236,6 +236,45 @@ func chromedpCaptureScreenshot(res *[]byte, h int64) chromedp.Action { }) } +func gifPalette(i image.Image, n int64) image.Image { + switch n { + case 2: + i = halfgone.FloydSteinbergDitherer{}.Apply(halfgone.ImageToGray(i)) + case 216: + var FastGifLut = [256]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} + r := i.Bounds() + // NOTE: the color index computation below works only for palette.WebSafe! + p := image.NewPaletted(r, palette.WebSafe) + if i64, ok := i.(image.RGBA64Image); ok { + for y := r.Min.Y; y < r.Max.Y; y++ { + for x := r.Min.X; x < r.Max.X; x++ { + c := i64.RGBA64At(x, y) + r6 := FastGifLut[c.R>>8] + g6 := FastGifLut[c.G>>8] + b6 := FastGifLut[c.B>>8] + p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + } + } + } else { + for y := r.Min.Y; y < r.Max.Y; y++ { + for x := r.Min.X; x < r.Max.X; x++ { + c := i.At(x, y) + r, g, b, _ := c.RGBA() + r6 := FastGifLut[r&0xff] + g6 := FastGifLut[g&0xff] + b6 := FastGifLut[b&0xff] + p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) + } + } + } + i = p + default: + q := median.Quantizer(n) + i = q.Paletted(i) + } + return i +} + // Capture currently rendered web page to an image and fake ISMAP func (rq *wrpReq) capture() { var err error @@ -283,60 +322,22 @@ func (rq *wrpReq) capture() { return } seq := rand.Intn(9999) - var imgpath string + imgpath := fmt.Sprintf("/img/%04d.%s", seq, rq.imgType) mappath := fmt.Sprintf("/map/%04d.map", seq) ismap[mappath] = *rq var ssize string var iw, ih int switch rq.imgType { - case "fastgif": - fallthrough case "gif": - imgpath = fmt.Sprintf("/img/%04d.gif", seq) i, err := png.Decode(bytes.NewReader(pngcap)) if err != nil { - log.Printf("%s Failed to decode screenshot: %s\n", rq.r.RemoteAddr, err) - fmt.Fprintf(rq.w, "
Unable to decode page screenshot:
%s
\n", err) + log.Printf("%s Failed to decode PNG screenshot: %s\n", rq.r.RemoteAddr, err) + fmt.Fprintf(rq.w, "
Unable to decode page PNG screenshot:
%s
\n", err) return } - if rq.colors == 2 { - gray := halfgone.ImageToGray(i) - i = halfgone.FloydSteinbergDitherer{}.Apply(gray) - } - var gifbuf bytes.Buffer st := time.Now() - var p *image.Paletted - if rq.imgType == "fastgif" { - r := i.Bounds() - // NOTE: the color index computation below works only for palette.WebSafe! - p = image.NewPaletted(r, palette.WebSafe) - if i64, ok := i.(image.RGBA64Image); ok { - for y := r.Min.Y; y < r.Max.Y; y++ { - for x := r.Min.X; x < r.Max.X; x++ { - c := i64.RGBA64At(x, y) - r6 := FastGifLut[c.R>>8] - g6 := FastGifLut[c.G>>8] - b6 := FastGifLut[c.B>>8] - p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) - } - } - } else { - for y := r.Min.Y; y < r.Max.Y; y++ { - for x := r.Min.X; x < r.Max.X; x++ { - c := i.At(x, y) - r, g, b, _ := c.RGBA() - r6 := FastGifLut[r&0xff] - g6 := FastGifLut[g&0xff] - b6 := FastGifLut[b&0xff] - p.SetColorIndex(x, y, uint8(36*r6+6*g6+b6)) - } - } - } - } else { - q := median.Quantizer(rq.colors) - p = q.Paletted(i) - } - err = gif.Encode(&gifbuf, p, &gif.Options{}) + var gifbuf bytes.Buffer + err = gif.Encode(&gifbuf, gifPalette(i, rq.colors), &gif.Options{}) if err != nil { log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err) fmt.Fprintf(rq.w, "
Unable to encode GIF:
%s
\n", err) @@ -346,16 +347,15 @@ func (rq *wrpReq) capture() { ssize = fmt.Sprintf("%.0f KB", float32(len(gifbuf.Bytes()))/1024.0) iw = i.Bounds().Max.X ih = i.Bounds().Max.Y - log.Printf("%s Encoded GIF image: %s, Size: %s, Colors: %d, %dx%d, Time: %vms\n", rq.r.RemoteAddr, imgpath, ssize, rq.colors, iw, ih, time.Since(st).Milliseconds()) + log.Printf("%s Encoded GIF image: %s, Size: %s, Colors: %d, Res: %dx%d, Time: %vms\n", rq.r.RemoteAddr, imgpath, ssize, rq.colors, iw, ih, time.Since(st).Milliseconds()) case "png": - imgpath = fmt.Sprintf("/img/%04d.png", seq) pngbuf := bytes.NewBuffer(pngcap) img[imgpath] = *pngbuf cfg, _, _ := image.DecodeConfig(pngbuf) ssize = fmt.Sprintf("%.0f KB", float32(len(pngbuf.Bytes()))/1024.0) iw = cfg.Width ih = cfg.Height - log.Printf("%s Got PNG image: %s, Size: %s, %dx%d\n", rq.r.RemoteAddr, imgpath, ssize, iw, ih) + log.Printf("%s Got PNG image: %s, Size: %s, Res: %dx%d\n", rq.r.RemoteAddr, imgpath, ssize, iw, ih) } rq.printHTML(printParams{ bgColor: fmt.Sprintf("#%02X%02X%02X", r, g, b), @@ -493,8 +493,8 @@ func main() { flag.BoolVar(&headless, "h", true, "Headless mode - hide browser window") flag.BoolVar(&debug, "d", false, "Debug ChromeDP") flag.BoolVar(&noDel, "n", false, "Do not free maps and images after use") - flag.StringVar(&defType, "t", "png", "Image type: fastgif|gif|png") - flag.StringVar(&fgeom, "g", "1152x600x256", "Geometry: width x height x colors, height can be 0 for unlimited") + flag.StringVar(&defType, "t", "gif", "Image type: gif|png") + flag.StringVar(&fgeom, "g", "1152x600x216", "Geometry: width x height x colors, height can be 0 for unlimited") flag.StringVar(&tHTML, "ui", "wrp.html", "HTML template file for the UI") flag.Parse() if len(os.Getenv("PORT")) > 0 { diff --git a/wrp.html b/wrp.html index cbd72e3..bbc494e 100644 --- a/wrp.html +++ b/wrp.html @@ -21,12 +21,12 @@ T C