#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 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)); } 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 ^ 3: from ^ 3; } 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; y