ulf.schroeter Posted April 30, 2011 Share Posted April 30, 2011 Problem There is a tricky PNG image read issue in case of PNG_COLOR_TYPE_RGB/PNG_COLOR_TYPE_PALETTE with only 1 channel. Actually images are grayscale images but some applications (e.g. Paint.Net) set PNG_COLOR_TYPE_RGB and channel count 1 instead of PNG_COLOR_TYPE_GRAY. In case of PNG_COLOR_TYPE_PALETTE current code in Image::load_png() triggers png_set_expand(png_ptr), which will expand a 1-channel palettized grayscale image to 3-channel RGB. In both cases Image::load_png() falsely creates FORMAT_RGB8/16 instead of FORMAT_R8/16 image format. This causes quite some problems when assigned as mask image. rejection for WorldClutter due to expected FORMAT_R8 changed mask interpretation for ObjectGrass Format_R8 vs FORMAT_RGB8 invalid mask interpretation for ObjectTerrainOccluder as setHeightsImageName() in case of FORMAT_RGB8 assumes an already "cone-step-converted" mask image with with dr/dh in G-/B-channels and therefore skips required cone-step data calculation. Fix In case of 1-channel input PNG image force conversion to grayscale format int Image::load_png(const char *name) { .... // set png parameters .... png_get_IHDR(png_ptr,png_info_ptr,&png_width,....); int png_channels = png_get_channels(png_ptr,png_info_ptr); // get before png expand etc .... // create image .... // read png image ... // reconstruct grayscale format for 1-channel RGB input PNG images // or PALETTE input PNG images expanded to 3-channel RGB if(png_channels == 1 && png_color_type == PNG_COLOR_TYPE_RGB ) { if ( png_bit_depth == 8 ) convertToFormat(FORMAT_R8); else if( png_bit_depth == 16 ) convertToFormat(FORMAT_R16); } return 1; } Link to comment
Recommended Posts