diff --git a/docker/frontend/shared/types/index.ts b/docker/frontend/shared/types/index.ts index 0a0fff6..14d70d1 100644 --- a/docker/frontend/shared/types/index.ts +++ b/docker/frontend/shared/types/index.ts @@ -1,4 +1,10 @@ -export type FrameId = 'none' | 'polaroid' | 'classic-white' | 'cinematic' | 'wallframe'; +export type FrameId = + | 'none' + | 'polaroid' + | 'classic-white' + | 'cinematic' + | 'wallframe' // WALL FRAME PORTRAIT — the artwork hung 90° CW + | 'wallframe-landscape'; // the same artwork upright: WALL FRAME LANDSCAPE // Viewfinder/composition aspect-ratio selector. Convention is an UPRIGHT // (portrait) picture: "4:3" = standing 3:4 photo (w/h = 3/4), "3:2" = standing diff --git a/docker/frontend/shared/utils/recipeShare.ts b/docker/frontend/shared/utils/recipeShare.ts index 61c3c31..d3c5c33 100644 --- a/docker/frontend/shared/utils/recipeShare.ts +++ b/docker/frontend/shared/utils/recipeShare.ts @@ -12,7 +12,7 @@ const KEY = 'RecipesCam::recipe-share::v1'; const ALGORITHM = 'xor16-v1'; const BASE_FILTERS: BaseFilter[] = [...FILM_SIMS.map((s) => s.baseFilter), 'none']; -const FRAMES: FrameId[] = ['none', 'polaroid', 'classic-white', 'cinematic', 'wallframe']; +const FRAMES: FrameId[] = ['none', 'polaroid', 'classic-white', 'cinematic', 'wallframe', 'wallframe-landscape']; const hash = (s: string): number => { let h = 0x811c9dc5; diff --git a/docker/frontend/src/App.tsx b/docker/frontend/src/App.tsx index 05cd99c..0c9fd57 100644 --- a/docker/frontend/src/App.tsx +++ b/docker/frontend/src/App.tsx @@ -48,6 +48,7 @@ const FRAMES: { id: FrameId; label: MsgKey }[] = [ { id: 'classic-white', label: 'frame.classic' }, { id: 'cinematic', label: 'frame.cinematic' }, { id: 'wallframe', label: 'frame.wall' }, + { id: 'wallframe-landscape', label: 'frame.wallLand' }, ]; // FREE draws the frame on the canvas and lets the user drag its corners, so @@ -326,6 +327,7 @@ export function Workspace() { gpsInfo: gps, assets: engine.assets, options: { + wallframeLandscape: frameId === 'wallframe-landscape', sharpen: true, photoRotation: rotation, cropRect: cropLive ? cropRect : null, @@ -623,6 +625,7 @@ export function Workspace() { gpsInfo: gps, assets: engine.assets, options: { + wallframeLandscape: frameId === 'wallframe-landscape', dpi: 300, sharpen: true, photoRotation: rotation, diff --git a/docker/frontend/src/engine/exportEngine.ts b/docker/frontend/src/engine/exportEngine.ts index f1ea761..09f0ffe 100644 --- a/docker/frontend/src/engine/exportEngine.ts +++ b/docker/frontend/src/engine/exportEngine.ts @@ -219,6 +219,10 @@ function loadFaces(assets: RenderAssets) { return faces; } +// Both walls are one artwork on one code path: `wallframe` hangs the PNG turned +// 90° CW (the portrait opening), `wallframe-landscape` lays it down as it is. +const isWallframe = (id: FrameId) => id === 'wallframe' || id === 'wallframe-landscape'; + function loadWallframe(assets: RenderAssets) { if (wallframeImage) return wallframeImage; wallframeImage = Skia.Image.MakeImageFromEncoded(assets.wallframe); @@ -254,7 +258,7 @@ export async function renderPhoto(input: RenderInput): Promise