Convert: Case-insensitive related file search
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
606e416e2a
commit
f43154be93
3 changed files with 91 additions and 19 deletions
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/photoprism/photoprism/internal/event"
|
"github.com/photoprism/photoprism/internal/event"
|
||||||
"github.com/photoprism/photoprism/internal/mutex"
|
"github.com/photoprism/photoprism/internal/mutex"
|
||||||
"github.com/photoprism/photoprism/internal/thumb"
|
"github.com/photoprism/photoprism/internal/thumb"
|
||||||
|
"github.com/photoprism/photoprism/pkg/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Convert represents a converter that can convert RAW/HEIF images to JPEG.
|
// Convert represents a converter that can convert RAW/HEIF images to JPEG.
|
||||||
|
@ -123,9 +124,7 @@ func (c *Convert) ToJpeg(image *MediaFile) (*MediaFile, error) {
|
||||||
return image, nil
|
return image, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
base := image.AbsBase(c.conf.Settings().Library.GroupRelated)
|
jpegName := fs.TypeJpeg.Find(image.FileName(), c.conf.Settings().Library.GroupRelated)
|
||||||
|
|
||||||
jpegName := base + ".jpg"
|
|
||||||
|
|
||||||
mediaFile, err := NewMediaFile(jpegName)
|
mediaFile, err := NewMediaFile(jpegName)
|
||||||
|
|
||||||
|
@ -133,6 +132,8 @@ func (c *Convert) ToJpeg(image *MediaFile) (*MediaFile, error) {
|
||||||
return mediaFile, nil
|
return mediaFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jpegName = image.AbsBase(c.conf.Settings().Library.GroupRelated) + ".jpg"
|
||||||
|
|
||||||
if c.conf.ReadOnly() {
|
if c.conf.ReadOnly() {
|
||||||
return nil, fmt.Errorf("convert: disabled in read only mode (%s)", image.FileName())
|
return nil, fmt.Errorf("convert: disabled in read only mode (%s)", image.FileName())
|
||||||
}
|
}
|
||||||
|
@ -141,11 +142,7 @@ func (c *Convert) ToJpeg(image *MediaFile) (*MediaFile, error) {
|
||||||
|
|
||||||
log.Infof("convert: %s -> %s", fileName, jpegName)
|
log.Infof("convert: %s -> %s", fileName, jpegName)
|
||||||
|
|
||||||
xmpName := base + ".xmp"
|
xmpName := fs.TypeXMP.Find(image.FileName(), c.conf.Settings().Library.GroupRelated)
|
||||||
|
|
||||||
if _, err := os.Stat(xmpName); err != nil {
|
|
||||||
xmpName = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
event.Publish("index.converting", event.Data{
|
event.Publish("index.converting", event.Data{
|
||||||
"fileType": image.FileType(),
|
"fileType": image.FileType(),
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
_ "image/gif" // Import for image.
|
_ "image/gif" // Import for image.
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
_ "image/png"
|
_ "image/png"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -21,19 +22,22 @@ const (
|
||||||
TypeMov FileType = "mov" // Video files.
|
TypeMov FileType = "mov" // Video files.
|
||||||
TypeMP4 FileType = "mp4"
|
TypeMP4 FileType = "mp4"
|
||||||
TypeAvi FileType = "avi"
|
TypeAvi FileType = "avi"
|
||||||
TypeXMP FileType = "xmp" // Adobe XMP sidecar file (XML).
|
TypeXMP FileType = "xmp" // Adobe XMP sidecar file (XML).
|
||||||
TypeAAE FileType = "aae" // Apple sidecar file (XML).
|
TypeAAE FileType = "aae" // Apple sidecar file (XML).
|
||||||
TypeXML FileType = "xml" // XML metadata / config / sidecar file.
|
TypeXML FileType = "xml" // XML metadata / config / sidecar file.
|
||||||
TypeYaml FileType = "yml" // YAML metadata / config / sidecar file.
|
TypeYaml FileType = "yml" // YAML metadata / config / sidecar file.
|
||||||
TypeToml FileType = "toml" // Tom's Obvious, Minimal Language sidecar file.
|
TypeToml FileType = "toml" // Tom's Obvious, Minimal Language sidecar file.
|
||||||
TypeJson FileType = "json" // JSON metadata / config / sidecar file.
|
TypeJson FileType = "json" // JSON metadata / config / sidecar file.
|
||||||
TypeText FileType = "txt" // Text config / sidecar file.
|
TypeText FileType = "txt" // Text config / sidecar file.
|
||||||
TypeMarkdown FileType = "md" // Markdown text sidecar file.
|
TypeMarkdown FileType = "md" // Markdown text sidecar file.
|
||||||
TypeOther FileType = "unknown" // Unknown file format.
|
TypeOther FileType = "" // Unknown file format.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FileExtensions map[string]FileType
|
||||||
|
type TypeExtensions map[FileType][]string
|
||||||
|
|
||||||
// FileExt contains the filename extensions of file formats known to PhotoPrism.
|
// FileExt contains the filename extensions of file formats known to PhotoPrism.
|
||||||
var FileExt = map[string]FileType{
|
var FileExt = FileExtensions{
|
||||||
".bmp": TypeBitmap,
|
".bmp": TypeBitmap,
|
||||||
".gif": TypeGif,
|
".gif": TypeGif,
|
||||||
".tif": TypeTiff,
|
".tif": TypeTiff,
|
||||||
|
@ -48,9 +52,14 @@ var FileExt = map[string]FileType{
|
||||||
".avi": TypeAvi,
|
".avi": TypeAvi,
|
||||||
".mp4": TypeMP4,
|
".mp4": TypeMP4,
|
||||||
".yml": TypeYaml,
|
".yml": TypeYaml,
|
||||||
|
".yaml": TypeYaml,
|
||||||
".jpg": TypeJpeg,
|
".jpg": TypeJpeg,
|
||||||
".thm": TypeJpeg,
|
|
||||||
".jpeg": TypeJpeg,
|
".jpeg": TypeJpeg,
|
||||||
|
".jpe": TypeJpeg,
|
||||||
|
".jif": TypeJpeg,
|
||||||
|
".jfif": TypeJpeg,
|
||||||
|
".jfi": TypeJpeg,
|
||||||
|
".thm": TypeJpeg,
|
||||||
".xmp": TypeXMP,
|
".xmp": TypeXMP,
|
||||||
".aae": TypeAAE,
|
".aae": TypeAAE,
|
||||||
".heif": TypeHEIF,
|
".heif": TypeHEIF,
|
||||||
|
@ -97,6 +106,50 @@ var FileExt = map[string]FileType{
|
||||||
".json": TypeJson,
|
".json": TypeJson,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m FileExtensions) TypeExt() TypeExtensions {
|
||||||
|
result := make(TypeExtensions)
|
||||||
|
|
||||||
|
for ext, t := range m {
|
||||||
|
extUpper := strings.ToUpper(ext)
|
||||||
|
if _, ok := result[t]; ok {
|
||||||
|
result[t] = append(result[t], ext, extUpper)
|
||||||
|
} else {
|
||||||
|
result[t] = []string{ext, extUpper}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
var TypeExt = FileExt.TypeExt()
|
||||||
|
|
||||||
|
// Find returns the first filename with the same base name and a given type.
|
||||||
|
func (t FileType) Find(fileName string, stripSequence bool) string {
|
||||||
|
base := Base(fileName, stripSequence)
|
||||||
|
dir := filepath.Dir(fileName)
|
||||||
|
|
||||||
|
prefix := filepath.Join(dir, base)
|
||||||
|
prefixLower := filepath.Join(dir, strings.ToLower(base))
|
||||||
|
prefixUpper := filepath.Join(dir, strings.ToUpper(base))
|
||||||
|
|
||||||
|
for _, ext := range TypeExt[t] {
|
||||||
|
if info, err := os.Stat(prefix + ext); err == nil && info.Mode().IsRegular() {
|
||||||
|
return filepath.Join(dir, info.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
if info, err := os.Stat(prefixLower + ext); err == nil && info.Mode().IsRegular() {
|
||||||
|
return filepath.Join(dir, info.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
if info, err := os.Stat(prefixUpper + ext); err == nil && info.Mode().IsRegular() {
|
||||||
|
return filepath.Join(dir, info.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFileType returns the (expected) type for a given file name.
|
||||||
func GetFileType(fileName string) FileType {
|
func GetFileType(fileName string) FileType {
|
||||||
fileExt := strings.ToLower(filepath.Ext(fileName))
|
fileExt := strings.ToLower(filepath.Ext(fileName))
|
||||||
result, ok := FileExt[fileExt]
|
result, ok := FileExt[fileExt]
|
||||||
|
|
|
@ -22,3 +22,25 @@ func TestGetFileType(t *testing.T) {
|
||||||
assert.Equal(t, TypeOther, result)
|
assert.Equal(t, TypeOther, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileType_Find(t *testing.T) {
|
||||||
|
t.Run("find jpg", func(t *testing.T) {
|
||||||
|
result := TypeJpeg.Find("testdata/test.xmp", false)
|
||||||
|
assert.Equal(t, "testdata/test.jpg", result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("upper ext", func(t *testing.T) {
|
||||||
|
result := TypeJpeg.Find("testdata/test.XMP", false)
|
||||||
|
assert.Equal(t, "testdata/test.jpg", result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with sequence", func(t *testing.T) {
|
||||||
|
result := TypeJpeg.Find("testdata/test (2).xmp", false)
|
||||||
|
assert.Equal(t, "", result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("strip sequence", func(t *testing.T) {
|
||||||
|
result := TypeJpeg.Find("testdata/test (2).xmp", true)
|
||||||
|
assert.Equal(t, "testdata/test.jpg", result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue