OCR, Envelope OCR, Document Detection, Image Enhancement and Image Upscaling used to be separate plugins. All five now run on Start, Grow and Scale, and the included allowances and overage rates are the same as they were. Free is the one Filestack plan they do not run on.
This is the fourth of six posts on the Start, Grow and Scale processing tasks, one per task.
Image Enhancement is the one that colour corrects a photograph on the way out, as a path segment in front of a handle.
That is one URL segment on a file shot at roughly a third of correct exposure. Nothing was re-uploaded and no editor was opened. The rest of the image editing API, from crop and resize to watermark and convert, works the same way.
Key takeaways
- We now include Image Enhancement on the Filestack Start, Grow and Scale plans at 1,000 images a month, then $0.04 an image.
enhancewith no parameters applies the auto preset.enhance=preset:fix_darktook a photograph from 43.6 mean luminance to 153.7 against a correctly exposed reference of 131.0.- The response is
Cache-Control: publicwith about a month of freshness, so the task runs once per URL however much traffic the page takes. - Noise detection depends on the ISO level and the camera make and model, so
fix_noiseneeds an upload that still carries that metadata.
How to call the image enhancement API
The task is one segment in front of the handle, and in its bare form it takes no parameters:
https://cdn.filestackcontent.com/enhance/HANDLE
HANDLE is the file handle an upload returns, the last segment of the file’s Filestack URL. Add a preset to ask for a specific correction instead:
https://cdn.filestackcontent.com/enhance=preset:fix_dark/HANDLE
Filled in with the handle of the underexposed photograph above and a resize in front of it, that is the request the image below makes:
https://cdn.filestackcontent.com/resize=width:1200/enhance=preset:fix_dark/3Y8nFNWLT52UtqQaDZbn
The bare task applies the auto preset, so enhance and enhance=preset:auto return the same image. Write whichever reads better in your code.
Whether a delivery URL needs a signed policy is a setting on your application. With security switched on, enhance answers an unsigned request, while ocr on the same handle returns 403 security required for tasks: ocr. Where your application does require a signed policy on delivery, the security segment goes in front of the task:
https://cdn.filestackcontent.com/security=policy:POLICY,signature:SIGNATURE/enhance=preset:fix_dark/HANDLE
A preset value the task does not recognise comes back as a validation error naming the value, rather than as a quietly unenhanced image, so a typo surfaces on the first request. The fix is to send one of the values in the table below:
HTTP 400
validation error: invalid value format bogus_preset for parameter preset required by enhance task (invalid value bogus_preset)
Which enhance presets are available
The task accepts these eight documented preset values. The descriptions come from Processing API, and the luminance column is each preset’s result on the same 1200×800 underexposed photograph, as mean luminance of the 8 bit greyscale conversion. The upload measures 43.6 and the same scene correctly exposed measures 131.0.
| Preset | What it corrects | Mean luminance |
|---|---|---|
auto |
Chooses the preset that does the best enhancement for the photo. | 119.6 |
fix_dark |
Extremely underexposed photos, and a dark subject in front of a very bright background. Contrast is turned off so shadow detail comes back without blowing out the bright areas. | 153.7 |
vivid |
More depth and brightness. | 140.0 |
beautify_plus |
Stronger corrections than beautify, drawn from a larger set of modifications. | 138.8 |
fix_noise |
Detects noise and removes grain while preserving detail, depending on the ISO level and the camera make and model. | 137.0 |
fix_tint |
An abnormal colour cast, such as green from fluorescent light, yellow from tungsten, or blue from ultraviolet. | 131.9 |
outdoor |
Landscape colour vibrancy, with contrast adjusted to reveal more detail in the shadows. | 135.4 |
fireworks |
A dark night sky, holding back the excess colour that fireworks throw. | 120.6 |
beautify is a ninth preset value, and on these photographs it gives the same result as beautify_plus. cache is not a preset value and returns the 400 above.
How to pick an enhance preset per upload type
The luminance column is the argument against one global setting. The same underexposed photograph ranges from 119.6 to 153.7 depending on the segment, so the choice changes what the visitor sees.
The presets are also scoped to the problem they name rather than being brightness dials. On a correctly exposed copy of the same scene, fix_dark gives 131.2 against 131.0 for the input, and leaves it where it was. A preset aimed at a problem the photograph does not have has little to correct, and a colour cast or a night sky is a different problem with its own preset.
So the preset belongs with the upload path rather than in a config file. Each row below pairs a route with the preset whose documented subject matches it:
| Upload | Preset | The documented subject it matches |
|---|---|---|
| Marketplace listing shot indoors on a phone | fix_dark |
A dark subject in front of a very bright background. |
| Property and travel photography | outdoor |
Landscape photographs. |
| Documents and products under office lighting | fix_tint |
Green cast from fluorescent light. |
| Event photography after dark | fireworks |
A dark night sky with excess colour in it. |
| A mixed feed you do not control | enhance |
The auto preset, which chooses for the photo. |
A route that knows what it is accepting can pick the segment when it writes the URL:
const PRESET_BY_KIND = {
listing: 'fix_dark',
property: 'outdoor',
scan: 'fix_tint',
event: 'fireworks',
};
function deliveryUrl(handle, kind, width = 1200) {
const preset = PRESET_BY_KIND[kind];
const enhance = preset ? `enhance=preset:${preset}` : 'enhance';
return `https://cdn.filestackcontent.com/resize=width:${width}/${enhance}/${handle}`;
}
Presets sit alongside the crop, rotate and watermark tasks in the same URL. Where a person should choose rather than a route, the photo editor SDK puts the same corrections in an editor.
Why to put resize before enhance in the URL
Tasks in a transformation URL run left to right. resize=width:600/crop=dim:[0,0,100,100] returns a 100×100 image, and swapping the two segments returns 600×600, because the crop then happens first and the resize enlarges it. So putting resize in front means the correction runs on the pixels you actually deliver:
https://cdn.filestackcontent.com/resize=width:600/enhance=preset:fix_dark/HANDLE
At the same 600×400 output from the same source, resize first produces 73,190 bytes and enhance first produces 103,643, a 29% smaller file for a mean luminance within a point of the other.
The output also carries an EXIF ProcessingSoftware tag reading Perfectly Clear, which the source file did not have. That tag is how you tell an enhanced copy from an original once both are sitting in your storage.
What the fix_noise preset needs in order to fire
How much grain removal fix_noise applies depends on the ISO level and the camera make and model, which is where this preset differs from the rest of the table. Those two values travel in a photograph’s EXIF block, so on a noisy photograph with no EXIF, such as the one below, fix_noise has nothing to work from and the grain stays:
So fix_noise has a condition of use attached. Send it the camera original with the EXIF intact and the ISO and the camera model are there for it to work from. Where your upload path strips metadata before storing, keep the EXIF on the copy you enhance, or use auto, which the docs describe as choosing the preset for the photo rather than reading a specific value.
What Image Enhancement costs and how it caches
Enhanced output is cached at the CDN. The response carries cache-control: public with about 30 days of freshness, and a second request to the same URL is served from cache, x-cache-hits: 0, 1, without running the task again.
A listing page showing the same enhanced photograph to every visitor therefore runs the enhancement once for that URL rather than once per view. The included allowance is 1,000 images a month, then $0.04 an image. The OCR tasks behave the other way round. ocr, the task behind the invoice OCR API, answers Cache-Control: private and re-runs on every request, so it belongs at upload with the JSON in your own table.
Because it caches, the whole integration is a string change:
<img src="https://cdn.filestackcontent.com/resize=width:1200/enhance=preset:fix_dark/HANDLE"
alt="Listing photograph">
There is no backend to stand up, no webhook to receive and nothing to store. The same URL works from a server, which is how you would run the task across a catalogue you uploaded last year.
When to use upscaling instead of enhancement
Exposure, cast and grain are what enhance addresses. A photograph that is correctly exposed and too small for a retina product page needs pixels rather than correction. That is the image upscaling API, a different task with its own parameters, on the same three plans.
Which applications use image enhancement
Every upload path that takes photographs from other people has the same shape. You do not control the camera, the light or the person holding the phone, and you do control the URL that delivers what they sent you. A marketplace, a property listing and a seller catalogue all sit in that gap.
Pick the preset for the problem that route tends to produce, put it after the resize segment, and the correction happens on the way to the browser.
FAQ
Is there a difference between enhance and enhance=preset:auto?
No. The bare task applies the auto preset, so both return the same image. Write whichever reads better in your code.
Why did fix_noise leave the grain in my photograph?
The file had no EXIF. Grain removal depends on the ISO level and the camera make and model, both of which travel in the EXIF block, so a stripped upload gives the preset nothing to work from. Enhance the camera original, or use auto.
Does the order of resize and enhance matter?
Yes, for file size. Tasks run left to right, so resize first means the correction runs on the pixels you deliver. At the same 600×400 output that is 29% smaller than putting enhance first, for a luminance within a point.
Will enhancement run on every page view?
No. The response is Cache-Control: public with about thirty days of freshness, so a page showing the same URL to every visitor runs the task once. That is the opposite of the OCR tasks, which answer private and re-run each request.
Joshua is a web developer with over 4 years of experience building responsive, high-performance websites and web applications. Currently working as an AI Automation Specialist, he combines modern web development with automation to create efficient, scalable digital solutions. He shares practical insights on WordPress, web development, and emerging technologies.
Read More →