diff --git a/bin/export.c b/bin/export.c index 421ae27..3722029 100644 --- a/bin/export.c +++ b/bin/export.c @@ -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; diff --git a/include/cammy/image.h b/include/cammy/image.h index fc8c163..944aa26 100644 --- a/include/cammy/image.h +++ b/include/cammy/image.h @@ -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 */ diff --git a/include/cammy/photo.h b/include/cammy/photo.h index 1d7a8d9..6bf23ee 100644 --- a/include/cammy/photo.h +++ b/include/cammy/photo.h @@ -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 */ diff --git a/include/cammy/tile.h b/include/cammy/tile.h index 487de95..c4f7bde 100644 --- a/include/cammy/tile.h +++ b/include/cammy/tile.h @@ -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 */ diff --git a/src/Makefile b/src/Makefile index b362bc5..7035611 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/image.c b/src/image.c index 618ccbd..a901290 100644 --- a/src/image.c +++ b/src/image.c @@ -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, - 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 bitmap_read(uint8_t *buf, + size_t x, size_t y, size_t stride, + uint8_t *r, uint8_t *g, uint8_t *b, + 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, - 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; +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 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, - size_t width, - size_t height) { +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, - cammy_image *src, - cammy_image_point *to, - cammy_image_region *from) { +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,28 +544,28 @@ static void copy_buf(cammy_image *dest, break; } - buf_read(src->buf, - from->x + x, - from->y + y, - src->width, - &r, &g, &b, channels_src); + bitmap_read(src->buf, + from->x + x, + from->y + y, + src->width, + &r, &g, &b, channels_src); - buf_write(dest->buf, - to->x + x, - to->y + y, - dest->width, - r, g, b, channels_dest); + bitmap_write(dest->buf, + to->x + x, + to->y + y, + dest->width, + r, g, b, channels_dest); } } } -static void copy_rgb_to_2bpp_tile(cammy_image *dest, - cammy_image *src, - cammy_image_point *to, - cammy_image_region *from) { +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,11 +579,11 @@ static void copy_rgb_to_2bpp_tile(cammy_image *dest, break; } - buf_read(src->buf, - from->x + x, - from->y + y, - from->width, - &r, &g, &b, channels); + bitmap_read(src->buf, + from->x + x, + from->y + y, + from->width, + &r, &g, &b, channels); tile_write((cammy_tile *)dest->buf, 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, - cammy_image *src, - cammy_image_point *to, - cammy_image_region *from) { +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,14 +620,14 @@ static void copy_2bpp_tile_to_rgb(cammy_image *dest, from->y + y, from->width); - buf_write(dest->buf, - from->x + x, - from->y + y, - from->width, - src->palette[c].r, - src->palette[c].g, - src->palette[c].b, - channels); + bitmap_write(dest->buf, + from->x + x, + from->y + y, + from->width, + src->palette[c].r, + src->palette[c].g, + src->palette[c].b, + channels); } } } @@ -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; +} diff --git a/src/photo.c b/src/photo.c index f9c6cf3..c827920 100644 --- a/src/photo.c +++ b/src/photo.c @@ -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) {