Image Upload
Relevant source files
The following files were used as context for generating this wiki page:The Image Upload and Processing feature is the core functionality of the hdrify application. It allows users to upload a standard dynamic range (SDR) image, which is then processed by a backend service to create a high dynamic range (HDR) version. The system is composed of a vanilla JavaScript frontend for user interaction and a Rust backend that orchestrates image processing via the ImageMagick command-line tool.
The process is designed to be intuitive, featuring a drag-and-drop upload area, real-time adjustment of HDR intensity, and visual feedback during processing. The goal is to produce HDR-infused images suitable for displays and platforms that support them, such as modern browsers on HDR-capable monitors.
Sources: README.md:3-5, static/index.html:11-15, src/main.rs
Architecture Overview
The system follows a client-server architecture. The client is a single-page application responsible for capturing user input and displaying results. The server is a lightweight Rust application built with warp that exposes a single API endpoint to handle image processing requests.
This diagram illustrates the high-level interaction between the components.
Sources: static/script.js, src/main.rs, README.md:40-44
Frontend
The frontend is built with vanilla HTML, CSS, and JavaScript, providing a modern and responsive user interface.
Sources: README.md:41, static/index.html, static/script.js
UI Components
The user interface is defined in index.html and consists of several key components managed by the HDRify JavaScript class.
| Component ID | Element | Description | Source File |
|---|---|---|---|
uploadArea | <div> | A drag-and-drop area and clickable button for initiating file upload. | static/index.html:26 |
imageInput | <input type="file"> | The hidden file input element, triggered by interaction with uploadArea. | static/index.html:29 |
imageDisplay | <div> | A container that appears after an image is uploaded, holding the result. | static/index.html:32 |
resultImage | <img> | Displays the processed HDR image. | static/index.html:33 |
processingOverlay | <div> | An overlay with a spinner shown during image processing. | static/index.html:34 |
controls | <section> | A container for the HDR slider and action buttons, visible after upload. | static/index.html:42 |
hdrSlider | <input type="range"> | Allows the user to adjust the HDR intensity from 0.5 to 3.0. | static/index.html:45 |
downloadButton | <a> | A button to download the processed image. | static/index.html:48 |
resetButton | <button> | A button to reset the interface to its initial state. | static/index.html:51 |
error | <div> | A container to display error messages. | static/index.html:73 |
Client-Side Logic (HDRify Class)
All frontend logic is encapsulated within the HDRify class in script.js.
Sources: static/script.js:1
State Management and Flow
The HDRify class manages the UI state transitions, from the initial upload prompt to displaying the processed image.
This diagram shows the frontend UI state flow.
Sources: static/script.js:154-180, 313-339
Event Handling
The setupEventListeners method binds events to DOM elements to handle user interactions.
- Upload:
click,keydown,dragover,dragleave, anddropevents onuploadAreahandle file selection. - Processing: The
inputevent onhdrSlidertriggers image reprocessing with a 250ms debounce. - Reset: A
clickonresetButtonor pressing theEscapekey calls thereset()method.
Sources: static/script.js:30-123
Client-Side Validation
Before uploading, the handleFile method performs validation on the selected file.
| Validation Rule | Condition | Error Message |
|---|---|---|
| File Type | File's type is not image/jpeg, image/jpg, image/png, or image/webp. | "Unsupported file format..." |
| File Size | File's size is greater than 10MB (10 * 1024 * 1024 bytes). | "File too large... Maximum size is 10MB." |
Sources: static/script.js:155-179
Caching
To improve performance when adjusting the HDR slider, the frontend maintains a Map to cache processed images. The cache key is the hdrValue (fixed to one decimal place). If a result for a given HDR value exists in the cache, it is displayed instantly without a new API request. The cache is cleared whenever a new image is uploaded.
Sources: static/script.js:6, 186, 230-248, 276-277
Backend
The backend is a Rust application using the warp web framework. Its primary role is to receive image data, execute an external ImageMagick command to process it, and return the result.
Sources: src/main.rs, Cargo.toml
API Endpoint
The application exposes a single endpoint for image processing.
- Endpoint:
POST /upload - Request Content-Type:
application/x-www-form-urlencoded - Response Content-Type:
application/json
Sources: src/main.rs:180-183, static/script.js:292-294
Request Parameters
The request body is a URL-encoded form with the following fields:
| Parameter | Type | Description | Required | Default |
|---|---|---|---|---|
image | String | Base64-encoded string of the source image data. | Yes | N/A |
hdr_value | Float | The HDR intensity multiplier. | No | 1.5 |
Sources: src/main.rs:18-23, static/script.js:289-291
Response Body
The server responds with a JSON object conforming to the ProcessResponse struct.
| Field | Type | Description |
|---|---|---|
success | Boolean | true if processing was successful, false otherwise. |
message | String | A status message, e.g., "Image processed successfully" or an error detail. |
image_data | String | A Base64-encoded string of the processed PNG image. null on failure. |
Sources: src/main.rs:8-13
Request Handling (handle_upload)
The handle_upload async function in src/main.rs contains the core backend logic.
This flowchart outlines the steps taken by the handle_upload function.
Sources: src/main.rs:16-174
Server-Side Validation
The backend performs its own validation to ensure security and stability.
- Image Data Presence: Checks if the
imagefield is provided.
Sources: src/main.rs:26-32 - File Size: Ensures the decoded image byte array does not exceed 10MB.
Sources: src/main.rs:47-58 - Image Format: The
is_supported_image_formatfunction checks the magic bytes of the uploaded data to verify it is a JPEG, PNG, or WebP file. This prevents processing of non-image files.
Sources: src/main.rs:61-68, 145-174
ImageMagick Processing
The core image transformation is delegated to the magick command-line tool. The backend constructs and executes a command with a specific set of arguments derived from the technique described in the project's README.md.
| Argument | Value | Purpose |
|---|---|---|
(input_file) | (dynamic) | Path to the temporary input image. |
-define | quantum:format=floating-point | Enables high-precision color processing. |
-colorspace | RGB | Converts to a linear RGB colorspace. |
-auto-gamma | Applies automatic gamma correction. | |
-evaluate | Multiply | Prepares to multiply pixel values. |
(hdr_value) | (dynamic) | The brightness multiplier from the user. |
-evaluate | Pow | Prepares to apply a power curve adjustment. |
0.9 | The power curve exponent. | |
-colorspace | sRGB | Converts back to the sRGB colorspace. |
-depth | 16 | Sets the color depth to 16 bits per channel. |
-profile | 2020_profile.icc | Applies the Rec. 2020 color profile for HDR. |
(output_file) | (dynamic) | Path to the temporary output file. |
Sources: src/main.rs:94-113, README.md:28-34
End-to-End Data Flow
The following sequence diagram illustrates the complete process, from a user uploading a file to receiving the processed HDR image.
Sources: static/script.js:154-311, src/main.rs:16-143