Last active
March 18, 2018 16:53
-
-
Save cls/394484a79fc5eca33eb2be21715269a3 to your computer and use it in GitHub Desktop.
Translate raw two-dimensional bitmap into word-aligned rows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <string.h> | |
void | |
row_align(uint8_t *dst, const uint8_t *src, const size_t width_in_bits, const size_t height) | |
{ | |
const size_t width_in_whole_bytes = width_in_bits / 8; | |
if (width_in_bits % 32 == 0) { // word-aligned | |
memcpy(dst, src, width_in_whole_bytes * height); | |
return; | |
} | |
const size_t width_in_partial_bytes = (width_in_bits + 7) / 8; | |
const size_t width_in_aligned_bytes = ((width_in_partial_bytes + 3) / 4) * 4; | |
const size_t overhang = width_in_bits % 8; | |
if (overhang == 0) { // byte-aligned | |
for (size_t row = 0; row < height; row++) { | |
memcpy(dst, src, width_in_whole_bytes); | |
src += width_in_whole_bytes; | |
dst += width_in_aligned_bytes; | |
} | |
return; | |
} | |
uint8_t leftover; | |
size_t bits = 0; | |
for (size_t row = 0; row < height; row++) { | |
if (bits == 0) { | |
memcpy(dst, src, width_in_partial_bytes); | |
leftover = src[width_in_whole_bytes] << overhang; | |
src += width_in_partial_bytes; | |
bits = 8; | |
} | |
else { | |
for (size_t i = 0; i < width_in_whole_bytes; i++) { | |
const uint8_t byte = src[i]; | |
dst[i] = leftover | (byte >> bits); | |
leftover = byte << (8 - bits); | |
} | |
src += width_in_whole_bytes; | |
if (bits < overhang) { | |
const uint8_t byte = *src++; | |
dst[width_in_whole_bytes] = leftover | (byte >> bits); | |
leftover = byte << (overhang - bits); | |
bits += 8; | |
} | |
else { | |
dst[width_in_whole_bytes] = leftover; | |
leftover <<= overhang; | |
} | |
} | |
bits -= overhang; | |
dst += width_in_aligned_bytes; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define MAX_WIDTH 64 | |
#define MAX_HEIGHT 64 | |
#define ALIGN(W) ((((W) + 31) / 32) * 32) | |
#define NELEM(X) (sizeof (X) / sizeof *(X)) | |
extern void row_align(uint8_t *, const uint8_t *, size_t, size_t); | |
static bool is_set(size_t, size_t, const uint8_t *, size_t); | |
int | |
main(void) | |
{ | |
uint8_t src[MAX_WIDTH * MAX_HEIGHT]; | |
uint8_t dst[ALIGN(MAX_WIDTH) * MAX_HEIGHT]; | |
int status = EXIT_SUCCESS; | |
for (size_t width = 1; width <= MAX_WIDTH; width++) { | |
for (size_t height = 1; height <= MAX_HEIGHT; height++) { | |
for (size_t i = 0; i < NELEM(src); i++) { | |
src[i] = rand(); | |
} | |
row_align(dst, src, width, height); | |
size_t errors = 0; | |
for (size_t y = 0; y < height; y++) { | |
for (size_t x = 0; x < width; x++) { | |
if (is_set(x, y, src, width) != is_set(x, y, dst, ALIGN(width))) { | |
errors++; | |
} | |
} | |
} | |
if (errors != 0) { | |
fprintf(stderr, "%zux%zu: %zu errors\n", width, height, errors); | |
status = EXIT_FAILURE; | |
} | |
} | |
} | |
return status; | |
} | |
bool | |
is_set(size_t x, size_t y, const uint8_t *data, size_t wrap) | |
{ | |
const size_t index = (y * wrap) + x; | |
const size_t byte = index / 8; | |
const size_t bit = index % 8; | |
return data[byte] & ((1 << 7) >> bit); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment