mirror of
https://github.com/tenox7/wrp.git
synced 2025-02-14 21:30:35 +00:00
Merge pull request #99 from mahiuchun/master
Introduce "fastgif" image type
This commit is contained in:
commit
1c18fb9b81
260
fastgif_lut.go
Normal file
260
fastgif_lut.go
Normal file
@ -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,
|
||||
}
|
2
go.mod
2
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
|
||||
)
|
||||
|
4
go.sum
4
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=
|
||||
|
46
wrp.go
46
wrp.go
@ -15,6 +15,7 @@ import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"image"
|
||||
"image/color/palette"
|
||||
"image/gif"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
@ -35,7 +36,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 (
|
||||
@ -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)
|
||||
@ -282,13 +283,16 @@ 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
|
||||
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)
|
||||
@ -301,7 +305,38 @@ 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{}})
|
||||
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{})
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err)
|
||||
fmt.Fprintf(rq.w, "<BR>Unable to encode GIF:<BR>%s<BR>\n", err)
|
||||
@ -313,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)
|
||||
@ -457,7 +493,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()
|
||||
|
1
wrp.html
1
wrp.html
@ -21,6 +21,7 @@
|
||||
<OPTION VALUE="1.3" {{ if eq .Zoom 1.3}}SELECTED{{end}}>1.3 x</OPTION>
|
||||
</SELECT>
|
||||
T <SELECT NAME="t">
|
||||
<OPTION VALUE="fastgif" {{ if eq .ImgType "fastgif"}}SELECTED{{end}}>Fast GIF</OPTION>
|
||||
<OPTION VALUE="gif" {{ if eq .ImgType "gif"}}SELECTED{{end}}>GIF</OPTION>
|
||||
<OPTION VALUE="png" {{ if eq .ImgType "png"}}SELECTED{{end}}>PNG</OPTION>
|
||||
</SELECT>
|
||||
|
Loading…
x
Reference in New Issue
Block a user