package thumbnail import ( "bytes" "image" "image/jpeg" "image/png" "golang.org/x/image/bmp" "golang.org/x/image/draw" ) func (this *DirectThumbnailer) scaleImage(src image.Image) (image.Image, error) { srcW := src.Bounds().Max.X srcH := src.Bounds().Max.Y var srcCopyPosition, destCopyPosition image.Rectangle switch this.cfg.Aspect { case FitInside: var destW, destH int 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 srcCopyPosition = src.Bounds() destCopyPosition = image.Rect(offsetX, offsetY, destW+offsetX, destH+offsetY) case FitOutside: var srcSmallestDim, offsetX, offsetY int if srcW > srcH { // Landscape srcSmallestDim = srcH offsetY = 0 offsetX = (srcW - srcH) / 2 } else { // Portrait (or square) srcSmallestDim = srcW offsetY = (srcH - srcW) / 2 offsetX = 0 } srcCopyPosition = image.Rect(offsetX, offsetY, srcSmallestDim+offsetX, srcSmallestDim+offsetY) destCopyPosition = image.Rect(0, 0, this.cfg.Width, this.cfg.Height) case Stretch: srcCopyPosition = src.Bounds() destCopyPosition = image.Rect(0, 0, this.cfg.Width, this.cfg.Height) default: return nil, ErrInvalidOption } // dest := image.NewRGBA(image.Rect(0, 0, this.cfg.Width, this.cfg.Height)) // For a transparent destination, Op.Src is faster than Op.Over switch this.cfg.Scale { case NearestNeighbour: draw.NearestNeighbor.Scale(dest, destCopyPosition, src, srcCopyPosition, draw.Src, nil) case BilinearFast: draw.ApproxBiLinear.Scale(dest, destCopyPosition, src, srcCopyPosition, draw.Src, nil) case BilinearAccurate: draw.BiLinear.Scale(dest, destCopyPosition, src, srcCopyPosition, draw.Src, nil) case Bicubic: draw.CatmullRom.Scale(dest, destCopyPosition, src, srcCopyPosition, draw.Src, nil) } return dest, nil } 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 } }