Core Feature: Image Comparison
Relevant source files
The following files were used as context for generating this wiki page:The Image Comparison feature provides users with an interactive, side-by-side view to compare an original AI-generated image against its 4x upscaled version. This is a crucial part of the image enhancement workflow, allowing users to visually inspect the results of the AI upscaling process before deciding to keep or discard the changes. The feature is implemented as a dedicated React component with an interactive slider that reveals the "before" and "after" states of the image.
Sources: README.md, App.tsx:219-227, components/ImageComparison.tsx
System Architecture and State Management
The entire comparison workflow is managed within the main App.tsx component. It relies on a set of state variables to control the UI, transitioning from the standard image viewer to the comparison interface.
Sources: App.tsx:82-84
Key State Variables
The following state variables in App.tsx are central to the image comparison logic:
| State Variable | Type | Description |
|---|---|---|
isComparing | boolean | A flag that determines whether the ImageComparison component or the standard image viewer is rendered. |
currentImage | GeneratedImage | null | Holds the data for the original image being displayed (the "before" image). |
tempUpscaledImage | string | null | Stores the URL of the newly upscaled image (the "after" image) while in comparison mode. This is cleared when the mode is exited. |
Sources: App.tsx:82-84
State Flow
The application transitions between a standard viewing mode and a comparison mode based on user actions. The isComparing state acts as the primary trigger for this UI change.
This diagram illustrates the state transitions involved in the upscaling and comparison process.
Sources: App.tsx:82-84, App.tsx:210-244
User Flow and Interaction
The process begins when a user decides to upscale an existing image and ends when they either accept or reject the upscaled result.
- The user views a generated image and clicks the "Upscale" button in the toolbar.
- This action triggers the
handleUpscalefunction inApp.tsx. handleUpscalesets theisUpscalingstate totrueand calls theupscalerservice function fromhfService.ts, passing the URL of thecurrentImage.- The
upscalerservice performs an API call to a Hugging Face space to get the 4x upscaled image. - Upon successful return from the API,
handleUpscalereceives the new image URL. - It then sets
tempUpscaledImageto the new URL andisComparingtotrue. - The UI re-renders, replacing the standard image viewer with the
ImageComparisoncomponent. - The user can now interact with the slider. Two new buttons, "Keep Changes" and "Discard", appear.
- Keep Changes: Calls
handleApplyUpscale, which updates thecurrentImagein the history with the new URL and sets itsisUpscaledflag totrue. The app then exits comparison mode. - Discard: Calls
handleCancelUpscale, which simply resetsisComparingtofalseandtempUpscaledImagetonull, returning to the original image view.
- Keep Changes: Calls
Sources: App.tsx:210-244, services/hfService.ts:221-242
Sequence Diagram
The following diagram shows the sequence of events from the user's click to the final state update.
Sources: App.tsx:210-244, services/hfService.ts:221-242
The ImageComparison Component
This is a self-contained React component responsible for rendering the interactive slider view.
*Source: components/ImageComparison.tsx
Component Properties
| Prop | Type | Description |
|---|---|---|
beforeImage | string | URL of the original image (left side). |
afterImage | string | URL of the upscaled image (right side). |
alt | string | Alt text for both images. |
Source: components/ImageComparison.tsx:5-9
Rendering Strategy
The component uses a clever layering and clipping technique to create the slider effect:
- The
afterImage(upscaled) is rendered as the base layer. Its natural dimensions define the size of the container. - The
beforeImage(original) is rendered inside adivthat is absolutely positioned to perfectly overlay the base image. - This overlay
divhas itsclip-pathCSS property dynamically updated based on the slider'spositionstate. The styleclipPath: inset(0 ${100 - position}% 0 0)clips the "before" image from the right, revealing the "after" image underneath. - A slider handle is absolutely positioned using
left:${position}%`` to match the clip boundary.
This diagram shows the component's internal structure.
Interaction Logic
- A state variable
position(defaulting to 50) tracks the slider's percentage from the left. - Mouse and touch event handlers (
onMouseDown,onMouseMove,onTouchMove, etc.) are attached to the main container. - When a drag event occurs, the
handleMovefunction calculates the new position based on the cursor'sclientXrelative to the component's bounding box and updates thepositionstate, causing a re-render with the newclip-path.
Source: components/ImageComparison.tsx:13-43
Upscaling Service Integration
The upscaler function in services/hfService.ts is responsible for communicating with the external upscaling service hosted on Hugging Face.
- Endpoint:
https://tuan2308-upscaler.hf.space - API Method: It uses the Gradio API protocol, which involves two steps:
- A
POSTrequest to/gradio_api/call/realesrganto queue the job. The payload includes the image URL and model parameters. - A
GETrequest to/gradio_api/call/realesrgan/{event_id}to stream the status and retrieve the final result.
- A
- Authentication: The function uses
getAuthHeaders()to include anAuthorizationbearer token if one is saved inlocalStorage, allowing for higher usage quotas.
Source: services/hfService.ts:221-242
Data Model and Persistence
When the user accepts an upscaled image, the application state is updated and persisted.
- The
GeneratedImagetype includes an optional boolean flagisUpscaled. - The
handleApplyUpscalefunction creates anupdatedImageobject by spreading thecurrentImage, replacing itsurlwithtempUpscaledImage, and settingisUpscaled: true. - This
updatedImagethen replaces the original object in thehistorystate array. - A
useEffecthook inApp.tsxautomatically saves the entirehistoryarray to the browser'slocalStoragewhenever it changes, ensuring the upscaled status is preserved across sessions.
Sources: types.ts:10, App.tsx:229-244, App.tsx:132-134