Massive, mind-blowing refactor
This commit is contained in:
parent
2a489ee40c
commit
04ad40d69a
7 changed files with 259 additions and 206 deletions
15
bin/main.c
15
bin/main.c
|
@ -5,8 +5,19 @@
|
|||
#include <errno.h>
|
||||
#include "pnglite.h"
|
||||
|
||||
#include <cammy/image.h>
|
||||
#include <cammy/photo.h>
|
||||
#include <cammy/sram.h>
|
||||
|
||||
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",
|
||||
|
|
|
@ -5,30 +5,24 @@
|
|||
|
||||
#include <cammy/tile.h>
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
201
src/image.c
Normal file
201
src/image.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cammy/image.h>
|
||||
|
||||
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; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t r, g, b, value;
|
||||
|
||||
buf_read(src, x, y, width, &r, &g, &b, depth);
|
||||
|
||||
value = rgb_to_tile_2bpp(r, g, b, x, y);
|
||||
|
||||
r = palette->colors[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; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t value = tile_read(src, x, y, width);
|
||||
|
||||
buf_write(dest, x, y, width, palette->colors[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<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t r, g, b;
|
||||
|
||||
buf_read(src, x, y, width, &r, &g, &b, depth);
|
||||
|
||||
tile_write(dest, x, y, width, rgb_to_tile_2bpp(r, g, b, x, y) ^ 3);
|
||||
}
|
||||
}
|
||||
}
|
188
src/photo.c
188
src/photo.c
|
@ -2,179 +2,25 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cammy/image.h>
|
||||
#include <cammy/photo.h>
|
||||
|
||||
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; y<CAMMY_PHOTO_HEIGHT; y++) {
|
||||
for (x=0; x<CAMMY_PHOTO_WIDTH; x++) {
|
||||
uint8_t rgb = tile_2bpp_palette[tile_read(src, x, y)];
|
||||
|
||||
buf_write(dest, x, y, CAMMY_PHOTO_WIDTH, rgb, rgb, rgb, stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cammy_photo_import(cammy_photo *dest, uint8_t *src, int stride) {
|
||||
size_t x, y;
|
||||
|
||||
memset(&dest->tiles, '\x00', sizeof(dest->tiles));
|
||||
memset(&dest->thumb, '\xff', sizeof(dest->thumb));
|
||||
|
||||
for (y=0; y<CAMMY_PHOTO_HEIGHT; y++) {
|
||||
for (x=0; x<CAMMY_PHOTO_WIDTH; x++) {
|
||||
uint8_t r, g, b;
|
||||
|
||||
buf_read(src, x, y, CAMMY_PHOTO_WIDTH, &r, &g, &b, stride);
|
||||
|
||||
tile_write(dest, x, y, rgb_to_tile_2bpp(r, g, b, x, y) ^ 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cammy_photo_dither(uint8_t *dest,
|
||||
uint8_t *src,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int stride) {
|
||||
size_t x, y;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t r, g, b, gray;
|
||||
|
||||
buf_read(src, x, y, width, &r, &g, &b, stride);
|
||||
|
||||
gray = tile_2bpp_palette[rgb_to_tile_2bpp(r, g, b, x, y)];
|
||||
|
||||
buf_write(dest, x, y, width, gray, gray, gray, stride);
|
||||
}
|
||||
}
|
||||
void cammy_photo_import(cammy_photo *dest, uint8_t *src, int depth) {
|
||||
cammy_image_dither_to_tile((cammy_tile *)&dest->tiles,
|
||||
src,
|
||||
CAMMY_PHOTO_WIDTH,
|
||||
CAMMY_PHOTO_HEIGHT,
|
||||
depth);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue