Jump to content

PNG 1-Channel Image Format Bug


photo

Recommended Posts

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;
}

post-82-0-78211700-1304151456_thumb.png

Link to comment
×
×
  • Create New...