Request Data Flow
Relevant source files
The following files were used as context for generating this wiki page:
This document outlines the complete data flow for an image processing request in the hdrify application. It covers the journey from a user uploading an image in the browser to the server-side processing with ImageMagick and the final response back to the client. The entire process is orchestrated between a vanilla JavaScript frontend and a Rust warp backend.
The flow is initiated by a user action, handled by the HDRify JavaScript class, which sends a request to a single API endpoint. The backend validates the request, processes the image using an external command-line tool, and returns the result. The frontend then updates the UI to display either the processed image or an error message.
High-Level Sequence Diagram
The following diagram illustrates the end-to-end interaction between the user, the browser client, the backend server, and the ImageMagick process.
Sources: static/script.js, src/main.rs
Frontend: Client-Side Request Initiation
The client-side logic is encapsulated within the HDRify class in script.js. It manages the UI state, user interactions, and communication with the backend.
Sources: static/script.js, static/index.html
User Interaction and File Handling
- A user initiates the process by either clicking the upload area (
#uploadArea) or dragging and dropping a file onto it. - Event listeners for
click,keydown,dragover,dragleave, anddropare set up in thesetupEventListenersmethod. - When a file is selected, the
handleFilemethod is called.
Sources: static/script.js:28-83, static/index.html:25-29
The handleFile method performs initial client-side validation:
- File Type: Checks if the file's MIME type is one of
image/jpeg,image/jpg,image/png, orimage/webp. - File Size: Ensures the file size does not exceed a 10MB limit (
10 * 1024 * 1024bytes).
If validation passes, a FileReader reads the image file as a Data URL. The Base64-encoded portion of the URL is stored in this.currentImageData.
Sources: static/script.js:154-181
API Request
Once the file is read, the processImage method is invoked. It constructs and sends a POST request to the /upload endpoint.
This diagram shows the flow of the processImage function.
Sources: static/script.js:230-307
The request is sent using the fetch API with the following configuration:
- Method:
POST - Endpoint:
/upload - Headers:
Content-Type: application/x-www-form-urlencoded - Body: The image data and HDR value are sent as URL-encoded form data using
URLSearchParams.
// static/script.js:283-291
const params = new URLSearchParams();
params.append('image', this.currentImageData);
params.append('hdr_value', hdrValue.toString());
const response = await fetch('/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params,
});
Sources: static/script.js:283-291
Backend: Server-Side Request Processing
The backend is a Rust application using the warp web server framework. It defines a single endpoint to handle the image processing.
Sources: src/main.rs, Cargo.toml
Routing and Request Handling
The server sets up routes in the main function. The relevant route for data processing is /upload, which only accepts POST requests and expects form-encoded data. This route is handled by the handle_upload async function.
// src/main.rs:194-198
let upload = warp::path("upload")
.and(warp::post())
.and(warp::body::form())
.and_then(handle_upload);
Sources: src/main.rs:194-198
The handle_upload function receives the form data as a HashMap<String, String>. It extracts the Base64 image data and the hdr_value.
Sources: src/main.rs:15-22
Server-Side Validation
Before processing, the server performs its own validation steps:
- Presence Check: Verifies that
image_datais not empty. - Base64 Decoding: Decodes the image string into bytes.
- File Size Limit: Checks if the decoded byte length exceeds 10MB (
10 * 1024 * 1024). - Image Format: Calls
is_supported_image_formatto check the file's magic bytes to ensure it is a JPEG, PNG, or WebP file.
If any validation fails, it immediately returns a JSON response with success: false and an error message.
Sources: src/main.rs:25-72, src/main.rs:155-184
Image Processing with ImageMagick
If validation is successful, the core image processing begins.
- Two temporary files are created using
tempfile::NamedTempFilefor the input and output images. - The decoded image bytes are written to the input temporary file.
- An external
magickcommand is constructed and executed usingstd::process::Command.
The arguments passed to the magick command are critical for the HDR effect.
| Argument | Value | Purpose |
|---|---|---|
[input_file] | (path) | The path to the uploaded SDR 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 | Multiplies pixel brightness. |
[hdr_value] | e.g., 1.5 | The multiplier value from the slider. |
-evaluate | Pow | Applies a power curve adjustment. |
0.9 | 0.9 | The exponent for the power curve. |
-colorspace | sRGB | Converts back to the sRGB colorspace. |
-depth | 16 | Sets the color depth to 16 bits. |
-profile | 2020_profile.icc | Applies the Rec. 2020 color profile for HDR. |
[output_file] | (path) | The path where the processed HDR image will be saved. |
Sources: src/main.rs:83-104, README.md:32-38
Response Generation and Frontend Handling
After the magick command finishes, the backend generates a final JSON response.
Backend Response
The ProcessResponse struct defines the structure of the JSON payload sent back to the client.
// src/main.rs:6-11
#[derive(Debug, Serialize)]
struct ProcessResponse {
success: bool,
message: String,
image_data: Option<String>, // base64 encoded HDR image
}
Sources: src/main.rs:6-11
- On Success: The processed image is read from the output temporary file, encoded into Base64, and sent in the
image_datafield withsuccess: true. - On Failure: If the
magickcommand fails or the output file cannot be read,successis set tofalse, and a descriptive error message is provided.
Sources: src/main.rs:106-153
Frontend Response Handling
Back in the browser, the processImage method in script.js handles the server's response:
- If
result.successistrue, theresult.image_datais cached using the HDR value as a key. - The
<img>element'ssrcis updated to a Data URL with the new Base64 image data. - The download button is enabled with the new image data.
- If
result.successisfalse, theshowErrormethod is called to display the error message from the server.
Sources: static/script.js:297-320