[feature] Enable basic video support (mp4 only) (#1274)

* [feature] basic video support

* fix missing semicolon

* replace text shadow with stacked icons

Co-authored-by: f0x <f0x@cthu.lu>
This commit is contained in:
tobi
2022-12-17 05:38:56 +01:00
committed by GitHub
parent 0f38e7c9b0
commit 2bbc64be43
39 changed files with 6276 additions and 93 deletions

View File

@@ -38,16 +38,7 @@ const (
thumbnailMaxHeight = 512
)
type imageMeta struct {
width int
height int
size int
aspect float64
blurhash string // defined only for calls to deriveThumbnail if createBlurhash is true
small []byte // defined only for calls to deriveStaticEmoji or deriveThumbnail
}
func decodeGif(r io.Reader) (*imageMeta, error) {
func decodeGif(r io.Reader) (*mediaMeta, error) {
gif, err := gif.DecodeAll(r)
if err != nil {
return nil, err
@@ -59,7 +50,7 @@ func decodeGif(r io.Reader) (*imageMeta, error) {
size := width * height
aspect := float64(width) / float64(height)
return &imageMeta{
return &mediaMeta{
width: width,
height: height,
size: size,
@@ -67,7 +58,7 @@ func decodeGif(r io.Reader) (*imageMeta, error) {
}, nil
}
func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
func decodeImage(r io.Reader, contentType string) (*mediaMeta, error) {
var i image.Image
var err error
@@ -96,7 +87,7 @@ func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
size := width * height
aspect := float64(width) / float64(height)
return &imageMeta{
return &mediaMeta{
width: width,
height: height,
size: size,
@@ -104,8 +95,37 @@ func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
}, nil
}
// deriveThumbnail returns a byte slice and metadata for a thumbnail
// of a given jpeg, png, gif or webp, or an error if something goes wrong.
// deriveStaticEmojji takes a given gif or png of an emoji, decodes it, and re-encodes it as a static png.
func deriveStaticEmoji(r io.Reader, contentType string) (*mediaMeta, error) {
var i image.Image
var err error
switch contentType {
case mimeImagePng:
i, err = StrippedPngDecode(r)
if err != nil {
return nil, err
}
case mimeImageGif:
i, err = gif.Decode(r)
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 &mediaMeta{
small: out.Bytes(),
}, nil
}
// deriveThumbnailFromImage returns a byte slice and metadata for a thumbnail
// of a given piece of media, or an error if something goes wrong.
//
// If createBlurhash is true, then a blurhash will also be generated from a tiny
// version of the image. This costs precious CPU cycles, so only use it if you
@@ -113,7 +133,7 @@ func decodeImage(r io.Reader, contentType string) (*imageMeta, error) {
//
// If createBlurhash is false, then the blurhash field on the returned ImageAndMeta
// will be an empty string.
func deriveThumbnail(r io.Reader, contentType string, createBlurhash bool) (*imageMeta, error) {
func deriveThumbnailFromImage(r io.Reader, contentType string, createBlurhash bool) (*mediaMeta, error) {
var i image.Image
var err error
@@ -126,7 +146,7 @@ func deriveThumbnail(r io.Reader, contentType string, createBlurhash bool) (*ima
})
i, err = imaging.Decode(strippedPngReader, imaging.AutoOrientation(true))
default:
err = fmt.Errorf("content type %s can't be thumbnailed", contentType)
err = fmt.Errorf("content type %s can't be thumbnailed as an image", contentType)
}
if err != nil {
@@ -149,7 +169,7 @@ func deriveThumbnail(r io.Reader, contentType string, createBlurhash bool) (*ima
size := thumbX * thumbY
aspect := float64(thumbX) / float64(thumbY)
im := &imageMeta{
im := &mediaMeta{
width: thumbX,
height: thumbY,
size: size,
@@ -178,32 +198,3 @@ func deriveThumbnail(r io.Reader, contentType string, createBlurhash bool) (*ima
return im, nil
}
// deriveStaticEmojji takes a given gif or png of an emoji, decodes it, and re-encodes it as a static png.
func deriveStaticEmoji(r io.Reader, contentType string) (*imageMeta, error) {
var i image.Image
var err error
switch contentType {
case mimeImagePng:
i, err = StrippedPngDecode(r)
if err != nil {
return nil, err
}
case mimeImageGif:
i, err = gif.Decode(r)
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 &imageMeta{
small: out.Bytes(),
}, nil
}