From c6f18e91235d8757c5fd975f33f430c4171731c8 Mon Sep 17 00:00:00 2001 From: Travis Ralston <travpc@gmail.com> Date: Thu, 10 Feb 2022 19:36:38 -0700 Subject: [PATCH] Support JPEG XL Fixes https://github.com/turt2live/matrix-media-repo/issues/355 --- CHANGELOG.md | 1 + thumbnailing/i/jpegxl.go | 69 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 thumbnailing/i/jpegxl.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 9223991e..c3cd6854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added * New config option to set user agent when requesting URL previews. +* Added support for `image/jxl` thumbnailing. ### Fixed diff --git a/thumbnailing/i/jpegxl.go b/thumbnailing/i/jpegxl.go new file mode 100644 index 00000000..7c46f0a3 --- /dev/null +++ b/thumbnailing/i/jpegxl.go @@ -0,0 +1,69 @@ +package i + +import ( + "errors" + "io/ioutil" + "os" + "os/exec" + "path" + + "github.com/turt2live/matrix-media-repo/common/rcontext" + "github.com/turt2live/matrix-media-repo/thumbnailing/m" + "github.com/turt2live/matrix-media-repo/util" + "github.com/turt2live/matrix-media-repo/util/cleanup" +) + +type jpegxlGenerator struct { +} + +func (d jpegxlGenerator) supportedContentTypes() []string { + return []string{"image/jxl"} +} + +func (d jpegxlGenerator) supportsAnimation() bool { + return false +} + +func (d jpegxlGenerator) matches(img []byte, contentType string) bool { + return contentType == "image/jxl" +} + +func (d jpegxlGenerator) GetOriginDimensions(b []byte, contentType string, ctx rcontext.RequestContext) (bool, int, int, error) { + return false, 0, 0, nil +} + +func (d jpegxlGenerator) GenerateThumbnail(b []byte, contentType string, width int, height int, method string, animated bool, ctx rcontext.RequestContext) (*m.Thumbnail, error) { + key, err := util.GenerateRandomString(16) + if err != nil { + return nil, errors.New("jpegxl: error generating temp key: " + err.Error()) + } + + tempFile1 := path.Join(os.TempDir(), "media_repo."+key+".1.jpegxl") + tempFile2 := path.Join(os.TempDir(), "media_repo."+key+".2.png") + + defer os.Remove(tempFile1) + defer os.Remove(tempFile2) + + f, err := os.OpenFile(tempFile1, os.O_RDWR|os.O_CREATE, 0640) + if err != nil { + return nil, errors.New("jpegxl: error writing temp jpegxl file: " + err.Error()) + } + _, _ = f.Write(b) + cleanup.DumpAndCloseStream(f) + + err = exec.Command("convert", tempFile1, tempFile2).Run() + if err != nil { + return nil, errors.New("jpegxl: error converting jpegxl file: " + err.Error()) + } + + b, err = ioutil.ReadFile(tempFile2) + if err != nil { + return nil, errors.New("jpegxl: error reading temp png file: " + err.Error()) + } + + return pngGenerator{}.GenerateThumbnail(b, "image/png", width, height, method, false, ctx) +} + +func init() { + generators = append(generators, jpegxlGenerator{}) +} -- GitLab