package mediaprovider import ( "bytes" "encoding/base64" "errors" "image" "image/jpeg" "image/png" "io" "strings" "github.com/gabriel-vasile/mimetype" "github.com/gen2brain/avif" "golang.org/x/image/draw" "golang.org/x/image/webp" ) var ErrUnknownImageType = errors.New("unknown image format") func Compress(dataReader io.Reader, mimeType *string) (io.Reader, error) { data, err := io.ReadAll(dataReader) if err != nil { return nil, err } if mimeType == nil { *mimeType = mimetype.Detect(data).String() } uberType, subType, _ := strings.Cut(*mimeType, "/") var dataOut []byte switch uberType { case "text": case "application": case "image": dataOut, err = compressImage(data, subType, 1280, 720) case "video": dataOut, err = compressVideo(data, subType) case "audio": case "font": default: } if err != nil && err != ErrUnknownImageType { return nil, err } dataOut = compressBase64(dataOut) return bytes.NewReader(dataOut), nil } func compressVideo(dataIn []byte, subType string) (dataOut []byte, err error) { // TODO: Implement me panic("Implement me") } func compressImage(dataIn []byte, subType string, maxSizeX, maxSizeY uint) (dataOut []byte, err error) { imageSize := image.Rect(0, 0, int(maxSizeX), int(maxSizeY)) dst := image.NewRGBA(imageSize) var sourceImage image.Image switch subType { case "png": sourceImage, err = png.Decode(bytes.NewReader(dataIn)) if err != nil { return nil, err } case "jpg", "jpeg": sourceImage, err = jpeg.Decode(bytes.NewReader(dataIn)) case "webp": sourceImage, err = webp.Decode(bytes.NewReader(dataIn)) case "avif": sourceImage, err = avif.Decode(bytes.NewReader(dataIn)) default: return nil, ErrUnknownImageType } if err != nil { return nil, err } draw.CatmullRom.Scale(dst, imageSize, sourceImage, sourceImage.Bounds(), draw.Src, nil) return dst.Pix, nil } func compressBase64(dataIn []byte) []byte { result := []byte{} base64.StdEncoding.Encode(result, dataIn) return result }