package image import ( "bytes" "image/gif" "image/jpeg" "image/png" "io" "mime/multipart" "os" ) // CompressImage 壓縮圖片至指定位置 func CompressImage(input interface{}, output string) (err error) { var file io.Reader var fileToClose io.Closer switch v := input.(type) { case string: f, err := os.Open(v) if err != nil { return err } file = f fileToClose = f defer func() { if fileToClose != nil { _ = fileToClose.Close() } _ = os.Remove(v) }() case *multipart.FileHeader: f, err := v.Open() if err != nil { return err } file = f fileToClose = f defer func() { if fileToClose != nil { _ = fileToClose.Close() } }() } var buf bytes.Buffer if _, err = io.Copy(&buf, file); err != nil { return err } bs := buf.Bytes() var ext string if _, err = jpeg.Decode(bytes.NewReader(bs)); err == nil { ext = "jpg" } else if _, err = png.Decode(bytes.NewReader(bs)); err == nil { ext = "png" } else if _, err = gif.Decode(bytes.NewReader(bs)); err == nil { ext = "gif" } outputFile, err := os.Create(output) if err != nil { return err } defer func() { if outputFile != nil { _ = outputFile.Close() } }() switch ext { case "jpg": img, err := jpeg.Decode(bytes.NewReader(bs)) if err != nil { return err } return jpeg.Encode(outputFile, img, &jpeg.Options{Quality: 70}) case "png": img, err := png.Decode(bytes.NewReader(bs)) if err != nil { return err } encoder := png.Encoder{CompressionLevel: png.BestCompression} return encoder.Encode(outputFile, img) case "gif": img, err := gif.DecodeAll(bytes.NewReader(bs)) if err != nil { return err } return gif.EncodeAll(outputFile, img) default: _, err = outputFile.Write(bs) return err } }