image: use png imagequant (cgo)
This commit is contained in:
parent
d5e9baf4e9
commit
08f0c94131
23
image.go
23
image.go
@ -1,10 +1,8 @@
|
|||||||
package thumbnail
|
package thumbnail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Blend(a, b color.Color) color.Color {
|
func Blend(a, b color.Color) color.Color {
|
||||||
@ -80,12 +78,21 @@ func (this *Thumbnailer) RenderScaledImage(src image.Image) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
/*var b bytes.Buffer*/
|
||||||
|
|
||||||
err := png.Encode(&b, dest)
|
return crush(dest, 3)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.Bytes(), nil
|
/*
|
||||||
|
err := png.Encode(&b, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
err := jpeg.Encode(&b, dest, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.Bytes(), nil*/
|
||||||
}
|
}
|
||||||
|
102
imagecrush.go
Normal file
102
imagecrush.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package thumbnail
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/png"
|
||||||
|
|
||||||
|
"code.ivysaur.me/imagequant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func goImageToRgba32(im image.Image) []byte {
|
||||||
|
w := im.Bounds().Max.X
|
||||||
|
h := im.Bounds().Max.Y
|
||||||
|
ret := make([]byte, w*h*4)
|
||||||
|
|
||||||
|
p := 0
|
||||||
|
|
||||||
|
for y := 0; y < h; y += 1 {
|
||||||
|
for x := 0; x < w; x += 1 {
|
||||||
|
r16, g16, b16, a16 := im.At(x, y).RGBA() // Each value ranges within [0, 0xffff]
|
||||||
|
|
||||||
|
ret[p+0] = uint8(r16 >> 8)
|
||||||
|
ret[p+1] = uint8(g16 >> 8)
|
||||||
|
ret[p+2] = uint8(b16 >> 8)
|
||||||
|
ret[p+3] = uint8(a16 >> 8)
|
||||||
|
p += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func rgb8PaletteToGoImage(w, h int, rgb8data []byte, pal color.Palette) image.Image {
|
||||||
|
rect := image.Rectangle{
|
||||||
|
Max: image.Point{
|
||||||
|
X: w,
|
||||||
|
Y: h,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := image.NewPaletted(rect, pal)
|
||||||
|
|
||||||
|
for y := 0; y < h; y += 1 {
|
||||||
|
for x := 0; x < w; x += 1 {
|
||||||
|
ret.SetColorIndex(x, y, rgb8data[y*h+x])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func crush(img image.Image, speed int) ([]byte, error) {
|
||||||
|
|
||||||
|
width := img.Bounds().Max.X
|
||||||
|
height := img.Bounds().Max.Y
|
||||||
|
|
||||||
|
attr, err := imagequant.NewAttributes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("NewAttributes: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer attr.Release()
|
||||||
|
|
||||||
|
err = attr.SetSpeed(speed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("SetSpeed: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
rgba32data := goImageToRgba32(img)
|
||||||
|
|
||||||
|
iqm, err := imagequant.NewImage(attr, string(rgba32data), width, height, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("NewImage: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer iqm.Release()
|
||||||
|
|
||||||
|
res, err := iqm.Quantize(attr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Quantize: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer res.Release()
|
||||||
|
|
||||||
|
rgb8data, err := res.WriteRemappedImage()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("WriteRemappedImage: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
im2 := rgb8PaletteToGoImage(res.GetImageWidth(), res.GetImageHeight(), rgb8data, res.GetPalette())
|
||||||
|
|
||||||
|
buff := bytes.Buffer{}
|
||||||
|
|
||||||
|
penc := png.Encoder{
|
||||||
|
CompressionLevel: png.BestCompression,
|
||||||
|
}
|
||||||
|
err = penc.Encode(&buff, im2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("png.Encode: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return buff.Bytes(), nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user