RGB565 color packer
This RGB565 color packer converts ordinary eight-bit red, green, and blue channels into the compact sixteen-bit pixel format used by embedded displays, microcontrollers, image assets, and framebuffers.
Run — free
It also decodes an RGB565 word back into scaled channels. Every conversion reports the packed decimal and padded hexadecimal value, the underlying five-bit, six-bit, and five-bit fields, and the visible round-trip result. Strict validation catches out-of-range channels and malformed packed values before they can silently wrap into a different color.
Pack three 8-bit channels into one RGB565 word
Choose the pack operation and provide integer r, g, and b channels between 0 and 255 inclusive. The converter first quantizes red and blue from eight bits to five bits, giving each a range from 0 to 31. Green is quantized to six bits, giving it a range from 0 to 63 because the RGB565 layout reserves an extra bit for green. Each conversion uses proportional scaling with nearest-integer rounding, so zero and 255 map exactly to the endpoints while intermediate colors use the closest available reduced-depth level. The tool then places red in bits 15 through 11, green in bits 10 through 5, and blue in bits 4 through 0. A bitwise OR combines those fields into one unsigned sixteen-bit integer. The response includes both a decimal value and a consistently padded four-digit hexadecimal value, which is convenient for C constants, binary encoders, display drivers, lookup tables, and fixture files. The separate component fields make every step inspectable instead of presenting the result as an unexplained number.
Understand quantization and the reported round trip
RGB565 cannot preserve every twenty-four-bit RGB color because it represents 16,777,216 possible input colors with only 65,536 packed values. Several nearby input colors therefore map to the same word, and unpacking cannot reconstruct low-order information that packing discarded. To make that loss explicit, a successful pack response includes an unpacked object showing the eight-bit color represented by the generated word. The decoder expands red and blue by multiplying their five-bit values by 255, dividing by 31, and rounding to the nearest integer. It expands green in the same way with a divisor of 63. This proportional rule is deterministic, maps both endpoints exactly, and is easy to reproduce across JavaScript, C, Rust, Python, and other environments. The round-trip channels may differ slightly from the original input, but that difference is expected quantization rather than an error. Returning the reduced bit fields, packed word, and expanded channels together helps you compare implementations, diagnose byte-order confusion, verify color constants, and decide whether the reduced precision is acceptable for a particular display or visual asset.
Unpack existing values and avoid common format mistakes
Choose the unpack operation when you already have an RGB565 word from firmware, a framebuffer, a protocol capture, or an image file. Supply value as decimal digits from 0 through 65535 or as hexadecimal with a 0x prefix. The converter rejects negative values, fractions, bare hexadecimal letters, trailing characters, and numbers above the unsigned sixteen-bit range rather than truncating them. Its output includes the normalized decimal integer, padded hexadecimal representation, three stored bit fields, and scaled r, g, and b channels. Remember that RGB565 describes bit allocation, not byte order. A value may be serialized with its high byte first or low byte first depending on the device, protocol, or file format; swap bytes before conversion if your source uses the opposite order. Likewise, RGB565 is different from BGR565, where red and blue occupy reversed positions. This tool follows the conventional red-high, blue-low layout and does not guess alternative arrangements. Interactive browser use is useful for isolated checks, while an API request costs $0.002 when you need deterministic conversion inside a build, test suite, asset pipeline, or diagnostic service.
What you can do with it
Generate display constants
Turn design RGB channels into padded RGB565 values for embedded display drivers, firmware headers, and lookup tables.
Verify framebuffer pixels
Decode captured sixteen-bit words and compare their expanded channels with the colors expected by rendering tests.
Create cross-language fixtures
Record inputs, reduced bit fields, packed words, and round-trip channels for consistent tests across device and application code.
FAQ
How are 8-bit channels reduced for packing?
Red and blue use round(channel × 31 ÷ 255), while green uses round(channel × 63 ÷ 255).
Why can the unpacked color differ from my input?
Packing removes low-order channel information. The returned round trip is the nearest color represented by the resulting RGB565 word.
Which packed input formats can I unpack?
Use decimal digits from 0 to 65535 or a hexadecimal string with a 0x prefix, such as 0xF800.
Does this tool swap bytes?
No. It converts the numeric RGB565 word. Handle byte order when reading or writing the word in a byte-oriented format.
What does an API conversion cost?
Each API request costs $0.002; interactive browser conversion is also available.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/rgb565-pack \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"r":255,"g":128,"b":0}'const res = await fetch("https://api.kit.forhosting.com/dev/rgb565-pack", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"r": 255,
"g": 128,
"b": 0
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/rgb565-pack",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"r": 255,
"g": 128,
"b": 0
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/rgb565-pack", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"r":255,"g":128,"b":0}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"r":255,"g":128,"b":0}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/rgb565-pack", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"r": 255,
"g": 128,
"b": 0
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.rgb565_pack",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |