src/rcrt/textures/pngHelper.hxx

Go to the documentation of this file.
00001 
00008 #ifndef __LIBPNG_HELPERS__
00009 #define __LIBPNG_HELPERS__
00010 
00011 #include <png.h>
00012 #include <cstdio>
00013 #include <iostream>
00014 #include <fstream>
00015 
00016 #define PNG_BYTES_TO_CHECK 8
00017 
00018 using namespace std;
00019 
00020 
00021 int check_if_png(const char *file_name, FILE **fp)
00022 {
00023    png_byte buf[PNG_BYTES_TO_CHECK];
00024 
00025    /* Open the prospective PNG file. */
00026    if ((*fp = fopen(file_name, "rb")) == NULL)
00027       return 0;
00028 
00029    /* Read in some of the signature bytes */
00030    if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
00031       return 0;
00032 
00033    /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
00034       Return nonzero (true) if they match */
00035 
00036    bool res = (!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
00037    fclose(*fp);
00038    return res;
00039 }
00040 
00041 void read_png(const char* file_name, 
00042               unsigned char*& buffer,
00043               int& width,
00044               int& height,
00045               int& channels,
00046               int& bit_depth, 
00047               int& color_type,
00048               bool flip_vert)
00049   
00050 {
00051    png_structp png_ptr;
00052    png_infop info_ptr;
00053    //   int interlace_type;
00054 
00055    FILE *fp;
00056    bool check=check_if_png(file_name,&fp);
00057 
00058    if (!check)
00059      {
00060        std::cerr << "This is not a PNG file !!" << endl;
00061        exit(1);
00062     }
00063    
00064   fp=fopen(file_name, "rb");
00065    
00066   
00067   
00068   /* Create and initialize the png_struct with the desired error handler
00069    * functions.  If you want to use the default stderr and longjump method,
00070    * you can supply NULL for the last three parameters.  We also supply the
00071    * the compiler header file version, so that we know if the application
00072    * was compiled with a compatible version of the library.  REQUIRED
00073    */
00074   //png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00075   //   png_voidp user_error_ptr, user_error_fn, user_warning_fn);
00076   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00077                                    NULL, NULL, NULL);
00078   
00079   if (png_ptr == NULL)
00080     {
00081       fclose(fp);
00082       std::cerr << "Error initializing png_ptr !" << endl;
00083       exit(1);
00084     }
00085   
00086    /* Allocate/initialize the memory for image information.  REQUIRED. */
00087    info_ptr = png_create_info_struct(png_ptr);
00088    if (info_ptr == NULL)
00089    {
00090       fclose(fp);
00091       png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00092       std::cerr << "Error initializing info_ptr !" << endl;
00093       exit(1);
00094    }
00095 
00096    /* Set error handling if you are using the setjmp/longjmp method (this is
00097     * the normal method of doing things with libpng).  REQUIRED unless you
00098     * set up your own error handlers in the png_create_read_struct() earlier.
00099     */
00100 
00101    if (setjmp(png_jmpbuf(png_ptr)))
00102    {
00103       /* Free all of the memory associated with the png_ptr and info_ptr */
00104       png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00105       fclose(fp);
00106       /* If we get here, we had a problem reading the file */
00107       std::cerr << "Error initializing png_ptr !" << endl;
00108       exit(1);
00109    }
00110 
00111    png_init_io(png_ptr, fp);
00112 
00113    /* If we have already read some of the signature */
00114    png_set_sig_bytes(png_ptr,0);
00115 
00116    /*
00117     * If you have enough memory to read in the entire image at once,
00118     * and you need to specify only transforms that can be controlled
00119     * with one of the PNG_TRANSFORM_* bits (this presently excludes
00120     * dithering, filling, setting background, and doing gamma
00121     * adjustment), then you can read the entire image (including
00122     * pixels) into the info structure with this call:
00123     */
00124    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);   
00125 
00126    width            = png_get_image_width(png_ptr,
00127                                           info_ptr);
00128    height           = png_get_image_height(png_ptr,
00129                                            info_ptr);
00130    channels         = png_get_channels(png_ptr,
00131                                        info_ptr);
00132    bit_depth = png_get_bit_depth(png_ptr,info_ptr);
00133    color_type = png_get_color_type(png_ptr,info_ptr);
00134    png_uint_32 valid = 0;
00135    png_get_valid(png_ptr,info_ptr,valid);
00136 
00137    png_bytep* row_pointers=(png_bytep*)malloc(height*sizeof(png_bytep));
00138    row_pointers=png_get_rows(png_ptr, info_ptr);
00139 
00140    //allocate buffer
00141    const int c=width*channels*bit_depth/8;
00142    buffer=(unsigned char*)malloc(sizeof(unsigned char)*channels*width*height*bit_depth/8);
00143 
00144    if (!flip_vert)
00145      {
00146        for (int y=0;y<height;++y)
00147          memcpy((void*)&(buffer[y*c]),(void*)(row_pointers[y]),c);
00148      }
00149    else
00150      {
00151        for (int y=0;y<height;++y)
00152          memcpy((void*)&(buffer[(height-1-y)*c]),(void*)(row_pointers[y]),c);
00153      }
00154    
00155    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00156    fclose(fp);
00157 }
00158 
00159 
00160 /* write a png file */
00161 
00173 void write_png(const char *file_name, unsigned char* buffer, 
00174                int width, int height, int channels, 
00175                int bit_depth, png_uint_32 color_type,
00176                bool flip_vert)
00177 {
00178    FILE *fp;
00179    png_structp png_ptr;
00180    png_infop info_ptr;
00181    //   png_colorp palette;
00182 
00183    /* open the file */
00184    fp = fopen(file_name, "wb");
00185    if (fp == NULL)
00186      {
00187        std::cerr << "Error opening file " << endl;
00188      }
00189 
00190    /* Create and initialize the png_struct with the desired error handler
00191     * functions.  If you want to use the default stderr and longjump method,
00192     * you can supply NULL for the last three parameters.  We also check that
00193     * the library version is compatible with the one used at compile time,
00194     * in case we are using dynamically linked libraries.  REQUIRED.
00195     */
00196    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00197                                      NULL,NULL,NULL);
00198 
00199    if (png_ptr == NULL)
00200    {
00201       fclose(fp);
00202       std::cerr << "Error allocating png_ptr !!" << endl;
00203       exit(1);
00204    }
00205 
00206    /* Allocate/initialize the image information data.  REQUIRED */
00207    info_ptr = png_create_info_struct(png_ptr);
00208    if (info_ptr == NULL)
00209    {
00210       fclose(fp);
00211       png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
00212       std::cerr << "Error allocating info ptr !!" << endl;
00213       exit(1);
00214    }
00215 
00216    /* Set error handling.  REQUIRED if you aren't supplying your own
00217     * error handling functions in the png_create_write_struct() call.
00218     */
00219    if (setjmp(png_jmpbuf(png_ptr)))
00220    {
00221       /* If we get here, we had a problem reading the file */
00222       fclose(fp);
00223       png_destroy_write_struct(&png_ptr, &info_ptr);
00224       exit(1);
00225    }
00226 
00227    png_init_io(png_ptr, fp);
00228 
00229    png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32) height,
00230                 (png_byte) bit_depth, (png_byte) color_type, PNG_INTERLACE_NONE,
00231                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
00232 
00233    //setup row data structure from buffer
00234    
00235    png_bytep row_pointers[height];
00236    const int c=width*channels*bit_depth/8;
00237    if (!flip_vert)
00238      {
00239        for (int y=0;y<height;++y)
00240          {
00241            row_pointers[y]=(png_bytep) &(buffer[y*c]);
00242          }
00243      }
00244    else
00245      {
00246        for (int y=0;y<height;++y)
00247          {
00248            row_pointers[height-1-y]=(png_bytep) &(buffer[y*c]);
00249          }
00250      }
00251    //raise(5);
00252    
00253    png_set_rows(png_ptr, info_ptr, row_pointers);
00254    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00255 
00256    png_destroy_write_struct(&png_ptr, &info_ptr);
00257    fclose(fp);
00258 }
00259 
00260 #endif

Generated on Thu Jan 31 19:26:20 2008 for RenderingCompetitionRayTracer by  doxygen 1.5.3