don't make me start singing patriotic shit. come convert me now
This commit is contained in:
parent
8330736b1e
commit
22ce22fa4c
7 changed files with 326 additions and 415 deletions
86
bin/png.c
86
bin/png.c
|
@ -7,89 +7,3 @@
|
|||
|
||||
#include "pnglite.h"
|
||||
#include "png.h"
|
||||
|
||||
int cammy_png_save(const char *file,
|
||||
void *buf,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int depth,
|
||||
int format) {
|
||||
png_t *png;
|
||||
|
||||
png_init(malloc, free);
|
||||
|
||||
if ((png = malloc(sizeof(*png))) == NULL) {
|
||||
goto error_malloc_png;
|
||||
}
|
||||
|
||||
if (png_open_file_write(png, file) < 0) {
|
||||
goto error_png_open_file_write;
|
||||
}
|
||||
|
||||
if (png_set_data(png, width, height, depth, format, buf) < 0) {
|
||||
goto error_png_set_data;
|
||||
}
|
||||
|
||||
png_close_file(png);
|
||||
|
||||
free(png);
|
||||
|
||||
return 0;
|
||||
|
||||
error_png_set_data:
|
||||
png_close_file(png);
|
||||
|
||||
error_png_open_file_write:
|
||||
free(png);
|
||||
|
||||
error_malloc_png:
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *cammy_png_load(const char *file,
|
||||
size_t *width,
|
||||
size_t *height,
|
||||
int *depth) {
|
||||
png_t *png;
|
||||
uint8_t *buf;
|
||||
|
||||
png_init(malloc, free);
|
||||
|
||||
if ((png = malloc(sizeof(*png))) == NULL) {
|
||||
goto error_malloc_png;
|
||||
}
|
||||
|
||||
if (png_open_file_read(png, file) < 0) {
|
||||
goto error_png_open_file_read;
|
||||
}
|
||||
|
||||
*width = png->width;
|
||||
*height = png->height;
|
||||
*depth = png->bpp;
|
||||
|
||||
if ((buf = malloc(*width * *height * *depth)) == NULL) {
|
||||
goto error_malloc_buf;
|
||||
}
|
||||
|
||||
if (png_get_data(png, buf) < 0) {
|
||||
goto error_png_get_data;
|
||||
}
|
||||
|
||||
png_close_file(png);
|
||||
|
||||
free(png);
|
||||
|
||||
return buf;
|
||||
|
||||
error_png_get_data:
|
||||
free(buf);
|
||||
|
||||
error_malloc_buf:
|
||||
png_close_file(png);
|
||||
|
||||
error_png_open_file_read:
|
||||
free(png);
|
||||
|
||||
error_malloc_png:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#ifndef _CAMMY_IMAGE_H
|
||||
#define _CAMMY_IMAGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cammy/tile.h>
|
||||
|
||||
#define CAMMY_IMAGE_Y_COEFFICIENT_R 0.2126
|
||||
#define CAMMY_IMAGE_Y_COEFFICIENT_G 0.7152
|
||||
#define CAMMY_IMAGE_Y_COEFFICIENT_B 0.0722
|
||||
|
@ -21,19 +20,19 @@ typedef enum {
|
|||
CAMMY_IMAGE_32BPP_RGBA
|
||||
} cammy_image_format;
|
||||
|
||||
typedef struct _cammy_image_color {
|
||||
uint8_t r, g, b, a;
|
||||
} cammy_image_color;
|
||||
|
||||
typedef struct _cammy_image {
|
||||
cammy_image_format format;
|
||||
cammy_image_color palette[4];
|
||||
|
||||
size_t size,
|
||||
width,
|
||||
height;
|
||||
|
||||
union {
|
||||
uint8_t *buf;
|
||||
cammy_tile *tiles;
|
||||
};
|
||||
|
||||
char *file;
|
||||
} cammy_image;
|
||||
|
||||
#define CAMMY_IMAGE_HEADER_VERSION 0x0001
|
||||
|
@ -42,6 +41,7 @@ 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 {
|
||||
|
@ -53,41 +53,19 @@ typedef struct _cammy_image_region {
|
|||
} cammy_image_region;
|
||||
|
||||
cammy_image *cammy_image_new(cammy_image_format format,
|
||||
cammy_image_color *palette,
|
||||
size_t width,
|
||||
size_t height);
|
||||
|
||||
cammy_image *cammy_image_open(const char *filename);
|
||||
|
||||
void cammy_image_destroy(cammy_image *image);
|
||||
|
||||
cammy_image *cammy_image_open(const char *filename);
|
||||
|
||||
int cammy_image_save(cammy_image *image, const char *filename);
|
||||
|
||||
void cammy_image_split_to_tiles(cammy_tile *destr,
|
||||
cammy_tile *destg,
|
||||
cammy_tile *destb,
|
||||
uint8_t *src,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int depth);
|
||||
|
||||
void cammy_image_merge_tiles(uint8_t *dest,
|
||||
cammy_tile *srcr,
|
||||
cammy_tile *srcg,
|
||||
cammy_tile *srcb,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int depth);
|
||||
|
||||
void cammy_image_copy(cammy_image *dest,
|
||||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from);
|
||||
|
||||
int cammy_image_slice(uint8_t *buf,
|
||||
size_t width,
|
||||
size_t height,
|
||||
size_t x_pad,
|
||||
size_t y_pad,
|
||||
int depth);
|
||||
|
||||
#endif /* _CAMMY_IMAGE_H */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cammy/image.h>
|
||||
#include <cammy/tile.h>
|
||||
|
||||
#define CAMMY_PHOTO_TILES_WIDTH 16
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cammy/image.h>
|
||||
|
||||
#define CAMMY_TILE_SIZE 16
|
||||
#define CAMMY_TILE_WIDTH 8
|
||||
#define CAMMY_TILE_HEIGHT 8
|
||||
|
|
|
@ -11,7 +11,7 @@ HEADERS_LOCAL = pnglite.h
|
|||
HEADERS_BUILD = $(HEADERS_LOCAL) \
|
||||
$(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS))
|
||||
|
||||
HEADERS = sram.h image.h photo.h
|
||||
HEADERS = sram.h image.h photo.h tile.h
|
||||
OBJS = sram.o image.o photo.o pnglite.o
|
||||
|
||||
VERSION_MAJOR = 0
|
||||
|
|
572
src/image.c
572
src/image.c
|
@ -77,8 +77,11 @@ static uint32_t bayer_matrix[256] = {
|
|||
0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff, 0x0203ffff,
|
||||
};
|
||||
|
||||
static uint8_t level_2bpp_to_8bpp[4] = {
|
||||
0, 87, 171, 255
|
||||
static cammy_image_color default_palette[4] = {
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 87, 87, 87, 0 },
|
||||
{ 171, 171, 171, 0 },
|
||||
{ 255, 255, 255, 0 }
|
||||
};
|
||||
|
||||
static uint8_t rgb_to_grayscale(uint8_t r, uint8_t g, uint8_t b) {
|
||||
|
@ -97,37 +100,6 @@ 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 uint8_t tile_read(cammy_tile *tiles,
|
||||
size_t x,
|
||||
size_t y,
|
||||
int stride) {
|
||||
cammy_tile *tile = CAMMY_TILE_INDEXED(tiles, x, y, stride);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static inline void tile_write(cammy_tile *tiles,
|
||||
size_t x,
|
||||
size_t y,
|
||||
int stride,
|
||||
uint8_t value) {
|
||||
cammy_tile *tile = CAMMY_TILE_INDEXED(tiles, x, y, stride);
|
||||
|
||||
int tile_x = x & 7,
|
||||
tile_y = y & 7;
|
||||
|
||||
tile->data[ tile_y<<1] &= ~(1 << (tile_x ^ 7));
|
||||
tile->data[(tile_y<<1)|1] &= ~(1 << (tile_x ^ 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,
|
||||
|
@ -157,6 +129,7 @@ static inline size_t size_2bpp_tile(size_t width, size_t height) {
|
|||
}
|
||||
|
||||
cammy_image *cammy_image_new(cammy_image_format format,
|
||||
cammy_image_color *palette,
|
||||
size_t width,
|
||||
size_t height) {
|
||||
cammy_image *image;
|
||||
|
@ -164,7 +137,12 @@ cammy_image *cammy_image_new(cammy_image_format format,
|
|||
|
||||
switch (format) {
|
||||
case CAMMY_IMAGE_2BPP_TILE: {
|
||||
if (palette == NULL) {
|
||||
palette = default_palette;
|
||||
}
|
||||
|
||||
size = size_2bpp_tile(width, height);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -192,11 +170,16 @@ cammy_image *cammy_image_new(cammy_image_format format,
|
|||
goto error_malloc_buf;
|
||||
}
|
||||
|
||||
if (palette) {
|
||||
memcpy(&image->palette, palette, sizeof(image->palette));
|
||||
} else {
|
||||
memset(&image->palette, '\0', sizeof(image->palette));
|
||||
}
|
||||
|
||||
image->format = format;
|
||||
image->size = size;
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->file = NULL;
|
||||
|
||||
return image;
|
||||
|
||||
|
@ -213,55 +196,6 @@ void cammy_image_destroy(cammy_image *image) {
|
|||
free(image);
|
||||
}
|
||||
|
||||
static cammy_image *load_png(const char *file) {
|
||||
png_t png;
|
||||
|
||||
cammy_image *image;
|
||||
cammy_image_format format = CAMMY_IMAGE_NONE;
|
||||
|
||||
png_init(malloc, free);
|
||||
|
||||
if (png_open_file_read(&png, file) < 0) {
|
||||
goto error_png_open_file_read;
|
||||
}
|
||||
|
||||
switch (png.bpp) {
|
||||
case 3:
|
||||
format = CAMMY_IMAGE_24BPP_RGB;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
format = CAMMY_IMAGE_32BPP_RGBA;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
goto error_invalid_format;
|
||||
}
|
||||
|
||||
if ((image = cammy_image_new(format, png.width, png.height)) == NULL) {
|
||||
goto error_image_new;
|
||||
}
|
||||
|
||||
if (png_get_data(&png, image->buf) < 0) {
|
||||
goto error_png_get_data;
|
||||
}
|
||||
|
||||
png_close_file(&png);
|
||||
|
||||
return image;
|
||||
|
||||
error_png_get_data:
|
||||
cammy_image_destroy(image);
|
||||
|
||||
error_image_new:
|
||||
error_invalid_format:
|
||||
png_close_file(&png);
|
||||
|
||||
error_png_open_file_read:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static cammy_image *load_tile(const char *filename) {
|
||||
int fd;
|
||||
size_t off;
|
||||
|
@ -284,6 +218,7 @@ static cammy_image *load_tile(const char *filename) {
|
|||
}
|
||||
|
||||
if ((image = cammy_image_new(CAMMY_IMAGE_2BPP_TILE,
|
||||
header.palette,
|
||||
be16toh(header.width),
|
||||
be16toh(header.height))) == NULL) {
|
||||
goto error_image_new;
|
||||
|
@ -315,6 +250,58 @@ error_open:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static cammy_image *load_png(const char *file) {
|
||||
png_t png;
|
||||
|
||||
cammy_image *image;
|
||||
cammy_image_format format = CAMMY_IMAGE_NONE;
|
||||
|
||||
png_init(malloc, free);
|
||||
|
||||
if (png_open_file_read(&png, file) < 0) {
|
||||
goto error_png_open_file_read;
|
||||
}
|
||||
|
||||
switch (png.bpp) {
|
||||
case 3:
|
||||
format = CAMMY_IMAGE_24BPP_RGB;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
format = CAMMY_IMAGE_32BPP_RGBA;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
goto error_invalid_format;
|
||||
}
|
||||
|
||||
if ((image = cammy_image_new(format,
|
||||
NULL,
|
||||
png.width,
|
||||
png.height)) == NULL) {
|
||||
goto error_image_new;
|
||||
}
|
||||
|
||||
if (png_get_data(&png, image->buf) < 0) {
|
||||
goto error_png_get_data;
|
||||
}
|
||||
|
||||
png_close_file(&png);
|
||||
|
||||
return image;
|
||||
|
||||
error_png_get_data:
|
||||
cammy_image_destroy(image);
|
||||
|
||||
error_image_new:
|
||||
error_invalid_format:
|
||||
png_close_file(&png);
|
||||
|
||||
error_png_open_file_read:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cammy_image *cammy_image_open(const char *file) {
|
||||
cammy_image *image;
|
||||
|
||||
|
@ -361,7 +348,7 @@ error_open:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int cammy_image_save(cammy_image *image, const char *filename) {
|
||||
static int save_tile(cammy_image *image, const char *filename) {
|
||||
size_t off,
|
||||
rest = image->size;
|
||||
|
||||
|
@ -374,6 +361,8 @@ int cammy_image_save(cammy_image *image, const char *filename) {
|
|||
.height = htobe16(image->height)
|
||||
};
|
||||
|
||||
memcpy(&header.palette, image->palette, sizeof(header.palette));
|
||||
|
||||
if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) {
|
||||
goto error_open;
|
||||
}
|
||||
|
@ -406,154 +395,252 @@ error_open:
|
|||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
static inline void format_info_png(cammy_image_format format,
|
||||
int *depth,
|
||||
int *color) {
|
||||
switch (format) {
|
||||
case CAMMY_IMAGE_24BPP_RGB:
|
||||
if (depth) *depth = 3;
|
||||
if (color) *color = PNG_TRUECOLOR;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t r, g, b, value;
|
||||
break;
|
||||
|
||||
buf_read(src, x, y, width, &r, &g, &b, depth);
|
||||
case CAMMY_IMAGE_32BPP_RGBA:
|
||||
if (depth) *depth = 4;
|
||||
if (color) *color = PNG_TRUECOLOR_ALPHA;
|
||||
|
||||
value = rgb_to_tile_2bpp(r, g, b, x, y);
|
||||
break;
|
||||
|
||||
r = palette->colors[value][0];
|
||||
g = palette->colors[value][1];
|
||||
b = palette->colors[value][2];
|
||||
default:
|
||||
if (depth) *depth = 0;
|
||||
if (color) *color = 0;
|
||||
|
||||
buf_write(dest, x, y, width, r, g, b, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int save_png(cammy_image *image, const char *file) {
|
||||
png_t png;
|
||||
|
||||
int depth, color;
|
||||
|
||||
format_info_png(image->format, &depth, &color);
|
||||
|
||||
png_init(malloc, free);
|
||||
|
||||
if (png_open_file_write(&png, file) < 0) {
|
||||
goto error_png_open_file_write;
|
||||
}
|
||||
|
||||
void cammy_image_split_to_tiles(cammy_tile *destr,
|
||||
cammy_tile *destg,
|
||||
cammy_tile *destb,
|
||||
uint8_t *src,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int depth) {
|
||||
size_t x, y;
|
||||
|
||||
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(destr, x, y, width, rgb_to_tile_2bpp(r, r, r, x, y) ^ 3);
|
||||
tile_write(destg, x, y, width, rgb_to_tile_2bpp(g, g, g, x, y) ^ 3);
|
||||
tile_write(destb, x, y, width, rgb_to_tile_2bpp(b, b, b, x, y) ^ 3);
|
||||
}
|
||||
}
|
||||
if (png_set_data(&png,
|
||||
image->width,
|
||||
image->height,
|
||||
depth,
|
||||
color,
|
||||
image->buf) < 0) {
|
||||
goto error_png_set_data;
|
||||
}
|
||||
|
||||
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;
|
||||
png_close_file(&png);
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t value = tile_read(src, x, y, width) ^ 3;
|
||||
return 0;
|
||||
|
||||
buf_write(dest, x, y, width, palette->colors[value][0],
|
||||
palette->colors[value][1],
|
||||
palette->colors[value][2], depth);
|
||||
}
|
||||
}
|
||||
error_png_set_data:
|
||||
png_close_file(&png);
|
||||
|
||||
error_png_open_file_write:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cammy_image_merge_tiles(uint8_t *dest,
|
||||
cammy_tile *srcr,
|
||||
cammy_tile *srcg,
|
||||
cammy_tile *srcb,
|
||||
size_t width,
|
||||
size_t height,
|
||||
int depth) {
|
||||
size_t x, y;
|
||||
int cammy_image_save(cammy_image *image, const char *filename) {
|
||||
switch (image->format) {
|
||||
case CAMMY_IMAGE_2BPP_TILE:
|
||||
return save_tile(image, filename);
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
uint8_t r = tile_read(srcr, x, y, width) ^ 3,
|
||||
g = tile_read(srcg, x, y, width) ^ 3,
|
||||
b = tile_read(srcb, x, y, width) ^ 3;
|
||||
case CAMMY_IMAGE_24BPP_RGB:
|
||||
case CAMMY_IMAGE_32BPP_RGBA:
|
||||
return save_png(image, filename);
|
||||
|
||||
buf_write(dest, x, y, width, level_2bpp_to_8bpp[r],
|
||||
level_2bpp_to_8bpp[g],
|
||||
level_2bpp_to_8bpp[b], depth);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline uint8_t tile_read(cammy_tile *tiles,
|
||||
size_t x,
|
||||
size_t y,
|
||||
int stride) {
|
||||
cammy_tile *tile = CAMMY_TILE_INDEXED(tiles, x, y, stride);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static inline void tile_write(cammy_tile *tiles,
|
||||
size_t x,
|
||||
size_t y,
|
||||
int stride,
|
||||
uint8_t value) {
|
||||
cammy_tile *tile = CAMMY_TILE_INDEXED(tiles, x, y, stride);
|
||||
|
||||
int tile_x = x & 7,
|
||||
tile_y = y & 7;
|
||||
|
||||
tile->data[ tile_y<<1] &= ~(1 << (tile_x ^ 7));
|
||||
tile->data[(tile_y<<1)|1] &= ~(1 << (tile_x ^ 7));
|
||||
|
||||
tile->data[ tile_y<<1] |= (value & 0x01) << (tile_x ^ 7);
|
||||
tile->data[(tile_y<<1)|1] |= ((value & 0x02) >> 1) << (tile_x ^ 7);
|
||||
}
|
||||
|
||||
static void copy_2bpp(cammy_image *dest,
|
||||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from) {
|
||||
size_t x_offset,
|
||||
y_offset;
|
||||
size_t x,
|
||||
y;
|
||||
|
||||
for (y_offset=0; y_offset < from->height; y_offset++) {
|
||||
if (to->y + y_offset > dest->height) {
|
||||
for (y=0; y < from->height; y++) {
|
||||
if (to->y + y > dest->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (x_offset=0; x_offset < from->width; x_offset++) {
|
||||
uint8_t value = tile_read(src->tiles, from->x + x_offset,
|
||||
from->y + y_offset,
|
||||
for (x=0; x < from->width; x++) {
|
||||
uint8_t value = tile_read((cammy_tile *)src->buf,
|
||||
from->x + x,
|
||||
from->y + y,
|
||||
src->width);
|
||||
|
||||
if (to->x + x_offset > dest->width) {
|
||||
if (to->x + x > dest->width) {
|
||||
break;
|
||||
}
|
||||
|
||||
tile_write(dest->tiles, to->x + x_offset,
|
||||
to->y + y_offset,
|
||||
tile_write((cammy_tile *)dest->buf,
|
||||
to->x + x,
|
||||
to->y + y,
|
||||
dest->width,
|
||||
value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_to_2bpp_tile(cammy_image *dest,
|
||||
static void copy_buf(cammy_image *dest,
|
||||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from,
|
||||
int depth) {
|
||||
size_t x_offset, y_offset;
|
||||
cammy_image_region *from) {
|
||||
size_t x, y;
|
||||
|
||||
for (y_offset=0; y_offset < from->height; y_offset++) {
|
||||
if (to->y + y_offset > dest->height) {
|
||||
int depth, color;
|
||||
|
||||
format_info_png(dest->format, &depth, &color);
|
||||
|
||||
for (y=0; y < from->height; y++) {
|
||||
if (to->y + y > dest->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (x_offset=0; x_offset < from->width; x_offset++) {
|
||||
for (x=0; x < from->width; x++) {
|
||||
uint8_t r, g, b;
|
||||
|
||||
if (to->x + x_offset > from->width) {
|
||||
if (to->x + x > from->width) {
|
||||
break;
|
||||
}
|
||||
|
||||
buf_read(src->buf,
|
||||
from->x + x_offset,
|
||||
from->y + y_offset,
|
||||
from->x + x,
|
||||
from->y + y,
|
||||
from->width,
|
||||
&r, &g, &b, depth);
|
||||
|
||||
tile_write(dest->tiles,
|
||||
to->x + x_offset,
|
||||
to->y + y_offset,
|
||||
buf_write(dest->buf,
|
||||
to->x + x,
|
||||
to->y + y,
|
||||
dest->width,
|
||||
rgb_to_tile_2bpp(r, g, b, to->x + x_offset,
|
||||
to->y + y_offset) ^ 3);
|
||||
r, g, b, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void copy_rgb_to_2bpp_tile(cammy_image *dest,
|
||||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from) {
|
||||
size_t x, y;
|
||||
|
||||
int depth, color;
|
||||
|
||||
format_info_png(dest->format, &depth, &color);
|
||||
|
||||
for (y=0; y < from->height; y++) {
|
||||
if (to->y + y > dest->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (x=0; x < from->width; x++) {
|
||||
uint8_t r, g, b;
|
||||
|
||||
if (to->x + x > from->width) {
|
||||
break;
|
||||
}
|
||||
|
||||
buf_read(src->buf,
|
||||
from->x + x,
|
||||
from->y + y,
|
||||
from->width,
|
||||
&r, &g, &b, depth);
|
||||
|
||||
tile_write((cammy_tile *)dest->buf,
|
||||
to->x + x,
|
||||
to->y + y,
|
||||
dest->width,
|
||||
rgb_to_tile_2bpp(r, g, b, to->x + x,
|
||||
to->y + y) ^ 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_2bpp_tile_to_rgb(cammy_image *dest,
|
||||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from) {
|
||||
size_t x, y;
|
||||
|
||||
int depth, color;
|
||||
|
||||
format_info_png(dest->format, &depth, &color);
|
||||
|
||||
for (y=0; y < from->height; y++) {
|
||||
if (to->y + y > dest->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (x=0; x < from->width; x++) {
|
||||
uint8_t c;
|
||||
|
||||
if (to->x + x > from->width) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = tile_read((cammy_tile *)src->buf,
|
||||
from->x + x,
|
||||
from->y + y,
|
||||
from->width);
|
||||
|
||||
buf_write(src->buf,
|
||||
from->x + x,
|
||||
from->y + y,
|
||||
from->width,
|
||||
src->palette[c].r,
|
||||
src->palette[c].g,
|
||||
src->palette[c].b,
|
||||
depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -562,124 +649,43 @@ void cammy_image_copy(cammy_image *dest,
|
|||
cammy_image *src,
|
||||
cammy_image_point *to,
|
||||
cammy_image_region *from) {
|
||||
if (src->format == dest->format) {
|
||||
switch (src->format) {
|
||||
case CAMMY_IMAGE_2BPP_TILE:
|
||||
copy_2bpp(dest, src, to, from); break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (dest->format) {
|
||||
case CAMMY_IMAGE_2BPP_TILE:
|
||||
copy_2bpp(dest, src, to, from);
|
||||
|
||||
return;
|
||||
|
||||
case CAMMY_IMAGE_24BPP_RGB:
|
||||
case CAMMY_IMAGE_32BPP_RGBA:
|
||||
copy_2bpp_tile_to_rgb(dest, src, to, from);
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dest->format == CAMMY_IMAGE_2BPP_TILE) {
|
||||
switch (src->format) {
|
||||
case CAMMY_IMAGE_24BPP_RGB:
|
||||
copy_to_2bpp_tile(dest, src, to, from, 3);
|
||||
break;
|
||||
|
||||
case CAMMY_IMAGE_32BPP_RGBA:
|
||||
copy_to_2bpp_tile(dest, src, to, from, 4);
|
||||
switch (dest->format) {
|
||||
case CAMMY_IMAGE_2BPP_TILE:
|
||||
copy_rgb_to_2bpp_tile(dest, src, to, from);
|
||||
|
||||
return;
|
||||
|
||||
case CAMMY_IMAGE_24BPP_RGB:
|
||||
case CAMMY_IMAGE_32BPP_RGBA:
|
||||
copy_buf(dest, src, to, from);
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int save_tile_to_file(cammy_tile *tiles, size_t width,
|
||||
size_t height,
|
||||
int file) {
|
||||
static const char *format = "slice%04d.tile";
|
||||
char name[32];
|
||||
int fd;
|
||||
struct stat st;
|
||||
|
||||
if (snprintf(name, sizeof(name), format, file) < 0) {
|
||||
goto error_snprintf_name;
|
||||
}
|
||||
|
||||
if (stat(name, &st) == 0) {
|
||||
errno = EEXIST;
|
||||
|
||||
goto error_exists;
|
||||
}
|
||||
|
||||
if ((fd = open(name, O_CREAT | O_WRONLY, 0644)) < 0) {
|
||||
goto error_open;
|
||||
}
|
||||
|
||||
if (write(fd, tiles, (width * height) >> 2) < 0) {
|
||||
goto error_write;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
|
||||
error_write:
|
||||
close(fd);
|
||||
|
||||
error_open:
|
||||
error_exists:
|
||||
error_snprintf_name:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cammy_image_slice(uint8_t *buf,
|
||||
size_t width,
|
||||
size_t height,
|
||||
size_t x_pad,
|
||||
size_t y_pad,
|
||||
int depth) {
|
||||
cammy_image src = {
|
||||
.format = CAMMY_IMAGE_2BPP_TILE,
|
||||
.size = size_2bpp_tile(width, height),
|
||||
.width = width,
|
||||
.height = height,
|
||||
.buf = buf
|
||||
}, *dest;
|
||||
|
||||
int file = 0;
|
||||
|
||||
size_t x, y;
|
||||
|
||||
if ((dest = cammy_image_new(CAMMY_IMAGE_2BPP_TILE,
|
||||
width,
|
||||
height
|
||||
)) == NULL) {
|
||||
goto error_image_new;
|
||||
}
|
||||
|
||||
for (x=0; x<width; x+=CAMMY_SCREEN_WIDTH + (2 * x_pad)) {
|
||||
for (y=0; y<height; y+=CAMMY_SCREEN_HEIGHT + y_pad) {
|
||||
cammy_image_point to = {
|
||||
0, 0
|
||||
};
|
||||
|
||||
cammy_image_region from = {
|
||||
x + x_pad, y, CAMMY_SCREEN_WIDTH, CAMMY_SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
cammy_image_copy(dest, &src, &to, &from);
|
||||
|
||||
if (save_tile_to_file(dest->tiles, CAMMY_SCREEN_WIDTH,
|
||||
CAMMY_SCREEN_HEIGHT, file++) < 0) {
|
||||
goto error_save_tile_to_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cammy_image_destroy(dest);
|
||||
|
||||
return 0;
|
||||
|
||||
error_save_tile_to_file:
|
||||
cammy_image_destroy(dest);
|
||||
|
||||
error_image_new:
|
||||
return -1;
|
||||
}
|
||||
|
|
12
src/photo.c
12
src/photo.c
|
@ -10,13 +10,23 @@ cammy_image *cammy_photo_export(cammy_photo *src,
|
|||
cammy_tile_palette *palette) {
|
||||
cammy_image *image;
|
||||
|
||||
if ((image = cammy_image_))
|
||||
if ((image = cammy_image_new(format,
|
||||
CAMMY_PHOTO_WIDTH,
|
||||
CAMMY_PHOTO_HEIGHT)) == NULL) {
|
||||
goto error_image_new;
|
||||
}
|
||||
|
||||
cammy_image_copy_from_tile(dest,
|
||||
(cammy_tile *)&src->tiles,
|
||||
CAMMY_PHOTO_WIDTH,
|
||||
CAMMY_PHOTO_HEIGHT,
|
||||
depth,
|
||||
palette);
|
||||
|
||||
return image;
|
||||
|
||||
error_image_new:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cammy_photo_merge(cammy_photo *srcr,
|
||||
|
|
Loading…
Add table
Reference in a new issue