I am host to a vast array of brain parasites

This commit is contained in:
XANTRONIX Development 2021-12-03 18:16:38 -05:00
parent a52bc53ee6
commit aab5ce27a4
7 changed files with 152 additions and 119 deletions

View file

@ -64,6 +64,7 @@ int cammy_export(int argc, char **argv) {
} }
if ((image = cammy_photo_export(&sram->data->photos[photo], if ((image = cammy_photo_export(&sram->data->photos[photo],
CAMMY_IMAGE_BITMAP,
CAMMY_IMAGE_24BPP_RGB, CAMMY_IMAGE_24BPP_RGB,
palette)) == NULL) { palette)) == NULL) {
goto error_photo_export; goto error_photo_export;

View file

@ -10,22 +10,28 @@
#define CAMMY_IMAGE_CHUNK_SIZE 4096 #define CAMMY_IMAGE_CHUNK_SIZE 4096
#define CAMMY_IMAGE_MAGIC_TILE "TILE"
#define CAMMY_IMAGE_MAGIC_PNG "\x89PNG" #define CAMMY_IMAGE_MAGIC_PNG "\x89PNG"
typedef enum { typedef enum {
CAMMY_IMAGE_NONE, CAMMY_IMAGE_NONE,
CAMMY_IMAGE_2BPP_TILE, CAMMY_IMAGE_TILE,
CAMMY_IMAGE_24BPP_RGB, CAMMY_IMAGE_BITMAP
CAMMY_IMAGE_32BPP_RGBA
} cammy_image_format; } cammy_image_format;
typedef enum {
CAMMY_IMAGE_2BPP = 2,
CAMMY_IMAGE_24BPP_RGB = 24,
CAMMY_IMAGE_32BPP_RGBA = 32
} cammy_image_depth;
typedef struct _cammy_image_color { typedef struct _cammy_image_color {
uint8_t r, g, b, a; uint8_t r, g, b, a;
} cammy_image_color; } cammy_image_color;
typedef struct _cammy_image { typedef struct _cammy_image {
cammy_image_format format; cammy_image_format format;
cammy_image_depth depth;
cammy_image_color palette[4]; cammy_image_color palette[4];
size_t size, size_t size,
@ -35,15 +41,6 @@ typedef struct _cammy_image {
uint8_t *buf; uint8_t *buf;
} cammy_image; } cammy_image;
#define CAMMY_IMAGE_HEADER_VERSION 0x0001
typedef struct _cammy_image_header {
uint8_t magic[4];
uint16_t version;
uint16_t width, height;
cammy_image_color palette[4];
} cammy_image_header;
typedef struct _cammy_image_point { typedef struct _cammy_image_point {
size_t x, y; size_t x, y;
} cammy_image_point; } cammy_image_point;
@ -54,12 +51,14 @@ typedef struct _cammy_image_region {
int cammy_image_init(cammy_image *image, int cammy_image_init(cammy_image *image,
cammy_image_format format, cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette, cammy_image_color *palette,
size_t width, size_t width,
size_t height, size_t height,
uint8_t *buf); uint8_t *buf);
cammy_image *cammy_image_new(cammy_image_format format, cammy_image *cammy_image_new(cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette, cammy_image_color *palette,
size_t width, size_t width,
size_t height); size_t height);
@ -75,4 +74,9 @@ void cammy_image_copy(cammy_image *dest,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from); cammy_image_region *from);
int cammy_image_split(cammy_image *image,
cammy_image **r,
cammy_image **g,
cammy_image **b);
#endif /* _CAMMY_IMAGE_H */ #endif /* _CAMMY_IMAGE_H */

View file

@ -43,6 +43,7 @@ int cammy_photo_import(cammy_photo *dest,
cammy_image *cammy_photo_export(cammy_photo *src, cammy_image *cammy_photo_export(cammy_photo *src,
cammy_image_format format, cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette); cammy_image_color *palette);
#endif /* _CAMMY_PHOTO_H */ #endif /* _CAMMY_PHOTO_H */

View file

@ -22,6 +22,16 @@ typedef struct _cammy_tile {
uint8_t data[CAMMY_TILE_SIZE]; uint8_t data[CAMMY_TILE_SIZE];
} cammy_tile; } cammy_tile;
#define CAMMY_TILE_HEADER_MAGIC "TILE"
#define CAMMY_TILE_HEADER_VERSION 0x0001
typedef struct _cammy_tile_header {
uint8_t magic[4];
uint16_t version;
uint16_t width, height;
cammy_image_color palette[4];
} cammy_tile_header;
#pragma pack(pop) #pragma pack(pop)
#endif /* _CAMMY_TILE_H */ #endif /* _CAMMY_TILE_H */

View file

@ -7,12 +7,12 @@ CC = $(CROSS)cc
CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH) CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
LDFLAGS = -lz LDFLAGS = -lz
HEADERS_LOCAL = pnglite.h HEADERS_LOCAL =
HEADERS_BUILD = $(HEADERS_LOCAL) \ HEADERS_BUILD = $(HEADERS_LOCAL) \
$(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS)) $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS))
HEADERS = sram.h image.h photo.h tile.h HEADERS = sram.h image.h photo.h tile.h
OBJS = sram.o image.o photo.o pnglite.o OBJS = sram.o image.o photo.o
VERSION_MAJOR = 0 VERSION_MAJOR = 0
VERSION_MINOR = 0.1 VERSION_MINOR = 0.1

