Created
May 14, 2019 18:12
-
-
Save PikalaxALT/b720087fb365788b282cefc9e3f68d0a to your computer and use it in GitHub Desktop.
C script which prints x, y, and y_offset fields of sprite coordinates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <png.h> | |
#include <stdlib.h> | |
#define FATAL_ERROR(...) ({fprintf(stderr, __VA_ARGS__);exit(1);}) | |
#define min(a, b) ((a) < (b) ? (a) : (b)) | |
struct Image | |
{ | |
unsigned width; | |
unsigned height; | |
unsigned char * pixels; | |
unsigned char bitDepth; | |
unsigned char pixelsPerByte; | |
unsigned char mask; | |
}; | |
static int image_get_pixel(struct Image const * image, int x, int y) { | |
int pixelOffset = y * image->width + x; | |
int pixel = image->pixels[pixelOffset / image->pixelsPerByte]; | |
pixel >>= image->bitDepth * (pixelOffset % image->pixelsPerByte); | |
return pixel & image->mask; | |
} | |
static int get_left_margin(struct Image const * image) { | |
int maxw = image->width / 2; | |
for (int x = 0; x < maxw; x++) { | |
for (int y = 0; y < image->height; y++) { | |
if (image_get_pixel(image, x, y)) return x; | |
} | |
} | |
return maxw; | |
} | |
static int get_right_margin(struct Image const * image) { | |
int maxw = image->width / 2; | |
for (int x = 0; x < maxw; x++) { | |
for (int y = 0; y < image->height; y++) { | |
if (image_get_pixel(image, image->width - x - 1, y)) return x; | |
} | |
} | |
return maxw; | |
} | |
static int get_top_margin(struct Image const * image) { | |
int maxh = image->height / 2; | |
for (int y = 0; y < maxh; y++) { | |
for (int x = 0; x < image->width; x++) { | |
if (image_get_pixel(image, x, y)) return y; | |
} | |
} | |
return maxh; | |
} | |
static int get_bottom_margin(struct Image const * image) { | |
int maxh = image->height / 2; | |
for (int y = 0; y < maxh; y++) { | |
for (int x = 0; x < image->width; x++) { | |
if (image_get_pixel(image, x, image->height - y - 1)) return y; | |
} | |
} | |
return maxh; | |
} | |
static void read_png(const char * path, struct Image * image) { | |
png_structp png_ptr; | |
png_infop info_ptr; | |
FILE *fp = fopen(path, "rb"); | |
unsigned char sig[8]; | |
if (fp == NULL) | |
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); | |
if (fread(sig, sizeof(unsigned char), 8, fp) != 8) | |
FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path); | |
if (png_sig_cmp(sig, 0, 8)) | |
FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path); | |
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
if (!png_ptr) | |
FATAL_ERROR("Failed to create PNG read struct.\n"); | |
info_ptr = png_create_info_struct(png_ptr); | |
if (!info_ptr) | |
FATAL_ERROR("Failed to create PNG info struct.\n"); | |
if (setjmp(png_jmpbuf(png_ptr))) | |
FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path); | |
png_init_io(png_ptr, fp); | |
png_set_sig_bytes(png_ptr, 8); | |
png_read_info(png_ptr, info_ptr); | |
image->width = png_get_image_width(png_ptr, info_ptr); | |
image->height = png_get_image_height(png_ptr, info_ptr); | |
image->bitDepth = png_get_bit_depth(png_ptr, info_ptr); | |
if (image->bitDepth != 1 && image->bitDepth != 2 && image->bitDepth != 4 && image->bitDepth != 8) | |
FATAL_ERROR("Bit depth of image must be 1, 2, 4, or 8."); | |
unsigned rowbytes = png_get_rowbytes(png_ptr, info_ptr); | |
image->mask = (1 << image->bitDepth) - 1; | |
image->pixelsPerByte = 8 / image->bitDepth; | |
image->pixels = malloc(image->height * rowbytes); | |
if (image->pixels == NULL) | |
FATAL_ERROR("Failed to allocate pixel buffer.\n"); | |
png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); | |
if (row_pointers == NULL) | |
FATAL_ERROR("Failed to allocate row pointers.\n"); | |
for (int i = 0; i < image->height; i++) | |
row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); | |
if (setjmp(png_jmpbuf(png_ptr))) | |
FATAL_ERROR("Error reading from \"%s\".\n", path); | |
png_read_image(png_ptr, row_pointers); | |
png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
fclose(fp); | |
free(row_pointers); | |
} | |
static void get_sprite_coords(const char * path, int *width, int *height, int *bottom) { | |
struct Image image = {}; | |
read_png(path, &image); | |
int left = get_left_margin(&image); | |
int right = get_right_margin(&image); | |
int top = get_top_margin(&image); | |
*bottom = get_bottom_margin(&image); | |
*width = image.width / 8 - min(left, right) / 4; | |
*height = image.height / 8 - min(top, *bottom) / 4; | |
free(image.pixels); | |
} | |
int main(int argc, char ** argv) { | |
for (int i = 1; i < argc; i++) { | |
int width, height, bottom; | |
get_sprite_coords(argv[i], &width, &height, &bottom); | |
printf("%s %d %d %d\n", argv[i], width, height, bottom); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment