From 1eff62bd9d4a97bab3973aaf55f64aabc9ec9876 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 19 Aug 2016 21:10:41 +0100 Subject: allow icons with transparaency to be saved in P7 format --- test/decode_ico.c | 315 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 182 insertions(+), 133 deletions(-) diff --git a/test/decode_ico.c b/test/decode_ico.c index 935001c..266b3bb 100644 --- a/test/decode_ico.c +++ b/test/decode_ico.c @@ -7,6 +7,11 @@ * http://www.opensource.org/licenses/mit-license.php */ +/** + * \file + * Use libnsbmp to decode icons into ppm or pam files for testing + */ + #include #include #include @@ -32,172 +37,216 @@ size_t bitmap_get_bpp(void *bitmap); void bitmap_destroy(void *bitmap); +static void write_pam(FILE* fh, const char *name, struct bmp_image *bmp) +{ + uint16_t row, col; + uint8_t *image; + + fprintf(fh, "P7\n"); + fprintf(fh, "# %s\n", name); + fprintf(fh, "WIDTH %u\n", bmp->width); + fprintf(fh, "HEIGHT %u\n", bmp->height); + fprintf(fh, "DEPTH 4\n"); + fprintf(fh, "MAXVAL 255\n"); + fprintf(fh, "TUPLTYPE RGB_ALPHA\n"); + fprintf(fh, "ENDHDR\n"); + + + image = (uint8_t *) bmp->bitmap; + for (row = 0; row != bmp->height; row++) { + for (col = 0; col != bmp->width; col++) { + size_t z = (row * bmp->width + col) * BYTES_PER_PIXEL; + putc(image[z], fh); + putc(image[z + 1], fh); + putc(image[z + 2], fh); + putc(image[z + 3], fh); + } + } + +} + +static void write_ppm(FILE* fh, const char *name, struct bmp_image *bmp) +{ + uint16_t row, col; + uint8_t *image; + + fprintf(fh, "P3\n"); + fprintf(fh, "# %s\n", name); + fprintf(fh, "# width %u \n", bmp->width); + fprintf(fh, "# height %u \n", bmp->height); + fprintf(fh, "%u %u 256\n", bmp->width, bmp->height); + + image = (uint8_t *) bmp->bitmap; + for (row = 0; row != bmp->height; row++) { + for (col = 0; col != bmp->width; col++) { + size_t z = (row * bmp->width + col) * BYTES_PER_PIXEL; + fprintf(fh, "%u %u %u ", + image[z], + image[z + 1], + image[z + 2]); + } + fprintf(fh, "\n"); + } +} + int main(int argc, char *argv[]) { - bmp_bitmap_callback_vt bitmap_callbacks = { - bitmap_create, - bitmap_destroy, - bitmap_get_buffer, - bitmap_get_bpp - }; - uint16_t width, height; - ico_collection ico; - bmp_result code; - struct bmp_image *bmp; - size_t size; - unsigned short res = 0; - - if ((argc < 2) || (argc > 4)) { - fprintf(stderr, "Usage: %s collection.ico [width=255] [height=255]\n", argv[0]); - return 1; - } - width = (argc >= 3) ? atoi(argv[2]) : 255; - height = (argc == 4) ? atoi(argv[3]) : 255; - - /* create our bmp image */ - ico_collection_create(&ico, &bitmap_callbacks); - - /* load file into memory */ - unsigned char *data = load_file(argv[1], &size); - - /* analyse the BMP */ - code = ico_analyse(&ico, size, data); - if (code != BMP_OK) { - warning("ico_analyse", code); - res = 1; - goto cleanup; - } - - /* decode the image */ - bmp = ico_find(&ico, width, height); - assert(bmp); - - code = bmp_decode(bmp); - /* code = bmp_decode_trans(bmp, TRANSPARENT_COLOR); */ - if (code != BMP_OK) { - warning("bmp_decode", code); - /* allow partially decoded images */ - if (code != BMP_INSUFFICIENT_DATA) { - res = 1; - goto cleanup; - } - } - - printf("P3\n"); - printf("# %s\n", argv[1]); - printf("# width %u \n", bmp->width); - printf("# height %u \n", bmp->height); - printf("%u %u 256\n", bmp->width, bmp->height); - - { - uint16_t row, col; - uint8_t *image; - image = (uint8_t *) bmp->bitmap; - for (row = 0; row != bmp->height; row++) { - for (col = 0; col != bmp->width; col++) { - size_t z = (row * bmp->width + col) * BYTES_PER_PIXEL; - printf("%u %u %u ", image[z], - image[z + 1], - image[z + 2]); - } - printf("\n"); - } - } + bmp_bitmap_callback_vt bitmap_callbacks = { + bitmap_create, + bitmap_destroy, + bitmap_get_buffer, + bitmap_get_bpp + }; + uint16_t width, height; + ico_collection ico; + bmp_result code; + struct bmp_image *bmp; + size_t size; + unsigned short res = 0; + unsigned char *data; + + if ((argc < 2) || (argc > 4)) { + fprintf(stderr, "Usage: %s collection.ico [width=255] [height=255]\n", argv[0]); + return 1; + } + width = (argc >= 3) ? atoi(argv[2]) : 255; + height = (argc == 4) ? atoi(argv[3]) : 255; + + /* create our bmp image */ + ico_collection_create(&ico, &bitmap_callbacks); + + /* load file into memory */ + data = load_file(argv[1], &size); + + /* analyse the BMP */ + code = ico_analyse(&ico, size, data); + if (code != BMP_OK) { + warning("ico_analyse", code); + res = 1; + goto cleanup; + } + + /* decode the image */ + bmp = ico_find(&ico, width, height); + assert(bmp); + + code = bmp_decode(bmp); + /* code = bmp_decode_trans(bmp, TRANSPARENT_COLOR); */ + if (code != BMP_OK) { + warning("bmp_decode", code); + /* allow partially decoded images */ + if ((code != BMP_INSUFFICIENT_DATA) && + (code != BMP_DATA_ERROR)) { + res = 1; + goto cleanup; + } + + /* skip if the decoded image would be ridiculously large */ + if ((bmp->width * bmp->height) > 200000) { + res = 1; + goto cleanup; + } + } + + if (bmp->opaque) { + write_ppm(stdout, argv[1], bmp); + } else { + write_pam(stdout, argv[1], bmp); + } cleanup: - /* clean up */ - ico_finalise(&ico); - free(data); + /* clean up */ + ico_finalise(&ico); + free(data); - return res; + return res; } unsigned char *load_file(const char *path, size_t *data_size) { - FILE *fd; - struct stat sb; - unsigned char *buffer; - size_t size; - size_t n; - - fd = fopen(path, "rb"); - if (!fd) { - perror(path); - exit(EXIT_FAILURE); - } - - if (stat(path, &sb)) { - perror(path); - exit(EXIT_FAILURE); - } - size = sb.st_size; - - buffer = malloc(size); - if (!buffer) { - fprintf(stderr, "Unable to allocate %lld bytes\n", - (long long) size); - exit(EXIT_FAILURE); - } - - n = fread(buffer, 1, size, fd); - if (n != size) { - perror(path); - exit(EXIT_FAILURE); - } - - fclose(fd); - - *data_size = size; - return buffer; + FILE *fd; + struct stat sb; + unsigned char *buffer; + size_t size; + size_t n; + + fd = fopen(path, "rb"); + if (!fd) { + perror(path); + exit(EXIT_FAILURE); + } + + if (stat(path, &sb)) { + perror(path); + exit(EXIT_FAILURE); + } + size = sb.st_size; + + buffer = malloc(size); + if (!buffer) { + fprintf(stderr, "Unable to allocate %lld bytes\n", + (long long) size); + exit(EXIT_FAILURE); + } + + n = fread(buffer, 1, size, fd); + if (n != size) { + perror(path); + exit(EXIT_FAILURE); + } + + fclose(fd); + + *data_size = size; + return buffer; } void warning(const char *context, bmp_result code) { - fprintf(stderr, "%s failed: ", context); - switch (code) { - case BMP_INSUFFICIENT_MEMORY: - fprintf(stderr, "BMP_INSUFFICIENT_MEMORY"); - break; - case BMP_INSUFFICIENT_DATA: - fprintf(stderr, "BMP_INSUFFICIENT_DATA"); - break; - case BMP_DATA_ERROR: - fprintf(stderr, "BMP_DATA_ERROR"); - break; - default: - fprintf(stderr, "unknown code %i", code); - break; - } - fprintf(stderr, "\n"); + fprintf(stderr, "%s failed: ", context); + switch (code) { + case BMP_INSUFFICIENT_MEMORY: + fprintf(stderr, "BMP_INSUFFICIENT_MEMORY"); + break; + case BMP_INSUFFICIENT_DATA: + fprintf(stderr, "BMP_INSUFFICIENT_DATA"); + break; + case BMP_DATA_ERROR: + fprintf(stderr, "BMP_DATA_ERROR"); + break; + default: + fprintf(stderr, "unknown code %i", code); + break; + } + fprintf(stderr, "\n"); } void *bitmap_create(int width, int height, unsigned int state) { - (void) state; /* unused */ - return calloc(width * height, BYTES_PER_PIXEL); + (void) state; /* unused */ + return calloc(width * height, BYTES_PER_PIXEL); } unsigned char *bitmap_get_buffer(void *bitmap) { - assert(bitmap); - return bitmap; + assert(bitmap); + return bitmap; } size_t bitmap_get_bpp(void *bitmap) { - (void) bitmap; /* unused */ - return BYTES_PER_PIXEL; + (void) bitmap; /* unused */ + return BYTES_PER_PIXEL; } void bitmap_destroy(void *bitmap) { - assert(bitmap); - free(bitmap); + assert(bitmap); + free(bitmap); } - -- cgit v1.2.3