void LoadPNG( Img& img, RGBx* palette, const char* filename ) { FILE *fp = fopen(filename, "rb"); if (!fp) throw Wobbly( "open failed: %s", strerror(errno) ); unsigned char header[8]; fread( header, 1, 8, fp ); bool is_png = !png_sig_cmp( header, 0, 8 ); if( !is_png ) { fclose(fp); throw Wobbly( "Not a PNG file." ); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL ); if( !png_ptr ) { fclose(fp); throw Wobbly( "png_create_read_struct() failed" ); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); throw Wobbly( "png_create_info_struct() failed" ); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); throw Wobbly( "png_create_info_struct() failed" ); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); throw Wobbly( "error reading PNG" ); } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width; png_uint_32 height; int color_type; int bit_depth; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL ); if( color_type != PNG_COLOR_TYPE_PALETTE ) { throw Wobbly( "PNG does not have a palette" ); } if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); // read in the image data Img tmp( Img::INDEXED8BIT, width, height ); png_bytep row_pointers[ tmp.H() ]; int y; for( y=0;y<tmp.H();++y) row_pointers[y] = (png_bytep)tmp.Ptr(0,y); png_read_image( png_ptr, row_pointers ); img.Copy(tmp); // now read in the palette png_colorp colours; int num_colours; png_get_PLTE(png_ptr, info_ptr, &colours, &num_colours); assert( num_colours <= 256 ); int i=0; while( i<num_colours ) { png_color c = colours[i]; palette[i] = RGBx( c.red, c.green, c.blue ); ++i; } // black out any missing colours while( i<=255 ) { palette[i] = RGBx(0,0,0); ++i; } png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); }
RGBx RGBPickerWidget::PointToRGB( QPoint const& p ) const { float x = (float)p.x() / (float)size().width(); float y = (float)p.y() / (float)size().height(); int zone = (int)(y*6.0f); float t = fmod(y,1.0f/6.0f) * 6.0f; assert(zone>=0 && zone<6); RGBx a,b; switch(zone) { case 0: a=RGBx(255,0,0); b=RGBx(255,255,0); break; case 1: a=RGBx(255,255,0); b=RGBx(0,255,0); break; case 2: a=RGBx(0,255,0); b=RGBx(0,255,255); break; case 3: a=RGBx(0,255,255); b=RGBx(0,0,255); break; case 4: a=RGBx(0,0,255); b=RGBx(255,0,255); break; case 5: a=RGBx(255,0,255); b=RGBx(255,0,0); break; } if( x<0.5) { RGBx white(255,255,255); return Lerp(white,Lerp(a,b,t),x*2.0f); } else { RGBx black(0,0,0); return Lerp(Lerp(a,b,t),black,(x-0.5f)*2.0f); } }