diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39a33ed..924d397 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,41 +1,31 @@ name: CI on: [push, pull_request] jobs: - test-ubuntu: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install dependencies - run: | - sudo .github/workflows/install-deps.sh - - name: Test - run: | - gmake test - - test-bsd: + bsd: runs-on: ${{ matrix.os.host }} strategy: matrix: os: - name: freebsd architecture: x86-64 - version: '13.2' + version: '14.1' host: ubuntu-latest + - name: netbsd architecture: x86-64 - version: '9.3' + version: '10.0' host: ubuntu-latest + - name: openbsd architecture: x86-64 - version: '7.4' + version: '7.5' host: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Run CI script on ${{ matrix.os.name }} - uses: cross-platform-actions/action@v0.24.0 + uses: cross-platform-actions/action@v0.25.0 with: operating_system: ${{ matrix.os.name }} architecture: ${{ matrix.os.architecture }} @@ -47,3 +37,58 @@ jobs: # See https://github.com/cross-platform-actions/action/issues/75 sudo .github/workflows/install-deps.sh gmake test + + linux: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo .github/workflows/install-deps.sh + + - name: Test + run: | + gmake test + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: hicolor-linux-x86_64 + path: | + hicolor + + windows: + runs-on: windows-latest + steps: + - name: 'Disable `autocrlf` in Git' + run: git config --global core.autocrlf false + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up MSYS2 + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: mingw32 + install: | + make + mingw-w64-i686-gcc + mingw-w64-i686-libpng + mingw-w64-i686-pkgconf + mingw-w64-i686-zlib + tcl + + - name: Test + shell: msys2 {0} + run: | + make test + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: hicolor-win32 + path: | + hicolor.exe diff --git a/.github/workflows/install-deps.sh b/.github/workflows/install-deps.sh index 2e6f9a2..8114e13 100755 --- a/.github/workflows/install-deps.sh +++ b/.github/workflows/install-deps.sh @@ -2,19 +2,19 @@ set -e if [ "$(uname)" = Linux ]; then - apt-get install -y graphicsmagick + apt-get install -y graphicsmagick pkgconf fi if [ "$(uname)" = FreeBSD ]; then - pkg install -y gmake GraphicsMagick tcl86 + pkg install -y gmake GraphicsMagick png pkgconf tcl86 ln -s /usr/local/bin/tclsh8.6 /usr/local/bin/tclsh fi if [ "$(uname)" = NetBSD ]; then - pkgin -y install gmake GraphicsMagick tcl + pkgin -y install gmake GraphicsMagick png pkgconf tcl zlib fi if [ "$(uname)" = OpenBSD ]; then - pkg_add -I gmake GraphicsMagick tcl%8.6 + pkg_add -I gmake GraphicsMagick png pkgconf tcl%8.6 ln -s /usr/local/bin/tclsh8.6 /usr/local/bin/tclsh fi diff --git a/GNUmakefile b/GNUmakefile index e9e301a..30c9be9 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,13 +1,13 @@ -WIN32_CC ?= i686-w64-mingw32-gcc -CFLAGS ?= -g -O3 -static -ffunction-sections -fdata-sections -Wl,--gc-sections -lm -Wall -Wextra +LIBPNG ?= $(shell pkg-config --cflags libpng) $(shell pkg-config --libs libpng) +ZLIB ?= $(shell pkg-config --cflags zlib) $(shell pkg-config --libs zlib) + +CFLAGS ?= -g -O3 -static -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra $(LIBPNG) $(ZLIB) -lm PREFIX ?= /usr/local all: hicolor hicolor: cli.c hicolor.h vendor/cute_png.h $(CC) $< -o $@ $(CFLAGS) -hicolor.exe: cli.c hicolor.h vendor/cute_png.h - $(WIN32_CC) $< -o $@ $(CFLAGS) clean: clean-no-ext clean-exe clean-no-ext: -rm -f hicolor @@ -21,11 +21,9 @@ install-include: hicolor.h install -m 0644 $< $(DESTDIR)$(PREFIX)/include release: clean-no-ext test - cp hicolor hicolor-v"$$(./hicolor version)"-"$$(uname | tr 'A-Z' 'a-z')"-"$$(uname -m)" + cp hicolor hicolor-v"$$(./hicolor version | head -n 1 | awk '{ print $$2 }')"-"$$(uname | tr 'A-Z' 'a-z')"-"$$(uname -m)" test: all tests/hicolor.test -test-wine: hicolor.exe - HICOLOR_COMMAND='wine ../hicolor.exe' WINEDEBUG=-all tests/hicolor.test -.PHONY: all clean install-bin install-include test test-wine +.PHONY: all clean install-bin install-include test diff --git a/README.md b/README.md index 2e26102..f4d0866 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,9 @@ It is known to work on Linux (aarch64, i386, riscv64, x86_64), FreeBSD, NetBSD, ### Security -The command-line version of HiColor (but not the library) uses [cute_png](https://github.com/RandyGaul/cute_headers) to read PNG files. -cute_png is intended for trusted input. -This means that a maliciously-crafted PNG file could hack the HiColor CLI. -To be safe, only feed HiColor PNG files you created yourself. -Recompress PNG files from the Internet with a trusted program. +The command-line program (but not the library) was vulnerable to malicious PNG files +because it used a PNG library intended only for trusted input. +The vulnerabilities were fixed in version 0.6.0 by switching to libpng. ### PNG file size @@ -80,7 +78,7 @@ Use it to create high-color images readable by other programs. `info` displays information about a HiColor file: version (`5` for 15-bit or `6` for 16), width, and height. ```none -HiColor 0.5.0 +HiColor 0.6.0 Create 15/16-bit color RGB images. usage: @@ -94,7 +92,7 @@ commands: decode convert HiColor to PNG quantize quantize PNG to PNG info print HiColor image version and resolution - version print program version + version print version of HiColor, libpng, and zlib help print this help message options: @@ -114,16 +112,15 @@ sudo apt install -y build-essential graphicsmagick tclsh gmake test ``` -### Cross-compiling for Windows +### Windows -The following commands build a 32-bit executable for Windows. +Install [MSYS2](https://www.msys2.org/). +Run the following commands in the MSYS2 mingw32 shell +to build an x86 executable for Windows. ```sh -sudo apt install -y build-essential gcc-mingw-w64-i686 -gmake hicolor.exe -# Wine, Tcl, and GraphicsMagick are needed only for testing. -sudo apt install -y graphicsmagick tclsh wine -gmake test-wine +pacman -Syuu make mingw-w64-i686-gcc mingw-w64-i686-libpng mingw-w64-i686-pkgconf mingw-w64-i686-zlib tcl +make test ``` ## Alternatives @@ -142,7 +139,8 @@ What differentiates HiColor is being a small dedicated tool and embeddable C lib MIT. -[cute_png](https://github.com/RandyGaul/cute_headers/) is copyright (c) 2019, 2021-2023 Randy Gaul and is licensed under the zlib license. +HiColor uses [libpng](http://www.libpng.org/pub/png/libpng.html) and [zlib](https://www.zlib.net/). +Follow the links for their respective licenses. ### Photos from Unsplash diff --git a/cli.c b/cli.c index a3fa140..457f76d 100644 --- a/cli.c +++ b/cli.c @@ -1,18 +1,21 @@ /* HiColor CLI. * - * Copyright (c) 2021, 2023 D. Bohdan and contributors listed in AUTHORS. + * Copyright (c) 2021, 2023-2024 D. Bohdan and contributors listed in AUTHORS. * License: MIT. */ +#include +#include #include -#define CUTE_PNG_IMPLEMENTATION -#include "vendor/cute_png.h" +#include +#include #define HICOLOR_IMPLEMENTATION #include "hicolor.h" #define HICOLOR_CLI_ERROR "error: " +#define HICOLOR_CLI_LIB_NAME_FORMAT "%-9s" #define HICOLOR_CLI_NO_MEMORY_EXIT_CODE 255 #define HICOLOR_CLI_CMD_ENCODE "encode" @@ -22,61 +25,223 @@ #define HICOLOR_CLI_CMD_VERSION "version" #define HICOLOR_CLI_CMD_HELP "help" -bool check_and_report_error(char* step, hicolor_result res) +const char* libpng_error_msg; + +void libpng_error_handler( + png_structp png_ptr, + png_const_charp error_msg +) { - if (res == HICOLOR_OK) return false; + libpng_error_msg = error_msg; + longjmp(png_jmpbuf(png_ptr), 1); +} - fprintf( - stderr, - HICOLOR_CLI_ERROR "%s: %s\n", - step, - hicolor_error_message(res) - ); +bool load_png( + const char* filename, + int* width, + int* height, + hicolor_rgb** rgb_img, + uint8_t** alpha +) +{ + FILE* fp = fopen(filename, "rb"); + if (!fp) { + fprintf(stderr, HICOLOR_CLI_ERROR "can't open file %s for reading\n", filename); + return false; + } + + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, libpng_error_handler, NULL); + if (!png) { + fclose(fp); + return false; + } + + png_infop info = png_create_info_struct(png); + if (!info) { + png_destroy_read_struct(&png, NULL, NULL); + fclose(fp); + return false; + } + + if (setjmp(png_jmpbuf(png))) { + png_destroy_read_struct(&png, &info, NULL); + fclose(fp); + return false; + } + + png_init_io(png, fp); + png_read_info(png, info); + + *width = png_get_image_width(png, info); + *height = png_get_image_height(png, info); + png_byte color_type = png_get_color_type(png, info); + png_byte bit_depth = png_get_bit_depth(png, info); + + if (bit_depth == 16) { + png_set_strip_16(png); + } + + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png); + } + + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png); + } + + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + } + + if (color_type == PNG_COLOR_TYPE_RGB + || color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_filler(png, 0xFF, PNG_FILLER_AFTER); + } + + if (color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png); + } + + png_read_update_info(png, info); + + *rgb_img = malloc(sizeof(hicolor_rgb) * *width * *height); + *alpha = malloc(sizeof(uint8_t) * *width * *height); + + if (*rgb_img == NULL || *alpha == NULL) { + png_destroy_read_struct(&png, &info, NULL); + fclose(fp); + return false; + } + + png_bytep row = malloc(png_get_rowbytes(png, info)); + if (row == NULL) { + free(*rgb_img); + free(*alpha); + png_destroy_read_struct(&png, &info, NULL); + fclose(fp); + return false; + } + + for (int y = 0; y < *height; y++) { + png_read_row(png, row, NULL); + + for (int x = 0; x < *width; x++) { + png_bytep pixel = &(row[x * 4]); + (*rgb_img)[y * (*width) + x].r = pixel[0]; + (*rgb_img)[y * (*width) + x].g = pixel[1]; + (*rgb_img)[y * (*width) + x].b = pixel[2]; + (*alpha)[y * (*width) + x] = pixel[3]; + } + } + + free(row); + png_destroy_read_struct(&png, &info, NULL); + fclose(fp); return true; } -hicolor_rgb* cp_to_rgb(const cp_image_t img) +bool save_png( + const char* filename, + int width, + int height, + const hicolor_rgb* rgb_img, + const uint8_t* alpha +) { - hicolor_rgb* rgb_img = malloc(sizeof(hicolor_rgb) * img.w * img.h); - if (rgb_img == NULL) return NULL; + FILE* fp = fopen(filename, "wb"); + if (!fp) { + fprintf(stderr, HICOLOR_CLI_ERROR "can't open file %s for writing\n", filename); + return false; + } + + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, libpng_error_handler, NULL); + if (!png) { + fclose(fp); + return false; + } + + png_infop info = png_create_info_struct(png); + if (!info) { + png_destroy_write_struct(&png, NULL); + fclose(fp); + return false; + } + + if (setjmp(png_jmpbuf(png))) { + png_destroy_write_struct(&png, &info); + fclose(fp); + return false; + } + + png_init_io(png, fp); + + png_set_IHDR( + png, + info, + width, + height, + 8, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT + ); + png_set_compression_level(png, 9); + png_write_info(png, info); + + png_bytep row = malloc(png_get_rowbytes(png, info)); + if (row == NULL) { + png_destroy_write_struct(&png, &info); + fclose(fp); + return false; + } - for (uint32_t i = 0; i < (uint32_t) img.w * (uint32_t) img.h; i++) { - rgb_img[i].r = img.pix[i].r; - rgb_img[i].g = img.pix[i].g; - rgb_img[i].b = img.pix[i].b; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + png_bytep pixel = &(row[x * 4]); + pixel[0] = rgb_img[y * width + x].r; + pixel[1] = rgb_img[y * width + x].g; + pixel[2] = rgb_img[y * width + x].b; + pixel[3] = alpha == NULL ? 255 : alpha[y * width + x]; + } + + png_write_row(png, row); } - return rgb_img; + free(row); + png_write_end(png, NULL); + png_destroy_write_struct(&png, &info); + fclose(fp); + + return true; } -cp_image_t rgb_to_cp(const hicolor_metadata meta, const hicolor_rgb* rgb_img) +bool check_and_report_error( + char* step, + hicolor_result res +) { - cp_pixel_t* pix = - malloc(sizeof(cp_pixel_t) * meta.width * meta.height); - cp_image_t img = { - .w = meta.width, - .h = meta.height, - .pix = pix - }; - if (pix == NULL) { - img.w = 0; - img.h = 0; + if (res == HICOLOR_OK) { + return false; } - for (uint32_t i = 0; i < (uint32_t) img.w * (uint32_t) img.h; i++) { - img.pix[i].r = rgb_img[i].r; - img.pix[i].g = rgb_img[i].g; - img.pix[i].b = rgb_img[i].b; - img.pix[i].a = 255; - } + fprintf( + stderr, + HICOLOR_CLI_ERROR "%s: %s\n", + step, + hicolor_error_message(res) + ); - return img; + return true; } bool check_src_exists( const char* src -) { +) +{ if (access(src, F_OK) != 0) { fprintf( stderr, @@ -103,13 +268,15 @@ bool png_to_hicolor( return false; } - cp_image_t png_img = cp_load_png(src); - if (png_img.pix == 0) { + int width, height; + hicolor_rgb* rgb_img = NULL; + uint8_t* alpha = NULL; + if (!load_png(src, &width, &height, &rgb_img, &alpha)) { fprintf( stderr, HICOLOR_CLI_ERROR "can't load PNG file \"%s\": %s\n", src, - cp_error_reason + libpng_error_msg ); return false; } @@ -121,29 +288,23 @@ bool png_to_hicolor( HICOLOR_CLI_ERROR "can't open file \"%s\" for writing\n", dest ); + + free(rgb_img); return false; } hicolor_metadata meta = { .version = version, - .width = png_img.w, - .height = png_img.h + .width = width, + .height = height }; res = hicolor_write_header(hi_file, meta); + bool success = false; if (check_and_report_error("can't write header", res)) { goto clean_up_file; } - hicolor_rgb* rgb_img = cp_to_rgb(png_img); - if (rgb_img == NULL) { - fprintf( - stderr, - HICOLOR_CLI_ERROR "can't allocate memory for RGB image\n" - ); - goto clean_up_file; - } - res = hicolor_quantize_rgb_image(meta, dither, rgb_img); if (check_and_report_error("can't quantize image", res)) { goto clean_up_images; @@ -157,9 +318,6 @@ bool png_to_hicolor( success = true; clean_up_images: - free(png_img.pix); - CUTE_PNG_MEMSET(&png_img, 0, sizeof(png_img)); - free(rgb_img); clean_up_file: @@ -182,57 +340,39 @@ bool png_quantize( return false; } - cp_image_t png_img = cp_load_png(src); - if (png_img.pix == 0) { + int width, height; + hicolor_rgb* rgb_img = NULL; + uint8_t* alpha = NULL; + if (!load_png(src, &width, &height, &rgb_img, &alpha)) { fprintf( stderr, HICOLOR_CLI_ERROR "can't load PNG file \"%s\": %s\n", src, - cp_error_reason + libpng_error_msg ); return false; } hicolor_metadata meta = { .version = version, - .width = png_img.w, - .height = png_img.h + .width = width, + .height = height }; - hicolor_rgb* rgb_img = cp_to_rgb(png_img); - if (rgb_img == NULL) { - fprintf( - stderr, - HICOLOR_CLI_ERROR "can't allocate memory for RGB image\n" - ); - return false; - } - res = hicolor_quantize_rgb_image(meta, dither, rgb_img); bool success = false; if (check_and_report_error("can't quantize image", res)) { goto clean_up_images; } - cp_image_t quant_png_img = rgb_to_cp(meta, rgb_img); - /* Restore the alpha channel. */ - for (uint32_t i = 0; i < (uint32_t) png_img.w * (uint32_t) png_img.h; i++) { - quant_png_img.pix[i].a = png_img.pix[i].a; - } - if (!cp_save_png(dest, &quant_png_img)) { + if (!save_png(dest, width, height, rgb_img, alpha)) { fprintf(stderr, HICOLOR_CLI_ERROR "can't save PNG\n"); - goto clean_up_quant_image; + goto clean_up_images; } success = true; -clean_up_quant_image: - free(quant_png_img.pix); - clean_up_images: - free(png_img.pix); - CUTE_PNG_MEMSET(&png_img, 0, sizeof(png_img)); - free(rgb_img); return success; @@ -252,11 +392,7 @@ bool hicolor_to_png( FILE* hi_file = fopen(src, "rb"); if (hi_file == NULL) { - fprintf( - stderr, - HICOLOR_CLI_ERROR "can't open source image \"%s\" for reading\n", - src - ); + fprintf(stderr, HICOLOR_CLI_ERROR "can't open source image \"%s\" for reading\n", src); return false; } @@ -267,8 +403,7 @@ bool hicolor_to_png( goto clean_up_file; } - hicolor_rgb* rgb_img = - malloc(sizeof(hicolor_rgb) * meta.width * meta.height); + hicolor_rgb* rgb_img = malloc(sizeof(hicolor_rgb) * meta.width * meta.height); if (rgb_img == NULL) { goto clean_up_file; } @@ -277,17 +412,13 @@ bool hicolor_to_png( goto clean_up_rgb_img; } - cp_image_t png_img = rgb_to_cp(meta, rgb_img); - if (!cp_save_png(dest, &png_img)) { + if (!save_png(dest, meta.width, meta.height, rgb_img, NULL)) { fprintf(stderr, HICOLOR_CLI_ERROR "can't save PNG\n"); - goto clean_up_png_image; + goto clean_up_rgb_img; } success = true; -clean_up_png_image: - free(png_img.pix); - clean_up_rgb_img: free(rgb_img); @@ -346,7 +477,9 @@ bool hicolor_print_info( return success; } -void usage(FILE* output) +void usage( + FILE* output +) { fprintf( output, @@ -358,13 +491,42 @@ void usage(FILE* output) ); } -void version() { - uint32_t version = HICOLOR_LIBRARY_VERSION; +void version( + bool full +) +{ + if (full) { + printf( + HICOLOR_CLI_LIB_NAME_FORMAT, + "HiColor" + ); + } + + uint32_t program_version = HICOLOR_LIBRARY_VERSION; printf( "%u.%u.%u\n", - version / 10000, - version % 10000 / 100, - version % 100 + program_version / 10000, + program_version % 10000 / 100, + program_version % 100 + ); + + if (!full) { + return; + } + + png_uint_32 libpng_version = png_access_version_number(); + printf( + HICOLOR_CLI_LIB_NAME_FORMAT "%u.%u.%u\n", + "libpng", + libpng_version / 10000, + libpng_version % 10000 / 100, + libpng_version % 100 + ); + + printf( + HICOLOR_CLI_LIB_NAME_FORMAT "%s\n", + "zlib", + ZLIB_VERSION ); } @@ -373,7 +535,7 @@ void help() printf( "HiColor " ); - version(); + version(false); printf( "Create 15/16-bit color RGB images.\n\n" ); @@ -384,7 +546,7 @@ void help() " decode convert HiColor to PNG\n" " quantize quantize PNG to PNG\n" " info print HiColor image version and resolution\n" - " version print program version\n" + " version print version of HiColor, libpng, and zlib\n" " help print this help message\n" "\noptions:\n" " -5, --15-bit 15-bit color\n" @@ -395,15 +557,22 @@ void help() ); } -bool str_prefix(const char* ref, const char* str) +bool str_prefix( + const char* ref, + const char* str +) { size_t i; for (i = 0; str[i] != '\0'; i++) { - if (str[i] != ref[i]) return false; + if (str[i] != ref[i]) { + return false; + } } - if (i == 0) return false; + if (i == 0) { + return false; + } return true; } @@ -412,7 +581,10 @@ typedef enum command { ENCODE, DECODE, QUANTIZE, INFO, VERSION, HELP } command; -int main(int argc, char** argv) +int main( + int argc, + char** argv +) { command opt_command = ENCODE; hicolor_dither opt_dither = HICOLOR_BAYER; @@ -472,7 +644,6 @@ int main(int argc, char** argv) stderr, HICOLOR_CLI_ERROR "unknown command \"%s\"\n", argv[i] - ); usage(stderr); return 1; @@ -508,7 +679,6 @@ int main(int argc, char** argv) ); usage(stderr); return 1; - } i++; @@ -542,7 +712,9 @@ int main(int argc, char** argv) if (i == argc) { arg_dest = malloc(strlen(arg_src) + 5); - if (arg_dest == NULL) return HICOLOR_CLI_NO_MEMORY_EXIT_CODE; + if (arg_dest == NULL) { + return HICOLOR_CLI_NO_MEMORY_EXIT_CODE; + } sprintf( arg_dest, opt_command == ENCODE ? "%s.hic" : "%s.png", @@ -563,7 +735,7 @@ int main(int argc, char** argv) case INFO: return !hicolor_print_info(arg_src); case VERSION: - version(); + version(true); return 0; case HELP: help(); diff --git a/hicolor.h b/hicolor.h index c9e4c8b..e356924 100644 --- a/hicolor.h +++ b/hicolor.h @@ -19,13 +19,13 @@ #include #define HICOLOR_BAYER_SIZE 8 -#define HICOLOR_LIBRARY_VERSION 501 +#define HICOLOR_LIBRARY_VERSION 600 /* Types. */ static const uint8_t hicolor_magic[7] = "HiColor"; -/* These arrays are generated by `scripts/conversion-tables.tcl`. */ +/* These arrays are generated with `scripts/conversion-tables.tcl`. */ static const uint8_t hicolor_256_to_32[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, diff --git a/tests/hicolor.test b/tests/hicolor.test index c24b9d7..1083359 100755 --- a/tests/hicolor.test +++ b/tests/hicolor.test @@ -97,7 +97,7 @@ tcltest::test encode-1.5 {} -body { tcltest::test encode-1.6 {} -body { hicolor encode [file tail [info script]] -} -returnCodes error -match glob -result {*incorrect file signature*} +} -returnCodes error -match glob -result {*Not a PNG file*} tcltest::test encode-2.1 {encode flags} -body { @@ -147,7 +147,7 @@ tcltest::test encode-2.9 {} -body { tcltest::test encode-3.1 {bad input} -body { hicolor encode truncated.png } -returnCodes error -result {error: can't load PNG file "truncated.png":\ - corrupt zlib structure in DEFLATE stream} + Read Error} tcltest::test encode-3.2 {bad input} -body { hicolor encode wrong-size.png @@ -190,12 +190,12 @@ tcltest::test quantize-1.2 {} -body { tcltest::test quantize-2.1 {bad input} -body { hicolor encode [file tail [info script]] -} -returnCodes error -match glob -result {*incorrect file signature*} +} -returnCodes error -match glob -result {*Not a PNG file*} tcltest::test quantize-2.2 {bad input} -body { hicolor quantize truncated.png } -returnCodes error -result {error: can't load PNG file "truncated.png":\ - corrupt zlib structure in DEFLATE stream} + Read Error} tcltest::test quantize-2.3 {bad input} -body { hicolor quantize wrong-size.png