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.
This commit is contained in:
Hill Ma 2022-11-09 21:29:58 -08:00
parent a238a0ea6f
commit fec812bc32
3 changed files with 284 additions and 3 deletions

260
fastgif_lut.go Normal file
View 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,
}

24
wrp.go
View File

@ -15,6 +15,7 @@ import (
"fmt" "fmt"
"html/template" "html/template"
"image" "image"
"image/color/palette"
"image/gif" "image/gif"
"image/png" "image/png"
"io/ioutil" "io/ioutil"
@ -129,7 +130,7 @@ func (rq *wrpReq) parseForm() {
rq.keys = rq.r.FormValue("k") rq.keys = rq.r.FormValue("k")
rq.buttons = rq.r.FormValue("Fn") rq.buttons = rq.r.FormValue("Fn")
rq.imgType = rq.r.FormValue("t") 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 rq.imgType = defType
} }
log.Printf("%s WrpReq from UI Form: %+v\n", rq.r.RemoteAddr, rq) 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 ssize string
var iw, ih int var iw, ih int
switch rq.imgType { switch rq.imgType {
case "fastgif":
fallthrough
case "gif": case "gif":
i, err := png.Decode(bytes.NewReader(pngcap)) i, err := png.Decode(bytes.NewReader(pngcap))
if err != nil { if err != nil {
@ -301,8 +304,25 @@ func (rq *wrpReq) capture() {
} }
var gifbuf bytes.Buffer var gifbuf bytes.Buffer
st := time.Now() 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)
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) q := median.Quantizer(rq.colors)
p := q.Paletted(i) p = q.Paletted(i)
}
err = gif.Encode(&gifbuf, p, &gif.Options{}) err = gif.Encode(&gifbuf, p, &gif.Options{})
if err != nil { if err != nil {
log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err) log.Printf("%s Failed to encode GIF: %s\n", rq.r.RemoteAddr, err)

View File

@ -21,6 +21,7 @@
<OPTION VALUE="1.3" {{ if eq .Zoom 1.3}}SELECTED{{end}}>1.3 x</OPTION> <OPTION VALUE="1.3" {{ if eq .Zoom 1.3}}SELECTED{{end}}>1.3 x</OPTION>
</SELECT> </SELECT>
T <SELECT NAME="t"> 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="gif" {{ if eq .ImgType "gif"}}SELECTED{{end}}>GIF</OPTION>
<OPTION VALUE="png" {{ if eq .ImgType "png"}}SELECTED{{end}}>PNG</OPTION> <OPTION VALUE="png" {{ if eq .ImgType "png"}}SELECTED{{end}}>PNG</OPTION>
</SELECT> </SELECT>