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