feature (plg_image_*): support for new images and cleanup

This commit is contained in:
Mickael Kerjean
2022-12-22 22:07:52 +11:00
parent 541ad580f1
commit 2645fd62d0
10 changed files with 205 additions and 70 deletions

6
go.mod
View File

@ -25,6 +25,8 @@ require (
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 // indirect github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 // indirect github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 // indirect
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
github.com/suyashkumar/dicom v1.0.5 github.com/suyashkumar/dicom v1.0.5
github.com/tidwall/gjson v1.13.0 github.com/tidwall/gjson v1.13.0
github.com/tidwall/sjson v1.0.4 github.com/tidwall/sjson v1.0.4
@ -32,8 +34,8 @@ require (
github.com/vmware/go-nfs-client v0.0.0-20190605212624-d43b92724c1b github.com/vmware/go-nfs-client v0.0.0-20190605212624-d43b92724c1b
github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838
golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9

9
go.sum
View File

@ -245,6 +245,11 @@ github.com/spacemonkeygo/monkit/v3 v3.0.17/go.mod h1:kj1ViJhlyADa7DiA4xVnTuPA46l
github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a/go.mod h1:ul4bvvnCOPZgq8w0nTkSmWVg/hauVpFS97Am1YM1XXo= github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a/go.mod h1:ul4bvvnCOPZgq8w0nTkSmWVg/hauVpFS97Am1YM1XXo=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@ -310,6 +315,8 @@ golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c h1:FRR4fGZm/CMwZka5baQ4z8c8StbxJOMjS/45e0BAxK0= golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c h1:FRR4fGZm/CMwZka5baQ4z8c8StbxJOMjS/45e0BAxK0=
golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20210622092929-e6eecd499c2c/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -343,6 +350,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=

View File

@ -28,8 +28,8 @@ import (
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_editor_onlyoffice" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_editor_onlyoffice"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_console" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_console"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_ascii" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_ascii"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_dicom"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_thumbnail" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_thumbnail"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_transcode"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_search_stateless" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_search_stateless"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_scanner" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_scanner"
_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_svg" _ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_svg"

View File

@ -1,64 +0,0 @@
package plg_image_dicom
import (
"bufio"
"bytes"
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/suyashkumar/dicom"
"github.com/suyashkumar/dicom/pkg/tag"
"image/jpeg"
"io"
"net/http"
)
func init() {
Hooks.Register.ProcessFileContentBeforeSend(renderDicom)
}
func renderDicom(reader io.ReadCloser, ctx *App, res *http.ResponseWriter, req *http.Request) (io.ReadCloser, error) {
query := req.URL.Query()
if query.Get("size") == "" {
return reader, nil
} else if GetMimeType(query.Get("path")) != "image/dicom" {
return reader, nil
}
var b bytes.Buffer
w := bufio.NewWriter(&b)
io.Copy(w, reader)
reader.Close()
dataset, err := dicom.Parse(&b, int64(len(b.Bytes())), nil)
if err != nil {
Log.Debug("plg_image_dicom::parse '%s'", err.Error())
return nil, ErrNotValid
}
pixelDataElement, err := dataset.FindElementByTag(tag.PixelData)
if err != nil {
Log.Debug("plg_image_dicom::findElementByTag '%s'", err.Error())
return nil, ErrNotValid
}
pixelDataInfo := dicom.MustGetPixelDataInfo(pixelDataElement.Value)
for _, fr := range pixelDataInfo.Frames {
img, err := fr.GetImage()
if err != nil {
if err.Error() == "unsupported JPEG feature: unknown marker" {
// known issue with lossless jpeg codec which isn't supported in golang
// and is not trivial to support in Filestash
return nil, ErrNotImplemented
}
Log.Stdout("plg_image_dicom::getImage '%s'", err.Error())
return nil, err
}
var b bytes.Buffer
w := bufio.NewWriter(&b)
err = jpeg.Encode(w, img, &jpeg.Options{Quality: 100})
if err != nil {
Log.Debug("plg_image_dicom::encode '%s'", err.Error())
return nil, err
}
h := (*res).Header()
h.Set("Content-Type", "image/jpeg")
return NewReadCloserFromReader(&b), nil
}
return nil, ErrNotValid
}

View File

@ -23,9 +23,6 @@ func init() {
for _, mType := range []string{ for _, mType := range []string{
"image/x-canon-cr2", "image/x-fuji-raf", "image/x-nikon-nef", "image/x-canon-cr2", "image/x-fuji-raf", "image/x-nikon-nef",
"image/x-nikon-nrw", "image/x-epson-erf", "image/x-nikon-nrw", "image/x-epson-erf",
// "image/tiff",
// "image/x-kodak-dcr", "image/x-hasselblad-3fr",
// "image/x-raw",
} { } {
Hooks.Register.Thumbnailer(mType, thumbnailBuilder{thumbnailRaw}) Hooks.Register.Thumbnailer(mType, thumbnailBuilder{thumbnailRaw})
} }

View File

@ -0,0 +1,45 @@
package plg_image_transcode
import (
. "github.com/mickael-kerjean/filestash/server/common"
"io"
"net/http"
)
func init() {
Hooks.Register.ProcessFileContentBeforeSend(renderImages)
}
func renderImages(reader io.ReadCloser, ctx *App, res *http.ResponseWriter, req *http.Request) (io.ReadCloser, error) {
query := req.URL.Query()
if query.Get("thumbnail") == "true" {
return reader, nil
} else if query.Get("size") == "" {
return reader, nil
}
var (
out io.ReadCloser = nil
err error = nil
)
mType := GetMimeType(query.Get("path"))
switch mType {
case "image/x-ms-bmp":
out, mType, err = transcodeBmp(reader)
case "image/tiff":
out, mType, err = transcodeTiff(reader)
case "image/dicom":
out, mType, err = transcodeDicom(reader)
default:
err = ErrNotImplemented
}
reader.Close()
if err == nil {
(*res).Header().Set("Content-Type", mType)
}
if err != nil && err != ErrNotImplemented && err != ErrNotValid {
Log.Debug("plg_image_transcode::err %s", err.Error())
return nil, ErrNotValid
}
return out, err
}

View File

@ -0,0 +1,26 @@
package plg_image_transcode
import (
. "github.com/mickael-kerjean/filestash/server/common"
_ "golang.org/x/image/bmp"
"image"
"image/jpeg"
"io"
)
func transcodeBmp(reader io.Reader) (io.ReadCloser, string, error) {
img, _, err := image.Decode(reader)
if err != nil {
return nil, "", err
}
r, w := io.Pipe()
go func() {
err := jpeg.Encode(w, img, &jpeg.Options{Quality: 80})
w.Close()
if err != nil {
Log.Debug("plg_image_transcode::bmp jpeg encoding error '%s'", err.Error())
}
}()
return NewReadCloserFromReader(r), "image/jpeg", nil
}

View File

@ -0,0 +1,53 @@
package plg_image_transcode
import (
"bufio"
"bytes"
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/suyashkumar/dicom"
"github.com/suyashkumar/dicom/pkg/tag"
"image/jpeg"
"io"
)
func transcodeDicom(reader io.Reader) (io.ReadCloser, string, error) {
var b bytes.Buffer
w := bufio.NewWriter(&b)
io.Copy(w, reader)
dataset, err := dicom.Parse(&b, int64(len(b.Bytes())), nil)
if err != nil {
Log.Debug("plg_image_transcode::dicom::parse '%s'", err.Error())
return nil, "", ErrNotValid
}
pixelDataElement, err := dataset.FindElementByTag(tag.PixelData)
if err != nil {
Log.Debug("plg_image_transcode::dicom::findElementByTag '%s'", err.Error())
return nil, "", ErrNotValid
}
pixelDataInfo := dicom.MustGetPixelDataInfo(pixelDataElement.Value)
for _, fr := range pixelDataInfo.Frames {
img, err := fr.GetImage()
if err != nil {
if err.Error() == "unsupported JPEG feature: unknown marker" {
// known issue with lossless jpeg codec which isn't supported in golang
// and is not trivial to support in Filestash
return nil, "", ErrNotImplemented
}
Log.Stdout("plg_image_transcode_dicom::getImage '%s'", err.Error())
return nil, "", err
}
r, w := io.Pipe()
go func() {
err := jpeg.Encode(w, img, &jpeg.Options{Quality: 80})
w.Close()
if err != nil {
Log.Debug("plg_image_transcode::dicom jpeg encoding error '%s'", err.Error())
}
}()
return NewReadCloserFromReader(r), "image/jpeg", nil
}
return nil, "", ErrNotValid
}

View File

@ -0,0 +1,41 @@
package plg_image_transcode
import (
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/srwiley/oksvg"
"github.com/srwiley/rasterx"
"image"
"image/png"
"io"
)
/*
* This bit isn't used because the rendering is very poor and would
* generate too many bug reports
*/
func transcodeSvg(reader io.Reader) (io.ReadCloser, string, error) {
icon, err := oksvg.ReadIconStream(reader)
if err != nil {
return nil, "", err
}
icon.SetTarget(0, 0, icon.ViewBox.W, icon.ViewBox.H)
width := int(icon.ViewBox.W)
height := int(icon.ViewBox.H)
img := image.NewRGBA(image.Rect(0, 0, width, height))
icon.Draw(
rasterx.NewDasher(
width, height,
rasterx.NewScannerGV(width, height, img, img.Bounds()),
), 1,
)
r, w := io.Pipe()
go func() {
err := png.Encode(w, img)
w.Close()
if err != nil {
Log.Debug("plg_image_transcode::svg png encoding error '%s'", err.Error())
}
}()
return NewReadCloserFromReader(r), "image/png", nil
}

View File

@ -0,0 +1,26 @@
package plg_image_transcode
import (
. "github.com/mickael-kerjean/filestash/server/common"
_ "golang.org/x/image/tiff"
"image"
"image/jpeg"
"io"
)
func transcodeTiff(reader io.Reader) (io.ReadCloser, string, error) {
img, _, err := image.Decode(reader)
if err != nil {
return nil, "", err
}
r, w := io.Pipe()
go func() {
err := jpeg.Encode(w, img, &jpeg.Options{Quality: 80})
w.Close()
if err != nil {
Log.Debug("plg_image_transcode::tiff jpeg encoding error '%s'", err.Error())
}
}()
return NewReadCloserFromReader(r), "image/jpeg", nil
}