added initial support for png image output

This commit is contained in:
Antoni Sawicki 2019-08-22 00:38:36 -07:00
parent 4cd55b31b0
commit eb4201c56b
2 changed files with 43 additions and 36 deletions

View File

@ -33,6 +33,8 @@ docker run -d -p 8080:8080 tenox7/wrp
-l listen address:port, default :8080 -l listen address:port, default :8080
-h headed mode, display browser window -h headed mode, display browser window
-d chromedp debug logging -d chromedp debug logging
-n do not free maps and gif images after use
-t image type gif (default) or png, when using PNG number of colors is ignored
``` ```
## Minimal Requirements ## Minimal Requirements

77
wrp.go
View File

@ -36,9 +36,10 @@ var (
srv http.Server srv http.Server
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
gifmap = make(map[string]bytes.Buffer) imgmap = make(map[string]bytes.Buffer)
ismap = make(map[string]wrpReq) ismap = make(map[string]wrpReq)
nodel bool nodel bool
imgtype string
) )
type wrpReq struct { type wrpReq struct {
@ -151,31 +152,30 @@ func mapServer(out http.ResponseWriter, req *http.Request) {
func imgServer(out http.ResponseWriter, req *http.Request) { func imgServer(out http.ResponseWriter, req *http.Request) {
log.Printf("%s IMG Request for %s\n", req.RemoteAddr, req.URL.Path) log.Printf("%s IMG Request for %s\n", req.RemoteAddr, req.URL.Path)
gifbuf, ok := gifmap[req.URL.Path] imgbuf, ok := imgmap[req.URL.Path]
if !ok || gifbuf.Bytes() == nil { if !ok || imgbuf.Bytes() == nil {
fmt.Fprintf(out, "Unable to find image %s\n", req.URL.Path) fmt.Fprintf(out, "Unable to find image %s\n", req.URL.Path)
log.Printf("Unable to find image %s\n", req.URL.Path) log.Printf("%s Unable to find image %s\n", req.RemoteAddr, req.URL.Path)
return return
} }
if !nodel { if !nodel {
defer delete(gifmap, req.URL.Path) defer delete(imgmap, req.URL.Path)
} }
out.Header().Set("Content-Type", "image/gif") if strings.HasPrefix(req.URL.Path, ".gif") {
out.Header().Set("Content-Length", strconv.Itoa(len(gifbuf.Bytes()))) out.Header().Set("Content-Type", "image/gif")
} else if strings.HasPrefix(req.URL.Path, ".png") {
out.Header().Set("Content-Type", "image/png")
}
out.Header().Set("Content-Length", strconv.Itoa(len(imgbuf.Bytes())))
out.Header().Set("Cache-Control", "max-age=0") out.Header().Set("Cache-Control", "max-age=0")
out.Header().Set("Expires", "-1") out.Header().Set("Expires", "-1")
out.Header().Set("Pragma", "no-cache") out.Header().Set("Pragma", "no-cache")
out.Write(gifbuf.Bytes()) out.Write(imgbuf.Bytes())
out.(http.Flusher).Flush() out.(http.Flusher).Flush()
} }
func (w wrpReq) capture(c string, out http.ResponseWriter) { func (w wrpReq) capture(c string, out http.ResponseWriter) {
var pngbuf []byte
var gifbuf bytes.Buffer
var err error var err error
var styles []*css.ComputedProperty
var r, g, b int
if w.X > 0 && w.Y > 0 { if w.X > 0 && w.Y > 0 {
log.Printf("%s Mouse Click %d,%d\n", c, w.X, w.Y) log.Printf("%s Mouse Click %d,%d\n", c, w.X, w.Y)
err = chromedp.Run(ctx, chromedp.MouseClickXY(int64(float64(w.X)/w.S), int64(float64(w.Y)/w.S))) err = chromedp.Run(ctx, chromedp.MouseClickXY(int64(float64(w.X)/w.S), int64(float64(w.Y)/w.S)))
@ -218,6 +218,8 @@ func (w wrpReq) capture(c string, out http.ResponseWriter) {
} }
return return
} }
var styles []*css.ComputedProperty
var r, g, b int
chromedp.Run(ctx, chromedp.Run(ctx,
chromedp.Sleep(time.Second*2), chromedp.Sleep(time.Second*2),
chromedp.ComputedStyle("body", &styles, chromedp.ByQuery), chromedp.ComputedStyle("body", &styles, chromedp.ByQuery),
@ -230,36 +232,38 @@ func (w wrpReq) capture(c string, out http.ResponseWriter) {
} }
} }
w.printPage(out, fmt.Sprintf("#%02X%02X%02X", r, g, b)) w.printPage(out, fmt.Sprintf("#%02X%02X%02X", r, g, b))
var pngcap []byte
// Process Screenshot Image err = chromedp.Run(ctx, chromedp.CaptureScreenshot(&pngcap))
err = chromedp.Run(ctx, chromedp.CaptureScreenshot(&pngbuf))
if err != nil { if err != nil {
log.Printf("%s Failed to capture screenshot: %s\n", c, err) log.Printf("%s Failed to capture screenshot: %s\n", c, err)
fmt.Fprintf(out, "<BR>Unable to capture screenshot:<BR>%s<BR>\n", err) fmt.Fprintf(out, "<BR>Unable to capture screenshot:<BR>%s<BR>\n", err)
return return
} }
bytes.NewReader(pngbuf).Seek(0, 0)
img, err := png.Decode(bytes.NewReader(pngbuf))
if err != nil {
log.Printf("%s Failed to decode screenshot: %s\n", c, err)
fmt.Fprintf(out, "<BR>Unable to decode page screenshot:<BR>%s<BR>\n", err)
return
}
gifbuf.Reset()
err = gif.Encode(&gifbuf, img, &gif.Options{NumColors: int(w.C), Quantizer: quantize.MedianCutQuantizer{}})
if err != nil {
log.Printf("%s Failed to encode GIF: %s\n", c, err)
fmt.Fprintf(out, "<BR>Unable to encode GIF:<BR>%s<BR>\n", err)
return
}
// Compose map and gif
seq := rand.Intn(9999) seq := rand.Intn(9999)
imgpath := fmt.Sprintf("/img/%04d.gif", seq) imgpath := fmt.Sprintf("/img/%04d.%s", seq, imgtype)
mappath := fmt.Sprintf("/map/%04d.map", seq) mappath := fmt.Sprintf("/map/%04d.map", seq)
gifmap[imgpath] = gifbuf
ismap[mappath] = w ismap[mappath] = w
log.Printf("%s Encoded GIF image: %s, Size: %dKB, Colors: %d\n", c, imgpath, len(gifbuf.Bytes())/1024, w.C) if imgtype == "gif" {
img, err := png.Decode(bytes.NewReader(pngcap))
if err != nil {
log.Printf("%s Failed to decode screenshot: %s\n", c, err)
fmt.Fprintf(out, "<BR>Unable to decode page screenshot:<BR>%s<BR>\n", err)
return
}
var gifbuf bytes.Buffer
err = gif.Encode(&gifbuf, img, &gif.Options{NumColors: int(w.C), Quantizer: quantize.MedianCutQuantizer{}})
if err != nil {
log.Printf("%s Failed to encode GIF: %s\n", c, err)
fmt.Fprintf(out, "<BR>Unable to encode GIF:<BR>%s<BR>\n", err)
return
}
imgmap[imgpath] = gifbuf
log.Printf("%s Encoded GIF image: %s, Size: %dKB, Colors: %d\n", c, imgpath, len(gifbuf.Bytes())/1024, w.C)
} else if imgtype == "png" {
pngbuf := bytes.NewBuffer(pngcap)
imgmap[imgpath] = *pngbuf
log.Printf("%s Got PNG image: %s, Size: %dKB\n", c, imgpath, len(pngbuf.Bytes())/1024)
}
fmt.Fprintf(out, "<A HREF=\"%s\"><IMG SRC=\"%s\" BORDER=\"0\" ISMAP></A>", mappath, imgpath) fmt.Fprintf(out, "<A HREF=\"%s\"><IMG SRC=\"%s\" BORDER=\"0\" ISMAP></A>", mappath, imgpath)
w.printFooter(out) w.printFooter(out)
log.Printf("%s Done with caputure for %s\n", c, w.U) log.Printf("%s Done with caputure for %s\n", c, w.U)
@ -286,7 +290,8 @@ func main() {
flag.StringVar(&addr, "l", ":8080", "Listen address:port, default :8080") flag.StringVar(&addr, "l", ":8080", "Listen address:port, default :8080")
flag.BoolVar(&head, "h", false, "Headed mode - display browser window") flag.BoolVar(&head, "h", false, "Headed mode - display browser window")
flag.BoolVar(&debug, "d", false, "Debug ChromeDP") flag.BoolVar(&debug, "d", false, "Debug ChromeDP")
flag.BoolVar(&nodel, "n", false, "Do not delete maps and gif images in memory") flag.BoolVar(&nodel, "n", false, "Do not free maps and images after use")
flag.StringVar(&imgtype, "t", "gif", "Image type: gif|png")
flag.Parse() flag.Parse()
if head { if head {
headless = false headless = false