99 lines
4.1 KiB
C
99 lines
4.1 KiB
C
/*#############################################################################
|
|
## Author: Shaun Reed ##
|
|
## Legal: All Content (c) 2025 Shaun Reed, all rights reserved ##
|
|
## ##
|
|
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com ##
|
|
##############################################################################
|
|
*/
|
|
|
|
/**
|
|
* Calculate byte offset for the pixel at [x,y] within a horizontally-mapped
|
|
* monochrome uint8 draw buffer, using the initialized horizontal resolution.
|
|
*
|
|
* We use `>> 3` because each pixel requires 1 bit, but each uint8 in the draw
|
|
* buffer can hold 8 bits. To find the uint8 value in our draw buffer that
|
|
* stores this pixel's value we must compensate for this when using pixel
|
|
* coordinates in byte math.
|
|
*
|
|
* Therefore, each uint8 in the draw buffer stores the state of 8 pixels.
|
|
* Below is an example of calculating for [x, y] pixel coordinates [20, 10].
|
|
* The example uses a horizontal resolution of 128.
|
|
*
|
|
* For the horizontal case, each row (y) of the image is represented by
|
|
* `hor_res >> 3` bytes (16). The byte-offset of the first pixel in the 10th
|
|
* row for example is `16 * 10` = 160.
|
|
*
|
|
* Since the pixels are stored horizontally we must calculate the 20th pixel
|
|
* column (x) as `160 + (20 >> 3)`, or `160 + (20 / 8)` to get a final offset
|
|
* of 162.
|
|
*
|
|
* @param x X pixel coordinate to find byte offset.
|
|
* @param y Y pixel coordinate to find byte offset.
|
|
* @param hor_res horizontal resolution of the display.
|
|
* @return byte offset for a single-byte monochrome pixel at [x,y].
|
|
*/
|
|
static ptrdiff_t horizontal_byte_offset_long(const int32_t x, const int32_t y,
|
|
const int32_t hor_res)
|
|
{
|
|
// Convert pixel (bit) coordinates to byte coordinates in the draw buffer.
|
|
return (hor_res >> 3) * y + (x >> 3);
|
|
}
|
|
|
|
/**
|
|
* Calculate byte offset for the pixel at [x,y] within a vertically-mapped
|
|
* monochrome uint8 draw buffer, using the initialized horizontal resolution.
|
|
*
|
|
* We use `>> 3` because each pixel requires 1 bit, but each uint8 in the draw
|
|
* buffer can hold 8 bits. To find the uint8 value in our draw buffer that
|
|
* stores this pixel's value we must compensate for this when using pixel
|
|
* coordinates in byte math.
|
|
*
|
|
* Therefore, each uint8 in the draw buffer stores the state of 8 pixels.
|
|
* Below is an example of calculating for [x, y] pixel coordinates [20, 10].
|
|
* The example uses a horizontal resolution of 128.
|
|
*
|
|
* For the vertical case, each row (y) of the image is represented by
|
|
* `hor_res` bytes (128) - one for each column (x). Because the pixels are
|
|
* stored vertically, the byte-offset of the first pixel in the 10th row is
|
|
* `128 * (10 >> 3)` or * `128 * (10 / 8)` = 128.
|
|
*
|
|
* From this location we can simply calculate the 20th pixel column (x) as
|
|
* `128 + 20` to get a final offset of 148, because the pixels are stored in a
|
|
* columnar format.
|
|
*
|
|
* @param x X pixel coordinate to find byte offset.
|
|
* @param y Y pixel coordinate to find byte offset.
|
|
* @param hor_res horizontal resolution of the display.
|
|
* @return byte offset for a single-byte monochrome pixel at [x,y].
|
|
*/
|
|
static ptrdiff_t vertical_byte_offset_long(const int32_t x, const int32_t y,
|
|
const int32_t hor_res)
|
|
{
|
|
// Convert pixel (bit) coordinates to byte coordinates in the draw buffer.
|
|
return hor_res * (y >> 3) + x;
|
|
}
|
|
|
|
/**
|
|
* Finds the Most Significant Bit location of bit `i` in a byte.
|
|
*
|
|
* MSB LSB
|
|
* bits 7 6 5 4 3 2 1 0
|
|
* data 8 7 6 5 4 3 2 1
|
|
* Left Right
|
|
*
|
|
* @return bitmask for MSB location of `i`.
|
|
*/
|
|
static uint8_t msb_mask(const int32_t i) { return 1 << (7 - i % 8); }
|
|
|
|
/**
|
|
* Finds the Least Significant Bit location of bit `i` in a byte.
|
|
*
|
|
* LSB MSB
|
|
* bits 0 1 2 3 4 5 6 7
|
|
* data 1 2 3 4 5 6 7 8
|
|
* Left Right
|
|
*
|
|
* @return bitmask for LSB location of `i`.
|
|
*/
|
|
static uint8_t lsb_mask(const int32_t i) { return 1 << (i % 8); }
|