diff --git a/assets/resources/examples/Screenshot 2019-05-21 at 10.45.52.png b/assets/resources/examples/Screenshot 2019-05-21 at 10.45.52.png
new file mode 100644
index 000000000..0b935420b
Binary files /dev/null and b/assets/resources/examples/Screenshot 2019-05-21 at 10.45.52.png differ
diff --git a/frontend/src/pages/library/originals.vue b/frontend/src/pages/library/originals.vue
index f64f2702a..21442e747 100644
--- a/frontend/src/pages/library/originals.vue
+++ b/frontend/src/pages/library/originals.vue
@@ -66,6 +66,18 @@
Index
update
+
+
+ The index currently contains {{ config.count.hidden }} hidden files. Their format may not be supported,
+ they haven't been converted to JPEG yet or there are duplicates.
+
@@ -87,6 +99,7 @@
return {
settings: new Settings(this.$config.settings()),
readonly: this.$config.get("readonly"),
+ config: this.$config.values,
started: false,
busy: false,
loading: false,
diff --git a/internal/config/client.go b/internal/config/client.go
index 9e115c969..ce9862216 100644
--- a/internal/config/client.go
+++ b/internal/config/client.go
@@ -59,6 +59,7 @@ func (c *Config) PublicClientConfig() ClientConfig {
var count = struct {
Photos uint `json:"photos"`
+ Hidden uint `json:"hidden"`
Favorites uint `json:"favorites"`
Private uint `json:"private"`
Stories uint `json:"stories"`
@@ -131,6 +132,7 @@ func (c *Config) ClientConfig() ClientConfig {
var count = struct {
Photos uint `json:"photos"`
+ Hidden uint `json:"hidden"`
Favorites uint `json:"favorites"`
Private uint `json:"private"`
Stories uint `json:"stories"`
@@ -141,7 +143,7 @@ func (c *Config) ClientConfig() ClientConfig {
}{}
db.Table("photos").
- Select("COUNT(*) AS photos, SUM(photo_favorite) AS favorites, SUM(photo_private) AS private, SUM(photo_story) AS stories").
+ Select("SUM(photo_quality = -1) AS hidden, SUM(photo_quality >= 0) AS photos, SUM(photo_favorite) AS favorites, SUM(photo_private) AS private, SUM(photo_story) AS stories").
Where("deleted_at IS NULL").
Take(&count)
diff --git a/internal/entity/file.go b/internal/entity/file.go
index 5d34088fd..2b9a3e67b 100644
--- a/internal/entity/file.go
+++ b/internal/entity/file.go
@@ -35,8 +35,8 @@ type File struct {
FileOrientation int
FileAspectRatio float32 `gorm:"type:FLOAT;"`
FileMainColor string `gorm:"type:varbinary(16);index;"`
- FileColors string `gorm:"type:binary(9);"`
- FileLuminance string `gorm:"type:binary(9);"`
+ FileColors string `gorm:"type:varbinary(9);"`
+ FileLuminance string `gorm:"type:varbinary(9);"`
FileDiff uint32
FileChroma uint8
FileNotes string `gorm:"type:text"`
diff --git a/internal/photoprism/colors_test.go b/internal/photoprism/colors_test.go
index d635023fb..9406c91b0 100644
--- a/internal/photoprism/colors_test.go
+++ b/internal/photoprism/colors_test.go
@@ -52,6 +52,12 @@ func TestMediaFile_Colors_Testdata(t *testing.T) {
Luminance: colors.LightMap{0x9, 0x5, 0xb, 0x6, 0x1, 0x6, 0xa, 0x1, 0x8},
Chroma: 20,
},
+ "Screenshot 2019-05-21 at 10.45.52.png": {
+ Colors: colors.Colors{},
+ MainColor: 0,
+ Luminance: colors.LightMap{},
+ Chroma: 0,
+ },
}
if err := fastwalk.Walk(conf.ExamplesPath(), func(filename string, info os.FileMode) error {
@@ -61,7 +67,12 @@ func TestMediaFile_Colors_Testdata(t *testing.T) {
mediaFile, err := NewMediaFile(filename)
- if err != nil || !mediaFile.IsJpeg() {
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !mediaFile.IsJpeg() {
+ t.Logf("not a jpeg: %s", filepath.Base(mediaFile.FileName()))
return nil
}
diff --git a/internal/photoprism/index_mediafile.go b/internal/photoprism/index_mediafile.go
index d06799ca3..c11231865 100644
--- a/internal/photoprism/index_mediafile.go
+++ b/internal/photoprism/index_mediafile.go
@@ -56,14 +56,16 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
start := time.Now()
- var photo entity.Photo
- var description entity.Description
- var file, primaryFile entity.File
- var metaData meta.Data
var photoQuery, fileQuery *gorm.DB
var locKeywords []string
+ file, primaryFile := entity.File{}, entity.File{}
+
+ photo := entity.Photo{}
+ metaData := meta.Data{}
+ description := entity.Description{}
labels := classify.Labels{}
+
fileBase := m.Base(ind.conf.Settings().Index.Group)
filePath := m.RelativePath(ind.originalsPath())
fileName := m.RelativeName(ind.originalsPath())
@@ -120,6 +122,8 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
if photoExists {
ind.db.Model(&photo).Related(&description)
+ } else {
+ photo.PhotoQuality = -1
}
if fileHash == "" {
@@ -377,7 +381,9 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
log.Warnf("%s (%s)", err.Error(), photo.PhotoUUID)
}
} else {
- photo.PhotoQuality = photo.QualityScore()
+ if photo.PhotoQuality >= 0 {
+ photo.PhotoQuality = photo.QualityScore()
+ }
if err := ind.db.Unscoped().Save(&photo).Error; err != nil {
log.Errorf("index: %s", err)
diff --git a/internal/photoprism/purge.go b/internal/photoprism/purge.go
index 8d2c59007..e2ef2532d 100644
--- a/internal/photoprism/purge.go
+++ b/internal/photoprism/purge.go
@@ -163,6 +163,8 @@ func (prg *Purge) Start(opt PurgeOptions) (purgedFiles map[string]bool, purgedPh
offset += limit
}
+ err = q.ResetPhotosQuality()
+
return purgedFiles, purgedPhotos, err
}
diff --git a/internal/query/photo.go b/internal/query/photo.go
index d63126ec0..15bc00bb3 100644
--- a/internal/query/photo.go
+++ b/internal/query/photo.go
@@ -469,3 +469,10 @@ func (q *Query) MissingPhotos(limit int, offset int) (entities []entity.Photo, e
return entities, err
}
+
+// ResetPhotosQuality resets the quality of photos without primary file to -1.
+func (q *Query) ResetPhotosQuality() error {
+ return q.db.Table("photos").
+ Where("id IN (SELECT photos.id FROM photos LEFT JOIN files ON photos.id = files.photo_id AND files.file_primary = 1 WHERE files.id IS NULL GROUP BY photos.id)").
+ Update("photo_quality", -1).Error
+}
diff --git a/pkg/fs/base.go b/pkg/fs/base.go
index 7780203c3..0f9f78d8f 100644
--- a/pkg/fs/base.go
+++ b/pkg/fs/base.go
@@ -2,6 +2,7 @@ package fs
import (
"path/filepath"
+ "strconv"
"strings"
)
@@ -9,8 +10,8 @@ import (
func Base(fileName string, stripSequence bool) string {
basename := filepath.Base(fileName)
- if end := strings.Index(basename, "."); end != -1 {
- // ignore everything behind the first dot in the file name
+ // strip file type extension
+ if end := strings.LastIndex(basename, "."); end != -1 {
basename = basename[:end]
}
@@ -18,7 +19,14 @@ func Base(fileName string, stripSequence bool) string {
return basename
}
- // common sequential naming schemes
+ // strip numeric extensions like .0000, .0001, .4542353245,....
+ if dot := strings.LastIndex(basename, "."); dot != -1 {
+ if i, err := strconv.Atoi(basename[dot+1:]); err == nil && i >= 0 {
+ basename = basename[:dot]
+ }
+ }
+
+ // other common sequential naming schemes
if end := strings.Index(basename, " ("); end != -1 {
// copies created by Chrome & Windows, example: IMG_1234 (2)
basename = basename[:end]
diff --git a/pkg/fs/base_test.go b/pkg/fs/base_test.go
index 1f82f3218..f540e2ec0 100644
--- a/pkg/fs/base_test.go
+++ b/pkg/fs/base_test.go
@@ -7,13 +7,15 @@ import (
)
func TestBase(t *testing.T) {
- t.Run("Test.jpg", func(t *testing.T) {
- result := Base("/testdata/Test.jpg", true)
- assert.Equal(t, "Test", result)
+ t.Run("Screenshot 2019-05-21 at 10.45.52.png", func(t *testing.T) {
+ regular := Base("Screenshot 2019-05-21 at 10.45.52.png", false)
+ assert.Equal(t, "Screenshot 2019-05-21 at 10.45.52", regular)
+ stripped := Base("Screenshot 2019-05-21 at 10.45.52.png", true)
+ assert.Equal(t, "Screenshot 2019-05-21 at 10.45", stripped)
})
- t.Run("Test.3453453.jpg", func(t *testing.T) {
- result := Base("/testdata/Test.3453453.jpg", true)
+ t.Run("Test.jpg", func(t *testing.T) {
+ result := Base("/testdata/Test.jpg", true)
assert.Equal(t, "Test", result)
})
@@ -33,8 +35,19 @@ func TestBase(t *testing.T) {
})
t.Run("Test.3453453.jpg", func(t *testing.T) {
- result := Base("/testdata/Test.3453453.jpg", false)
- assert.Equal(t, "Test", result)
+ regular := Base("/testdata/Test.3453453.jpg", false)
+ assert.Equal(t, "Test.3453453", regular)
+
+ stripped := Base("/testdata/Test.3453453.jpg", true)
+ assert.Equal(t, "Test", stripped)
+ })
+
+ t.Run("/foo/bar.0000.ZIP", func(t *testing.T) {
+ regular := Base("/foo/bar.0000.ZIP", false)
+ assert.Equal(t, "bar.0000", regular)
+
+ stripped := Base("/foo/bar.0000.ZIP", true)
+ assert.Equal(t, "bar", stripped)
})
t.Run("Test copy 3.jpg", func(t *testing.T) {