thumbnail/scaler.go

102 lines
2.1 KiB
Go

package thumbnail
import (
"bytes"
"image"
"image/jpeg"
"image/png"
"golang.org/x/image/bmp"
)
func (this *DirectThumbnailer) scaleImage(src image.Image) image.Image {
srcW := src.Bounds().Max.X
srcH := src.Bounds().Max.Y
destW := 0
destH := 0
if srcW > srcH {
destW = this.cfg.Width
destH = this.cfg.Height * srcH / srcW
} else {
destW = this.cfg.Width * srcW / srcH
destH = this.cfg.Height
}
offsetX := (this.cfg.Width - destW) / 2
offsetY := (this.cfg.Height - destH) / 2
scaleW := float64(srcW) / float64(destW)
scaleH := float64(srcH) / float64(destH)
dest := image.NewRGBA(image.Rectangle{Max: image.Point{X: this.cfg.Width, Y: this.cfg.Height}})
switch this.cfg.Scale {
case Bilinear:
for y := 0; y < destH; y += 1 {
for x := 0; x < destW; x += 1 {
c00 := src.At(int(float64(x)*scaleW), int(float64(y)*scaleH))
c01 := src.At(int((float64(x)+0.5)*scaleW), int(float64(y)*scaleH))
c10 := src.At(int(float64(x)*scaleW), int((float64(y)+0.5)*scaleH))
c11 := src.At(int((float64(x)+0.5)*scaleW), int((float64(y)+0.5)*scaleH))
cBlend := Blend(Blend(c00, c01), Blend(c10, c11))
dest.Set(x+offsetX, y+offsetY, cBlend)
}
}
case NearestNeighbour:
for y := 0; y < destH; y += 1 {
for x := 0; x < destW; x += 1 {
mapx := int(float64(x) * scaleW)
mapy := int(float64(y) * scaleH)
dest.Set(x+offsetX, y+offsetY, src.At(mapx, mapy))
}
}
}
return dest
}
func (this *DirectThumbnailer) encode(dest image.Image) ([]byte, error) {
switch this.cfg.Output {
case Png:
buff := bytes.Buffer{}
err := png.Encode(&buff, dest)
if err != nil {
return nil, err
}
return buff.Bytes(), nil
case PngCrush:
return crushFast(dest)
case Jpeg:
buff := bytes.Buffer{}
err := jpeg.Encode(&buff, dest, &jpeg.Options{Quality: jpeg.DefaultQuality})
if err != nil {
return nil, err
}
return buff.Bytes(), nil
case Bmp:
buff := bytes.Buffer{}
err := bmp.Encode(&buff, dest)
if err != nil {
return nil, err
}
return buff.Bytes(), nil
default:
return nil, ErrInvalidOption
}
}