fix(upscale): auto-orient images before upscaling and improve UI

Fix rotated output by calling autoOrient() before passing images to
the Python upscaler, correcting EXIF orientation metadata. Replace
2x/4x buttons with 2x-8x slider plus quick-select buttons (2x, 3x,
4x, 6x, 8x). Remove technical jargon about Real-ESRGAN/Lanczos from
the UI and progress bar.
This commit is contained in:
Siddharth Kumar Sah
2026-03-26 16:01:40 +08:00
parent f357b18ced
commit 8ee4d7b2fb
2 changed files with 21 additions and 10 deletions
+4
View File
@@ -3,6 +3,7 @@ import { writeFile } from "node:fs/promises";
import { basename, join } from "node:path";
import { upscale } from "@stirling-image/ai";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { autoOrient } from "../../lib/auto-orient.js";
import { validateImageBuffer } from "../../lib/file-validation.js";
import { createWorkspace } from "../../lib/workspace.js";
import { updateSingleFileProgress } from "../progress.js";
@@ -54,6 +55,9 @@ export function registerUpscale(app: FastifyInstance) {
const settings = settingsRaw ? JSON.parse(settingsRaw) : {};
const scale = Number(settings.scale) || 2;
// Auto-orient to fix EXIF rotation before upscaling
fileBuffer = await autoOrient(fileBuffer);
const jobId = randomUUID();
const workspacePath = await createWorkspace(jobId);
@@ -4,6 +4,8 @@ import { ProgressCard } from "@/components/common/progress-card";
import { useToolProcessor } from "@/hooks/use-tool-processor";
import { useFileStore } from "@/stores/file-store";
const QUICK_SCALES = [2, 3, 4, 6, 8];
export function UpscaleSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
@@ -21,9 +23,12 @@ export function UpscaleSettings() {
<div className="space-y-4">
{/* Scale factor */}
<div>
<p className="text-sm font-medium text-muted-foreground">Scale Factor</p>
<div className="flex gap-1 mt-1">
{[2, 4].map((s) => (
<div className="flex justify-between items-center">
<p className="text-sm font-medium text-muted-foreground">Scale Factor</p>
<span className="text-sm font-mono font-medium">{scale}x</span>
</div>
<div className="flex gap-1 mt-1.5">
{QUICK_SCALES.map((s) => (
<button
key={s}
type="button"
@@ -38,14 +43,17 @@ export function UpscaleSettings() {
</button>
))}
</div>
<input
type="range"
min={2}
max={8}
step={1}
value={scale}
onChange={(e) => setScale(Number(e.target.value))}
className="w-full mt-2"
/>
</div>
{/* Info */}
<p className="text-[10px] text-muted-foreground">
Uses Real-ESRGAN for AI upscaling when available, otherwise falls back to high-quality
Lanczos interpolation.
</p>
{/* Error */}
{error && <p className="text-xs text-red-500">{error}</p>}
@@ -63,7 +71,6 @@ export function UpscaleSettings() {
active={processing}
phase={progress.phase === "idle" ? "uploading" : progress.phase}
label="Upscaling image"
stage={progress.stage}
percent={progress.percent}
elapsed={progress.elapsed}
/>