1
Fork 0

Determine image type by file extension

This commit is contained in:
viktorstrate 2020-05-13 15:28:50 +02:00
parent 5a5c06fb32
commit 4d57d43011
3 changed files with 73 additions and 28 deletions

View File

@ -19,7 +19,7 @@ import (
type scanner_cache map[string]interface{} 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 (*cache)["photo_type//"+path] = content_type
} }

View File

@ -4,22 +4,25 @@ import (
"io" "io"
"log" "log"
"os" "os"
"path/filepath"
"strings"
"github.com/h2non/filetype" "github.com/h2non/filetype"
"github.com/pkg/errors"
) )
type FileType string type ImageType string
const ( const (
TypeJpeg FileType = "image/jpeg" TypeJpeg ImageType = "image/jpeg"
TypePng FileType = "image/png" TypePng ImageType = "image/png"
TypeTiff FileType = "image/tiff" TypeTiff ImageType = "image/tiff"
TypeWebp FileType = "image/webp" TypeWebp ImageType = "image/webp"
TypeCr2 FileType = "image/x-canon-cr2" TypeBmp ImageType = "image/bmp"
TypeBmp FileType = "image/bmp" TypeCr2 ImageType = "image/x-canon-cr2"
) )
var SupportedMimetypes = [...]FileType{ var SupportedMimetypes = [...]ImageType{
TypeJpeg, TypeJpeg,
TypePng, TypePng,
TypeTiff, TypeTiff,
@ -28,46 +31,88 @@ var SupportedMimetypes = [...]FileType{
TypeCr2, TypeCr2,
} }
var WebMimetypes = [...]FileType{ var WebMimetypes = [...]ImageType{
TypeJpeg, TypeJpeg,
TypePng, TypePng,
TypeWebp, TypeWebp,
TypeBmp, TypeBmp,
} }
func isPathImage(path string, cache *scanner_cache) bool { var fileExtensions = map[string]ImageType{
if cache.get_photo_type(path) != nil { ".jpg": TypeJpeg,
return true ".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) file, err := os.Open(path)
if err != nil { if err != nil {
ScannerError("Could not open file %s: %s\n", path, err) return nil, errors.Wrapf(err, "could not open file %s", path)
return false
} }
defer file.Close() defer file.Close()
head := make([]byte, 261) head := make([]byte, 261)
if _, err := file.Read(head); err != nil { if _, err := file.Read(head); err != nil {
if err == io.EOF { if err == io.EOF {
return false return nil, nil
} }
ScannerError("Could not read file %s: %s\n", path, err) return nil, errors.Wrapf(err, "could not read file: %s", path)
return false
} }
imgType, err := filetype.Image(head) _imgType, err := filetype.Image(head)
if err != nil { 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 return false
} }
for _, supported_mime := range SupportedMimetypes { if imageType != nil {
if supported_mime == FileType(imgType.MIME.Value) { cache.insert_photo_type(path, *imageType)
cache.insert_photo_type(path, supported_mime) return true
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 return false
} }

View File

@ -269,11 +269,11 @@ type ProcessImageData struct {
photo *models.Photo photo *models.Photo
_photoImage image.Image _photoImage image.Image
_thumbnailImage image.Image _thumbnailImage image.Image
_contentType *FileType _contentType *ImageType
} }
// ContentType reads the image to determine its content type // 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 { if img._contentType != nil {
return img._contentType, nil return img._contentType, nil
} }
@ -296,7 +296,7 @@ func (img *ProcessImageData) ContentType() (*FileType, error) {
return nil, err return nil, err
} }
imgType := FileType(_imgType.MIME.Value) imgType := ImageType(_imgType.MIME.Value)
img._contentType = &imgType img._contentType = &imgType
return img._contentType, nil return img._contentType, nil
} }