diff --git a/include/common.h b/include/common.h index 58d6722..af27512 100644 --- a/include/common.h +++ b/include/common.h @@ -19,7 +19,7 @@ #define VERSION_X 1 #define VERSION_Y 2 #define VERSION_A 0 -#define VERSION_Z 3 +#define VERSION_Z 4 // Remember to bump "Z" basically every time you change the engine! // Remember to bump the version in Lua too! // Remember to document API changes in a new version! diff --git a/pkg/base/gfx/loading_default-256c.png b/pkg/base/gfx/loading_default-256c.png new file mode 100644 index 0000000..56918de Binary files /dev/null and b/pkg/base/gfx/loading_default-256c.png differ diff --git a/pkg/base/main_client.lua b/pkg/base/main_client.lua index d68b2d1..f817ea6 100644 --- a/pkg/base/main_client.lua +++ b/pkg/base/main_client.lua @@ -135,10 +135,12 @@ end dofile("pkg/base/lib_gui.lua") -- 0.1.2-2 introduces PNG support -if common.version.num < 4259840+2 then +-- 0.1.2-4 introduces support for indexed+greyscale images and tRNS-block (magic colour + palette alpha) transparency +-- there's no reason to make them load the full RGB image when they don't support the indexed one. +if common.version.num < 4259840+4 then img_loading = img_loading or skin_load("tga", "loading_default-64c.tga", DIR_PKG_GFX) else - img_loading = img_loading or skin_load("png", "loading_default.png", DIR_PKG_GFX) + img_loading = img_loading or skin_load("png", "loading_default-256c.png", DIR_PKG_GFX) end img_map = img_map or common.img_load("*MAPIMG") diff --git a/pkg/base/version.lua b/pkg/base/version.lua index a848ef3..a8c9713 100644 --- a/pkg/base/version.lua +++ b/pkg/base/version.lua @@ -16,9 +16,9 @@ ]] VERSION_ENGINE = { - cmp={0,1,2,0,3}, - num=4259840+3, - str="0.1.2-3", + cmp={0,1,2,0,4}, + num=4259840+4, + str="0.1.2-4", } -- 0.1: 4194304 @@ -114,7 +114,9 @@ VERSION_BUGS = { {intro=nil, fix=4259840, msg="Sound broken wrt stereo (only the last sound played is in stereo; the rest uses the left for both channels)"}, {renderer="softgm", intro=nil, fix=4259840+1, msg="[OSX][softgm] Colours are incorrect (32-bit endian swap)"}, {intro=nil, fix=4259840+2, msg="PNG not supported"}, -{intro=4259840+2, fix=nil, msg="Preliminary PNG support - more support to come when we can be bothered (RGB/RGBA only for now)"}, +{intro=4259840+2, fix=nil, msg="Preliminary PNG support - more support to come when we can be bothered"}, +{intro=4259840+2, fix=4259840+4, msg="PNG reader lacks support for greyscale/indexed images"}, +{intro=4259840+2, fix=4259840+4, msg="PNG reader lacks support for tRNS-block transparency"}, {intro=4259840+3, fix=nil, msg="[OpenGL] option to set render quality"}, } diff --git a/src/png.c b/src/png.c index 3dd3a81..a3195bb 100644 --- a/src/png.c +++ b/src/png.c @@ -150,9 +150,12 @@ img_t *img_parse_png(int len, const char *data) return NULL; } + // TODO: implement 1,2,4bpc for modes 0 (greyscale) and 3 (indexed) + //if(((ihdr.ctyp != 3 && ihdr.ctyp != 0) || (ihdr.bpc != 1 && ihdr.bpc != 2 && ihdr.bpc != 4)) && ihdr.bpc != 8) if(ihdr.bpc != 8) { - fprintf(stderr, "img_parse_png: only 8-bits-per-component images currently supported\n"); + //fprintf(stderr, "img_parse_png: given bits-per-component not supported (16bpc unsupported at the moment)\n"); + fprintf(stderr, "img_parse_png: given bits-per-component not supported (only 8bpc supported at the moment)\n"); return NULL; } @@ -162,12 +165,6 @@ img_t *img_parse_png(int len, const char *data) return NULL; } - if(ihdr.ctyp != 2 && ihdr.ctyp != 6) - { - fprintf(stderr, "img_parse_png: given colour type not supported yet!"); - return NULL; - } - if(ihdr.cmpr != 0) { fprintf(stderr, "img_parse_png: compression type not supported"); @@ -186,6 +183,11 @@ img_t *img_parse_png(int len, const char *data) return NULL; } + uint8_t pal[256*3]; + uint8_t trns[256]; + int pal_len = 0; + int trns_len = 0; + char *cbuf = NULL; size_t cbuf_len = 0; for(;;) @@ -216,6 +218,40 @@ img_t *img_parse_png(int len, const char *data) cbuf_len += clen; } else if(!memcmp("IEND", tag, 4)) { break; + } else if(!memcmp("PLTE", tag, 4)) { + if(ihdr.ctyp != 3) + { + // probably best not to spam this stuff. + //fprintf(stderr, "img_parse_png: PLTE tag for non-indexed image ignored\n"); + } else if((clen % 3) != 0 || clen > (3< 256*3) { + fprintf(stderr, "img_parse_png: invalid PLTE length\n"); + if(cbuf != NULL) + free(cbuf); + return NULL; + } else { + pal_len = clen / 3; + memcpy(pal, data+8, clen); + } + } else if(!memcmp("tRNS", tag, 4)) { + // we might as well be better than Internet Explorer + int explen = -1; + if(ihdr.ctyp == 0) + explen = 2; + else if(ihdr.ctyp == 2) + explen = 6; + else if(ihdr.ctyp == 3) + explen = pal_len; + + if(explen == -1) + { + fprintf(stderr, "img_parse_png: warning: tRNS not expected for this image type!\n"); + } else if((ihdr.ctyp == 3 ? clen > explen : explen != clen)) { + fprintf(stderr, "img_parse_png: warning: tRNS chunk length incorrect; ignored\n"); + } else { + memset(trns+clen, 0xFF, 256-clen); + memcpy(trns, data+8, clen); + trns_len = clen; + } } else if(!(tag[0]&0x20)) { fprintf(stderr, "img_parse_png: unexpected compulsory tag %c%c%c%c\n" , tag[0], tag[1], tag[2], tag[3]); @@ -384,6 +420,21 @@ img_t *img_parse_png(int len, const char *data) switch(ihdr.ctyp) { + case 0: + // Greyscale + for(x = 0; x < iwidth; x++) + { + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = (trns_len == 0 + || trns[0] != src[0] + ? 0xFF : 0x00); + src += 1; + dst += 4; + } + break; + case 2: // RGB for(x = 0; x < iwidth; x++) @@ -391,11 +442,42 @@ img_t *img_parse_png(int len, const char *data) dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; - dst[3] = 0xFF; // TODO: tRNS block + dst[3] = (trns_len == 0 + || trns[0] != src[0] + || trns[2] != src[1] + || trns[4] != src[2] + ? 0xFF : 0x00); src += 3; dst += 4; } break; + + case 3: + // Indexed colour + for(x = 0; x < iwidth; x++) + { + dst[0] = pal[src[0]*3+2]; + dst[1] = pal[src[0]*3+1]; + dst[2] = pal[src[0]*3+0]; + dst[3] = (trns_len == 0 ? 0xFF : trns[src[0]]); + src += 1; + dst += 4; + } + break; + + case 4: + // Greyscale + Alpha + for(x = 0; x < iwidth; x++) + { + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = src[1]; + src += 2; + dst += 4; + } + break; + case 6: // RGBA for(x = 0; x < iwidth; x++) diff --git a/zipdist.sh b/zipdist.sh index 28fb819..799e7a8 100755 --- a/zipdist.sh +++ b/zipdist.sh @@ -1,6 +1,6 @@ #!/bin/sh -export ZIPNAME=nubdist/iceball-indev-0.1.1-9.zip +export ZIPNAME=nubdist/iceball-indev-0.1.2-4.zip zip -r $ZIPNAME *.dll *.exe *.txt opencmd.bat docs/ \ dlcache/info.txt clsave/info.txt \