View file

@ -88,14 +88,14 @@ static cammy_image_color default_palette[4] = {
{ 255, 255, 255, 0 } { 255, 255, 255, 0 }
}; };
static uint8_t rgb_to_grayscale(uint8_t r, uint8_t g, uint8_t b) { static uint8_t rgb_to_luma(uint8_t r, uint8_t g, uint8_t b) {
return (uint8_t)((CAMMY_IMAGE_Y_COEFFICIENT_R * (float)r) return (uint8_t)((CAMMY_IMAGE_Y_COEFFICIENT_R * (float)r)
+ (CAMMY_IMAGE_Y_COEFFICIENT_G * (float)g) + (CAMMY_IMAGE_Y_COEFFICIENT_G * (float)g)
+ (CAMMY_IMAGE_Y_COEFFICIENT_B * (float)b)); + (CAMMY_IMAGE_Y_COEFFICIENT_B * (float)b));
} }
static uint8_t rgb_to_tile_2bpp(uint8_t r, uint8_t g, uint8_t b, size_t x, size_t y) { 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); uint8_t gray = rgb_to_luma(r, g, b);
uint32_t slot = bayer_matrix[gray]; uint32_t slot = bayer_matrix[gray];
uint8_t from = (slot & 0x03000000) >> 24; uint8_t from = (slot & 0x03000000) >> 24;
@ -104,22 +104,22 @@ static uint8_t rgb_to_tile_2bpp(uint8_t r, uint8_t g, uint8_t b, size_t x, size_
return (slot & (0x8000 >> ((y & 3) << 2) >> (x & 3)))? to: from; return (slot & (0x8000 >> ((y & 3) << 2) >> (x & 3)))? to: from;
} }
static inline void buf_read(uint8_t *buf, static inline void bitmap_read(uint8_t *buf,
size_t x, size_t y, size_t stride, size_t x, size_t y, size_t stride,
uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *r, uint8_t *g, uint8_t *b,
int depth) { int channels) {
*r = buf[depth*stride*y + depth*x]; *r = buf[channels*stride*y + channels*x];
*g = buf[depth*stride*y + depth*x + 1]; *g = buf[channels*stride*y + channels*x + 1];
*b = buf[depth*stride*y + depth*x + 2]; *b = buf[channels*stride*y + channels*x + 2];
} }
static inline void buf_write(uint8_t *buf, static inline void bitmap_write(uint8_t *buf,
size_t x, size_t y, size_t stride, size_t x, size_t y, size_t stride,
uint8_t r, uint8_t g, uint8_t b, uint8_t r, uint8_t g, uint8_t b,
int depth) { int channels) {
buf[depth*stride*y + depth*x] = r; buf[channels*stride*y + channels*x] = r;
buf[depth*stride*y + depth*x + 1] = g; buf[channels*stride*y + channels*x + 1] = g;
buf[depth*stride*y + depth*x + 2] = b; buf[channels*stride*y + channels*x + 2] = b;
} }
static inline size_t size_2bpp_tile(size_t width, size_t height) { static inline size_t size_2bpp_tile(size_t width, size_t height) {
@ -132,18 +132,16 @@ static inline size_t size_2bpp_tile(size_t width, size_t height) {
return CAMMY_TILE_SIZE * tiles_width * tiles_height; return CAMMY_TILE_SIZE * tiles_width * tiles_height;
} }
static inline size_t size_format(cammy_image_format format, static inline size_t image_size(cammy_image_format format,
size_t width, cammy_image_depth depth,
size_t height) { size_t width,
size_t height) {
switch (format) { switch (format) {
case CAMMY_IMAGE_2BPP_TILE: case CAMMY_IMAGE_TILE:
return size_2bpp_tile(width, height); return size_2bpp_tile(width, height);
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_BITMAP:
return 3 * width * height; return (depth >> 3) * width * height;
case CAMMY_IMAGE_32BPP_RGBA:
return 4 * width * height;
default: default:
return 0; return 0;
@ -152,11 +150,12 @@ static inline size_t size_format(cammy_image_format format,
int cammy_image_init(cammy_image *image, int cammy_image_init(cammy_image *image,
cammy_image_format format, cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette, cammy_image_color *palette,
size_t width, size_t width,
size_t height, size_t height,
uint8_t *buf) { uint8_t *buf) {
size_t size = size_format(format, width, height); size_t size = image_size(format, depth, width, height);
if (size == 0) { if (size == 0) {
errno = EINVAL; errno = EINVAL;
@ -181,6 +180,7 @@ int cammy_image_init(cammy_image *image,
memcpy(&image->palette, palette, sizeof(image->palette)); memcpy(&image->palette, palette, sizeof(image->palette));
image->format = format; image->format = format;
image->depth = depth;
image->size = size; image->size = size;
image->width = width; image->width = width;
image->height = height; image->height = height;
@ -193,6 +193,7 @@ error_invalid_size:
} }
cammy_image *cammy_image_new(cammy_image_format format, cammy_image *cammy_image_new(cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette, cammy_image_color *palette,
size_t width, size_t width,
size_t height) { size_t height) {
@ -202,7 +203,7 @@ cammy_image *cammy_image_new(cammy_image_format format,
goto error_malloc_image; goto error_malloc_image;
} }
if (cammy_image_init(image, format, palette, width, height, NULL) < 0) { if (cammy_image_init(image, format, depth, palette, width, height, NULL) < 0) {
goto error_image_init; goto error_image_init;
} }
@ -225,7 +226,7 @@ static cammy_image *load_tile(const char *filename) {
size_t off; size_t off;
cammy_image *image; cammy_image *image;
cammy_image_header header; cammy_tile_header header;
if ((fd = open(filename, O_RDONLY)) < 0) { if ((fd = open(filename, O_RDONLY)) < 0) {
goto error_open; goto error_open;
@ -235,13 +236,14 @@ static cammy_image *load_tile(const char *filename) {
goto error_read_header; goto error_read_header;
} }
if (be16toh(header.version) != CAMMY_IMAGE_HEADER_VERSION) { if (be16toh(header.version) != CAMMY_TILE_HEADER_VERSION) {
errno = EINVAL; errno = EINVAL;
goto error_invalid_version; goto error_invalid_version;
} }
if ((image = cammy_image_new(CAMMY_IMAGE_2BPP_TILE, if ((image = cammy_image_new(CAMMY_IMAGE_TILE,
CAMMY_IMAGE_2BPP,
header.palette, header.palette,
be16toh(header.width), be16toh(header.width),
be16toh(header.height))) == NULL) { be16toh(header.height))) == NULL) {
@ -277,7 +279,7 @@ error_open:
static cammy_image *load_stb(const char *file) { static cammy_image *load_stb(const char *file) {
uint8_t *buf; uint8_t *buf;
cammy_image *image; cammy_image *image;
cammy_image_format format = CAMMY_IMAGE_NONE; cammy_image_depth depth = 0;
int width, height, channels; int width, height, channels;
@ -287,23 +289,29 @@ static cammy_image *load_stb(const char *file) {
switch (channels) { switch (channels) {
case 3: case 3:
format = CAMMY_IMAGE_24BPP_RGB; depth = CAMMY_IMAGE_24BPP_RGB;
break; break;
case 4: case 4:
format = CAMMY_IMAGE_32BPP_RGBA; depth = CAMMY_IMAGE_32BPP_RGBA;
break; break;
default: default:
errno = EINVAL; errno = EINVAL;
goto error_invalid_format; goto error_invalid_depth;
} }
if ((image = malloc(sizeof(*image))) == NULL) { if ((image = malloc(sizeof(*image))) == NULL) {
goto error_malloc_image; goto error_malloc_image;
} }
if (cammy_image_init(image, format, default_palette, width, height, buf) < 0) { if (cammy_image_init(image,
CAMMY_IMAGE_BITMAP,
depth,
default_palette,
width,
height,
buf) < 0) {
goto error_image_init; goto error_image_init;
} }
@ -312,7 +320,7 @@ static cammy_image *load_stb(const char *file) {
error_image_init: error_image_init:
free(image); free(image);
error_invalid_format: error_invalid_depth:
error_malloc_image: error_malloc_image:
free(buf); free(buf);
@ -340,7 +348,7 @@ cammy_image *cammy_image_open(const char *file) {
close(fd); close(fd);
if (memcmp(buf, CAMMY_IMAGE_MAGIC_TILE, sizeof(buf)) == 0) { if (memcmp(buf, CAMMY_TILE_HEADER_MAGIC, sizeof(buf)) == 0) {
loader = load_tile; loader = load_tile;
} else { } else {
loader = load_stb; loader = load_stb;
@ -362,9 +370,9 @@ static int save_tile(cammy_image *image, const char *filename) {
int fd; int fd;
cammy_image_header header = { cammy_tile_header header = {
.magic = CAMMY_IMAGE_MAGIC_TILE, .magic = CAMMY_TILE_HEADER_MAGIC,
.version = htobe16(CAMMY_IMAGE_HEADER_VERSION), .version = htobe16(CAMMY_TILE_HEADER_VERSION),
.width = htobe16(image->width), .width = htobe16(image->width),
.height = htobe16(image->height) .height = htobe16(image->height)
}; };
@ -403,21 +411,23 @@ error_open:
return -1; return -1;
} }
static inline int format_channels(cammy_image_format format) { static inline int depth_channels(cammy_image_depth depth) {
switch (format) { switch (depth) {
case CAMMY_IMAGE_2BPP:
return 1;
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_24BPP_RGB:
return 3; return 3;
case CAMMY_IMAGE_32BPP_RGBA: case CAMMY_IMAGE_32BPP_RGBA:
return 4; return 4;
default:
return 0;
} }
return 0;
} }
static int save_png(cammy_image *image, const char *file) { static int save_png(cammy_image *image, const char *file) {
int channels = format_channels(image->format); int channels = depth_channels(image->depth);
if (!stbi_write_png(file, if (!stbi_write_png(file,
image->width, image->width,
@ -436,11 +446,10 @@ error_stbi_write_png:
int cammy_image_save(cammy_image *image, const char *filename) { int cammy_image_save(cammy_image *image, const char *filename) {
switch (image->format) { switch (image->format) {
case CAMMY_IMAGE_2BPP_TILE: case CAMMY_IMAGE_TILE:
return save_tile(image, filename); return save_tile(image, filename);
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_BITMAP:
case CAMMY_IMAGE_32BPP_RGBA:
return save_png(image, filename); return save_png(image, filename);
default: default:
@ -483,7 +492,7 @@ static inline void tile_write(cammy_tile *tiles,
tile->data[(tile_y<<1)|1] |= ((value & 0x02) >> 1) << (tile_x ^ 7); tile->data[(tile_y<<1)|1] |= ((value & 0x02) >> 1) << (tile_x ^ 7);
} }
static void copy_2bpp(cammy_image *dest, static void copy_tile(cammy_image *dest,
cammy_image *src, cammy_image *src,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from) { cammy_image_region *from) {
@ -514,14 +523,14 @@ static void copy_2bpp(cammy_image *dest,
} }
} }
static void copy_buf(cammy_image *dest, static void copy_bitmap(cammy_image *dest,
cammy_image *src, cammy_image *src,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from) { cammy_image_region *from) {
size_t x, y; size_t x, y;
int channels_dest = format_channels(dest->format), int channels_dest = depth_channels(dest->depth),
channels_src = format_channels(src->format); channels_src = depth_channels(src->depth);
for (y=0; y < from->height; y++) { for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) { if (to->y + y > dest->height) {
@ -535,28 +544,28 @@ static void copy_buf(cammy_image *dest,
break; break;
} }
buf_read(src->buf, bitmap_read(src->buf,
from->x + x, from->x + x,
from->y + y, from->y + y,
src->width, src->width,
&r, &g, &b, channels_src); &r, &g, &b, channels_src);
buf_write(dest->buf, bitmap_write(dest->buf,
to->x + x, to->x + x,
to->y + y, to->y + y,
dest->width, dest->width,
r, g, b, channels_dest); r, g, b, channels_dest);
} }
} }
} }
static void copy_rgb_to_2bpp_tile(cammy_image *dest, static void copy_bitmap_to_tile(cammy_image *dest,
cammy_image *src, cammy_image *src,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from) { cammy_image_region *from) {
size_t x, y; size_t x, y;
int channels = format_channels(src->format); int channels = depth_channels(src->depth);
for (y=0; y < from->height; y++) { for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) { if (to->y + y > dest->height) {
@ -570,11 +579,11 @@ static void copy_rgb_to_2bpp_tile(cammy_image *dest,
break; break;
} }
buf_read(src->buf, bitmap_read(src->buf,
from->x + x, from->x + x,
from->y + y, from->y + y,
from->width, from->width,
&r, &g, &b, channels); &r, &g, &b, channels);
tile_write((cammy_tile *)dest->buf, tile_write((cammy_tile *)dest->buf,
to->x + x, to->x + x,
@ -586,13 +595,13 @@ static void copy_rgb_to_2bpp_tile(cammy_image *dest,
} }
} }
static void copy_2bpp_tile_to_rgb(cammy_image *dest, static void copy_tile_to_bitmap(cammy_image *dest,
cammy_image *src, cammy_image *src,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from) { cammy_image_region *from) {
size_t x, y; size_t x, y;
int channels = format_channels(dest->format); int channels = depth_channels(dest->depth);
for (y=0; y < from->height; y++) { for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) { if (to->y + y > dest->height) {
@ -611,14 +620,14 @@ static void copy_2bpp_tile_to_rgb(cammy_image *dest,
from->y + y, from->y + y,
from->width); from->width);
buf_write(dest->buf, bitmap_write(dest->buf,
from->x + x, from->x + x,
from->y + y, from->y + y,
from->width, from->width,
src->palette[c].r, src->palette[c].r,
src->palette[c].g, src->palette[c].g,
src->palette[c].b, src->palette[c].b,
channels); channels);
} }
} }
} }
@ -628,16 +637,15 @@ void cammy_image_copy(cammy_image *dest,
cammy_image_point *to, cammy_image_point *to,
cammy_image_region *from) { cammy_image_region *from) {
switch (src->format) { switch (src->format) {
case CAMMY_IMAGE_2BPP_TILE: case CAMMY_IMAGE_TILE:
switch (dest->format) { switch (dest->format) {
case CAMMY_IMAGE_2BPP_TILE: case CAMMY_IMAGE_TILE:
copy_2bpp(dest, src, to, from); copy_tile(dest, src, to, from);
return; return;
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_BITMAP:
case CAMMY_IMAGE_32BPP_RGBA: copy_tile_to_bitmap(dest, src, to, from);
copy_2bpp_tile_to_rgb(dest, src, to, from);
return; return;
@ -645,17 +653,15 @@ void cammy_image_copy(cammy_image *dest,
break; break;
} }
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_BITMAP:
case CAMMY_IMAGE_32BPP_RGBA:
switch (dest->format) { switch (dest->format) {
case CAMMY_IMAGE_2BPP_TILE: case CAMMY_IMAGE_TILE:
copy_rgb_to_2bpp_tile(dest, src, to, from); copy_bitmap_to_tile(dest, src, to, from);
return; return;
case CAMMY_IMAGE_24BPP_RGB: case CAMMY_IMAGE_BITMAP:
case CAMMY_IMAGE_32BPP_RGBA: copy_bitmap(dest, src, to, from);
copy_buf(dest, src, to, from);
return; return;
@ -667,3 +673,10 @@ void cammy_image_copy(cammy_image *dest,
break; break;
} }
} }
int cammy_image_split(cammy_image *image,
cammy_image **r,
cammy_image **g,
cammy_image **b) {
return 0;
}

View file

@ -18,7 +18,8 @@ int cammy_photo_import(cammy_photo *dest,
}; };
if (cammy_image_init(&image, if (cammy_image_init(&image,
CAMMY_IMAGE_2BPP_TILE, CAMMY_IMAGE_TILE,
CAMMY_IMAGE_2BPP,
NULL, NULL,
CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT, CAMMY_PHOTO_HEIGHT,
@ -36,6 +37,7 @@ error_image_init:
cammy_image *cammy_photo_export(cammy_photo *src, cammy_image *cammy_photo_export(cammy_photo *src,
cammy_image_format format, cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette) { cammy_image_color *palette) {
cammy_image image, *dest; cammy_image image, *dest;
@ -48,7 +50,8 @@ cammy_image *cammy_photo_export(cammy_photo *src,
}; };
if (cammy_image_init(&image, if (cammy_image_init(&image,
CAMMY_IMAGE_2BPP_TILE, CAMMY_IMAGE_TILE,
CAMMY_IMAGE_2BPP,
palette, palette,
CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT, CAMMY_PHOTO_HEIGHT,
@ -57,6 +60,7 @@ cammy_image *cammy_photo_export(cammy_photo *src,
} }
if ((dest = cammy_image_new(format, if ((dest = cammy_image_new(format,
depth,
palette, palette,
CAMMY_PHOTO_WIDTH, CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT)) == NULL) { CAMMY_PHOTO_HEIGHT)) == NULL) {