二进制格式调色板转十六进制颜色:转换结果异常求助
Let’s dig into why your conversion isn’t working as expected—your approach sounds logical at first glance, but binary data handling has a few tricky edge cases that trip up even experienced devs. Here are the most likely issues and how to fix them:
1. You’re Confusing Two Types of “Binary” Data
This is the biggest culprit. When you say “binary format stored palette,” it could mean one of two things, and using the wrong tool for the job will break your results:
- Binary byte stream: Raw bytes (each RGB color is 3 consecutive bytes, e.g.,
0xFF 0xAA 0x00for #FFAA00) - Binary string: A sequence of 0s and 1s (each color is 24 bits, e.g.,
111111111010101000000000for the same color)
Your use of bin2hex() suggests you might be mixing these up:
bin2hex()converts raw binary bytes to hex strings. If your input is a string of 0s and 1s, this function will treat each character as a byte (e.g., "0" becomes30in hex, which is not what you want).- If you have a binary string of 0s/1s, you need to use
bindec()to convert 8-bit chunks to decimal, thendechex()to get hex.
2. Your Splitting Logic Is Breaking the Data
Using explode() assumes your binary data is separated by a delimiter—but binary palettes are almost always continuous streams with no separators. trim() is also dangerous here, as it might strip leading/trailing bytes that are part of valid color data (like null bytes or non-printable characters).
Instead, use str_split() to split the data into fixed-size chunks:
- For raw byte streams: Split into individual bytes (
str_split($binaryData)). - For binary 0/1 strings: Split into 24-bit chunks per color, then split each into 8-bit RGB components.
3. Grouping by 3 Elements Is Misaligned
If you’re splitting the data into individual characters (e.g., each 0 or 1 as an element) and grouping 3 together, you’re creating 3-bit chunks instead of 8-bit RGB components. That’s why your hex values are garbage—you’re converting tiny, meaningless bits instead of full color channels.
Fixes for Common Scenarios
Scenario 1: Raw Binary Byte Stream (Most Likely for Program-Stored Palettes)
If your imported data is a raw binary string (e.g., from a file or API response that returns bytes):
// Assume $binaryPalette is your imported raw binary data $colorBytes = str_split($binaryPalette); $hexColors = []; // Process 3 bytes at a time (R, G, B) for ($i = 0; $i < count($colorBytes); $i += 3) { // Skip incomplete color entries if (!isset($colorBytes[$i+1]) || !isset($colorBytes[$i+2])) { break; } // Convert each byte to 2-digit hex $r = bin2hex($colorBytes[$i]); $g = bin2hex($colorBytes[$i+1]); $b = bin2hex($colorBytes[$i+2]); // Build the full hex color (uppercase for consistency) $hexColors[] = "#" . strtoupper($r . $g . $b); }
Scenario 2: Binary String (0s and 1s)
If your input is a string of 0s and 1s (e.g., "111100001010101000001111"):
// Assume $binaryString is your imported 0/1 string $binaryString = trim($binaryString); // Safe here since 0/1 are printable $colorChunks = str_split($binaryString, 24); // Split into 24-bit color chunks $hexColors = []; foreach ($colorChunks as $chunk) { // Skip incomplete chunks if (strlen($chunk) !== 24) { continue; } // Split into 8-bit R, G, B components $rBin = substr($chunk, 0, 8); $gBin = substr($chunk, 8, 8); $bBin = substr($chunk, 16, 8); // Convert each 8-bit binary to 2-digit hex $r = str_pad(dechex(bindec($rBin)), 2, '0', STR_PAD_LEFT); $g = str_pad(dechex(bindec($gBin)), 2, '0', STR_PAD_LEFT); $b = str_pad(dechex(bindec($bBin)), 2, '0', STR_PAD_LEFT); $hexColors[] = "#" . strtoupper($r . $g . $b); }
The key takeaway is to first confirm exactly what kind of "binary" data you’re working with—raw bytes vs. a string of 0s/1s. Once you clarify that, adjusting the splitting and conversion logic will get you the correct hex colors.
内容的提问来源于stack exchange,提问作者Alan

