// ase2spr, based on atlas code by Sepehr Taghdisian (BSD2 licensed) // - rlyeh, public domain. #include #include #include #include #include #ifndef _MSC_VER #include #define strcmpi strcasecmp #else #define strcmpi stricmp #endif #define ATLAS_REALLOC vrealloc #define ATLAS_MSIZE vlen void* vrealloc( void* p, size_t sz ) { if( !sz ) { if( p ) { size_t *ret = (size_t*)p - 2; ret[0] = 0; ret[1] = 0; realloc( ret, 0 ); } return 0; } else { size_t *ret; if( !p ) { ret = (size_t*)realloc( 0, sizeof(size_t) * 2 + sz ); ret[0] = sz; ret[1] = 0; } else { ret = (size_t*)p - 2; size_t osz = ret[0]; size_t ocp = ret[1]; if( sz <= (osz + ocp) ) { ret[0] = sz; ret[1] = ocp - (sz - osz); } else { ret = (size_t*)realloc( ret, sizeof(size_t) * 2 + sz * 1.75 ); ret[0] = sz; ret[1] = (size_t)(sz * 1.75) - sz; } } return &ret[2]; } } size_t vlen( void* p ) { return p ? 0[ (size_t*)p - 2 ] : 0; } char *STRDUP(const char *s) { size_t n = strlen(s)+1; return ((char*)memcpy(ATLAS_REALLOC(0,n), s, n)); } ///- static unsigned array_c; #define array(t) t* #define array_push(arr, v) ( array_c = array_count(arr), array_c[(arr) = vrealloc((arr), (array_c + 1) * sizeof(0[arr]))] = (v) ) #define array_pop(arr) ( (arr) ? (arr) = vrealloc((arr), (array_count(arr)-1) * sizeof(0[arr])) : (0) ) #define array_count(arr) (int)( (arr) ? vlen(arr) / sizeof(0[arr]) : sizeof(0[arr]) - sizeof(0[arr]) ) #define array_free(arr) ( (arr) ? (vrealloc(arr, 0), 1) : 0 ) const uint64_t hash_init = 14695981039346656037ULL; uint64_t hash_bin(const void* ptr, unsigned len, uint64_t hash ) { for( unsigned char *str = (unsigned char *)ptr; len--; ) hash = ( (unsigned char)*str++ ^ hash ) * 0x100000001b3ULL; return hash; } char *trimspace(char *str) { for( char *s = str; *s; ++s ) if(*s <= 32) memmove(s, s+1, strlen(s)); return str; } char* strcatf(char **src_, const char *fmt, ...) { static char buf[1024] = {0}; va_list va; va_start(va, fmt); int buflen = vsnprintf( buf, sizeof(buf), fmt, va ); va_end(va); char *src = src_ ? *src_ : 0; int srclen = (src ? strlen(src) : 0); src = (char*)vrealloc(src, srclen + buflen + 1 ); memcpy(src + srclen, buf, buflen + 1 ); if(src_) *src_ = src; return src; } #ifdef __TINYC__ #define STBI_NO_SIMD #endif #define STB_IMAGE_IMPLEMENTATION #include "3rd_stb_image.h" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "3rd_stb_image_write.h" #define STB_IMAGE_RESIZE_IMPLEMENTATION #include "3rd_stb_image_resize.h" #define STB_RECT_PACK_IMPLEMENTATION #include "3rd_stb_rect_pack.h" #define S2O_IMPLEMENTATION #include "3rd_sproutline.h" #define DELAUNAY_C #include "3rd_delaunay.h" #define CUTE_ASEPRITE_IMPLEMENTATION #include "3rd_aseprite.h" #define DIR_C #include "3rd_archive.h" #define MALLOC(sz) ATLAS_REALLOC(0,(sz)) #define FREE(p) ATLAS_REALLOC((p),0) #define BASE64_C #include "3rd_base64.h" #define ATLASC_IMPLEMENTATION #include "3rd_atlasc.h" #if defined _WIN32 && defined _MSC_VER __declspec(dllexport) #elif defined _WIN32 && defined __GNUC__ __attribute__ ((dllexport)) #endif int main(int argc, char* argv[]) { const char *help = " [flags] -o outfile [folder or file...]\n\n" "-h Show help\n" "-V Show version\n" "-o Output file (defaults: stdout)\n" "-W Maximum output image width (default:1024)\n" "-H Maximum output image height (default:1024)\n" "-B Border size for each sprite (default:2)\n" "-2 Make output image size power-of-two\n" "-P Set padding for each sprite (default:1)\n" "-m Make sprite meshes\n" "-M Set maximum vertices for each generated sprite mesh (default:25)\n" "-A Alpha threshold for cropping [1..255] (default:20)\n" "-s Set scale for individual images (default:1.0)\n\n" ; atlas_flags flags = { .alpha_threshold = 20, .max_width = 2048, .max_height = 2048, .border = 2, .padding = 1, .max_verts_per_mesh = 25, .scale = 1.0 }; array(char*) files = 0; char *outfile = 0; for( int i = 1; i < argc; ++i) { const char *arg = argv[i]; if( arg[0] != '-' ) { assert(array_count(files) == 0); if( path_isfile(arg) ) array_push(files, STRDUP(arg)); else for( dir *d = dir_open(arg, "r"); d; dir_close(d), d = 0) { for( int i = 0, end = dir_count(d); i < end; ++i ) { if( path_isfile(dir_name(d, i))) array_push(files, STRDUP(dir_name(d, i))); } } assert(array_count(files) == 1); } else switch( arg[1] ) { case 'V': exit(-printf("%s\nUsing atlasc v" ATLASC_VERSION "\n", argv[0])); case '2': flags.pot = 1; break; case 'm': flags.mesh = 1; break; case '?': case 'h': exit(-printf("%s%s", argv[0], help)); case 'o': outfile = argv[++i]; break; case 'A': flags.alpha_threshold = atoi(argv[++i]); break; case 'W': flags.max_width = atoi(argv[++i]); break; case 'H': flags.max_height = atoi(argv[++i]); break; case 'B': flags.border = atoi(argv[++i]); break; case 'P': flags.padding = atoi(argv[++i]); break; case 'M': flags.max_verts_per_mesh = atoi(argv[++i]); break; case 's': flags.scale = atof(argv[++i]); break; default: exit(-printf("Unknown argument: %s\n", arg)); } } if( flags.scale < 0.0001f ) { printf("%s%s", argv[0], help); return(-puts("invalid `scale` parameter")); } if( !files ) { printf("%s%s", argv[0], help); return(-puts("no input file(s)")); } if( !outfile ) outfile = "stdout"; char *error = g_error_str; atlas_t* atlas = atlas_loadfiles(files, flags); if ( atlas ) { bool r = atlas_save(outfile, atlas, flags); if( r ) { // fprintf(stderr, "Written: %d->%d\n", flags.num_files, !!r); error = 0; } atlas_free(atlas); } // for( int i = 0; i < array_count(files); ++i) // ATLAS_REALLOC(files[i], 0); // array_free(files); return error ? fprintf(stderr, "%s\n", error), -1 : 0; } // cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT // cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT /LD // tcc ase2ini.c -I ..\engine\split -DNDEBUG // cc ase2ini.c -I ../engine/split -lm -O3 -oase2ini.linux