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],
CAMMY_IMAGE_BITMAP,
CAMMY_IMAGE_24BPP_RGB,
palette)) == NULL) {
goto error_photo_export;

View file

@ -10,22 +10,28 @@
#define CAMMY_IMAGE_CHUNK_SIZE 4096
#define CAMMY_IMAGE_MAGIC_TILE "TILE"
#define CAMMY_IMAGE_MAGIC_PNG "\x89PNG"
typedef enum {
CAMMY_IMAGE_NONE,
CAMMY_IMAGE_2BPP_TILE,
CAMMY_IMAGE_24BPP_RGB,
CAMMY_IMAGE_32BPP_RGBA
CAMMY_IMAGE_TILE,
CAMMY_IMAGE_BITMAP
} 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 {
uint8_t r, g, b, a;
} cammy_image_color;
typedef struct _cammy_image {
cammy_image_format format;
cammy_image_depth depth;
cammy_image_color palette[4];
size_t size,
@ -35,15 +41,6 @@ typedef struct _cammy_image {
uint8_t *buf;
} 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 {
size_t x, y;
} cammy_image_point;
@ -54,12 +51,14 @@ typedef struct _cammy_image_region {
int cammy_image_init(cammy_image *image,
cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette,
size_t width,
size_t height,
uint8_t *buf);
cammy_image *cammy_image_new(cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette,
size_t width,
size_t height);
@ -75,4 +74,9 @@ void cammy_image_copy(cammy_image *dest,
cammy_image_point *to,
cammy_image_region *from);
int cammy_image_split(cammy_image *image,
cammy_image **r,
cammy_image **g,
cammy_image **b);
#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_format format,
cammy_image_depth depth,
cammy_image_color *palette);
#endif /* _CAMMY_PHOTO_H */

View file

@ -22,6 +22,16 @@ typedef struct _cammy_tile {
uint8_t data[CAMMY_TILE_SIZE];
} 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)
#endif /* _CAMMY_TILE_H */

View file

@ -7,12 +7,12 @@ CC = $(CROSS)cc
CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
LDFLAGS = -lz
HEADERS_LOCAL = pnglite.h
HEADERS_LOCAL =
HEADERS_BUILD = $(HEADERS_LOCAL) \
$(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS))
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_MINOR = 0.1

View file

