There are two main ways to store two-dimensional images in computers.
One is to explicitly store the different pixels that compose the image. In these bitmaps, the pixels are arranged sequentially and implicitly organized into lines. A header typically provides information to determine how many pixels fit in each line:
<--- line_width ---> | pixel | pixel | … | pixel | pixel | … | … | line 1 | line 2 |
Several properties have to be encoded for each pixel, depending on the sophistication of the image: for monochrome images each pixel can be just either switched on or off, so a single bit could be used to encode each pixel (this is the origin of the term “bitmap”). When color is added, a bit is no longer sufficient: the color of the pixel shall be encoded in some way, typically using a color schema such as RGB, that requires triplet of little integers to be encoded. If transparency is to be supported, the degree of transparency of the pixel shall also be encoded somehow.
The other way to store an image is to store a functional description of the “painted” parts of the image. This functional description usually contains instructions like “paint a line of thickness 1 and color red from the coordinate 10,20 to coordinate 10,40”. Once executed with certain parameters (like the desired resolution) the functional description generates a bitmap. Image formats using this approach are commonly known as vectorial formats.
When it comes to bitmaps, there are a plethora of different formats out there (bmp, jpg, png) competing in terms of capabilities such as higher color depths, better resolution, support for transparency (alpha channels), higher compression level, and the like. These capabilities greatly complicate these formats, but ultimately any bitmap can be reduced to a sequence of pixels, which can be further structured in terms of lines.
We don’t know enough poke yet to handle the complications of these real-life bitmap formats, so in subsequent sections we introduce a very simple format for bitmaps, the Stupid BitMap format, or simply SBM, that we will use for learning purposes.
But please do not feel disappointed: later in this book, when we become more proficient pokers, we will be messing with these shiny complex formats as well :)
A SBM file starts with a header that contains a “magic number” composed of the three bytes ’S’ (0x53UB), ’B’ (0x42UB) and ’M’ (0x4dUB). The next two bytes indicate the number of pixels per line, and the number of lines, respectively. In summary:
SBM header +-------+-------+-------+-------+-------+ | 'S' | 'B' | 'M' | ppl | lines | +-------+-------+-------+-------+-------+ byte0 byte1 byte2 byte3 byte4
Here ppl
stands for pixels-per-line. The encoding of these
fields implies that the bigger image that can be encoded in SBM has
dimensions 255x255.
Albeit stupid, SBM is a colorful format. It supports more than a million colors, encoding each color in what is known as RGB24. In RGB24, each color is encoded using three little integers, specifying the amount of red, green and blue that, added together, compose the color.
The name RGB24 comes from the fact that each color is encoded using three bytes, or 24 bits. Therefore, each pixel in a SBM image is encoded using three consecutive bytes:
SBM pixel +-------+-------+-------+ | Red | Green | Blue | +-------+-------+-------+ byte0 byte1 byte2
Each byte in this encoding determines the amount of the base color (red, green or blue) that compose the color. We will talk more about these components later.