mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-10-31 18:16:00 +08:00 
			
		
		
		
	feature (plg_image_*): support for new images and cleanup
This commit is contained in:
		| @ -28,8 +28,8 @@ import ( | ||||
| 	_ "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_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_transcode" | ||||
| 	_ "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_svg" | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
| @ -23,9 +23,6 @@ func init() { | ||||
| 	for _, mType := range []string{ | ||||
| 		"image/x-canon-cr2", "image/x-fuji-raf", "image/x-nikon-nef", | ||||
| 		"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}) | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										45
									
								
								server/plugin/plg_image_transcode/index.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								server/plugin/plg_image_transcode/index.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										26
									
								
								server/plugin/plg_image_transcode/transcode_bmp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								server/plugin/plg_image_transcode/transcode_bmp.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										53
									
								
								server/plugin/plg_image_transcode/transcode_dicom.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								server/plugin/plg_image_transcode/transcode_dicom.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										41
									
								
								server/plugin/plg_image_transcode/transcode_svg.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								server/plugin/plg_image_transcode/transcode_svg.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										26
									
								
								server/plugin/plg_image_transcode/transcode_tiff.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								server/plugin/plg_image_transcode/transcode_tiff.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Mickael Kerjean
					Mickael Kerjean