Image.cc

Go to the documentation of this file.
00001 
00005 #include "Image.h"
00006 #include <fstream>
00007 #include <iostream>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <stdarg.h>
00011 #include <png.h>
00012 
00013 using namespace std;
00014 
00015 static void error(const std::string& filename, const std::string& errtext)
00016 {
00017     cerr << "Error reading image: " << filename << ": " << errtext << '\n';
00018     exit(1);
00019 }
00020 
00021 Image::Image(const std::string& filename)
00022 {
00023     cerr << "Reading " << filename << "...";
00024 
00025     size_t found = filename.rfind(".png");
00026     if (found != string::npos) {
00027         // read a png file
00028 
00029         read_png_file(filename.c_str(), xres, yres);
00030 
00031         return;
00032     }
00033 
00034     // Assume reading ppm
00035     ifstream in(filename.c_str(), ios::in | ios::binary);
00036     if(!in)
00037         error(filename, "Error opening file");
00038     if(in.get() != 'P' || !in)
00039         error(filename, "Error reading magic number (1st digit)");
00040     if(in.get() != '6' || !in)
00041         error(filename, "Error reading magic number (2nd digit)");
00042     int maxValue;
00043     in >> xres >> yres >> maxValue;
00044     in.get();
00045     cerr << " " << xres << "x" << yres << "...";
00046     if(!in)
00047         error(filename, "Error reading metadaa");
00048     data = new Pixel*[yres];
00049     Pixel* p = new Pixel[xres*yres];
00050     for(int i=0;i<yres;i++)
00051         data[i] = p + i*xres;
00052     for(int i=yres-1;i>=0;i--)
00053         in.read(reinterpret_cast<char*>(data[i]), sizeof(Pixel)*xres);
00054     if(!in)
00055         error(filename, "Error reading pixels");
00056     cerr << " done\n";
00057 }
00058 
00059 
00060 Image::Image(int xres, int yres)
00061     : xres(xres), yres(yres)
00062 {
00063     data = new Pixel*[yres];
00064     Pixel* p = new Pixel[xres*yres];
00065     for(int i=0;i<yres;i++)
00066         data[i] = p + i*xres;
00067 }
00068 
00069 Image::~Image()
00070 {
00071     delete[] data[0];
00072     delete[] data;
00073 }
00074 
00075 
00076 void abort_(const char * s, ...)
00077 {
00078     va_list args;
00079     va_start(args, s);
00080     vfprintf(stderr, s, args);
00081     fprintf(stderr, "\n");
00082     va_end(args);
00083     abort();
00084 }
00085 
00086 
00087 void Image::write_png_file(const char* file_name, int width, int height) const
00088 {
00089     png_structp png_ptr;
00090     png_infop info_ptr;
00091     png_byte color_type = PNG_COLOR_TYPE_RGB;
00092     png_byte bit_depth = 8;
00093 
00094 
00095     /* create file */
00096     FILE *fp = fopen(file_name, "wb");
00097     if (!fp)
00098         abort_("[write_png_file] File %s could not be opened for writing", file_name);
00099 
00100 
00101     /* initialize stuff */
00102     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00103         
00104     if (!png_ptr)
00105         abort_("[write_png_file] png_create_write_struct failed");
00106 
00107     info_ptr = png_create_info_struct(png_ptr);
00108     if (!info_ptr)
00109         abort_("[write_png_file] png_create_info_struct failed");
00110 
00111     if (setjmp(png_jmpbuf(png_ptr)))
00112         abort_("[write_png_file] Error during init_io");
00113 
00114     png_init_io(png_ptr, fp);
00115 
00116 
00117     /* write header */
00118     if (setjmp(png_jmpbuf(png_ptr)))
00119         abort_("[write_png_file] Error during writing header");
00120 
00121     png_set_IHDR(png_ptr, info_ptr, width, height,
00122                  bit_depth, color_type, PNG_INTERLACE_NONE,
00123                  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00124 
00125     png_write_info(png_ptr, info_ptr);
00126 
00127 
00128     /* write bytes */
00129     if (setjmp(png_jmpbuf(png_ptr)))
00130         abort_("[write_png_file] Error during writing bytes");
00131 
00132 
00133     png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height);
00134     for (int y=0 ; y < height ; y++)
00135         row_pointers[(height-1)-y] = (png_bytep) &data[y][0];
00136 
00137     png_write_image(png_ptr, row_pointers);
00138 
00139 
00140     /* end write */
00141     if (setjmp(png_jmpbuf(png_ptr)))
00142         abort_("[write_png_file] Error during end of write");
00143 
00144     png_write_end(png_ptr, NULL);
00145 
00146     /* cleanup heap allocation */
00147     //  for (int y=0; y<height; y++)
00148     //          free(row_pointers[y]);
00149     free(row_pointers);
00150 
00151     fclose(fp);
00152 }
00153 
00154 void Image::write(const std::string& filename) const
00155 {
00156 #if 0
00157     std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary);
00158     out << "P6 " << xres << " " << yres << " 255\n";
00159     for(int i=yres-1;i>=0;i--)
00160         out.write(reinterpret_cast<char*>(data[i]), sizeof(Pixel)*xres);
00161 #else
00162     write_png_file(filename.c_str(), xres, yres);
00163 #endif
00164 
00165 }
00166 
00167 void Image::read_png_file(const char* file_name, int &width, int &height)
00168 {
00169     png_structp png_ptr;
00170     png_infop info_ptr;
00171     png_byte color_type = PNG_COLOR_TYPE_RGB;
00172     png_byte bit_depth = 8;
00173 
00174     char header[8];     // 8 is the maximum size that can be checked
00175 
00176     /* open file and test for it being a png */
00177     FILE *fp = fopen(file_name, "rb");
00178     if (!fp)
00179         abort_("[read_png_file] File %s could not be opened for reading", file_name);
00180     fread(header, 1, 8, fp);
00181     if (png_sig_cmp((png_byte *)header, 0, 8))
00182         abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
00183 
00184 
00185     /* initialize stuff */
00186     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00187         
00188     if (!png_ptr)
00189         abort_("[read_png_file] png_create_read_struct failed");
00190 
00191     info_ptr = png_create_info_struct(png_ptr);
00192     if (!info_ptr)
00193         abort_("[read_png_file] png_create_info_struct failed");
00194 
00195     if (setjmp(png_jmpbuf(png_ptr)))
00196         abort_("[read_png_file] Error during init_io");
00197 
00198     png_init_io(png_ptr, fp);
00199     png_set_sig_bytes(png_ptr, 8);
00200 
00201     png_read_info(png_ptr, info_ptr);
00202 
00203     width = info_ptr->width;
00204     height = info_ptr->height;
00205     color_type = info_ptr->color_type;
00206     bit_depth = info_ptr->bit_depth;
00207 
00208     png_set_interlace_handling(png_ptr);
00209     png_read_update_info(png_ptr, info_ptr);
00210 
00211 
00212     /* read file */
00213     if (setjmp(png_jmpbuf(png_ptr)))
00214         abort_("[read_png_file] Error during read_image");
00215 
00216     png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
00217     for (int y=0; y<height; y++)
00218         row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
00219 
00220     png_read_image(png_ptr, row_pointers);
00221 
00222     fclose(fp);
00223 
00224     // stash the data
00225 }

Generated on Tue Jan 29 21:34:53 2008 for specter by  doxygen 1.4.6