X-Git-Url: https://robinkrens.nl/gitweb/?a=blobdiff_plain;f=tools%2Fbmp2tiles%2Fbmp2tiles.c;h=b919fe9b78bf7b4629deffdc7f765af883e72845;hb=74065e28137eeaf423726b2a54de94d524910505;hp=42a88050e8f90e82fdd253398a86815165c95b14;hpb=e5de2e9ca1eb79d90e6bc662e49a6c23cbf62f40;p=swan-dev diff --git a/tools/bmp2tiles/bmp2tiles.c b/tools/bmp2tiles/bmp2tiles.c index 42a8805..b919fe9 100644 --- a/tools/bmp2tiles/bmp2tiles.c +++ b/tools/bmp2tiles/bmp2tiles.c @@ -2,84 +2,260 @@ * File : bmp2tiles.c * Author : Robin Krens * Date : 04.06.2022 - * Last Modified Date: 12.06.2022 + * Last Modified Date: 15.06.2022 * Last Modified By : Robin Krens */ #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include #include #define TILE_SZ 32 #define FOURBBP_ROW 8 #define FOURBPP_COL 8 -void bmp_info(SDL_Surface * img) +typedef struct { + unsigned width; + unsigned height; + unsigned row_tiles; + unsigned col_tiles; + unsigned bpp; + unsigned char * data; + SDL_Colour * palette; + unsigned short outpal[8]; +} swan_gfx_t; + +int set_info(swan_gfx_t * gfx, SDL_Surface * img) { - SDL_PixelFormat * fmt; - fmt = img->format; - fprintf(stdout,"WIDTH: %d, HEIGHT: %d, BPP: %d\n", img->w, img->h, fmt->BitsPerPixel); -} + gfx->width = img->w; + gfx->height = img->h; + gfx->bpp = img->format->BitsPerPixel; + + if (gfx->bpp != 8) { + fprintf(stderr, "error: %d bpp format detected\n", img->format->BitsPerPixel); + return -1; + } + + if (gfx->width % 8 | gfx->height % 8) { + fprintf(stderr, "error: image not multiple of 16x16 tiles\n \ + width: %d\theight: %d\n", gfx->width, gfx->height); + return -1; + } + gfx->row_tiles = gfx->height / 8; + gfx->col_tiles = gfx->width / 8; -void generate_4bpp_tile_planar(unsigned char *buf, void * userdata, int sz) + /* set userdata to iterate over + * pixels */ + SDL_LockSurface(img); + img->userdata = img->pixels; + gfx->data = (unsigned char *) img->userdata; + gfx->palette = img->format->palette->colors; + SDL_UnlockSurface(img); + + return 0; +} + +void generate_4bpp_tile(unsigned char *buf, swan_gfx_t * gfx, + bool packed) { - unsigned char * ptr = (unsigned char *) userdata; - for (int i = 0; i < 32; i+=4) { - /* fprintf(stdout, "userdata: pos: %d - %d\n", i, *ptr++); */ + unsigned char * ptr = gfx->data; + for (int i = 0; i < TILE_SZ; i+=4) { for (int j = 0; j < 4; ++j) { - for (int x = 0; x < 8; ++x) { - buf[i + j] = ptr[x] << j; + if (packed) { /* packed format */ + //printf("%d %d ", ptr[0], ptr[1]); + if (ptr[0] >= 8 || ptr[1] >= 8) + fprintf(stdout, "warning: too many colors detected\n"); + gfx->outpal[ptr[0]] = (gfx->palette[ptr[0]].r >> 4) << 8 | + (gfx->palette[ptr[0]].g >> 4) << 4 | + gfx->palette[ptr[0]].b >> 4; + buf[i+j] = ptr[0] << 4; + buf[i+j] |= ptr[1]; + ptr += 2; + } else { /* TODO: planar format */ + for (int x = 0; x < 8; ++x) { + if (ptr[x] >= 8) + fprintf(stdout, "warning: too many colors detected\n"); + buf[i + j] = ptr[x] << j; + } } - /* printf("%d: %x\n", i+j, buf[i+j]); */ } - ptr += 8; + if (!packed) + ptr += 8; + else { + ptr += (8 * (gfx->col_tiles-1)); + } } } -void generate_4bpp_tile_packed(unsigned char *buf, void * userdata, int sz) +FILE * openstream(const char * name, const char * prefix, + unsigned tile_nr, bool append) { - unsigned char * ptr = (unsigned char *) userdata; - for (int i = 0; i < 32; i+=4) { - for (int j = 0; j < 4; ++j) { - buf[i+j] = ptr[0] << 4; - buf[i+j] |= ptr[1]; - ptr += 2; - printf("%d: %x\n", i+j, buf[i+j]); - } + assert(strlen(name) < 200); + + FILE * stream; + + unsigned buf_len = 256; + char buf[buf_len]; + snprintf(buf, buf_len, "%s/%s%d.%s", prefix, name, tile_nr, prefix); + + //printf("%s\n", buf); + if (!append) { + stream = fopen(buf, "w"); + } else { + stream = fopen(buf, "a"); } + + return stream; } -int main(void) +int create_dir(const char *name) { - SDL_Surface * rawbmp; - SDL_PixelFormat * fmt; - char filename[] = "test.bmp"; - rawbmp = SDL_LoadBMP(filename); + struct stat statbuf; + + if (stat(name, &statbuf) == -1) + return mkdir(name, 0755); + if ((statbuf.st_mode & S_IFMT) != S_IFDIR) + return -1; + + return 0; +} + + +int main(int argc, char *argv[]) +{ + SDL_Surface * rawbmp; + FILE * gfxstream; + FILE * palstream; + int opt; + char * infile; + char outfile[256]; + bool bout = false; + const short fill = 0xFFFF; + bool seperate_gfx = false; + bool seperate_pal = false; + + while ((opt = getopt(argc, argv, "po:sv")) != -1) { + switch (opt) { + case 'p': + seperate_pal = true; + printf("generate individual .pal for each tile"); + break; + case 'o': + printf("output file %s\n", optarg); + strcpy(outfile, optarg); + bout = true; + break; + case 's': + seperate_gfx = true; + printf("generate .gfx for each tile\n"); + break; + case 'v': + printf("verbose"); + break; + default: /* '?' */ + fprintf(stderr, "Usage: %s [-s] [-o output] file \n", argv[0]); + exit(EXIT_FAILURE); + } + } + + if (optind >= argc) { + fprintf(stderr, "Expected input .bmp file!\n"); + fprintf(stderr, "Usage: %s [-s] [-o output] [file]\n", argv[0]); + exit(EXIT_FAILURE); + } + + infile = argv[optind]; + + rawbmp = SDL_LoadBMP(infile); if (!rawbmp) { - fprintf(stderr, "can not load .bmp file\n"); + fprintf(stderr, "can not load %s file\n", infile); exit(EXIT_FAILURE); } - bmp_info(rawbmp); + swan_gfx_t * gfx = calloc(1, sizeof(swan_gfx_t)); + int ret = set_info(gfx, rawbmp); - SDL_LockSurface(rawbmp); - rawbmp->userdata = rawbmp->pixels; - SDL_UnlockSurface(rawbmp); + if (ret != 0) + goto cleanup; - unsigned char *tile_buf = malloc(sizeof(unsigned char) * TILE_SZ); + unsigned char *tile_buf = calloc(TILE_SZ, sizeof(unsigned char)); - generate_4bpp_tile_packed(tile_buf, rawbmp->userdata, 64); + if (!bout) { + sprintf(outfile, "out"); + } - /* if (rawbmp->format->BitsPerPixel != 24) { - fprintf(stderr, "format %d not supported\n", rawbmp->format->BitsPerPixel); - exit(EXIT_FAILURE); - } */ + /* check for existing gfx/ and pal/ directories */ + ret = create_dir("gfx/"); + ret += create_dir("pal/"); + + if (ret) { + fprintf(stderr, "error: can not create output gfx/ or pal/ location\n"); + goto cleanup; + } + fprintf(stdout, "generating %d tile(s) \ + in %d gfx file(s) \ + with %d pal file(s)\n", + gfx->row_tiles * gfx->col_tiles, + seperate_gfx ? gfx->row_tiles * gfx->col_tiles : 1, + seperate_pal ? gfx->row_tiles * gfx->col_tiles : 1); - SDL_FreeSurface(rawbmp); + for (int i = 0, cnt = 0; i < gfx->row_tiles; ++i) { + for (int j = 0; j < gfx->col_tiles; ++j, ++cnt) { + + if (i == 0 && j == 0) { + gfxstream = openstream(outfile, "gfx", 0, false); + palstream = openstream(outfile, "pal", 0, false); + } else { + if (seperate_gfx) { + gfxstream = openstream(outfile, "gfx", cnt, false); + } + if (seperate_pal) { + palstream = openstream(outfile, "pal", cnt, false); + } + } + + generate_4bpp_tile(tile_buf, gfx, true); + int ret = fwrite(tile_buf, sizeof(unsigned char), TILE_SZ, gfxstream); + if (ret != TILE_SZ) { + fprintf(stderr, "failed to convert, only write %d instead of %d\n", ret, TILE_SZ); + fclose(gfxstream); + goto cleanup; + } + fwrite(gfx->outpal, sizeof(unsigned short), 8, palstream); + for (int i = 0; i < 8; ++i) + ret += fwrite(&fill, sizeof(unsigned short), 1, palstream); + + gfx->data += 8; /* next column */ + + if (gfx->row_tiles == (i-1) && gfx->col_tiles == (j-1)) { + fclose(gfxstream); + fclose(palstream); + } else { + if (seperate_gfx) + fclose(gfxstream); + if (seperate_pal) + fclose(palstream); + } + } + gfx->data += (gfx->col_tiles * 64) - (8 * gfx->col_tiles); + } + +cleanup: + free(gfx); + free(tile_buf); + SDL_FreeSurface(rawbmp); }