From 1cc95bb9254fc99dae41d820909262b44eaac379 Mon Sep 17 00:00:00 2001 From: "Patrik J. Braun" Date: Sun, 6 Sep 2020 10:11:30 +0200 Subject: [PATCH] removing image rotation to support the now available in-browser image orientation tag https://caniuse.com/#feat=css-image-orientation Fixes: #172 --- README.md | 6 +- package-lock.json | 105 ++++-------------- package.json | 6 +- src/backend/model/threading/MetadataLoader.ts | 12 +- src/backend/model/threading/PhotoWorker.ts | 3 +- src/common/entities/MediaDTO.ts | 26 +---- src/frontend/app/app.module.ts | 2 - src/frontend/app/pipes/FixOrientationPipe.ts | 91 --------------- .../photo/photo.duplicates.component.html | 4 +- .../photo/photo.duplicates.component.ts | 8 -- .../directory/directory.gallery.component.css | 25 ----- .../directory.gallery.component.html | 2 +- .../directory/directory.gallery.component.ts | 8 +- src/frontend/app/ui/gallery/grid/GridMedia.ts | 5 - .../app/ui/gallery/grid/GridRowBuilder.ts | 2 +- .../ui/gallery/grid/grid.gallery.component.ts | 2 +- .../photo/photo.grid.gallery.component.html | 2 +- .../controls.lightbox.gallery.component.ts | 4 +- .../media/media.lightbox.gallery.component.ts | 16 ++- .../lightbox.map.gallery.component.html | 2 +- .../lightbox.map.gallery.component.ts | 21 +--- .../settings-entry.component.ts | 2 +- 22 files changed, 63 insertions(+), 291 deletions(-) delete mode 100644 src/frontend/app/pipes/FixOrientationPipe.ts diff --git a/README.md b/README.md index b2480d9d..afe8fc70 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ apt-get install build-essential libkrb5-dev gcc g++ ## 2. Translate the page to your own language -1. [Install Pigallery2](#111-b-install-from-source) from source (with the release it won't work) +1. [Install Pigallery2](#121-b-install-from-source) from source (with the release it won't work) 2. add your language e.g: fr ```bash npm run add-translation -- --fr @@ -214,8 +214,8 @@ apt-get install build-essential libkrb5-dev gcc g++ ## 5. Known errors * EXIF orientation tag: - * There is no nice way to handle EXIF orientation tag properly. -The page handles these photos, but might cause same error in the user experience (e.g.: the pages loads those photos slower. See issue [#11](https://github.com/bpatrik/pigallery2/issues/11)) + * Some photos code the orientation tag and with/height in a less conventional format, like the "duck photo" in [#19](https://github.com/bpatrik/pigallery2/issues/19). +After Browsers support orientation tag natively [#172](https://github.com/bpatrik/pigallery2/issues/172), I could not find a solution for that. * Video support on weak servers (like raspberry pi) with low upload rate * video playback may use up too much resources and the server might not response for a while. Enable video transcoding in the app, to transcode the videos to lover bitrate. diff --git a/package-lock.json b/package-lock.json index e8b56190..b973d52f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3361,15 +3361,6 @@ "@types/node": "*" } }, - "@types/gm": { - "version": "1.18.6", - "resolved": "https://registry.npmjs.org/@types/gm/-/gm-1.18.6.tgz", - "integrity": "sha512-ghb4ZYoSovciyS/BcbGhH/3VBmTu6Hit7rIdtIZnzVjT/a2OOAp4ZrdJGyW0PtF94XXzJC5li7WgEpg8saHfPQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/gulp": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-4.0.6.tgz", @@ -4839,18 +4830,6 @@ } } }, - "array-parallel": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz", - "integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0=", - "optional": true - }, - "array-series": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz", - "integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8=", - "optional": true - }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -7201,16 +7180,6 @@ "sha.js": "^2.4.8" } }, - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "optional": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -8475,19 +8444,11 @@ "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" }, "exifreader": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/exifreader/-/exifreader-2.12.0.tgz", - "integrity": "sha512-Z0unewjtJ5uwiN5Q6qzPIC+LnM6S/oTFdM4fvbhhqZbDxaK6C4CkLOPltYwODL7Gvz1YwflewSRIqRPfBqoR9w==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/exifreader/-/exifreader-3.12.2.tgz", + "integrity": "sha512-4+WpOVVW0iVbdMq4JnsmOx7vOurKEwb6vfopVkDW/g/JSIpdflkH6Q04yEBvh4ZzAU9l0UbvsSGf9LaW/Bu14w==", "requires": { - "@types/node": "^10.12.18", - "xmldom": "^0.1.27" - }, - "dependencies": { - "@types/node": { - "version": "10.17.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz", - "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==" - } + "xmldom": "^0.1.31" } }, "exit": { @@ -10138,35 +10099,6 @@ "sparkles": "^1.0.0" } }, - "gm": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz", - "integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=", - "optional": true, - "requires": { - "array-parallel": "~0.1.3", - "array-series": "~0.1.5", - "cross-spawn": "^4.0.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "optional": true - } - } - }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -10985,9 +10917,9 @@ } }, "image-size": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.8.3.tgz", - "integrity": "sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.9.1.tgz", + "integrity": "sha512-yBo6xGGjiWtApYroCGR9wTvaIgande5vmAfTYIld5ss5kN4tyDG5lrW1qGomOXgB05ss7GLXLpDYXEiFqSqkzg==", "requires": { "queue": "6.0.1" } @@ -13084,6 +13016,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -15983,7 +15916,8 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "psl": { "version": "1.1.31", @@ -18547,9 +18481,12 @@ "dev": true }, "ts-exif-parser": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/ts-exif-parser/-/ts-exif-parser-0.1.4.tgz", - "integrity": "sha512-wLZowFj+25+WM5YQcdUN4YWO8FfIWMgRnDFCjDa94zUyqT3VyeISleCetDGOUWDOq1jho9XLfG8k/Lc9syMqlA==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ts-exif-parser/-/ts-exif-parser-0.2.1.tgz", + "integrity": "sha512-Cwhzwn6rM/VtHVr/2Mie2k35lE26rocacRttN6/VlkgBmtkuNSPQT6pPiE6naExDmuXpqJiMqNuJqpKJ7d+vow==", + "requires": { + "sax": "1.2.4" + } }, "ts-helpers": { "version": "1.1.2", @@ -21311,9 +21248,10 @@ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "optional": true }, "xmlhttprequest-ssl": { "version": "1.5.5", @@ -21335,7 +21273,8 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, "yargonaut": { "version": "1.1.4", diff --git a/package.json b/package.json index 136e149d..8d25c7b9 100644 --- a/package.json +++ b/package.json @@ -36,17 +36,17 @@ "cookie-session": "2.0.0-beta.3", "csurf": "1.10.0", "ejs": "3.0.1", - "exifreader": "2.12.0", + "exifreader": "3.12.2", "express": "4.17.1", "express-unless": "0.5.0", "fluent-ffmpeg": "2.1.2", - "image-size": "0.8.3", + "image-size": "0.9.1", "jimp": "0.9.3", "locale": "0.1.0", "reflect-metadata": "0.1.13", "rimraf": "3.0.0", "sqlite3": "4.1.1", - "ts-exif-parser": "0.1.4", + "ts-exif-parser": "0.2.1", "ts-node-iptc": "1.0.11", "typeconfig": "2.0.9", "typeorm": "0.2.21", diff --git a/src/backend/model/threading/MetadataLoader.ts b/src/backend/model/threading/MetadataLoader.ts index d8168125..1abc1be5 100644 --- a/src/backend/model/threading/MetadataLoader.ts +++ b/src/backend/model/threading/MetadataLoader.ts @@ -19,7 +19,7 @@ const ffmpeg = FFmpegFactory.get(); export class MetadataLoader { public static loadVideoMetadata(fullPath: string): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const metadata: VideoMetadata = { size: { width: 1, @@ -50,10 +50,12 @@ export class MetadataLoader { metadata.size.width = data.streams[i].width; metadata.size.height = data.streams[i].height; - if (Utils.isInt32(parseInt(data.streams[i].rotation, 10)) && + if (Utils.isInt32(parseInt(data.streams[i].rotation, 10)) && (Math.abs(parseInt(data.streams[i].rotation, 10)) / 90) % 2 === 1) { - metadata.size.width = data.streams[i].height; - metadata.size.height = data.streams[i].width; + // noinspection JSSuspiciousNameCombination + metadata.size.width = data.streams[i].height; + // noinspection JSSuspiciousNameCombination + metadata.size.height = data.streams[i].width; } if (Utils.isInt32(Math.floor(parseFloat(data.streams[i].duration) * 1000))) { @@ -246,6 +248,8 @@ export class MetadataLoader { } catch (err) { } } + + return resolve(metadata); } catch (err) { return reject({file: fullPath, error: err}); diff --git a/src/backend/model/threading/PhotoWorker.ts b/src/backend/model/threading/PhotoWorker.ts index 8f42437b..45e0ab42 100644 --- a/src/backend/model/threading/PhotoWorker.ts +++ b/src/backend/model/threading/PhotoWorker.ts @@ -1,5 +1,4 @@ import {Metadata, Sharp} from 'sharp'; -import {Dimensions, State} from 'gm'; import {Logger} from '../../Logger'; import {FfmpegCommand, FfprobeData} from 'fluent-ffmpeg'; import {FFmpegFactory} from '../FFmpegFactory'; @@ -215,7 +214,7 @@ export class ImageRendererFactory { fit: 'cover' }); } - await image.jpeg().toFile(input.outPath); + await image.withMetadata().jpeg().toFile(input.outPath); }; } diff --git a/src/common/entities/MediaDTO.ts b/src/common/entities/MediaDTO.ts index 08a15e55..4d4c5570 100644 --- a/src/common/entities/MediaDTO.ts +++ b/src/common/entities/MediaDTO.ts @@ -1,6 +1,5 @@ import {DirectoryDTO} from './DirectoryDTO'; import {PhotoDTO} from './PhotoDTO'; -import {OrientationTypes} from 'ts-exif-parser'; import {FileDTO} from './FileDTO'; import {SupportedFormats} from '../SupportedFormats'; @@ -39,18 +38,6 @@ export module MediaDTO { (media).metadata.positionData.GPSData.longitude)); }; - export const isSideWay = (media: MediaDTO): boolean => { - if (!(media).metadata.orientation) { - return false; - } - const photo = media; - return photo.metadata.orientation === OrientationTypes.LEFT_TOP || - photo.metadata.orientation === OrientationTypes.RIGHT_TOP || - photo.metadata.orientation === OrientationTypes.LEFT_BOTTOM || - photo.metadata.orientation === OrientationTypes.RIGHT_BOTTOM; - - }; - export const isPhoto = (media: FileDTO): boolean => { return !MediaDTO.isVideo(media); }; @@ -86,16 +73,7 @@ export module MediaDTO { }; - export const getRotatedSize = (photo: MediaDTO): MediaDimension => { - if (isSideWay(photo)) { - // noinspection JSSuspiciousNameCombination - return {width: photo.metadata.size.height, height: photo.metadata.size.width}; - } - return photo.metadata.size; - }; - - export const calcRotatedAspectRatio = (photo: MediaDTO): number => { - const size = getRotatedSize(photo); - return size.width / size.height; + export const calcAspectRatio = (photo: MediaDTO): number => { + return photo.metadata.size.width / photo.metadata.size.height; }; } diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts index 28d42ba3..d318b90e 100644 --- a/src/frontend/app/app.module.ts +++ b/src/frontend/app/app.module.ts @@ -63,7 +63,6 @@ import {IconizeSortingMethod} from './pipes/IconizeSortingMethod'; import {StringifySortingMethod} from './pipes/StringifySortingMethod'; import {RandomQueryBuilderGalleryComponent} from './ui/gallery/random-query-builder/random-query-builder.gallery.component'; import {RandomPhotoSettingsComponent} from './ui/settings/random-photo/random-photo.settings.component'; -import {FixOrientationPipe} from './pipes/FixOrientationPipe'; import {VideoSettingsComponent} from './ui/settings/video/video.settings.component'; import {DurationPipe} from './pipes/DurationPipe'; import {MapService} from './ui/gallery/map/map.service'; @@ -211,7 +210,6 @@ export function translationsFactory(locale: string) { StringifyRole, IconizeSortingMethod, StringifySortingMethod, - FixOrientationPipe, DurationPipe, FileSizePipe ], diff --git a/src/frontend/app/pipes/FixOrientationPipe.ts b/src/frontend/app/pipes/FixOrientationPipe.ts deleted file mode 100644 index f1fd89c0..00000000 --- a/src/frontend/app/pipes/FixOrientationPipe.ts +++ /dev/null @@ -1,91 +0,0 @@ -import {Pipe, PipeTransform} from '@angular/core'; -import {OrientationTypes} from 'ts-exif-parser'; - -/** - * This pipe is used to fix thumbnail and media orientation based on their exif orientation tag - */ - -@Pipe({name: 'fixOrientation'}) -export class FixOrientationPipe implements PipeTransform { - - public static transform(imageSrc: string, orientation: OrientationTypes): Promise { - if (orientation === OrientationTypes.TOP_LEFT) { - return Promise.resolve(imageSrc); - } - return new Promise((resolve) => { - const img = new Image(); - - // noinspection SpellCheckingInspection - img.onload = () => { - const width = img.width, - height = img.height, - canvas = document.createElement('canvas'), - ctx = canvas.getContext('2d'); - - // set proper canvas dimensions before transform & export - if (OrientationTypes.BOTTOM_LEFT < orientation && - orientation <= OrientationTypes.LEFT_BOTTOM) { - // noinspection JSSuspiciousNameCombination - canvas.width = height; - // noinspection JSSuspiciousNameCombination - canvas.height = width; - } else { - canvas.width = width; - canvas.height = height; - } - - // transform context before drawing image - - // transform function parameters: - // a Horizontal scaling - // b Horizontal skewing - // c Vertical skewing - // d Vertical scaling - // e Horizontal moving - // f Vertical moving - - switch (orientation) { - case OrientationTypes.TOP_RIGHT: // 2 - ctx.transform(-1, 0, 0, 1, width, 0); - break; - case OrientationTypes.BOTTOM_RIGHT: // 3 - ctx.transform(-1, 0, 0, -1, width, height); - break; - case OrientationTypes.BOTTOM_LEFT: // 4 - ctx.transform(1, 0, 0, -1, 0, height); - break; - case OrientationTypes.LEFT_TOP: // 5 - ctx.transform(0, 1, 1, 0, 0, 0); - break; - case OrientationTypes.RIGHT_TOP: // 6 - ctx.transform(0, 1, -1, 0, height, 0); - break; - case OrientationTypes.RIGHT_BOTTOM: // 7 - ctx.transform(0, -1, -1, 0, height, width); - break; - case OrientationTypes.LEFT_BOTTOM: // 8 - ctx.transform(0, -1, 1, 0, 0, width); - break; - default: - break; - } - - // draw image - ctx.drawImage(img, 0, 0); - - // export base64 - resolve(canvas.toDataURL()); - }; - - img.onerror = () => { - resolve(imageSrc); - }; - - img.src = imageSrc; - }); - } - - transform(imageSrc: string, orientation: OrientationTypes): Promise { - return FixOrientationPipe.transform(imageSrc, orientation); - } -} diff --git a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.html b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.html index f6091df4..e8bc0e88 100644 --- a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.html +++ b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.html @@ -2,7 +2,7 @@ {{media.name}} @@ -10,6 +10,6 @@ class="icon" [popover]="popTemplate" triggers="mouseenter:mouseleave" - [src]="thumbnail.Src | fixOrientation:Orientation | async" + [src]="thumbnail.Src" *ngIf="thumbnail.Available"> diff --git a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts index 29894f53..81c54edf 100644 --- a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts +++ b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts @@ -1,8 +1,6 @@ import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {MediaDTO} from '../../../../../common/entities/MediaDTO'; import {IconThumbnail, ThumbnailManagerService} from '../../gallery/thumbnailManager.service'; -import {PhotoDTO} from '../../../../../common/entities/PhotoDTO'; -import {OrientationTypes} from 'ts-exif-parser'; import {MediaIcon} from '../../gallery/MediaIcon'; @Component({ @@ -19,12 +17,6 @@ export class DuplicatesPhotoComponent implements OnInit, OnDestroy { constructor(private thumbnailService: ThumbnailManagerService) { } - get Orientation() { - if (!this.media) { - return OrientationTypes.TOP_LEFT; - } - return (this.media).metadata.orientation || OrientationTypes.TOP_LEFT; - } ngOnInit() { this.thumbnail = this.thumbnailService.getIcon(new MediaIcon(this.media)); diff --git a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.css b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.css index 5d0218c4..5428d229 100644 --- a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.css +++ b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.css @@ -54,28 +54,3 @@ a:hover .photo-container { width: 180px; white-space: normal; } - -/* transforming media, based on exif orientation*/ -.photo-orientation-1 { -} -.photo-orientation-2 { -transform: rotateY(180deg); -} -.photo-orientation-3 { - transform: rotate(180deg); -} -.photo-orientation-4 { - transform: rotate(180deg) rotateY(180deg); -} -.photo-orientation-5 { - transform: rotate(270deg) rotateY(180deg); -} -.photo-orientation-6 { - transform: rotate(90deg); -} -.photo-orientation-7 { - transform: rotate(90deg) rotateY(180deg); -} -.photo-orientation-8 { - transform: rotate(270deg); -} diff --git a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.html b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.html index b44eeb68..490533da 100644 --- a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.html +++ b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.html @@ -7,7 +7,7 @@
-
diff --git a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts index c4b1f2b8..5f9dcb44 100644 --- a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts +++ b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts @@ -7,8 +7,7 @@ import {Media} from '../../Media'; import {Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service'; import {QueryService} from '../../../../model/query.service'; import {MediaDTO} from '../../../../../../common/entities/MediaDTO'; -import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO'; -import {OrientationTypes} from 'ts-exif-parser'; + @Component({ selector: 'app-gallery-directory', @@ -35,11 +34,6 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy { return null; } - public get Orientation(): OrientationTypes { - return (this.SamplePhoto && (this.SamplePhoto as PhotoDTO).metadata.orientation) - || OrientationTypes.TOP_LEFT; - } - getSanitizedThUrl() { return this._sanitizer.bypassSecurityTrustStyle('url(' + encodeURI(this.thumbnail.Src) diff --git a/src/frontend/app/ui/gallery/grid/GridMedia.ts b/src/frontend/app/ui/gallery/grid/GridMedia.ts index 875b08ae..18202c34 100644 --- a/src/frontend/app/ui/gallery/grid/GridMedia.ts +++ b/src/frontend/app/ui/gallery/grid/GridMedia.ts @@ -1,6 +1,5 @@ import {Media} from '../Media'; import {MediaDTO} from '../../../../../common/entities/MediaDTO'; -import {OrientationTypes} from 'ts-exif-parser'; import {PhotoDTO} from '../../../../../common/entities/PhotoDTO'; import {VideoDTO} from '../../../../../common/entities/VideoDTO'; @@ -11,10 +10,6 @@ export class GridMedia extends Media { super(media, renderWidth, renderHeight); } - public get Orientation(): OrientationTypes { - return (this.media).metadata.orientation || OrientationTypes.TOP_LEFT; - } - get Video(): VideoDTO { return this.media; } diff --git a/src/frontend/app/ui/gallery/grid/GridRowBuilder.ts b/src/frontend/app/ui/gallery/grid/GridRowBuilder.ts index fe512df1..be4b0c8e 100644 --- a/src/frontend/app/ui/gallery/grid/GridRowBuilder.ts +++ b/src/frontend/app/ui/gallery/grid/GridRowBuilder.ts @@ -52,7 +52,7 @@ export class GridRowBuilder { public calcRowHeight(): number { let width = 0; for (let i = 0; i < this.photoRow.length; i++) { - const size = MediaDTO.getRotatedSize(this.photoRow[i]); + const size = this.photoRow[i].metadata.size; width += (size.width / size.height); // summing up aspect ratios } const height = (this.containerWidth - this.photoRow.length * (this.photoMargin * 2) - 1) / width; // cant be equal -> width-1 diff --git a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts index 774251f0..31c23149 100644 --- a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts +++ b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts @@ -182,7 +182,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O const imageHeight = rowHeight - (this.IMAGE_MARGIN * 2); photoRowBuilder.getPhotoRow().forEach((photo) => { - const imageWidth = imageHeight * MediaDTO.calcRotatedAspectRatio(photo); + const imageWidth = imageHeight * MediaDTO.calcAspectRatio(photo); this.photosToRender.push(new GridMedia(photo, imageWidth, imageHeight, this.renderedPhotoIndex)); }); diff --git a/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.html b/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.html index 81383795..ab57e22f 100644 --- a/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.html +++ b/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.html @@ -1,7 +1,7 @@
- {{gridMedia.media.name}} this.photoFrameDim.aspect; const divWidth = this.photoFrameDim.width; const divHeight = this.photoFrameDim.height; @@ -368,7 +368,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { } - const photoAspect = MediaDTO.calcRotatedAspectRatio(this.activePhoto.gridMedia.media); + const photoAspect = MediaDTO.calcAspectRatio(this.activePhoto.gridMedia.media); if (photoAspect < this.photoFrameDim.aspect) { this.faceContainerDim.height = this.photoFrameDim.height; diff --git a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts index fda87cc7..a1f8a011 100644 --- a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts @@ -1,6 +1,5 @@ import {Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild} from '@angular/core'; import {GridMedia} from '../../grid/GridMedia'; -import {FixOrientationPipe} from '../../../../pipes/FixOrientationPipe'; import {MediaDTO} from '../../../../../../common/entities/MediaDTO'; import {DomSanitizer, SafeStyle} from '@angular/platform-browser'; import {SupportedFormats} from '../../../../../../common/SupportedFormats'; @@ -111,11 +110,10 @@ export class GalleryLightboxMediaComponent implements OnChanges { this.setImageSize(); } if (this.thumbnailSrc == null && this.gridMedia && this.ThumbnailUrl !== null) { - FixOrientationPipe.transform(this.ThumbnailUrl, this.gridMedia.Orientation) - .then((src) => this.thumbnailSrc = src); + this.thumbnailSrc = this.ThumbnailUrl; } - this.loadPhoto().catch(console.error); + this.loadPhoto(); } @@ -161,7 +159,7 @@ export class GalleryLightboxMediaComponent implements OnChanges { this.videoSourceError.emit(); } - private async loadPhoto() { + private loadPhoto() { if (!this.gridMedia || !this.loadMedia || !this.gridMedia.isPhoto()) { return; } @@ -169,16 +167,16 @@ export class GalleryLightboxMediaComponent implements OnChanges { if (this.zoom === 1) { if (this.photo.src == null) { if (Config.Client.Media.Photo.Converting.enabled === true) { - this.photo.src = await FixOrientationPipe.transform(this.gridMedia.getBestFitMediaPath(), this.gridMedia.Orientation); + this.photo.src = this.gridMedia.getBestFitMediaPath(); this.photo.isBestFit = true; } else { - this.photo.src = await FixOrientationPipe.transform(this.gridMedia.getMediaPath(), this.gridMedia.Orientation); + this.photo.src = this.gridMedia.getMediaPath(); this.photo.isBestFit = false; } } // on zoom load high res photo } else if ((this.photo.isBestFit === true || this.photo.src == null)) { - this.photo.src = await FixOrientationPipe.transform(this.gridMedia.getMediaPath(), this.gridMedia.Orientation); + this.photo.src = this.gridMedia.getMediaPath(); this.photo.isBestFit = false; } } @@ -194,7 +192,7 @@ export class GalleryLightboxMediaComponent implements OnChanges { } - const photoAspect = MediaDTO.calcRotatedAspectRatio(this.gridMedia.media); + const photoAspect = MediaDTO.calcAspectRatio(this.gridMedia.media); if (photoAspect < this.windowAspect) { this.imageSize.height = '100'; diff --git a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html index aaca1034..1e9e4e6e 100644 --- a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html +++ b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html @@ -46,7 +46,7 @@ + [src]="photo.preview.thumbnail.Src">
{ let width = 500; let height = 500; - const rotatedSize = MediaDTO.getRotatedSize(p); - if (rotatedSize.width > rotatedSize.height) { - height = width * (rotatedSize.height / rotatedSize.width); + const size = p.metadata.size; + if (size.width > size.height) { + height = width * (size.height / size.width); } else { - width = height * (rotatedSize.width / rotatedSize.height); + width = height * (size.width / size.height); } const iconTh = this.thumbnailService.getIcon(new MediaIcon(p)); iconTh.Visible = true; @@ -157,7 +154,6 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit { lat: p.metadata.positionData.GPSData.latitude, lng: p.metadata.positionData.GPSData.longitude, iconThumbnail: iconTh, - orientation: p.metadata.orientation, preview: { width: width, height: height, @@ -167,14 +163,10 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit { }; if (Config.Client.Map.useImageMarkers === true) { if (iconTh.Available === true) { - FixOrientationPipe.transform(iconTh.Src, p.metadata.orientation).then((icon) => { - obj.iconUrl = icon; - }); + obj.iconUrl = iconTh.Src; } else { iconTh.OnLoad = () => { - FixOrientationPipe.transform(iconTh.Src, p.metadata.orientation).then((icon) => { - obj.iconUrl = icon; - }); + obj.iconUrl = iconTh.Src; }; } } @@ -258,7 +250,6 @@ export interface MapPhoto { lng: number; iconUrl?: string; iconThumbnail: IconThumbnail; - orientation: OrientationTypes; preview: { width: number; height: number; diff --git a/src/frontend/app/ui/settings/_abstract/settings-entry/settings-entry.component.ts b/src/frontend/app/ui/settings/_abstract/settings-entry/settings-entry.component.ts index 3bcdad3a..df2d737b 100644 --- a/src/frontend/app/ui/settings/_abstract/settings-entry/settings-entry.component.ts +++ b/src/frontend/app/ui/settings/_abstract/settings-entry/settings-entry.component.ts @@ -100,7 +100,7 @@ export class SettingsEntryComponent implements ControlValueAccessor, Validator, if (this.state.type === 'array' && (this.state.arrayType === 'string' || this.isNumberArray)) { value = value.replace(new RegExp(',', 'g'), ';'); - if(this.allowSpaces === false) { + if (this.allowSpaces === false) { value = value.replace(new RegExp(' ', 'g'), ';'); } this.state.value = value.split(';').filter((v: string) => v !== '');