TGA to TGA API
POST a TGA to /v2/convert/tga/to/tga to resize, recolor or normalize it. Whatever comes in, the result is an uncompressed 32-bit TGA (image type 2) with a top-left origin and 8 alpha bits.
- Endpoint
- POST /v2/
convert/ tga/ to/ tga - Accepts
- tga
- Sample timing
- 2 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/tga \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@shield-icon.tga \
--form-string ImageWidth=128 \
-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/tga",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("shield-icon.tga", "rb"))],
data={
"ImageWidth": "128",
},
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("ImageWidth", "128");
const url = "https://api.pdfconversionapi.com/v2/convert/tga/to/tga";
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.002,
"Files": [
{
"FileName": "shield-icon.tga",
"FileExt": "tga",
"FileSize": 65554,
"FileData": "AAACAAAAAAAAAAAAgACAACAo…"
}
]
}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.tga (64 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 |
|---|---|
ImageWidthinteger | New width; the sample asks for 128, so the 256 px shield comes back 128 × 128. Lanczos3 blending raised its 12 colors to 460, and the file is 65,554 bytes: 18 of header and 4 per pixel.Values: 1–20000 |
ImageHeightinteger | New height. With both given, the texture fits inside the box.Values: 1–20000 |
ScaleProportionsboolean, default true | false resizes to the exact box, for non-uniform texture sizes. |
ScaleIfLargerboolean, default false | true keeps textures already under the target size. |
ScaleImageboolean, default true | false cuts a top-left tile of the given size instead, for example one frame of a sprite sheet. |
ColorSpaceenum, default default | Rewrites the pixel values to gray or to black and white. The file stays 32-bit.Values: default, rgb, gray, monochrome; cmyk returns 400 |
TransparentColorstring | Turns one exact key color into alpha 0; #966034 made the shield's main wood color see-through.Values: #RRGGBB, R,G,B or a basic color name |
FileNamestring | Name for the new .tga; by default the upload's name is reused. |
StoreFileboolean, default false | Keep the TGA for 3 hours behind a download URL. |
What carries over, and what doesn't
Kept
- Every pixel when no option is sent: decoded back, the default output equals the input's 65,536 pixels
- Alpha at full 8-bit depth, including the shadow's 112
- The picture's orientation, though the stored row order changes to top-down
Lost or not yet supported
- The input's own layout. Grayscale, color-mapped and 16-bit TGAs come out as 32-bit color; a 6,596-byte gray test TGA became 262,162 bytes.
- Compression. The output has no run-length packets, so without resizing the 16,376-byte shield becomes 262,162 bytes, and the page's 128 px sample is 65,554.
- The image ID text, the TGA 2.0 footer and any extension area.
- Hard edges when resizing: there is no nearest-neighbor filter.
Limits
- One TGA per request.
- Sizes from 1 to 20,000 px per side, and 100,000,000 pixels per image.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- 120 seconds per conversion.
Where teams use it
Downsized textures and thumbnails
Make half- or quarter-size copies of textures for low-end builds or previews, in the same format the engine already loads.
One layout for an importer
Engines and scripts that only handle 32-bit, top-left TGAs can take anything after this step: grayscale, color-mapped, 16-bit and bottom-left files all come out the same way.
Key color to alpha
If an old sprite set marks transparency with one color, such as magenta, TransparentColor turns that color into alpha 0 so current engines can use the files directly.
Questions
Will my engine or editor read the output?
The file uses the simplest TGA layout: image type 2, 32 bits per pixel, no color map, no ID field and no footer, with the top-left origin flag set. Three readers we tried opened the sample, a strict one included, and decoded the same 16,384 pixels.
Why did a 128 px copy of pixel art get more colors?
Resizing uses a Lanczos3 filter that blends neighboring pixels, so edges get in-between shades: 460 distinct values in the sample instead of 12. For exact pixel art, scale by whole factors with nearest neighbor in your own code.
Can I keep the image ID or get a run-length-encoded TGA?
No. The writer always stores raw pixels, without run-length encoding, and writes no ID field or footer; no option changes either today.
Convert your first TGA file in a minute.