TGA to BMP API
POST a TGA to /v2/convert/tga/to/bmp and get an uncompressed BMP back. With transparency, like the sample, it is 32-bit with a 108-byte V4 header whose masks mark the fourth byte as alpha; an opaque TGA gives 24-bit with the 40-byte header. ImageResolution records a DPI.
- Endpoint
- POST /v2/
convert/ tga/ to/ bmp - Accepts
- tga
- Sample timing
- 1 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/tga/to/bmp \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@shield-icon.tga \
--form-string ImageResolution=96 \
-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
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/tga/to/bmp",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("shield-icon.tga", "rb"))],
data={
"ImageResolution": "96",
},
timeout=180,
)
result = response.json()
if not response.ok:
raise SystemExit(f"{result['Code']}: {result['Message']}")
os.makedirs("converted", exist_ok=True)
for file in result["Files"]:
path = os.path.join("converted", file["FileName"])
with open(path, "wb") as out:
out.write(base64.b64decode(file["FileData"]))
print(path, file["FileSize"], "bytes")
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
const form = new FormData();
const file = "shield-icon.tga";
form.append("File", new Blob([await readFile(file)]), file);
form.append("ImageResolution", "96");
const url = "https://api.pdfconversionapi.com/v2/convert/tga/to/bmp";
const key = process.env.PDFCONVERSIONAPI_KEY;
const response = await fetch(url, {
method: "POST",
headers: { Authorization: `Bearer ${key}` },
body: form,
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${result.Code}: ${result.Message}`);
}
await mkdir("converted", { recursive: true });
for (const file of result.Files) {
const path = join("converted", file.FileName);
await writeFile(path, Buffer.from(file.FileData, "base64"));
console.log(path, file.FileSize, "bytes");
}
{
"ConversionCost": 1,
"ConversionTime": 0.001,
"Files": [
{
"FileName": "shield-icon.bmp",
"FileExt": "bmp",
"FileSize": 262266,
"FileData": "Qk16AAQAAAAAAHoAAABsAAAA…"
}
]
}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.

- Input
- shield-icon.tga (16 KB)
- Output
- shield-icon.bmp (256 KB)
- Source
- A 256 x 256 pixel-art shield icon with a transparent background and a half-transparent shadow, drawn by us and saved as a 32-bit run-length-encoded TGA. (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.
| Parameter | What it does |
|---|---|
ImageResolutioninteger | Written into both pixels-per-meter fields of the header. The sample sends 96, stored as 3,780; without it both fields are 0.Values: 10–800 |
ImageWidthinteger | New width; since the BMP is uncompressed, the file grows with the square of the size (128 px: 65,658 bytes, 1,000 px: 4,000,122).Values: 1–20000 |
ImageHeightinteger | New height; with a width given too, the texture is fitted inside the pair.Values: 1–20000 |
ScaleProportionsboolean, default true | false stretches to the exact size you ask for. |
ScaleIfLargerboolean, default false | true never makes the bitmap bigger than the TGA. |
ScaleImageboolean, default true | false crops the top-left area at the given size. |
ColorSpaceenum, default default | Changes pixel values to gray or black and white, not the layout: the shield stays a 262,266-byte 32-bit BMP, and an opaque 24-bit TGA stays 24-bit.Values: default, rgb, gray, monochrome; cmyk returns 400 |
FileNamestring | Base name for the .bmp. |
StoreFileboolean, default false | Hold the bitmap for 3 hours behind a URL, useful because BMPs are large in base64. |
What carries over, and what doesn't
Kept
- Every pixel and alpha value of the sample, read back identically from the BMP
- Alpha as a real channel: the header's BI_BITFIELDS masks are 0x00FF0000, 0x0000FF00, 0x000000FF and 0xFF000000 for alpha
- The DPI you send, as pixels per meter (96 dpi is stored as 3,780)
Lost or not yet supported
- Compression. The 16,376-byte RLE sample becomes a 262,266-byte BMP: 122 bytes of headers plus 4 bytes per pixel.
- An 8-bit layout. An opaque 24-bit or grayscale TGA comes back as a 24-bit BMP (196,662 bytes at 256 × 256), so gray still costs 3 bytes per pixel; there is no palette option.
- Key colors:
TransparentColoris ignored for BMP. - The TGA ID text and footer.
Limits
- One TGA per request.
- Output grows with the pixel count: 4 bytes per pixel plus 122 with transparency (the shield at 1,000 px is 4,000,122 bytes), 3 plus 54 when opaque (3,000,054).
- 100,000,000 pixels per image (413 above).
- Requests up to 10 MB on the Free plan or 100 MB on paid plans; 120 seconds per conversion.
Where teams use it
Older Windows tools and game editors
If an older Windows editor or utility in your pipeline loads BMP but not TGA, convert textures for it on the fly instead of keeping two copies of every file.
Raw pixels for firmware or embedded loaders
An uncompressed BMP with fixed channel masks can be parsed in a few lines of C, which suits small display drivers and firmware build tools.
Questions
Will programs show the BMP's transparency?
That depends on the reader. The alpha values are all in the file and the header's masks mark them as alpha, so check the program you target; if transparency has to show everywhere, convert to PNG instead.
Why is the BMP so much bigger than the TGA?
The bitmap stores every pixel as 4 raw bytes with no compression, while the sample TGA packs repeated pixels with run-length encoding. 256 × 256 × 4 is 262,144 bytes of pixels, plus 122 bytes of headers.
Are the rows stored top-down or bottom-up?
Bottom-up, the usual BMP order: the height in the header is positive. The TGA's own origin doesn't matter, because the image is put the right way up before it is written.
Convert your first TGA file in a minute.