diff options
author | 2021-04-19 19:42:19 +0200 | |
---|---|---|
committer | 2021-04-19 19:42:19 +0200 | |
commit | 32c5fd987a06e11b14a4247d13187657c14adedd (patch) | |
tree | f5b787ca0f020bea5fd020925e52d3592a77a6ad /internal/media/util.go | |
parent | Api/v1/accounts (#8) (diff) | |
download | gotosocial-32c5fd987a06e11b14a4247d13187657c14adedd.tar.xz |
Api/v1/statuses (#11)
This PR adds:
Statuses
New status creation.
View existing status
Delete a status
Fave a status
Unfave a status
See who's faved a status
Media
Upload media attachment and store/retrieve it
Upload custom emoji and store/retrieve it
Fileserver
Serve files from storage
Testing
Test models, testrig -- run a GTS test instance and play around with it.
Diffstat (limited to 'internal/media/util.go')
-rw-r--r-- | internal/media/util.go | 125 |
1 files changed, 110 insertions, 15 deletions
diff --git a/internal/media/util.go b/internal/media/util.go index 9ffb79a46..64d1ee770 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -70,6 +70,36 @@ func supportedImageType(mimeType string) bool { return false } +// supportedVideoType checks mime type of a video against a slice of accepted types, +// and returns True if the mime type is accepted. +func supportedVideoType(mimeType string) bool { + acceptedVideoTypes := []string{ + "video/mp4", + "video/mpeg", + "video/webm", + } + for _, accepted := range acceptedVideoTypes { + if mimeType == accepted { + return true + } + } + return false +} + +// supportedEmojiType checks that the content type is image/png -- the only type supported for emoji. +func supportedEmojiType(mimeType string) bool { + acceptedEmojiTypes := []string{ + "image/gif", + "image/png", + } + for _, accepted := range acceptedEmojiTypes { + if mimeType == accepted { + return true + } + } + return false +} + // purgeExif is a little wrapper for the action of removing exif data from an image. // Only pass pngs or jpegs to this function. func purgeExif(b []byte) ([]byte, error) { @@ -87,11 +117,50 @@ func purgeExif(b []byte) ([]byte, error) { return clean, nil } -func deriveImage(b []byte, extension string) (*imageAndMeta, error) { +func deriveGif(b []byte, extension string) (*imageAndMeta, error) { + var g *gif.GIF + var err error + switch extension { + case "image/gif": + g, err = gif.DecodeAll(bytes.NewReader(b)) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("extension %s not recognised", extension) + } + + // use the first frame to get the static characteristics + width := g.Config.Width + height := g.Config.Height + size := width * height + aspect := float64(width) / float64(height) + + bh, err := blurhash.Encode(4, 3, g.Image[0]) + if err != nil || bh == "" { + return nil, err + } + + out := &bytes.Buffer{} + if err := gif.EncodeAll(out, g); err != nil { + return nil, err + } + + return &imageAndMeta{ + image: out.Bytes(), + width: width, + height: height, + size: size, + aspect: aspect, + blurhash: bh, + }, nil +} + +func deriveImage(b []byte, contentType string) (*imageAndMeta, error) { var i image.Image var err error - switch extension { + switch contentType { case "image/jpeg": i, err = jpeg.Decode(bytes.NewReader(b)) if err != nil { @@ -102,28 +171,25 @@ func deriveImage(b []byte, extension string) (*imageAndMeta, error) { if err != nil { return nil, err } - case "image/gif": - i, err = gif.Decode(bytes.NewReader(b)) - if err != nil { - return nil, err - } default: - return nil, fmt.Errorf("extension %s not recognised", extension) + return nil, fmt.Errorf("content type %s not recognised", contentType) } width := i.Bounds().Size().X height := i.Bounds().Size().Y size := width * height aspect := float64(width) / float64(height) + bh, err := blurhash.Encode(4, 3, i) if err != nil { - return nil, fmt.Errorf("error generating blurhash: %s", err) + return nil, err } out := &bytes.Buffer{} if err := jpeg.Encode(out, i, nil); err != nil { return nil, err } + return &imageAndMeta{ image: out.Bytes(), width: width, @@ -134,16 +200,16 @@ func deriveImage(b []byte, extension string) (*imageAndMeta, error) { }, nil } -// deriveThumbnailFromImage returns a byte slice and metadata for a 256-pixel-width thumbnail +// deriveThumbnail returns a byte slice and metadata for a thumbnail of width x and height y, // of a given jpeg, png, or gif, or an error if something goes wrong. // // Note that the aspect ratio of the image will be retained, -// so it will not necessarily be a square. -func deriveThumbnail(b []byte, extension string) (*imageAndMeta, error) { +// so it will not necessarily be a square, even if x and y are set as the same value. +func deriveThumbnail(b []byte, contentType string, x uint, y uint) (*imageAndMeta, error) { var i image.Image var err error - switch extension { + switch contentType { case "image/jpeg": i, err = jpeg.Decode(bytes.NewReader(b)) if err != nil { @@ -160,10 +226,10 @@ func deriveThumbnail(b []byte, extension string) (*imageAndMeta, error) { return nil, err } default: - return nil, fmt.Errorf("extension %s not recognised", extension) + return nil, fmt.Errorf("content type %s not recognised", contentType) } - thumb := resize.Thumbnail(256, 256, i, resize.NearestNeighbor) + thumb := resize.Thumbnail(x, y, i, resize.NearestNeighbor) width := thumb.Bounds().Size().X height := thumb.Bounds().Size().Y size := width * height @@ -182,6 +248,35 @@ func deriveThumbnail(b []byte, extension string) (*imageAndMeta, error) { }, nil } +// deriveStaticEmojji takes a given gif or png of an emoji, decodes it, and re-encodes it as a static png. +func deriveStaticEmoji(b []byte, contentType string) (*imageAndMeta, error) { + var i image.Image + var err error + + switch contentType { + case "image/png": + i, err = png.Decode(bytes.NewReader(b)) + if err != nil { + return nil, err + } + case "image/gif": + i, err = gif.Decode(bytes.NewReader(b)) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("content type %s not allowed for emoji", contentType) + } + + out := &bytes.Buffer{} + if err := png.Encode(out, i); err != nil { + return nil, err + } + return &imageAndMeta{ + image: out.Bytes(), + }, nil +} + type imageAndMeta struct { image []byte width int |