+ if( !ret ) {
+ png_init_io(png_ptr, fp);
+ png_read_info(png_ptr, info_ptr);
+
+ color_type = png_get_color_type(png_ptr, info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr, info_ptr);
+ width = png_get_image_width (png_ptr, info_ptr);
+ height = png_get_image_height(png_ptr, info_ptr);
+
+ /* Skip the alpha channel if present
+ * stripping alpha currently doesn't work in conjunction with
+ * converting to grayscale in libpng */
+ pixel_width = color_type & PNG_COLOR_MASK_ALPHA ? 2 : 1;
+ /* Convert 16 bit data to 8 bit */
+ if( bit_depth == 16 ) png_set_strip_16(png_ptr);
+ /* Expand to 1 pixel per byte if necessary */
+ if( bit_depth < 8 ) png_set_packing(png_ptr);
+
+ /* Convert to grayscale */
+ if( color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA )
+ png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
+
+ /* Allocate memory to hold the original png image */
+ image = (png_bytep*)new png_bytep[height];
+ for( row=0; row<(int)height; ++row )
+ image[row] = new png_byte[width*pixel_width];
+
+ /* Allocate memory for the pattern image that will actually be
+ * used for the wipe */
+ pattern_image = new unsigned char*[frame_height];
+
+ png_read_image(png_ptr, image);
+ png_read_end(png_ptr, end_info);
+
+ double row_factor, col_factor;
+ double row_offset = 0.5, col_offset = 0.5; // for rounding
+
+ if( config.preserve_aspect && aspect_w && aspect_h ) {
+ row_factor = (height-1)/aspect_h;
+ col_factor = (width-1)/aspect_w;
+ if( row_factor < col_factor )
+ col_factor = row_factor;
+ else
+ row_factor = col_factor;
+ row_factor *= aspect_h/(double)(frame_height-1);
+ col_factor *= aspect_w/(double)(frame_width-1);
+
+ // center the pattern over the frame
+ row_offset += (height-1-(frame_height-1)*row_factor)/2;
+ col_offset += (width-1-(frame_width-1)*col_factor)/2;
+ }
+ else {
+ // Stretch (or shrink) the pattern image to fill the frame
+ row_factor = (double)(height-1)/(double)(frame_height-1);
+ col_factor = (double)(width-1)/(double)(frame_width-1);
+ }
+ // first, determine range min..max
+ for( int y=0; y<frame_height; ++y ) {
+ row = (int)(row_factor*y + row_offset);
+ for( int x=0; x<frame_width; ++x ) {
+ col = (int)(col_factor*x + col_offset)*pixel_width;
+ value = image[row][col];
+ if( value < min_value ) min_value = value;
+ if( value > max_value ) max_value = value;
+ }
+ }
+ int range = max_value - min_value;
+ if( !range ) range = 1;
+ // scale to fade normalized pattern_image
+ for( int y=0; y<frame_height; ++y ) {
+ row = (int)(row_factor*y + row_offset);
+ pattern_image[y] = new unsigned char[frame_width];
+ for( int x=0; x<frame_width; ++x ) {
+ col = (int)(col_factor*x + col_offset)*pixel_width;
+ value = image[row][col];
+ pattern_image[y][x] = 0xff*(value - min_value) / range;
+ }