Bitmap
Bitmap is the low-level pixel container used throughout the library whenever a
boolean mask needs to be rendered, copied, or transformed.
A bitmap stores only on/off pixels. The actual terminal representation is
chosen later by Buffer::drawBitmap()
together with BitmapDrawOptions.
You will mostly encounter this class indirectly during glyph rendering and other pixel-based operations. That said, it is also a great tool when you want to build your own rendering helpers—such as icons, line maps, or small procedural effects.
Usage
Preparing a Small Pixel Mask
A Bitmap represents a two-dimensional grid of pixels. You can set or query each
pixel individually and copy regions between bitmaps.
This makes it straightforward to construct reusable masks or generate small procedural patterns.
auto bitmap = Bitmap{Size{8, 8}};
bitmap.setPixel({1, 1}, true);
bitmap.setPixel({2, 2}, true);
bitmap.setPixel({3, 3}, true);
auto copy = Bitmap{Size{8, 8}};
copy.draw(Position{2, 1}, bitmap);
if (copy.pixelQuad({1, 1}) != 0) {
// Use the encoded 2x2 mask for custom rendering.
}
Use draw() to copy one bitmap into another at a given position.
The pixelQuad() function reads a 2×2 group of pixels and encodes
them as a small integer. This is especially useful when translating bitmap
data into terminal cell representations (for example, when working with
half-block characters).
Building Bitmaps from Text Patterns
For small icons or handcrafted masks, Bitmap::fromPattern()
is usually the fastest and most readable way to define pixels.
Each input string represents one row. Dots and spaces are treated as cleared pixels, while every other character sets a pixel.
const auto rocket = Bitmap::fromPattern({
".....#.....",
"....###....",
"...#####...",
"....###....",
"...#####...",
"..#######..",
"...#####...",
"..#######..",
".#########.",
".....#.....",
".....#.....",
});
Rows may have different lengths. fromPattern() automatically uses
the longest row as the bitmap width and pads shorter rows with cleared
pixels on the right.
Rendering a Bitmap to a Buffer
Once your bitmap is prepared, you can render it using
Buffer::drawBitmap().
The BitmapDrawOptions control how pixels are translated into terminal
cells—this includes scaling, block characters, colors, and optional
neighbor-aware line styles.
auto bitmap = Bitmap{Size{8, 8}};
bitmap.setPixel({1, 1}, true);
bitmap.setPixel({2, 2}, true);
bitmap.setPixel({3, 3}, true);
bitmap.setPixel({4, 4}, true);
auto options = BitmapDrawOptions{};
options.setColorSequence(
ColorSequence{
Color{fg::BrightBlue, bg::Black},
Color{fg::BrightCyan, bg::Black},
Color{fg::BrightMagenta, bg::Black},
},
BitmapColorMode::ForwardDiagonalStripes);
buffer.drawBitmap(bitmap, Rectangle{2, 2, 20, 8}, Alignment::Center, options, animationCycle);
When using the rectangle overload, the rendered bitmap is aligned inside the target rectangle. If it exceeds the available space, it is cropped according to the selected alignment.
Choosing the Scale Mode
BitmapScaleMode determines how bitmap pixels are mapped to terminal cells:
HalfBlockGroups pixels into 2×2 blocks per character. This is the default mode and allows even empty cells to be colored, because the zero entry inhalfBlocks()is rendered.FullBlockUses one character per set bitmap pixel.DoubleBlockAlso uses one character per set pixel, but doubles the width in terminal cells to better match typical terminal aspect ratios.
If you enable char16Style(),
it overrides the scale mode entirely. In this mode, each set pixel becomes
one terminal cell, and the selected Char16Style
determines the character based on the pixel’s east, south, west, and north
neighbors.
This is particularly useful for rendering circuit diagrams, line art, or bitmap-derived frame structures.
Color and Animation Rules
The base color is defined by BitmapDrawOptions::color().
If you provide a color sequence, it is applied depending on the selected
BitmapColorMode. Stripe modes
derive their color from the rendered bitmap coordinates, combined with
animationCycle and
colorAnimationOffset().
If the sequence is empty, the bitmap inherits the color from the underlying buffer.
After selecting the base color, the color defined in
fullBlock(),
doubleBlocks(),
halfBlocks(),
or the chosen Char16Style is applied on top.
To explore all combinations interactively, run the bitmap-showcase demo.
Interface
-
class Bitmap
A mutable bitmap storing boolean pixels in row-major order.
Subclassed by erbsland::cterm::FontGlyph
Public Functions
-
Bitmap() = default
Create an empty bitmap with the size
(0,0).
-
inline explicit Bitmap(const Size size)
Create a bitmap with the given size and all pixels cleared.
- Parameters:
size – The bitmap dimensions.
-
inline const std::vector<bool> &data() const noexcept
Access the raw pixel storage.
-
inline std::vector<bool> &data() noexcept
Access the raw pixel storage for modification.
-
bool pixel(Position pos) const noexcept
Read one pixel.
- Parameters:
pos – The pixel position.
- Returns:
The pixel state, or
falseifposis outside the bitmap.
-
uint8_t pixelQuad(Position pos) const noexcept
Read a 2x2 pixel block encoded as four bits.
- Parameters:
pos – The quad position in half-resolution coordinates.
- Returns:
Bit mask with top-left/top-right/bottom-left/bottom-right pixels in bits
0..3.
-
uint8_t pixelCardinal(Position pos) const noexcept
Read the four cardinal pixels as a bit-mask.
Clockwise bit-order: right, down, left, up
- Parameters:
pos – The center pixel position.
- Returns:
The bit mask, where bits
0..3represent the pixels in clockwise order starting from the right.
-
uint8_t pixelRing(Position pos) const noexcept
Read the ring of eight pixels surrounding the given position as a bitmask.
Clockwise bit-order: 0:E, 1:SE, 2:S, 3:SW, 4:W, 5:NW, 6:N, 7:NE
- Parameters:
pos – The center pixel position.
- Returns:
The bit mask, where bits
0..7represent the pixels in clockwise order starting from the right.
-
Rectangle boundingRect(bool value = true) const noexcept
Get a rectangle around all set/cleared pixels.
- Parameters:
value – If true, return the bounding box of set pixels, otherwise cleared pixels.
- Returns:
The bounding rectangle of the specified pixels or an empty rectangle if none are set/cleared.
-
std::size_t pixelCount(bool value = true) const noexcept
Get the number of set/cleared pixels in this bitmap.
- Parameters:
value – The pixel type to count.
-
void setPixel(Position pos, bool value) noexcept
Set one pixel in the bitmap.
Note
Positions outside the bitmap are ignored.
- Parameters:
pos – The pixel position.
value – The new pixel state.
-
void flipHorizontal() noexcept
Mirror the bitmap horizontally in-place.
-
void invert() noexcept
Invert the bitmap in-place.
-
Bitmap inverted() const noexcept
Get an inverted version of this bitmap.
- Returns:
The inverted bitmap.
-
Bitmap outlined() const noexcept
Convert this bitmap to an outlined version.
The bitmap needs to have a margin large enough for the outline. Algorithm: If at a cleared source pixel is surrounded by at least one set pixel, the target pixel is set.
-
Bitmap expanded(Margins margins, bool value) const noexcept
Create a new bitmap expanded with a given margin.
Negative margins cut sections from the bitmap.
- Parameters:
margins – The margins for the expansion.
value – The value to fill the expanded area with.
- Returns:
The expanded/shrunk bitmap. If the new width or height is zero, an empty bitmap is returned.
-
template<typename T>
void draw(Position position, const std::vector<T> &data) noexcept Draw pixels from a numeric bit mask.
- Template Parameters:
T – The unsigned integer type.
- Parameters:
position – The top left corner where to draw the bit mask.
data – The array with the data.
-
inline void draw(const Position position, const Bitmap &bitmap) noexcept
Draw another bitmap to the given position.
- Parameters:
position – The top left corner of the bitmap to draw.
bitmap – The bitmap to draw.
-
void fillRect(Rectangle rect, bool value) noexcept
Fill a rectangle with a given pixel state.
Positions outside this bitmap are ignored.
- Parameters:
rect – The rectangle to fill.
value – The new pixel state.
-
void floodFill(Position pos, bool value) noexcept
Perform a flood fill from the given position.
If the pixel at the given position is already set to the given value, nothing happens. If the start position is outside the bitmap, nothing happens.
- Parameters:
pos – The start position.
value – The new pixel state.
Public Static Functions
-
template<typename Fn>
static inline Bitmap fromFunction(const Size size, Fn fn) noexcept Build a new bitmap using a function.
- Parameters:
size – The size of the new bitmap.
fn – The function to use for building the bitmap. Takes a position and returns a boolean.
- Returns:
The new bitmap.
-
static Bitmap fromPattern(std::initializer_list<std::string_view> rows)
Create a bitmap from an ASCII pattern.
Each input string becomes one row. Dots (
.) and spaces create cleared pixels, every other character sets a pixel. Shorter rows are padded with cleared pixels to the maximum row width.- Parameters:
rows – The pattern rows to parse.
- Returns:
The created bitmap.
-
Bitmap() = default
-
class BitmapDrawOptions
The options to draw a bitmap.
These options define how
Buffer::drawBitmap()converts bitmap pixels into terminal cells. For color animation and stripe modes, the color position is calculated in the rendered bitmap grid:FullBlock,DoubleBlock, andChar16Styleuse one logical position per bitmap pixel, whileHalfBlockuses one logical position per 2x2 pixel cell. The rectangle overload ofdrawBitmap()aligns this rendered grid inside the target rectangle and crops it if needed.Note
Creating custom option instances is expensive. For that reason, create them once and keep the instances for multiple
drawBitmapcalls.Public Functions
-
BitmapDrawOptions() = default
Create default bitmap draw options.
-
template<typename tColor>
inline explicit BitmapDrawOptions(tColor color) Create options for one fixed color.
- Parameters:
color – The base color for the bitmap.
-
BitmapDrawOptions(ColorSequence colorSequence, BitmapColorMode colorMode = BitmapColorMode::OneColor)
Create options from a color sequence.
- Parameters:
colorSequence – The base colors for the bitmap.
colorMode – The mode used to pick colors from the sequence.
-
const ColorSequence &color() const noexcept
The color to use for drawing the bitmap.
The color can be either a single color or a sequence of colors. If this is an empty sequence, the color is inherited from the buffer. Colors are applied using the
colorMode(). If the characters infullBlock(),doubleBlocks()orhalfBlocks()have colors set, these colors are overlaid after calculating this base color.Note
For full-block and double-block mode, the background color is only applied to set pixels. Fill the bitmap area if you need a custom background color for unset pixels.
-
void setColor(Color color) noexcept
Set a single color.
Replaces the current color sequence with one entry.
-
void setColor(Foreground foreground, Background background) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void setColor(Foreground foreground) noexcept
Set only a foreground color.
The background remains inherited from the buffer below.
-
void setColor(Foreground::Hue foreground) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void setColor(Background background) noexcept
Set only a background color.
The foreground remains inherited from the buffer below.
-
void setColor(Background::Hue background) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void setColorSequence(ColorSequence colorSequence, BitmapColorMode colorMode = BitmapColorMode::OneColor) noexcept
Set a color sequence.
Pass an empty
ColorSequence{}to inherit the complete color from the buffer below.
-
BitmapColorMode colorMode() const noexcept
The color mode.
This mode controls how colors are applied to the bitmap. See
BitmapColorModefor more information.
-
void setColorMode(BitmapColorMode colorMode) noexcept
Set the color mode.
-
std::size_t colorAnimationOffset() const noexcept
The offset for color animations.
This offset is added to the
animationCyclepassed todrawBitmap. AnimateanimationCycleand keep this offset static.
-
void setColorAnimationOffset(std::size_t offset) noexcept
Set the offset for color animations.
-
const Char16StylePtr &char16Style() const noexcept
The Char16Style instance.
If a Char16Style instance is set, it overrides the scale mode and renders one terminal cell for each set bitmap pixel. The selected block depends on the four direct neighbors of the set pixel: east=bit 0, south=bit 1, west=bit 2, north=bit 3.
-
void setChar16Style(Char16StylePtr char16Style) noexcept
Set a Char16Style instance.
-
const CharCombinationStylePtr &combinationStyle() const noexcept
The combination style.
If a combination style is set, every block that is set in the buffer is first passed to this combination style. This happens for every mode used to draw the bitmap.
-
void setCombinationStyle(CharCombinationStylePtr combinationStyle) noexcept
Set the combination style.
-
const Char &fullBlock() const noexcept
The full block.
The full block is only used when the scale mode
FullBlockis used and noChar16Styleis set. Character colors are overlaid on the color from the color mode.
-
void setFullBlock(Char fullBlock)
Set the full block.
The full block must have a display width of 1.
-
const String &doubleBlocks() const noexcept
The double blocks.
The double blocks are only used when the scale mode
DoubleBlockis used and noChar16Styleis set. Character index 0 is used for the left half and index 1 for the right half of each set bitmap pixel. Character colors are overlaid on the color from the color mode.
-
void setDoubleBlocks(String doubleBlocks)
Set the double block String.
The string must have exactly two characters.
-
const String &halfBlocks() const noexcept
The string with the half-blocks.
The half-blocks are only used when the scale mode
HalfBlockis used and noChar16Styleis set. Entry0is used for an empty 2x2 block and entry15for a full 2x2 block. Character colors are overlaid on the color from the color mode.
-
void setHalfBlocks(String halfBlocks)
Set the half-blocks string.
The half-blocks string must have exactly 16 characters.
-
BitmapScaleMode scaleMode() const noexcept
The scale mode.
See
BitmapScaleModefor more details.
-
void setScaleMode(BitmapScaleMode scaleMode) noexcept
Set the scale mode.
Public Static Functions
-
static const BitmapDrawOptions &defaultOptions() noexcept
Access the shared object with the default options.
Default options use default terminal colors, half-block rendering, and the standard Unicode half-block characters.
-
BitmapDrawOptions() = default
-
enum class erbsland::cterm::BitmapColorMode : uint8_t
The mode how color is applied to the bitmap.
Values:
-
enumerator OneColor
Uses one color from the sequence for the whole bitmap.
The selected sequence entry is
animationCycle + colorAnimationOffset.
-
enumerator VerticalStripes
Uses the color sequence in vertical stripes.
The selected sequence entry is
x + animationCycle + colorAnimationOffset.
-
enumerator HorizontalStripes
Uses the color sequence in horizontal stripes.
The selected sequence entry is
y + animationCycle + colorAnimationOffset.
-
enumerator ForwardDiagonalStripes
Uses the color sequence in forward diagonal stripes.
The selected sequence entry is
x + y + animationCycle + colorAnimationOffset.
-
enumerator BackwardDiagonalStripes
Uses the color sequence in backward diagonal stripes.
The selected sequence entry is
-x + y + animationCycle + colorAnimationOffset.
-
enumerator OneColor
-
enum class erbsland::cterm::BitmapScaleMode : uint8_t
The mode how the bitmap is scaled.
Values:
-
enumerator HalfBlock
Draw the bitmap with half-blocks.
This mode uses the 16 characters from
halfBlocks(). Each 2x2 pixel block creates a 4-bit index in this order: bit 0 = top-left, bit 1 = top-right, bit 2 = bottom-left, bit 3 = bottom-right. This renders the bitmap at half width and half height, rounded up. Character colors are overlaid on the color from the color mode.
-
enumerator FullBlock
Draw the bitmap with full-blocks.
This mode uses
fullBlock()to draw each set pixel of the bitmap. Character colors are overlaid on the color from the color mode. To color the unset pixels, you must fill the bitmap area first.
-
enumerator DoubleBlock
Draw the bitmap with double-blocks.
This mode uses
doubleBlocks()to draw each set pixel of the bitmap. The bitmap is twice as large in the X axis, to compensate for the rectangular shape of terminal characters. Character colors are overlaid on the color from the color mode. To color the unset pixels, you must fill the bitmap area first.
-
enumerator HalfBlock