From 4d57d4301100ea9d231563d8d7604408efca034b Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Wed, 13 May 2020 15:28:50 +0200 Subject: [PATCH] Determine image type by file extension --- api/scanner/album_scanner.go | 2 +- api/scanner/photo_type.go | 93 ++++++++++++++++++++++++++---------- api/scanner/process_photo.go | 6 +-- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/api/scanner/album_scanner.go b/api/scanner/album_scanner.go index 007c1c71..a07cce5b 100644 --- a/api/scanner/album_scanner.go +++ b/api/scanner/album_scanner.go @@ -19,7 +19,7 @@ import ( type scanner_cache map[string]interface{} -func (cache *scanner_cache) insert_photo_type(path string, content_type FileType) { +func (cache *scanner_cache) insert_photo_type(path string, content_type ImageType) { (*cache)["photo_type//"+path] = content_type } diff --git a/api/scanner/photo_type.go b/api/scanner/photo_type.go index 5c87b860..53d627f7 100644 --- a/api/scanner/photo_type.go +++ b/api/scanner/photo_type.go @@ -4,22 +4,25 @@ import ( "io" "log" "os" + "path/filepath" + "strings" "github.com/h2non/filetype" + "github.com/pkg/errors" ) -type FileType string +type ImageType string const ( - TypeJpeg FileType = "image/jpeg" - TypePng FileType = "image/png" - TypeTiff FileType = "image/tiff" - TypeWebp FileType = "image/webp" - TypeCr2 FileType = "image/x-canon-cr2" - TypeBmp FileType = "image/bmp" + TypeJpeg ImageType = "image/jpeg" + TypePng ImageType = "image/png" + TypeTiff ImageType = "image/tiff" + TypeWebp ImageType = "image/webp" + TypeBmp ImageType = "image/bmp" + TypeCr2 ImageType = "image/x-canon-cr2" ) -var SupportedMimetypes = [...]FileType{ +var SupportedMimetypes = [...]ImageType{ TypeJpeg, TypePng, TypeTiff, @@ -28,46 +31,88 @@ var SupportedMimetypes = [...]FileType{ TypeCr2, } -var WebMimetypes = [...]FileType{ +var WebMimetypes = [...]ImageType{ TypeJpeg, TypePng, TypeWebp, TypeBmp, } -func isPathImage(path string, cache *scanner_cache) bool { - if cache.get_photo_type(path) != nil { - return true +var fileExtensions = map[string]ImageType{ + ".jpg": TypeJpeg, + ".jpeg": TypeJpeg, + ".png": TypePng, + ".tif": TypeTiff, + ".tiff": TypeTiff, + ".bmp": TypeBmp, + ".cr2": TypeCr2, +} + +func isTypeSupported(img ImageType) bool { + for _, supported_mime := range SupportedMimetypes { + if supported_mime == img { + return true + } } + + return false +} + +func getImageType(path string) (*ImageType, error) { + + ext := filepath.Ext(path) + + fileExtType := fileExtensions[strings.ToLower(ext)] + + if isTypeSupported(fileExtType) { + return &fileExtType, nil + } + + // If extension was not recognized try to read file header file, err := os.Open(path) if err != nil { - ScannerError("Could not open file %s: %s\n", path, err) - return false + return nil, errors.Wrapf(err, "could not open file %s", path) } defer file.Close() head := make([]byte, 261) if _, err := file.Read(head); err != nil { if err == io.EOF { - return false + return nil, nil } - ScannerError("Could not read file %s: %s\n", path, err) - return false + return nil, errors.Wrapf(err, "could not read file: %s", path) } - imgType, err := filetype.Image(head) + _imgType, err := filetype.Image(head) if err != nil { + return nil, nil + } + + imgType := ImageType(_imgType.MIME.Value) + if isTypeSupported(imgType) { + return &imgType, nil + } + + return nil, nil +} + +func isPathImage(path string, cache *scanner_cache) bool { + if cache.get_photo_type(path) != nil { + return true + } + + imageType, err := getImageType(path) + if err != nil { + ScannerError("%s (%s)", err, path) return false } - for _, supported_mime := range SupportedMimetypes { - if supported_mime == FileType(imgType.MIME.Value) { - cache.insert_photo_type(path, supported_mime) - return true - } + if imageType != nil { + cache.insert_photo_type(path, *imageType) + return true } - log.Printf("Unsupported image %s of type %s\n", path, imgType.MIME.Value) + log.Printf("File is not a supported image %s\n", path) return false } diff --git a/api/scanner/process_photo.go b/api/scanner/process_photo.go index bf7c9759..e51b64f3 100644 --- a/api/scanner/process_photo.go +++ b/api/scanner/process_photo.go @@ -269,11 +269,11 @@ type ProcessImageData struct { photo *models.Photo _photoImage image.Image _thumbnailImage image.Image - _contentType *FileType + _contentType *ImageType } // ContentType reads the image to determine its content type -func (img *ProcessImageData) ContentType() (*FileType, error) { +func (img *ProcessImageData) ContentType() (*ImageType, error) { if img._contentType != nil { return img._contentType, nil } @@ -296,7 +296,7 @@ func (img *ProcessImageData) ContentType() (*FileType, error) { return nil, err } - imgType := FileType(_imgType.MIME.Value) + imgType := ImageType(_imgType.MIME.Value) img._contentType = &imgType return img._contentType, nil }