From 22464c434eb7faf3af4c8c44389996925c04eca6 Mon Sep 17 00:00:00 2001 From: xianon Date: Fri, 3 Dec 2021 11:19:28 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=94=BB=E5=83=8F=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=81=AE=E7=B8=A6=E6=A8=AA=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=82=BA=E3=81=AE=E5=8F=96=E5=BE=97=E3=81=A7=20Exif=20Orientat?= =?UTF-8?q?ion=20=E3=82=92=E8=80=83=E6=85=AE=E3=81=99=E3=82=8B=20(#8014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 画像ファイルの縦横サイズの取得で Exif Orientation を考慮する * test: Add rotate.jpg test * Webpublic 画像を返す時のみ Exif Orientation を考慮して縦横サイズを返す * test: Support orientation --- packages/backend/src/misc/get-file-info.ts | 5 ++++ .../backend/src/models/entities/drive-file.ts | 2 +- .../src/models/repositories/drive-file.ts | 20 +++++++++++++- .../backend/src/services/drive/add-file.ts | 4 +++ packages/backend/test/get-file-info.ts | 26 ++++++++++++++++++ packages/backend/test/resources/rotate.jpg | Bin 0 -> 12624 bytes packages/client/src/components/media-list.vue | 21 ++++++++++---- 7 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 packages/backend/test/resources/rotate.jpg diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 39ba54139..8d7f6b1bf 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -19,6 +19,7 @@ export type FileInfo = { }; width?: number; height?: number; + orientation?: number; blurhash?: string; warnings: string[]; }; @@ -47,6 +48,7 @@ export async function getFileInfo(path: string): Promise { // image dimensions let width: number | undefined; let height: number | undefined; + let orientation: number | undefined; if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/bmp', 'image/tiff', 'image/svg+xml', 'image/vnd.adobe.photoshop'].includes(type.mime)) { const imageSize = await detectImageSize(path).catch(e => { @@ -61,6 +63,7 @@ export async function getFileInfo(path: string): Promise { } else if (imageSize.wUnits === 'px') { width = imageSize.width; height = imageSize.height; + orientation = imageSize.orientation; // 制限を超えている画像は octet-stream にする if (imageSize.width > 16383 || imageSize.height > 16383) { @@ -87,6 +90,7 @@ export async function getFileInfo(path: string): Promise { type, width, height, + orientation, blurhash, warnings, }; @@ -163,6 +167,7 @@ async function detectImageSize(path: string): Promise<{ height: number; wUnits: string; hUnits: string; + orientation?: number; }> { const readable = fs.createReadStream(path); const imageSize = await probeImageSize(readable); diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 698dfac22..4ec7b94ed 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -77,7 +77,7 @@ export class DriveFile { default: {}, comment: 'The any properties of the DriveFile. For example, it includes image width/height.' }) - public properties: { width?: number; height?: number; avgColor?: string }; + public properties: { width?: number; height?: number; orientation?: number; avgColor?: string }; @Index() @Column('boolean') diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index ddf9a46af..f2f0308dc 100644 --- a/packages/backend/src/models/repositories/drive-file.ts +++ b/packages/backend/src/models/repositories/drive-file.ts @@ -28,6 +28,19 @@ export class DriveFileRepository extends Repository { ); } + public getPublicProperties(file: DriveFile): DriveFile['properties'] { + if (file.properties.orientation != null) { + const properties = JSON.parse(JSON.stringify(file.properties)); + if (file.properties.orientation >= 5) { + [properties.width, properties.height] = [properties.height, properties.width]; + } + properties.orientation = undefined; + return properties; + } + + return file.properties; + } + public getPublicUrl(file: DriveFile, thumbnail = false, meta?: Meta): string | null { // リモートかつメディアプロキシ if (file.uri != null && file.userHost != null && config.mediaProxy != null) { @@ -122,7 +135,7 @@ export class DriveFileRepository extends Repository { size: file.size, isSensitive: file.isSensitive, blurhash: file.blurhash, - properties: file.properties, + properties: opts.self ? file.properties : this.getPublicProperties(file), url: opts.self ? file.url : this.getPublicUrl(file, false, meta), thumbnailUrl: this.getPublicUrl(file, true, meta), comment: file.comment, @@ -202,6 +215,11 @@ export const packedDriveFileSchema = { optional: true as const, nullable: false as const, example: 720 }, + orientation: { + type: 'number' as const, + optional: true as const, nullable: false as const, + example: 8 + }, avgColor: { type: 'string' as const, optional: true as const, nullable: false as const, diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 6c5fefd4a..a57f9cf06 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -372,12 +372,16 @@ export default async function( const properties: { width?: number; height?: number; + orientation?: number; } = {}; if (info.width) { properties['width'] = info.width; properties['height'] = info.height; } + if (info.orientation != null) { + properties['orientation'] = info.orientation; + } const profile = user ? await UserProfiles.findOne(user.id) : null; diff --git a/packages/backend/test/get-file-info.ts b/packages/backend/test/get-file-info.ts index cc9eefbfc..a0146bd81 100644 --- a/packages/backend/test/get-file-info.ts +++ b/packages/backend/test/get-file-info.ts @@ -17,6 +17,7 @@ describe('Get file info', () => { }, width: undefined, height: undefined, + orientation: undefined, }); })); @@ -34,6 +35,7 @@ describe('Get file info', () => { }, width: 512, height: 512, + orientation: undefined, }); })); @@ -51,6 +53,7 @@ describe('Get file info', () => { }, width: 256, height: 256, + orientation: undefined, }); })); @@ -68,6 +71,7 @@ describe('Get file info', () => { }, width: 256, height: 256, + orientation: undefined, }); })); @@ -85,6 +89,7 @@ describe('Get file info', () => { }, width: 256, height: 256, + orientation: undefined, }); })); @@ -102,6 +107,7 @@ describe('Get file info', () => { }, width: 256, height: 256, + orientation: undefined, }); })); @@ -120,6 +126,7 @@ describe('Get file info', () => { }, width: 256, height: 256, + orientation: undefined, }); })); @@ -137,6 +144,25 @@ describe('Get file info', () => { }, width: 25000, height: 25000, + orientation: undefined, + }); + })); + + it('Rotate JPEG', async (async () => { + const path = `${__dirname}/resources/rotate.jpg`; + const info = await getFileInfo(path) as any; + delete info.warnings; + delete info.blurhash; + assert.deepStrictEqual(info, { + size: 12624, + md5: '68d5b2d8d1d1acbbce99203e3ec3857e', + type: { + mime: 'image/jpeg', + ext: 'jpg' + }, + width: 512, + height: 256, + orientation: 8, }); })); }); diff --git a/packages/backend/test/resources/rotate.jpg b/packages/backend/test/resources/rotate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..477c2baf5bbd0039dc08fa36e3d4b3cd5d39ecb9 GIT binary patch literal 12624 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 literal 0 HcmV?d00001 diff --git a/packages/client/src/components/media-list.vue b/packages/client/src/components/media-list.vue index 38f0f7066..344ad8784 100644 --- a/packages/client/src/components/media-list.vue +++ b/packages/client/src/components/media-list.vue @@ -44,12 +44,18 @@ export default defineComponent({ onMounted(() => { const lightbox = new PhotoSwipeLightbox({ - dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => ({ - src: media.url, - w: media.properties.width, - h: media.properties.height, - alt: media.name, - })), + dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => { + const item = { + src: media.url, + w: media.properties.width, + h: media.properties.height, + alt: media.name, + }; + if (media.properties.orientation != null && media.properties.orientation >= 5) { + [item.w, item.h] = [item.h, item.w]; + } + return item; + }), gallery: gallery.value, children: '.image', thumbSelector: '.image', @@ -77,6 +83,9 @@ export default defineComponent({ itemData.src = file.url; itemData.w = Number(file.properties.width); itemData.h = Number(file.properties.height); + if (file.properties.orientation != null && file.properties.orientation >= 5) { + [itemData.w, itemData.h] = [itemData.h, itemData.w]; + } itemData.msrc = file.thumbnailUrl; itemData.thumbCropped = true; });