2016-10-13 09:25:11 +00:00
|
|
|
package thumbnail
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
|
|
|
"image/color"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Blend(a, b color.Color) color.Color {
|
|
|
|
switch a.(type) {
|
|
|
|
case color.RGBA:
|
|
|
|
return BlendRGBA(a.(color.RGBA), b.(color.RGBA)) // FIXME there's syntax for this
|
|
|
|
|
|
|
|
case color.YCbCr:
|
|
|
|
return BlendYCbCr(a.(color.YCbCr), b.(color.YCbCr))
|
|
|
|
|
|
|
|
default:
|
|
|
|
return a // ??? unknown color format
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BlendYCbCr(a, b color.YCbCr) color.YCbCr {
|
|
|
|
return color.YCbCr{
|
|
|
|
Y: uint8((int(a.Y) + int(b.Y)) / 2),
|
|
|
|
Cb: uint8((int(a.Cb) + int(b.Cb)) / 2),
|
|
|
|
Cr: uint8((int(a.Cr) + int(b.Cr)) / 2),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BlendRGBA(a, b color.RGBA) color.RGBA {
|
|
|
|
return color.RGBA{
|
|
|
|
R: uint8((int(a.R) + int(b.R)) / 2),
|
|
|
|
G: uint8((int(a.G) + int(b.G)) / 2),
|
|
|
|
B: uint8((int(a.B) + int(b.B)) / 2),
|
|
|
|
A: uint8((int(a.A) + int(b.A)) / 2),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *Thumbnailer) RenderScaledImage(src image.Image) ([]byte, error) {
|
|
|
|
srcW := src.Bounds().Max.X
|
|
|
|
srcH := src.Bounds().Max.Y
|
|
|
|
destW := 0
|
|
|
|
destH := 0
|
|
|
|
|
|
|
|
if srcW > srcH {
|
|
|
|
destW = this.Width
|
|
|
|
destH = this.Height * srcH / srcW
|
|
|
|
} else {
|
|
|
|
destW = this.Width * srcW / srcH
|
|
|
|
destH = this.Height
|
|
|
|
}
|
|
|
|
|
|
|
|
offsetX := (this.Width - destW) / 2
|
|
|
|
offsetY := (this.Height - destH) / 2
|
|
|
|
|
|
|
|
scaleW := float64(srcW) / float64(destW)
|
|
|
|
scaleH := float64(srcH) / float64(destH)
|
|
|
|
|
|
|
|
dest := image.NewRGBA(image.Rectangle{Max: image.Point{X: this.Width, Y: this.Height}})
|
|
|
|
|
|
|
|
for y := 0; y < destH; y += 1 {
|
|
|
|
for x := 0; x < destW; x += 1 {
|
|
|
|
|
|
|
|
/*
|
|
|
|
// NN
|
|
|
|
mapx := int(float64(x) * scaleW)
|
|
|
|
mapy := int(float64(y) * scaleH)
|
|
|
|
dest.Set(x+offsetX, y+offsetY, src.At(mapx, mapy))
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Bilinear
|
|
|
|
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)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-05 06:00:42 +00:00
|
|
|
/*var b bytes.Buffer*/
|
2016-10-13 09:25:11 +00:00
|
|
|
|
2016-12-05 06:00:42 +00:00
|
|
|
return crush(dest, 3)
|
|
|
|
|
|
|
|
/*
|
|
|
|
err := png.Encode(&b, dest)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
err := jpeg.Encode(&b, dest, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-10-13 09:25:11 +00:00
|
|
|
|
2016-12-05 06:00:42 +00:00
|
|
|
return b.Bytes(), nil*/
|
2016-10-13 09:25:11 +00:00
|
|
|
}
|