精简后的项目:仅保留 api/ui 源码、文档、构建依赖
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package scanner_tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
_ "image/jpeg"
|
||||
"os"
|
||||
|
||||
"github.com/buckket/go-blurhash"
|
||||
"github.com/photoview/photoview/api/graphql/models"
|
||||
"github.com/photoview/photoview/api/log"
|
||||
"github.com/photoview/photoview/api/scanner/media_encoding"
|
||||
"github.com/photoview/photoview/api/scanner/scanner_task"
|
||||
)
|
||||
|
||||
type BlurhashTask struct {
|
||||
scanner_task.ScannerTaskBase
|
||||
}
|
||||
|
||||
func (t BlurhashTask) AfterProcessMedia(ctx scanner_task.TaskContext, mediaData *media_encoding.EncodeMediaData, updatedURLs []*models.MediaURL, mediaIndex int, mediaTotal int) error {
|
||||
hasThumbnailUpdated := false
|
||||
for _, url := range updatedURLs {
|
||||
if url.Purpose == models.PhotoThumbnail || url.Purpose == models.VideoThumbnail {
|
||||
hasThumbnailUpdated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var media *models.Media
|
||||
if err := ctx.GetDB().Preload("MediaURL").Where("id = ?", mediaData.Media.ID).First(&media).Error; err != nil {
|
||||
return fmt.Errorf("failed to get media(id:%d): %w", mediaData.Media.ID, err)
|
||||
}
|
||||
|
||||
if media.Blurhash != nil && !hasThumbnailUpdated {
|
||||
log.Info(ctx, "No thumbnail updated, ignore generating blurhash", "media", media.Path)
|
||||
return nil
|
||||
}
|
||||
|
||||
thumbnail, err := media.GetThumbnail()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get thumbnail of image %q: %w", mediaData.Media.Path, err)
|
||||
}
|
||||
|
||||
hashStr, err := generateBlurhashFromThumbnail(thumbnail)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate blurhash of image %q: %w", mediaData.Media.Path, err)
|
||||
}
|
||||
|
||||
media.Blurhash = &hashStr
|
||||
if err := ctx.GetDB().Select("blurhash").Save(media).Error; err != nil {
|
||||
return fmt.Errorf("failed to store blurhash of image %q: %w", mediaData.Media.Path, err)
|
||||
}
|
||||
|
||||
log.Info(ctx, "Generated blurhash of image", "media", mediaData.Media.Path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateBlurhashFromThumbnail generates a blurhash for a single media and stores it in the database
|
||||
func generateBlurhashFromThumbnail(thumbnail *models.MediaURL) (string, error) {
|
||||
path, err := thumbnail.CachedPath()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get path of media(id:%d) error: %w", thumbnail.MediaID, err)
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("open %q error: %w", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
imageData, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("decode %q error: %w", path, err)
|
||||
}
|
||||
|
||||
const (
|
||||
componentX = 4
|
||||
componentY = 3
|
||||
)
|
||||
hashStr, err := blurhash.Encode(componentX, componentY, imageData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("encode blurhash of %q error: %w", path, err)
|
||||
}
|
||||
|
||||
return hashStr, nil
|
||||
}
|
||||
Reference in New Issue
Block a user