@ -88,14 +88,14 @@ static cammy_image_color default_palette[4] = {
{ 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)
+ (CAMMY_IMAGE_Y_COEFFICIENT_G * (float)g)
+ (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) {
uint8_t gray = rgb_to_grayscale(r, g, b);
uint8_t gray = rgb_to_luma(r, g, b);
uint32_t slot = bayer_matrix[gray];
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;
}
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,
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];
int channels) {
*r = buf[channels*stride*y + channels*x];
*g = buf[channels*stride*y + channels*x + 1];
*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,
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;
int channels) {
buf[channels*stride*y + channels*x] = r;
buf[channels*stride*y + channels*x + 1] = g;
buf[channels*stride*y + channels*x + 2] = b;
}
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;
}
static inline size_t size_format(cammy_image_format format,
static inline size_t image_size(cammy_image_format format,
cammy_image_depth depth,
size_t width,
size_t height) {
switch (format) {
case CAMMY_IMAGE_2BPP_TILE:
case CAMMY_IMAGE_TILE:
return size_2bpp_tile(width, height);
case CAMMY_IMAGE_24BPP_RGB:
return 3 * width * height;
case CAMMY_IMAGE_32BPP_RGBA:
return 4 * width * height;
case CAMMY_IMAGE_BITMAP:
return (depth >> 3) * width * height;
default:
return 0;
@ -152,11 +150,12 @@ static inline size_t size_format(cammy_image_format format,
int cammy_image_init(cammy_image *image,
cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette,
size_t width,
size_t height,
uint8_t *buf) {
size_t size = size_format(format, width, height);
size_t size = image_size(format, depth, width, height);
if (size == 0) {
errno = EINVAL;
@ -181,6 +180,7 @@ int cammy_image_init(cammy_image *image,
memcpy(&image->palette, palette, sizeof(image->palette));
image->format = format;
image->depth = depth;
image->size = size;
image->width = width;
image->height = height;
@ -193,6 +193,7 @@ error_invalid_size:
}
cammy_image *cammy_image_new(cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette,
size_t width,
size_t height) {
@ -202,7 +203,7 @@ cammy_image *cammy_image_new(cammy_image_format format,
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;
}
@ -225,7 +226,7 @@ static cammy_image *load_tile(const char *filename) {
size_t off;
cammy_image *image;
cammy_image_header header;
cammy_tile_header header;
if ((fd = open(filename, O_RDONLY)) < 0) {
goto error_open;
@ -235,13 +236,14 @@ static cammy_image *load_tile(const char *filename) {
goto error_read_header;
}
if (be16toh(header.version) != CAMMY_IMAGE_HEADER_VERSION) {
if (be16toh(header.version) != CAMMY_TILE_HEADER_VERSION) {
errno = EINVAL;
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,
be16toh(header.width),
be16toh(header.height))) == NULL) {
@ -277,7 +279,7 @@ error_open:
static cammy_image *load_stb(const char *file) {
uint8_t *buf;
cammy_image *image;
cammy_image_format format = CAMMY_IMAGE_NONE;
cammy_image_depth depth = 0;
int width, height, channels;
@ -287,23 +289,29 @@ static cammy_image *load_stb(const char *file) {
switch (channels) {
case 3:
format = CAMMY_IMAGE_24BPP_RGB;
depth = CAMMY_IMAGE_24BPP_RGB;
break;
case 4:
format = CAMMY_IMAGE_32BPP_RGBA;
depth = CAMMY_IMAGE_32BPP_RGBA;
break;
default:
errno = EINVAL;
goto error_invalid_format;
goto error_invalid_depth;
}
if ((image = malloc(sizeof(*image))) == NULL) {
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;
}
@ -312,7 +320,7 @@ static cammy_image *load_stb(const char *file) {
error_image_init:
free(image);
error_invalid_format:
error_invalid_depth:
error_malloc_image:
free(buf);
@ -340,7 +348,7 @@ cammy_image *cammy_image_open(const char *file) {
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;
} else {
loader = load_stb;
@ -362,9 +370,9 @@ static int save_tile(cammy_image *image, const char *filename) {
int fd;
cammy_image_header header = {
.magic = CAMMY_IMAGE_MAGIC_TILE,
.version = htobe16(CAMMY_IMAGE_HEADER_VERSION),
cammy_tile_header header = {
.magic = CAMMY_TILE_HEADER_MAGIC,
.version = htobe16(CAMMY_TILE_HEADER_VERSION),
.width = htobe16(image->width),
.height = htobe16(image->height)
};
@ -403,21 +411,23 @@ error_open:
return -1;
}
static inline int format_channels(cammy_image_format format) {
switch (format) {
static inline int depth_channels(cammy_image_depth depth) {
switch (depth) {
case CAMMY_IMAGE_2BPP:
return 1;
case CAMMY_IMAGE_24BPP_RGB:
return 3;
case CAMMY_IMAGE_32BPP_RGBA:
return 4;
default:
return 0;
}
return 0;
}
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,
image->width,
@ -436,11 +446,10 @@ error_stbi_write_png:
int cammy_image_save(cammy_image *image, const char *filename) {
switch (image->format) {
case CAMMY_IMAGE_2BPP_TILE:
case CAMMY_IMAGE_TILE:
return save_tile(image, filename);
case CAMMY_IMAGE_24BPP_RGB:
case CAMMY_IMAGE_32BPP_RGBA:
case CAMMY_IMAGE_BITMAP:
return save_png(image, filename);
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);
}
static void copy_2bpp(cammy_image *dest,
static void copy_tile(cammy_image *dest,
cammy_image *src,
cammy_image_point *to,
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_point *to,
cammy_image_region *from) {
size_t x, y;
int channels_dest = format_channels(dest->format),
channels_src = format_channels(src->format);
int channels_dest = depth_channels(dest->depth),
channels_src = depth_channels(src->depth);
for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) {
@ -535,13 +544,13 @@ static void copy_buf(cammy_image *dest,
break;
}
buf_read(src->buf,
bitmap_read(src->buf,
from->x + x,
from->y + y,
src->width,
&r, &g, &b, channels_src);
buf_write(dest->buf,
bitmap_write(dest->buf,
to->x + x,
to->y + y,
dest->width,
@ -550,13 +559,13 @@ static void copy_buf(cammy_image *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_point *to,
cammy_image_region *from) {
size_t x, y;
int channels = format_channels(src->format);
int channels = depth_channels(src->depth);
for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) {
@ -570,7 +579,7 @@ static void copy_rgb_to_2bpp_tile(cammy_image *dest,
break;
}
buf_read(src->buf,
bitmap_read(src->buf,
from->x + x,
from->y + y,
from->width,
@ -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_point *to,
cammy_image_region *from) {
size_t x, y;
int channels = format_channels(dest->format);
int channels = depth_channels(dest->depth);
for (y=0; y < from->height; y++) {
if (to->y + y > dest->height) {
@ -611,7 +620,7 @@ static void copy_2bpp_tile_to_rgb(cammy_image *dest,
from->y + y,
from->width);
buf_write(dest->buf,
bitmap_write(dest->buf,
from->x + x,
from->y + y,
from->width,
@ -628,16 +637,15 @@ void cammy_image_copy(cammy_image *dest,
cammy_image_point *to,
cammy_image_region *from) {
switch (src->format) {
case CAMMY_IMAGE_2BPP_TILE:
case CAMMY_IMAGE_TILE:
switch (dest->format) {
case CAMMY_IMAGE_2BPP_TILE:
copy_2bpp(dest, src, to, from);
case CAMMY_IMAGE_TILE:
copy_tile(dest, src, to, from);
return;
case CAMMY_IMAGE_24BPP_RGB:
case CAMMY_IMAGE_32BPP_RGBA:
copy_2bpp_tile_to_rgb(dest, src, to, from);
case CAMMY_IMAGE_BITMAP:
copy_tile_to_bitmap(dest, src, to, from);
return;
@ -645,17 +653,15 @@ void cammy_image_copy(cammy_image *dest,
break;
}
case CAMMY_IMAGE_24BPP_RGB:
case CAMMY_IMAGE_32BPP_RGBA:
case CAMMY_IMAGE_BITMAP:
switch (dest->format) {
case CAMMY_IMAGE_2BPP_TILE:
copy_rgb_to_2bpp_tile(dest, src, to, from);
case CAMMY_IMAGE_TILE:
copy_bitmap_to_tile(dest, src, to, from);
return;
case CAMMY_IMAGE_24BPP_RGB:
case CAMMY_IMAGE_32BPP_RGBA:
copy_buf(dest, src, to, from);
case CAMMY_IMAGE_BITMAP:
copy_bitmap(dest, src, to, from);
return;
@ -667,3 +673,10 @@ void cammy_image_copy(cammy_image *dest,
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,
CAMMY_IMAGE_2BPP_TILE,
CAMMY_IMAGE_TILE,
CAMMY_IMAGE_2BPP,
NULL,
CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT,
@ -36,6 +37,7 @@ error_image_init:
cammy_image *cammy_photo_export(cammy_photo *src,
cammy_image_format format,
cammy_image_depth depth,
cammy_image_color *palette) {
cammy_image image, *dest;
@ -48,7 +50,8 @@ cammy_image *cammy_photo_export(cammy_photo *src,
};
if (cammy_image_init(&image,
CAMMY_IMAGE_2BPP_TILE,
CAMMY_IMAGE_TILE,
CAMMY_IMAGE_2BPP,
palette,
CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT,
@ -57,6 +60,7 @@ cammy_image *cammy_photo_export(cammy_photo *src,
}
if ((dest = cammy_image_new(format,
depth,
palette,
CAMMY_PHOTO_WIDTH,
CAMMY_PHOTO_HEIGHT)) == NULL) {