Skip to content
pdfconversionapi

HDR to GIF API

POST a .hdr to /v2/convert/hdr/to/gif and get a GIF89a of the same size. The linear RGBE pixels are clipped at 1.0, rounded to 8 bits and mapped to a palette chosen for the image: 233 entries for the sample sky, holding 227 distinct colors.

Endpoint
POST /v2/convert/hdr/to/gif
Accepts
hdr
Sample timing
82 ms median of 5 runsHow we measure
Request size
Up to 10 MB on the Free plan or 100 MB on paid plans, all files together

Request and response

Every sample below ran against the API before this page was published. Set PDFCONVERSIONAPI_KEY to your key and run it as is.

curl -sS -X POST \
  https://api.pdfconversionapi.com/v2/convert/hdr/to/gif \
  -H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
  -F File=@lakeside-sunset-sky.hdr \
  -o response.json

# FileData is base64. Save the first file in converted/,
# or print the JSON error.
if jq -e '.Files' response.json > /dev/null; then
  mkdir -p converted
  name=$(jq -r '.Files[0].FileName' response.json)
  jq -r '.Files[0].FileData' response.json \
    | base64 --decode > "converted/$name"
else
  cat response.json
fi
200 OK82 ms median1 file, 15 KB
{
  "ConversionCost": 1,
  "ConversionTime": 0.082,
  "Files": [
    {
      "FileName": "lakeside-sunset-sky.gif",
      "FileExt": "gif",
      "FileSize": 15217,
      "FileData": "R0lGODlhkAHIAIAAAAAAAAAA…"
    }
  ]
}

Response from our test run on 2026-11-03. ConversionTime shows the median of 5 runs. FileData is shortened here; the real response carries the whole file as base64.

The sample, converted

The same file the code sends. Download the input and the output and compare them yourself.

First page of lakeside-sunset-sky.gif, rendered by the API
Input
lakeside-sunset-sky.hdr (90 KB)
Output
lakeside-sunset-sky.gif (15 KB)
Source
A sunset sky panorama we drew in code and saved as a 400 × 200 Radiance RGBE file with run-length scanlines; the sun disc is 60.0. (CC0-1.0). How it was made
Made by
2026-11-04, API build 9eeeb0640aba

Parameters

Send these as form fields next to the file. Names are case-insensitive. If you set one of the documented options below that we don't support yet, the request fails with a 400 that names it instead of returning a file made without it.

ParameterWhat it does
ImageWidthintegerWidth of the GIF. ImageWidth=120 gave a 120 × 60 file of 4,084 bytes with 213 palette entries (203 distinct colors).Values: 1–20000
ImageHeightintegerHeight of the GIF; ImageHeight=100 came back 200 × 100 (7,089 bytes, 218 entries, 207 distinct colors).Values: 1–20000
ScaleProportionsboolean, default truefalse lets a 200 × 200 request stretch the panorama (11,694 bytes, 238 entries, 220 distinct colors).
ScaleIfLargerboolean, default falsetrue keeps the GIF at 400 × 200 when you ask for more; ImageWidth=800 alone gave 800 × 400 at 33,264 bytes.
ScaleImageboolean, default truefalse crops instead: the upper-left 200 × 100 quarter needed only 120 palette entries (118 distinct colors).
ColorSpaceenum, default defaultgray gave 240 shades in 20,808 bytes; monochrome 2 colors in 858 bytes.Values: default, rgb, gray, monochrome; cmyk returns 400
TransparentColorstringAdds a transparent index for one exact color. #FFFFFF made 333 white pixels clear: 101 at the sun and 232 along its streak on the lake.Values: #RRGGBB, R,G,B or a color name
FileNamestringOutput name; the upload's name is reused by default.
StoreFileboolean, default falsetrue replaces the data with a 3-hour link.

What carries over, and what doesn't

Kept

  • The overall picture: against the 8-bit image, the average error is under one level per channel, the largest 24
  • An opaque frame: Radiance has no alpha, and the GIF has no transparent index unless you ask for one
  • The 400 × 200 size

Lost or not yet supported

  • Most of the 9,031 colors: the palette keeps 227 in 233 entries, so neighbouring shades in a gradient can share one entry.
  • Highlights over 1.0. Each channel stops at 255: the glow keeps an orange or yellow tint with its red channel flat, and the 333 pixels bright in all three channels are plain white.
  • All precision beyond 8 bits, and the linear-light meaning of the values.
  • The EXPOSURE and GAMMA header lines, which are not read.

Limits

  • One .hdr file per call; one frame out.
  • 10 MB on the Free plan or 100 MB on paid plans per request.
  • 100,000,000 pixels, else 413.
  • A GIF side can't exceed 65,535 px: a 70,000 × 8 .hdr returned 413 GIF images can be at most 65,535 pixels on a side, and this one is 70,000×8.
  • Standard top-down orientation only; other .hdr layouts return 422.
  • 120 seconds per conversion.

Where teams use it

Previews in GIF-only places

Older forums, help desks and newsletter tools that take GIF but not HDR can still show a sky or lighting render.

Small stills of simple skies

Smooth, low-detail skies map well onto 256 colors; a 120 px wide copy of the sample is about 4 KB.

Questions

How are the 256 colors picked?

A palette is built for each image from its own pixels after they are cut to 8 bits. This sky used 233 entries. There is no option for a fixed palette, a smaller count or dithering.

Will the sky show bands?

It can, in slow gradients, because each palette entry stands for a range of similar colors. Against the 8-bit image, the sample's average difference was 0.78 levels and the largest 24 levels in one channel. Use hdr/to/png or hdr/to/webp when gradients must stay exact.

Can the GIF have a transparent area?

Only with TransparentColor, which clears one exact color. Sending #FFFFFF clears 333 pixels, the sun's clipped core and the middle of its streak on the lake, which is rarely what you want for a sky.

Convert your first HDR file in a minute.