4-Color Run-Length Protocol Example
[rev. 11/5/2006]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Let us agree to the following file protocol:
1. |
First 2 bytes are 4D 48 hex to indicate author’s initials (MH). |
2. |
Next 4 bytes are 46 4F 55 52 hex (the word FOUR) to indicate the type of protocol in use, namely Mr. Hansen’s 4-color compressed protocol. |
3. |
Next 2 bytes indicate height in pixels (stored little-endian). |
4. |
Next 2 bytes after that indicate width in pixels (stored little-endian). |
5. |
Next 3 bytes indicate the RGB color value to be represented by the 2-bit code 00. For example, if the color value is FF 00 FF (magenta), then each occurrence of 00 in the data will be interpreted as magenta. |
6. |
Next 3 bytes indicate the RGB color value associated with 01. |
7. |
Next 3 bytes indicate the RGB color value associated with 10. |
8. |
Next 3 bytes indicate the RGB color value associated with 11. |
9. |
Now that the header and color map are complete, the main data portion of the file can begin. Bitstream is to be interpreted as a group of 6-bit blocks, organized as follows: first 2 bits indicate the pixel color (00, 01, 10, or 11), and the next 4 bits indicate the repeat count. For example, consider the 12-bit sequence 9BC, which has 2 6-bit blocks, namely 100110 111100. The first group, 100110, indicates 2-bit color code “10” repeated 6 times, since 0110 is the binary representation of 6. The second group, 111100, indicates 2-bit color code “11” repeated 12 times, since 1100 is the binary representation of 12. |
10. |
Since data are in 6-bit blocks, it is possible that the last 6-bit block will not end on a byte boundary. If this occurs, the file will be padded with zeros to fill out the remaining byte evenly. |
11. |
The last byte of the file will be hex 1A (decimal 26) to indicate end of file. |
The protocol above allows us to use any 4 colors we wish.
However, for the Norwegian flag, we need the following color map:
00 = white (same as RGB value FF FF
FF hex)
01 = blue (same as RGB value 00 00
FF hex)
10 = red (same as RGB value FF 00 00
hex)
11 = black (same as RGB value 00 00
00 hex)
Here is how the Norwegian flag bitmap would be encoded in
hex as we implement the protocol above:
Step 1. 4D 48
Step 2. 46 4F 55 52
Step 3. 0C 00
Step 4. 24 00
Step 5. FF FF FF
Step 6. 00 00 FF
Step 7. FF 00 00
Step 8. 00 00 00
Step 9. *Note: Because each
block is 6 bits, it takes 2 blocks to make 12 bits, which can be translated
into 3 hex digits.
Action |
Binary |
Hex* (see note above) |
Byte count |
red repeated 5
times |
10 0101 |
|
22 from above |
white 1 |
00 0001 |
941 |
23.5 |
blue 2 |
01 0010 |
|
|
white 1 |
00 0001 |
481 |
25 |
red 14 |
10 1110 |
|
|
white 1 |
00 0001 |
B81 |
26.5 |
black 2 |
11 0010 |
|
|
white 2 |
00 0010 |
C82 |
28 |
black 1 |
11 0001 |
|
|
white 3 |
00 0011 |
C43 |
29.5 |
black 3 |
11 0011 |
|
|
white 1 |
00 0001 |
CC1 |
31 |
|
|
|
|
red 5 |
10 0101 |
|
|
white 1 |
00 0001 |
941 |
32.5 |
blue 2 |
01 0010 |
|
|
white 1 |
00 0001 |
481 |
34 |
red 14 |
10 1110 |
|
|
white 1 |
00 0001 |
B81 |
35.5 |
black 1 |
11 0001 |
|
|
white 1 |
00 0001 |
C41 |
37 |
black 1 |
11 0001 |
|
|
white 1 |
00 0001 |
C41 |
38.5 |
black 1 |
11 0001 |
|
|
white 2 |
00 0010 |
C42 |
40 |
black 1 |
11 0001 |
|
|
white 3 |
00 0011 |
C43 |
41.5 |
black 1 |
11 0001 |
|
|
|
|
|
|
red 5 |
10 0101 |
C65 |
43 |
white 1 |
00 0001 |
|
|
blue 2 |
01 0010 |
052 |
44.5 |
white 1 |
00 0001 |
|
|
red 14 |
10 1110 |
06E |
46 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
47.5 |
white 2 |
00 0010 |
|
|
black 2 |
11 0010 |
0B2 |
49 |
white 3 |
00 0011 |
|
|
black 3 |
11 0011 |
0F3 |
50.5 |
white 1 |
00 0001 |
|
|
|
|
|
|
red 5 |
10 0101 |
065 |
52 |
white 1 |
00 0001 |
|
|
blue 2 |
01 0010 |
052 |
53.5 |
white 1 |
00 0001 |
|
|
red 14 |
10 1110 |
06E |
55 |
white 15 |
00 1111 |
|
|
|
|
|
|
white 4 |
00 0100 |
3C4 |
56.5 |
blue 2 |
01 0010 |
|
|
white 15 |
00 1111 |
48F |
58 |
white 2 |
00 0010 |
|
|
black 4 |
11 0100 |
0B4 |
59.5 |
white 2 |
00 0010 |
|
|
black 1 |
11 0001 |
0B1 |
61 |
white 3 |
00 0011 |
|
|
black 1 |
11 0001 |
0F1 |
62.5 |
|
|
|
|
blue 15 |
01 1111 |
|
|
blue 8 |
01 1000 |
7D8 |
64 |
white 2 |
00 0010 |
|
|
black 1 |
11 0001 |
0B1 |
65.5 |
white 3 |
00 0011 |
|
|
black 1 |
11 0001 |
0F1 |
67 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
68.5 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
70 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
71.5 |
|
|
|
|
blue 15 |
01 1111 |
|
|
blue 8 |
01 1000 |
7D8 |
73 |
white 2 |
00 0010 |
|
|
black 4 |
11 0100 |
0B4 |
74.5 |
white 2 |
00 0010 |
|
|
black 1 |
11 0001 |
0B1 |
76 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
77.5 |
white 1 |
00 0001 |
|
|
black 1 |
11 0001 |
071 |
79 |
white 6 |
00 0110 |
|
|
|
|
|
|
blue 2 |
01 0010 |
192 |
80.5 |
white 15 |
00 1111 |
|
|
white 2 |
00 0010 |
3C2 |
82 |
black 1 |
11 0001 |
|
|
white 2 |
00 0010 |
C42 |
83.5 |
black 2 |
11 0010 |
|
|
white 2 |
00 0010 |
C82 |
85 |
black 1 |
11 0001 |
|
|
white 1 |
00 0001 |
C41 |
86.5 |
black 1 |
11 0001 |
|
|
white 1 |
00 0001 |
C41 |
88 |
|
|
|
|
red 5 |
10 0101 |
|
|
white 1 |
00 0001 |
541 |
89.5 |
blue 2 |
01 0010 |
|
|
white 1 |
00 0001 |
481 |
91 |
red 14 |
10 1110 |
|
|
white 4 |
00 0100 |
B84 |
92.5 |
black 1 |
11 0001 |
|
|
white 8 |
00 1000 |
C48 |
94 |
|
|
|
|
red 5 |
10 0101 |
|
|
white 1 |
00 0001 |
941 |
95.5 |
blue 2 |
01 0010 |
|
|
white 1 |
00 0001 |
481 |
97 |
red 14 |
10 1110 |
|
|
white 3 |
00 0011 |
B83 |
98.5 |
black 1 |
11 0001 |
|
|
white 1 |
00 0001 |
C41 |
100 |
black 1 |
11 0001 |
|
|
white 2 |
00 0010 |
C42 |
101.5 |
black 1 |
11 0001 |
|
|
white 3 |
00 0011 |
C43 |
103 |
black 1 |
11 0001 |
|
|
|
|
|
|
red 5 |
10 0101 |
C65 |
104.5 |
white 1 |
00 0001 |
|
|
blue 2 |
01 0010 |
052 |
106 |
white 1 |
00 0001 |
|
|
red 14 |
10 1110 |
06E |
107.5 |
white 2 |
00 0010 |
|
|
black 5 |
11 0101 |
0B5 |
109 |
white 2 |
00 0010 |
|
|
black 3 |
11 0011 |
0B3 |
110.5 |
white 1 |
00 0001 |
|
|
|
|
|
|
red 5 |
10 0101 |
065 |
112 |
white 1 |
00 0001 |
|
|
blue 2 |
01 0010 |
052 |
113.5 |
white 1 |
00 0001 |
|
|
red 14 |
10 1110 |
06E |
115 |
white 2 |
00 0010 |
|
|
black 1 |
11 0001 |
0B1 |
116.5 |
white 3 |
00 0011 |
|
|
black 1 |
11 0001 |
0F1 |
118 |
white 3 |
00 0011 |
|
|
black 1 |
11 0001 |
0F1 |
119.5 |
white 2 |
00 0010 |
0 hex (rounds out
the 120th byte), plus 2 leftover bits |
|
10. Append 6 zero bits (000000) to finish out the 121st byte: 1000 0000
= 80 hex
11. Last byte: 1A
Here is the entire file, in hex:
4D 48 46 4F 55 52
0C 00 24 00
FF FF FF
00 00 FF
FF 00 00
00 00 00
94 14 81 B8 1C 82 C4 3C C1 94
14 81 B8 1C 41 C4 1C 42 C4 3C
65 05 20 6E 07 10 B2 0F 30 65
05 20 6E 3C 44 8F 0B 40 B1 0F
17 D8 0B 10 F1 07 10 71 07 17
D8 0B 40 B1 07 10 71 19 23 C2
C4 2C 82 C4 1C 41 54 14 81 B8
4C 48 94 14 81 B8 3C 41 C4 2C
43 C6 50 52 06 E0 B5 0B 30 65
05 20 6E 0B 10 F1 0F 10 80 1A
Total file size = 122 bytes = 976 bits.
If the bitmap had been stored as a raw (uncompressed) 2-bit-per-pixel map, the
size required would have been 108 bytes (864 bits). Therefore, the run-length
encoding scheme here did not save any storage space—in fact, it wasted space.
However, this was largely because of the overhead consumed by the file header
and color map. The “guts” of the file were only 99 bytes, which represents a modest
savings.
With a cleverer compression protocol, it would be possible to save much more
space. For example, since the rows of the flag consist of only 3 different
patterns, the rows could be tokenized. The letters on the right side of the
flag are monochrome and hence could be efficiently encoded as an uncompressed
monochrome bitmap.