mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-01-04 03:49:28 +02:00
Replace readyThumbnail filed with missingThumbnail bitmap.
Expected to save 6% on the server result json size. #437
This commit is contained in:
parent
9b71674ef7
commit
845c70f6c6
@ -14,6 +14,7 @@ import {ServerTime} from '../ServerTimingMWs';
|
||||
|
||||
|
||||
export class ThumbnailGeneratorMWs {
|
||||
private static ThumbnailMap: { [key: number]: number };
|
||||
|
||||
@ServerTime('2.th', 'Thumbnail decoration')
|
||||
public static async addThumbnailInformation(req: Request, res: Response, next: NextFunction): Promise<any> {
|
||||
@ -67,7 +68,7 @@ export class ThumbnailGeneratorMWs {
|
||||
// generate thumbnail path
|
||||
const thPath = PhotoProcessing.generatePersonThumbnailPath(mediaPath, item.sampleRegion, size);
|
||||
|
||||
item.readyThumbnail = fs.existsSync(thPath);
|
||||
item.missingThumbnail = !fs.existsSync(thPath);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@ -148,6 +149,7 @@ export class ThumbnailGeneratorMWs {
|
||||
|
||||
|
||||
private static addThInfoTODir(directory: ParentDirectoryDTO | SubDirectoryDTO): void {
|
||||
ThumbnailGeneratorMWs.ThumbnailMap = Config.Client.Media.Thumbnail.generateThumbnailMap();
|
||||
if (typeof directory.media !== 'undefined') {
|
||||
ThumbnailGeneratorMWs.addThInfoToPhotos(directory.media);
|
||||
}
|
||||
@ -164,20 +166,16 @@ export class ThumbnailGeneratorMWs {
|
||||
|
||||
private static addThInfoToAPhoto(photo: MediaDTO): void {
|
||||
const fullMediaPath = path.join(ProjectPath.ImageFolder, photo.directory.path, photo.directory.name, photo.name);
|
||||
for (const size of Config.Client.Media.Thumbnail.thumbnailSizes) {
|
||||
const thPath = PhotoProcessing.generateConvertedPath(fullMediaPath, size);
|
||||
if (fs.existsSync(thPath) === true) {
|
||||
if (typeof photo.readyThumbnails === 'undefined') {
|
||||
photo.readyThumbnails = [];
|
||||
for (const size of Object.keys(ThumbnailGeneratorMWs.ThumbnailMap)) {
|
||||
const thPath = PhotoProcessing.generateConvertedPath(fullMediaPath, size as any);
|
||||
if (fs.existsSync(thPath) !== true) {
|
||||
if (typeof photo.missingThumbnails === 'undefined') {
|
||||
photo.missingThumbnails = 0;
|
||||
}
|
||||
photo.readyThumbnails.push(size);
|
||||
// this is a bitwise operation
|
||||
photo.missingThumbnails += ThumbnailGeneratorMWs.ThumbnailMap[size as any];
|
||||
}
|
||||
}
|
||||
const iconPath = PhotoProcessing.generateConvertedPath(fullMediaPath, Config.Client.Media.Thumbnail.iconSize);
|
||||
if (fs.existsSync(iconPath) === true) {
|
||||
photo.readyIcon = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -229,10 +229,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
|
||||
|
||||
dir.media = [];
|
||||
dir.isPartial = true;
|
||||
if (dir.preview) {
|
||||
dir.preview.readyThumbnails = [];
|
||||
dir.preview.readyIcon = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -282,8 +278,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
|
||||
.getMany();
|
||||
for (const item of dir.media) {
|
||||
item.directory = dir;
|
||||
item.readyThumbnails = [];
|
||||
item.readyIcon = false;
|
||||
(item as PhotoDTO).metadata.faces = indexedFaces
|
||||
.filter((fe): boolean => fe.media.id === item.id)
|
||||
.map((f): { name: any; box: any } => ({box: f.box, name: f.person.name}));
|
||||
|
@ -61,13 +61,6 @@ export class IndexingManager implements IIndexingManager {
|
||||
try {
|
||||
const scannedDirectory = await DiskManager.scanDirectory(relativeDirectoryName);
|
||||
|
||||
// returning with the result
|
||||
if (scannedDirectory.preview) {
|
||||
scannedDirectory.preview.readyThumbnails = [];
|
||||
}
|
||||
scannedDirectory.media.forEach((p): any[] => p.readyThumbnails = []);
|
||||
|
||||
|
||||
const dirClone = Utils.shallowClone(scannedDirectory);
|
||||
// filter server side only config from returning
|
||||
dirClone.metaFile = dirClone.metaFile.filter(m => !ServerPG2ConfMap[m.name]);
|
||||
|
@ -167,8 +167,5 @@ export abstract class MediaEntity implements MediaDTO {
|
||||
@Column(type => MediaMetadataEntity)
|
||||
metadata: MediaMetadataEntity;
|
||||
|
||||
readyThumbnails: number[] = [];
|
||||
|
||||
readyIcon = false;
|
||||
|
||||
missingThumbnails: number;
|
||||
}
|
||||
|
@ -103,6 +103,17 @@ export class ClientThumbnailConfig {
|
||||
thumbnailSizes: number[] = [240, 480];
|
||||
@ConfigProperty({volatile: true})
|
||||
concurrentThumbnailGenerations: number = 1;
|
||||
|
||||
/**
|
||||
* Generates a map for bitwise operation from icon and normal thumbnails
|
||||
*/
|
||||
generateThumbnailMap(): { [key: number]: number } {
|
||||
const m: { [key: number]: number } = {};
|
||||
[this.iconSize, ...this.thumbnailSizes.sort()].forEach((v, i) => {
|
||||
m[v] = Math.pow(2, i + 1);
|
||||
});
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
@SubConfigClass()
|
||||
|
@ -9,9 +9,7 @@ export interface MediaDTO extends FileDTO {
|
||||
name: string;
|
||||
directory: DirectoryPathDTO;
|
||||
metadata: MediaMetadata;
|
||||
readyThumbnails: number[];
|
||||
readyIcon: boolean;
|
||||
|
||||
missingThumbnails?: number;
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ export interface PersonDTO {
|
||||
id: number;
|
||||
name: string;
|
||||
count: number;
|
||||
readyThumbnail?: boolean;
|
||||
missingThumbnail?: boolean;
|
||||
isFavourite: boolean;
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ import {MediaDimension, MediaDTO, MediaMetadata} from './MediaDTO';
|
||||
export interface PreviewPhotoDTO extends MediaDTO {
|
||||
name: string;
|
||||
directory: DirectoryPathDTO;
|
||||
readyThumbnails: number[];
|
||||
readyIcon: boolean;
|
||||
}
|
||||
|
||||
export interface PhotoDTO extends PreviewPhotoDTO, MediaDTO {
|
||||
@ -14,8 +12,7 @@ export interface PhotoDTO extends PreviewPhotoDTO, MediaDTO {
|
||||
name: string;
|
||||
directory: DirectoryPathDTO;
|
||||
metadata: PhotoMetadata;
|
||||
readyThumbnails: number[];
|
||||
readyIcon: boolean;
|
||||
missingThumbnails?: number;
|
||||
}
|
||||
|
||||
export interface FaceRegionBox {
|
||||
|
@ -14,9 +14,13 @@ export class Media extends MediaIcon {
|
||||
|
||||
|
||||
thumbnailLoaded(): void {
|
||||
console.log(this.media.name, this.media.missingThumbnails);
|
||||
if (!this.isThumbnailAvailable()) {
|
||||
this.media.readyThumbnails = this.media.readyThumbnails || [];
|
||||
this.media.readyThumbnails.push(this.getThumbnailSize());
|
||||
this.media.missingThumbnails = this.media.missingThumbnails || 0;
|
||||
this.media.missingThumbnails -= MediaIcon.ThumbnailMap[this.getThumbnailSize()];
|
||||
if (this.media.missingThumbnails < 0) {
|
||||
throw new Error('missingThumbnails got below 0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,10 +35,12 @@ export class Media extends MediaIcon {
|
||||
this.replacementSizeCache = null;
|
||||
|
||||
const size = this.getThumbnailSize();
|
||||
if (!!this.media.readyThumbnails) {
|
||||
for (const item of this.media.readyThumbnails) {
|
||||
if (item < size) {
|
||||
this.replacementSizeCache = item;
|
||||
if (!!this.media.missingThumbnails) {
|
||||
for (const thSize of Config.Client.Media.Thumbnail.thumbnailSizes) {
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
if ((this.media.missingThumbnails & MediaIcon.ThumbnailMap[thSize]) === 0 &&
|
||||
thSize < size) {
|
||||
this.replacementSizeCache = thSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -48,7 +54,8 @@ export class Media extends MediaIcon {
|
||||
}
|
||||
|
||||
isThumbnailAvailable(): boolean {
|
||||
return this.media.readyThumbnails && this.media.readyThumbnails.indexOf(this.getThumbnailSize()) !== -1;
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
return (this.media.missingThumbnails & MediaIcon.ThumbnailMap[this.getThumbnailSize()]) === 0;
|
||||
}
|
||||
|
||||
getReplacementThumbnailPath(): string {
|
||||
|
@ -3,7 +3,7 @@ import {Config} from '../../../../common/config/public/Config';
|
||||
import {MediaDTO} from '../../../../common/entities/MediaDTO';
|
||||
|
||||
export class MediaIcon {
|
||||
|
||||
protected static readonly ThumbnailMap = Config.Client.Media.Thumbnail.generateThumbnailMap();
|
||||
|
||||
protected replacementSizeCache: number | boolean = false;
|
||||
|
||||
@ -16,11 +16,12 @@ export class MediaIcon {
|
||||
}
|
||||
|
||||
iconLoaded(): void {
|
||||
this.media.readyIcon = true;
|
||||
this.media.missingThumbnails -= MediaIcon.ThumbnailMap[Config.Client.Media.Thumbnail.iconSize];
|
||||
}
|
||||
|
||||
isIconAvailable(): boolean {
|
||||
return this.media.readyIcon;
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
return (this.media.missingThumbnails & MediaIcon.ThumbnailMap[Config.Client.Media.Thumbnail.iconSize]) === 0;
|
||||
}
|
||||
|
||||
getRelativePath(): string {
|
||||
|
@ -244,24 +244,27 @@ export class GalleryCacheService {
|
||||
* @param media: MediaBaseDTO
|
||||
*/
|
||||
public mediaUpdated(media: MediaDTO): void {
|
||||
|
||||
if (Config.Client.Other.enableCache === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const directoryName = Utils.concatUrls(media.directory.path, media.directory.name);
|
||||
const value = localStorage.getItem(directoryName);
|
||||
const directoryKey = GalleryCacheService.CONTENT_PREFIX + Utils.concatUrls(media.directory.path, media.directory.name);
|
||||
const value = localStorage.getItem(directoryKey);
|
||||
if (value != null) {
|
||||
const directory: ParentDirectoryDTO = JSON.parse(value);
|
||||
directory.media.forEach((p) => {
|
||||
if (p.name === media.name) {
|
||||
// update data
|
||||
p.metadata = media.metadata;
|
||||
p.readyThumbnails = media.readyThumbnails;
|
||||
if (media.missingThumbnails) {
|
||||
p.missingThumbnails = media.missingThumbnails;
|
||||
} else {
|
||||
delete p.missingThumbnails;
|
||||
}
|
||||
|
||||
// save changes
|
||||
localStorage.setItem(directoryName, JSON.stringify(directory));
|
||||
localStorage.setItem(directoryKey, JSON.stringify(directory));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -83,7 +83,7 @@ export class PersonThumbnail extends ThumbnailBase {
|
||||
super(thumbnailService);
|
||||
this.src = '';
|
||||
this.error = false;
|
||||
if (this.person.readyThumbnail) {
|
||||
if (!this.person.missingThumbnail) {
|
||||
this.src = Person.getThumbnailUrl(person);
|
||||
this.available = true;
|
||||
if (this.onLoad) {
|
||||
|
@ -1240,9 +1240,7 @@ describe('SearchManager', (sqlHelper: DBTestHelper) => {
|
||||
name: subDir.name,
|
||||
path: subDir.path
|
||||
},
|
||||
name: pFaceLess.name,
|
||||
readyIcon: false,
|
||||
readyThumbnails: []
|
||||
name: pFaceLess.name
|
||||
} as any;
|
||||
const query = {
|
||||
text: subDir.name,
|
||||
|
@ -354,9 +354,7 @@ export class TestHelper {
|
||||
id: null,
|
||||
name: rndStr() + '.jpg',
|
||||
directory: dir,
|
||||
metadata: m,
|
||||
readyThumbnails: [],
|
||||
readyIcon: false
|
||||
metadata: m
|
||||
};
|
||||
|
||||
for (let i = 0; i < faces; i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user