From 04ad40d69a276462cba0941e95717304a35ae4e0 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Tue, 17 May 2016 02:23:19 -0500 Subject: [PATCH] Massive, mind-blowing refactor --- bin/main.c | 15 +++- include/cammy/image.h | 40 ++++----- include/cammy/photo.h | 13 ++- include/cammy/tile.h | 4 + src/Makefile | 4 +- src/image.c | 201 ++++++++++++++++++++++++++++++++++++++++++ src/photo.c | 188 ++++----------------------------------- 7 files changed, 259 insertions(+), 206 deletions(-) create mode 100644 src/image.c diff --git a/bin/main.c b/bin/main.c index b08a080..8165d8d 100644 --- a/bin/main.c +++ b/bin/main.c @@ -5,8 +5,19 @@ #include #include "pnglite.h" +#include +#include #include +static cammy_tile_palette palette = { + .colors = { + { 0, 0, 0 }, + { 85, 85, 85 }, + { 171, 171, 171 }, + { 255, 255, 255 } + } +}; + static void usage(int argc, char **argv, const char *message, ...) { if (message) { va_list args; @@ -171,7 +182,7 @@ static int export(int argc, char **argv) { goto error_buf_malloc; } - cammy_photo_export(&sram->data->photos[photo-1], buf, 3); + cammy_photo_export(&sram->data->photos[photo-1], buf, 3, &palette); if ((error = png_set_data(png, CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_HEIGHT, 8, PNG_TRUECOLOR, buf)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", @@ -263,7 +274,7 @@ static int dither(int argc, char **argv) { goto error_png_get_data; } - cammy_photo_dither(bufout, bufin, in->width, in->height, in->bpp); + cammy_image_dither(bufout, bufin, in->width, in->height, in->bpp, &palette); if ((error = png_set_data(out, in->width, in->height, in->depth, in->color_type, bufout)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", diff --git a/include/cammy/image.h b/include/cammy/image.h index 190da69..6b04364 100644 --- a/include/cammy/image.h +++ b/include/cammy/image.h @@ -5,30 +5,24 @@ #include -typedef enum cammy_image_format { - CAMMY_IMAGE_UNKNOWN = 0, - CAMMY_IMAGE_2BPP_TILE = 1, - CAMMY_IMAGE_8BPP_GRAYSCALE = 2, - CAMMY_IMAGE_8BPP_RGB = 3, - CAMMY_IMAGE_8BPP_RGBA = 4 -}; +void cammy_image_dither(uint8_t *dest, + uint8_t *src, + size_t width, + size_t height, + int depth, + cammy_tile_palette *palette); -typedef struct _cammy_image { - cammy_image_format format; +void cammy_image_dither_to_tile(cammy_tile *dest, + uint8_t *src, + size_t width, + size_t height, + int depth); - size_t width, height; -} cammy_image; - -cammy_image *cammy_image_new(cammy_image_format format, - size_t width, - size_t height); - -void cammy_image_destroy(cammy_image *image); - -int cammy_image_copy(cammy_image *dest, - cammy_image *src, - size_t dest_x, size_t dest_y, - size_t src_x, size_t src_y, - size_t width, size_t height); +void cammy_image_copy_from_tile(uint8_t *dest, + cammy_tile *src, + size_t width, + size_t height, + int depth, + cammy_tile_palette *palette); #endif /* _CAMMY_IMAGE_H */ diff --git a/include/cammy/photo.h b/include/cammy/photo.h index d97d98c..79760ae 100644 --- a/include/cammy/photo.h +++ b/include/cammy/photo.h @@ -34,14 +34,11 @@ typedef struct _cammy_photo { #pragma pack(pop) -void cammy_photo_export(cammy_photo *src, uint8_t *dest, int stride); +void cammy_photo_export(cammy_photo *src, + uint8_t *dest, + int depth, + cammy_tile_palette *palette); -void cammy_photo_import(cammy_photo *dest, uint8_t *src, int stride); - -void cammy_photo_dither(uint8_t *dest, - uint8_t *src, - size_t width, - size_t height, - int stride); +void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth); #endif /* _CAMMY_PHOTO_H */ diff --git a/include/cammy/tile.h b/include/cammy/tile.h index 2bb1e70..453f1f7 100644 --- a/include/cammy/tile.h +++ b/include/cammy/tile.h @@ -14,6 +14,10 @@ typedef struct _cammy_tile { uint8_t data[CAMMY_TILE_SIZE]; } cammy_tile; +typedef struct _cammy_tile_palette { + uint8_t colors[4][3]; +} cammy_tile_palette; + #pragma pack(pop) #endif /* _CAMMY_TILE_H */ diff --git a/src/Makefile b/src/Makefile index 16824b9..2db9bdf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,8 +11,8 @@ HEADERS_LOCAL = HEADERS_BUILD = $(HEADERS_LOCAL) \ $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS)) -HEADERS = sram.h photo.h -OBJS = sram.o photo.o +HEADERS = sram.h image.h photo.h +OBJS = sram.o image.o photo.o VERSION_MAJOR = 0 VERSION_MINOR = 0.1 diff --git a/src/image.c b/src/image.c new file mode 100644 index 0000000..d829c6f --- /dev/null +++ b/src/image.c @@ -0,0 +1,201 @@ +#include +#include +#include + +#include + +static uint32_t bayer_matrix[256] = { + /* + * Black gamut + */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + + /* + * Black to dark gray gradient + */ + 0x00018000, 0x00018000, 0x00018000, 0x00018000, 0x00018000, + 0x00018020, 0x00018020, 0x00018020, 0x00018020, 0x00018020, + 0x000180a0, 0x000180a0, 0x000180a0, 0x000180a0, 0x000180a0, + 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, + 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, + 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, + 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, + 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, + 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, + 0x0001ada7, 0x0001ada7, 0x0001ada7, 0x0001ada7, 0x0001ada7, + 0x0001adaf, 0x0001adaf, 0x0001adaf, 0x0001adaf, 0x0001adaf, + 0x0001afaf, 0x0001afaf, 0x0001afaf, 0x0001afaf, 0x0001afaf, + 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, + 0x0001df7f, 0x0001df7f, 0x0001df7f, 0x0001df7f, 0x0001df7f, + 0x0001dfff, 0x0001dfff, 0x0001dfff, 0x0001dfff, 0x0001dfff, + 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, + + /* + * Dark gray to light gray gradient + */ + 0x01028000, 0x01028000, 0x01028000, 0x01028000, 0x01028000, 0x01028000, + 0x01028020, 0x01028020, 0x01028020, 0x01028020, 0x01028020, + 0x010280a0, 0x010280a0, 0x010280a0, 0x010280a0, 0x010280a0, + 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, + 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, + 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, + 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, + 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, + 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, + 0x0102ada7, 0x0102ada7, 0x0102ada7, 0x0102ada7, 0x0102ada7, + 0x0102adaf, 0x0102adaf, 0x0102adaf, 0x0102adaf, 0x0102adaf, + 0x0102afaf, 0x0102afaf, 0x0102afaf, 0x0102afaf, 0x0102afaf, + 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, + 0x0102df7f, 0x0102df7f, 0x0102df7f, 0x0102df7f, 0x0102df7f, + 0x0102dfff, 0x0102dfff, 0x0102dfff, 0x0102dfff, 0x0102dfff, + 0x0102ffff, 0x0102ffff, 0x0102ffff, 0x0102ffff, 0x0102ffff, + + /* Light gray to white gradient */ + 0x02038000, 0x02038000, 0x02038000, 0x02038000, 0x02038000, 0x02038000, + 0x02038020, 0x02038020, 0x02038020, 0x02038020, 0x02038020, + 0x020380a0, 0x020380a0, 0x020380a0, 0x020380a0, 0x020380a0, + 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, + 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, + 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, + 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, + 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, + 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, + 0x0203ada7, 0x0203ada7, 0x0203ada7, 0x0203ada7, 0x0203ada7, + 0x0203adaf, 0x0203adaf, 0x0203adaf, 0x0203adaf, 0x0203adaf, + 0x0203afaf, 0x0203afaf, 0x0203afaf, 0x0203afaf, 0x0203afaf, + 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, + 0x0203df7f, 0x0203df7f, 0x0203df7f, 0x0203df7f, 0x0203df7f, + 0x0203dfff, 0x0203dfff, 0x0203dfff, 0x0203dfff, 0x0203dfff, + 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, +}; + +static uint8_t rgb_to_grayscale(uint8_t r, uint8_t g, uint8_t b) { + return (uint8_t)((0.2126 * (float)r) + + (0.7152 * (float)g) + + (0.0722 * (float)b)); +} + +static uint8_t rgb_to_tile_2bpp(uint8_t r, uint8_t g, uint8_t b, size_t x, size_t y) { + uint8_t gray = rgb_to_grayscale(r, g, b); + + uint32_t slot = bayer_matrix[gray]; + uint8_t from = (slot & 0x03000000) >> 24; + uint8_t to = (slot & 0x00030000) >> 16; + + return (slot & (0x8000 >> ((y & 3) << 2) >> (x & 3)))? to: from; +} + +static inline uint8_t tile_read(cammy_tile *tiles, + size_t x, + size_t y, + int stride) { + size_t index = ((y >> 3) * (stride >> 3)) + (x >> 3); + + cammy_tile *tile = &tiles[index]; + + int tile_x = x & 7, + tile_y = y & 7; + + return + ((tile->data[ tile_y<<1] & (0x80 >> tile_x)) >> (tile_x ^ 7) + | ((tile->data[(tile_y<<1)|1] & (0x80 >> tile_x)) >> (tile_x ^ 7) << 1)) + ^ 3; +} + +static inline void tile_write(cammy_tile *tiles, + size_t x, + size_t y, + int stride, + uint8_t value) { + size_t index = ((y >> 3) * (stride >> 3)) + (x >> 3); + + cammy_tile *tile = &tiles[index]; + + int tile_x = x & 7, + tile_y = y & 7; + + tile->data[ tile_y<<1] |= (value & 0x01) << (tile_x ^ 7); + tile->data[(tile_y<<1)|1] |= ((value & 0x02) >> 1) << (tile_x ^ 7); +} + +static inline void buf_read(uint8_t *buf, + size_t x, size_t y, size_t stride, + uint8_t *r, uint8_t *g, uint8_t *b, + int depth) { + *r = buf[depth*stride*y + depth*x], + *g = buf[depth*stride*y + depth*x + 1], + *b = buf[depth*stride*y + depth*x + 2]; +} + +static inline void buf_write(uint8_t *buf, + size_t x, size_t y, size_t stride, + uint8_t r, uint8_t g, uint8_t b, + int depth) { + buf[depth*stride*y + depth*x] = r; + buf[depth*stride*y + depth*x + 1] = g; + buf[depth*stride*y + depth*x + 2] = b; +} + +void cammy_image_dither(uint8_t *dest, + uint8_t *src, + size_t width, + size_t height, + int depth, + cammy_tile_palette *palette) { + size_t x, y; + + for (y=0; ycolors[value][0]; + g = palette->colors[value][1]; + b = palette->colors[value][2]; + + buf_write(dest, x, y, width, r, g, b, depth); + } + } +} + +void cammy_image_copy_from_tile(uint8_t *dest, + cammy_tile *src, + size_t width, + size_t height, + int depth, + cammy_tile_palette *palette) { + size_t x, y; + + for (y=0; ycolors[value][0], + palette->colors[value][1], + palette->colors[value][2], depth); + } + } +} + +void cammy_image_dither_to_tile(cammy_tile *dest, + uint8_t *src, + size_t width, + size_t height, + int depth) { + size_t x, y; + + memset(dest, '\x00', CAMMY_TILE_SIZE * (width >> 3) * (height >> 3)); + + for (y=0; y #include +#include #include -static uint32_t bayer_matrix[256] = { - /* - * Black gamut - */ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - - /* - * Black to dark gray gradient - */ - 0x00018000, 0x00018000, 0x00018000, 0x00018000, 0x00018000, - 0x00018020, 0x00018020, 0x00018020, 0x00018020, 0x00018020, - 0x000180a0, 0x000180a0, 0x000180a0, 0x000180a0, 0x000180a0, - 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, 0x0001a0a0, - 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, 0x0001a4a0, - 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, 0x0001a4a1, - 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, 0x0001a4a5, - 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, 0x0001a5a5, - 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, 0x0001ada5, - 0x0001ada7, 0x0001ada7, 0x0001ada7, 0x0001ada7, 0x0001ada7, - 0x0001adaf, 0x0001adaf, 0x0001adaf, 0x0001adaf, 0x0001adaf, - 0x0001afaf, 0x0001afaf, 0x0001afaf, 0x0001afaf, 0x0001afaf, - 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, 0x0001df5f, - 0x0001df7f, 0x0001df7f, 0x0001df7f, 0x0001df7f, 0x0001df7f, - 0x0001dfff, 0x0001dfff, 0x0001dfff, 0x0001dfff, 0x0001dfff, - 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, - - /* - * Dark gray to light gray gradient - */ - 0x01028000, 0x01028000, 0x01028000, 0x01028000, 0x01028000, 0x01028000, - 0x01028020, 0x01028020, 0x01028020, 0x01028020, 0x01028020, - 0x010280a0, 0x010280a0, 0x010280a0, 0x010280a0, 0x010280a0, - 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, 0x0102a0a0, - 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, 0x0102a4a0, - 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, 0x0102a4a1, - 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, 0x0102a4a5, - 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, 0x0102a5a5, - 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, 0x0102ada5, - 0x0102ada7, 0x0102ada7, 0x0102ada7, 0x0102ada7, 0x0102ada7, - 0x0102adaf, 0x0102adaf, 0x0102adaf, 0x0102adaf, 0x0102adaf, - 0x0102afaf, 0x0102afaf, 0x0102afaf, 0x0102afaf, 0x0102afaf, - 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, 0x0102df5f, - 0x0102df7f, 0x0102df7f, 0x0102df7f, 0x0102df7f, 0x0102df7f, - 0x0102dfff, 0x0102dfff, 0x0102dfff, 0x0102dfff, 0x0102dfff, - 0x0102ffff, 0x0102ffff, 0x0102ffff, 0x0102ffff, 0x0102ffff, - - /* Light gray to white gradient */ - 0x02038000, 0x02038000, 0x02038000, 0x02038000, 0x02038000, 0x02038000, - 0x02038020, 0x02038020, 0x02038020, 0x02038020, 0x02038020, - 0x020380a0, 0x020380a0, 0x020380a0, 0x020380a0, 0x020380a0, - 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, 0x0203a0a0, - 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, 0x0203a4a0, - 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, 0x0203a4a1, - 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, 0x0203a4a5, - 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, 0x0203a5a5, - 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, 0x0203ada5, - 0x0203ada7, 0x0203ada7, 0x0203ada7, 0x0203ada7, 0x0203ada7, - 0x0203adaf, 0x0203adaf, 0x0203adaf, 0x0203adaf, 0x0203adaf, - 0x0203afaf, 0x0203afaf, 0x0203afaf, 0x0203afaf, 0x0203afaf, - 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, 0x0203df5f, - 0x0203df7f, 0x0203df7f, 0x0203df7f, 0x0203df7f, 0x0203df7f, - 0x0203dfff, 0x0203dfff, 0x0203dfff, 0x0203dfff, 0x0203dfff, - 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, -}; - -static uint8_t tile_2bpp_palette[4] = { - 0, 86, 171, 255 -}; - -static uint8_t rgb_to_grayscale(uint8_t r, uint8_t g, uint8_t b) { - return (uint8_t)((0.2126 * (float)r) - + (0.7152 * (float)g) - + (0.0722 * (float)b)); +void cammy_photo_export(cammy_photo *src, + uint8_t *dest, + int depth, + cammy_tile_palette *palette) { + cammy_image_copy_from_tile(dest, + (cammy_tile *)&src->tiles, + CAMMY_PHOTO_WIDTH, + CAMMY_PHOTO_HEIGHT, + depth, + palette); } -static uint8_t rgb_to_tile_2bpp(uint8_t r, uint8_t g, uint8_t b, size_t x, size_t y) { - uint8_t gray = rgb_to_grayscale(r, g, b); - - uint32_t slot = bayer_matrix[gray]; - uint8_t from = (slot & 0x03000000) >> 24; - uint8_t to = (slot & 0x00030000) >> 16; - - return (slot & (0x8000 >> ((y & 3) << 2) >> (x & 3)))? to: from; -} - -static inline uint8_t tile_read(cammy_photo *photo, size_t x, size_t y) { - cammy_tile *tile = &photo->tiles[y>>3][x>>3]; - - int tile_x = x & 7, - tile_y = y & 7; - - return - ((tile->data[ tile_y<<1] & (0x80 >> tile_x)) >> (tile_x ^ 7) - | ((tile->data[(tile_y<<1)|1] & (0x80 >> tile_x)) >> (tile_x ^ 7) << 1)) - ^ 3; -} - -static inline void tile_write(cammy_photo *photo, - size_t x, size_t y, uint8_t value) { - cammy_tile *tile = &photo->tiles[y>>3][x>>3]; - - int tile_x = x & 7, - tile_y = y & 7; - - tile->data[ tile_y<<1] |= (value & 0x01) << (tile_x ^ 7); - tile->data[(tile_y<<1)|1] |= ((value & 0x02) >> 1) << (tile_x ^ 7); -} - -static inline void buf_read(uint8_t *buf, - size_t x, size_t y, size_t width, - uint8_t *r, uint8_t *g, uint8_t *b, - int stride) { - *r = buf[stride*width*y + stride*x], - *g = buf[stride*width*y + stride*x + 1], - *b = buf[stride*width*y + stride*x + 2]; -} - -static inline void buf_write(uint8_t *buf, - size_t x, size_t y, size_t width, - uint8_t r, uint8_t g, uint8_t b, - int stride) { - buf[stride*width*y + stride*x] = r; - buf[stride*width*y + stride*x + 1] = g; - buf[stride*width*y + stride*x + 2] = b; -} - -void cammy_photo_export(cammy_photo *src, uint8_t *dest, int stride) { - size_t x, y; - - for (y=0; ytiles, '\x00', sizeof(dest->tiles)); - memset(&dest->thumb, '\xff', sizeof(dest->thumb)); - - for (y=0; ytiles, + src, + CAMMY_PHOTO_WIDTH, + CAMMY_PHOTO_HEIGHT, + depth); }