1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-25 02:04:15 +02:00

removing image rotation to support the now available in-browser image orientation tag https://caniuse.com/#feat=css-image-orientation

Fixes: #172
This commit is contained in:
Patrik J. Braun 2020-09-06 10:11:30 +02:00
parent f67dc7d58f
commit 1cc95bb925
22 changed files with 63 additions and 291 deletions

View File

@ -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.

105
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -19,7 +19,7 @@ const ffmpeg = FFmpegFactory.get();
export class MetadataLoader {
public static loadVideoMetadata(fullPath: string): Promise<VideoMetadata> {
return new Promise<VideoMetadata>((resolve, reject) => {
return new Promise<VideoMetadata>((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});

View File

@ -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);
};
}

View File

@ -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 {
(<PhotoDTO>media).metadata.positionData.GPSData.longitude));
};
export const isSideWay = (media: MediaDTO): boolean => {
if (!(<PhotoDTO>media).metadata.orientation) {
return false;
}
const photo = <PhotoDTO>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;
};
}

View File

@ -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
],

View File

@ -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<string> {
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<string> {
return FixOrientationPipe.transform(imageSrc, orientation);
}
}

View File

@ -2,7 +2,7 @@
<ng-template #popTemplate>
<img alt="{{media.name}}"
class="big-icon"
[src]="thumbnail.Src | fixOrientation:Orientation | async"
[src]="thumbnail.Src"
*ngIf="thumbnail.Available">
</ng-template>
@ -10,6 +10,6 @@
class="icon"
[popover]="popTemplate"
triggers="mouseenter:mouseleave"
[src]="thumbnail.Src | fixOrientation:Orientation | async"
[src]="thumbnail.Src"
*ngIf="thumbnail.Available">
</div>

View File

@ -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 (<PhotoDTO>this.media).metadata.orientation || OrientationTypes.TOP_LEFT;
}
ngOnInit() {
this.thumbnail = this.thumbnailService.getIcon(new MediaIcon(this.media));

View File

@ -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);
}

View File

@ -7,7 +7,7 @@
<div class="photo-container"
[style.width.px]="size"
[style.height.px]="size">
<div [ngClass]="'photo photo-orientation-'+Orientation"
<div class="photo"
*ngIf="thumbnail && thumbnail.Available"
[style.background-image]="getSanitizedThUrl()"></div>

View File

@ -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)

View File

@ -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 (<PhotoDTO>this.media).metadata.orientation || OrientationTypes.TOP_LEFT;
}
get Video(): VideoDTO {
return <VideoDTO>this.media;
}

View File

@ -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

View File

@ -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));
});

View File

@ -1,7 +1,7 @@
<div #photoContainer class="photo-container" (mouseover)="mouseOver()" (mouseout)="mouseOut()">
<img alt="{{gridMedia.media.name}}" #img [src]="thumbnail.Src | fixOrientation:gridMedia.Orientation | async"
<img alt="{{gridMedia.media.name}}" #img [src]="thumbnail.Src"
*ngIf="thumbnail.Available">
<app-gallery-grid-photo-loading

View File

@ -307,7 +307,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
return;
}
const photoAspect = MediaDTO.calcRotatedAspectRatio(this.activePhoto.gridMedia.media);
const photoAspect = MediaDTO.calcAspectRatio(this.activePhoto.gridMedia.media);
const widthFilled = photoAspect > 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;

View File

@ -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';

View File

@ -46,7 +46,7 @@
<img *ngIf="photo.preview.thumbnail.Src"
[style.width.px]="photo.preview.width"
[style.height.px]="photo.preview.height"
[src]="photo.preview.thumbnail.Src | fixOrientation:photo.orientation | async">
[src]="photo.preview.thumbnail.Src">
<div class="preview-loading"
*ngIf="!photo.preview.thumbnail.Src"
[style.width.px]="photo.preview.width"

View File

@ -6,15 +6,12 @@ import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../thumbnail
import {MediaIcon} from '../../MediaIcon';
import {Media} from '../../Media';
import {PageHelper} from '../../../../model/page.helper';
import {OrientationTypes} from 'ts-exif-parser';
import {MediaDTO} from '../../../../../../common/entities/MediaDTO';
import {FileDTO} from '../../../../../../common/entities/FileDTO';
import {Utils} from '../../../../../../common/Utils';
import {Config} from '../../../../../../common/config/public/Config';
import {MapService} from '../map.service';
import {LatLng, Point} from 'leaflet';
import {MapComponent} from '@yaga/leaflet-ng2';
import {FixOrientationPipe} from '../../../../pipes/FixOrientationPipe';
@Component({
selector: 'app-gallery-map-lightbox',
@ -144,11 +141,11 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
}).map(p => {
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;

View File

@ -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 !== '');