pngimage.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file pngimage.h
00004 ///
00005 /// Writing PNG images.
00006 /// This file contains the definition of a simple class "PngImage"
00007 /// which allows one to create an RGB bitmap image of a prescribed size,
00008 /// set the color of individual pixels, and save the image to a PNG file.
00009 /// This class also allows to read a PNG image which is automatically
00010 /// converted to an RGB bitmap.
00011 ///
00012 /// @author Pawel Pilarczyk
00013 ///
00014 /////////////////////////////////////////////////////////////////////////////
00015 
00016 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00017 //
00018 // This file is part of my research software package.  This is free software;
00019 // you can redistribute it and/or modify it under the terms of the GNU
00020 // General Public License as published by the Free Software Foundation;
00021 // either version 2 of the License, or (at your option) any later version.
00022 //
00023 // This software is distributed in the hope that it will be useful,
00024 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 // GNU General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License along
00029 // with this software; see the file "license.txt".  If not, write to the
00030 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00031 // MA 02111-1307, USA.
00032 
00033 // Started on February 13, 2007. Last revision: April 9, 2008.
00034 
00035 
00036 #ifndef _PWP_PNGIMAGE_H_
00037 #define _PWP_PNGIMAGE_H_
00038 
00039 
00040 #ifndef WITHOUT_PNG
00041 #include <png.h>
00042 #endif
00043 #include <cstdlib>
00044 
00045 
00046 // --------------------------------------------------
00047 // ------------------- PNG Image --------------------
00048 // --------------------------------------------------
00049 
00050 /// An interface to the PNG library. Supports creating a 24-bit image,
00051 /// writing individual pixels, and saving the image to a PNG file.
00052 class PngImage
00053 {
00054 public:
00055         /// The constructor of an empty 24-bit PNG image.
00056         /// The default background color is white.
00057         PngImage (int _width, int _height, int _bgcolor = 0xFFFFFF);
00058 
00059         /// The constructor which reads a PNG image from a file.
00060         /// Throws an error text message (const char *) in case of failure.
00061         PngImage (const char *filename);
00062 
00063         /// The destructor.
00064         ~PngImage ();
00065 
00066         /// Plots a pixel in the image with the given RGB color.
00067         /// The color is encoded as 0xRRGGBB. Black by default.
00068         void putPixel (int x, int y, int color = 0x000000);
00069 
00070         /// Returns the 0xRRGGBB color value of the given pixel
00071         /// or -1 if the pixel is outside the image.
00072         int getPixel (int x, int y) const;
00073 
00074         /// Returns the width of the image.
00075         int width () const;
00076 
00077         /// Returns the height of the image.
00078         int height () const;
00079 
00080         /// Writes the image to a PNG file.
00081         /// Throws an error text message (const char *) in case of failure.
00082         void save (const char *filename) const;
00083 
00084 private:
00085         /// The copy constructor is not allowed.
00086         PngImage (const PngImage &src);
00087 
00088         /// The assignment operator is not allowed.
00089         PngImage &operator = (const PngImage &src);
00090 
00091         /// The width of the image in pixels.
00092         int imgWidth;
00093 
00094         /// The height of the image in pixels.
00095         int imgHeight;
00096 
00097         /// The buffer of the picture in RGB byte sequences.
00098         unsigned char *buffer;
00099 
00100 }; /* PngImage */
00101 
00102 // --------------------------------------------------
00103 
00104 inline PngImage::PngImage (int _width, int _height, int _bgcolor):
00105         imgWidth (_width), imgHeight (_height), buffer (0)
00106 {
00107         if ((imgWidth <= 0) || (imgHeight <= 0))
00108                 throw "Wrong size of a PNG image requested.";
00109 
00110         buffer = new unsigned char [3 * imgWidth * imgHeight];
00111 
00112         unsigned char red =
00113                 static_cast<unsigned char> ((_bgcolor >> 16) & 0xFF);
00114         unsigned char green =
00115                 static_cast<unsigned char> ((_bgcolor >> 8) & 0xFF);
00116         unsigned char blue =
00117                 static_cast<unsigned char> (_bgcolor & 0xFF);
00118         unsigned char *buf = buffer;
00119         for (int i = imgWidth * imgHeight; i > 0; -- i)
00120         {
00121                 *(buf ++) = red;
00122                 *(buf ++) = green;
00123                 *(buf ++) = blue;
00124         }
00125         return;
00126 } /* PngImage::PngImage */
00127 
00128 inline PngImage::~PngImage ()
00129 {
00130         if (buffer)
00131                 delete [] buffer;
00132         return;
00133 } /* PngImage::~PngImage */
00134 
00135 inline PngImage::PngImage (const PngImage &)
00136 {
00137         return;
00138 } /* PngImage::PngImage */
00139 
00140 inline PngImage &PngImage::operator = (const PngImage &)
00141 {
00142         return *this;
00143 } /* PngImage::operator = */
00144 
00145 inline void PngImage::putPixel (int x, int y, int color)
00146 {
00147         if ((x < 0) || (x >= imgWidth) || (y < 0) || (y >= imgHeight))
00148                 return;
00149         unsigned char *buf = buffer + 3 * (imgWidth * y + x);
00150         *(buf ++) = static_cast<unsigned char> ((color >> 16) & 0xFF); // R
00151         *(buf ++) = static_cast<unsigned char> ((color >> 8) & 0xFF); // G
00152         *(buf ++) = static_cast<unsigned char> (color & 0xFF); // B
00153         return;
00154 } /* PngImage::putPixel */
00155 
00156 inline int PngImage::getPixel (int x, int y) const
00157 {
00158         if ((x < 0) || (x >= imgWidth) || (y < 0) || (y >= imgHeight))
00159                 return -1;
00160         unsigned char *buf = buffer + 3 * (imgWidth * y + x);
00161         return (buf [0] << 16) | (buf [1] << 8) | buf [2];
00162 } /* PngImage::getPixel */
00163 
00164 inline int PngImage::width () const
00165 {
00166         return imgWidth;
00167 } /* PngImage::width */
00168 
00169 inline int PngImage::height () const
00170 {
00171         return imgHeight;
00172 } /* PngImage::height */
00173 
00174 // --------------------------------------------------
00175 
00176 inline PngImage::PngImage (const char *filename):
00177         imgWidth (0), imgHeight (0), buffer (0)
00178 {
00179 #ifndef WITHOUT_PNG
00180         using namespace std;
00181 
00182         FILE *fp = fopen (filename, "rb");
00183         if (!fp)
00184                 throw "Unable to open a PNG file.";
00185 
00186         png_byte header [8];
00187         fread (header, 1, 8, fp);
00188         if (png_sig_cmp (header, 0, 8))
00189                 throw "The file does not contain a PNG image.";
00190 
00191         png_structp png_ptr = png_create_read_struct
00192                 (PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00193                 png_error_ptr_NULL, png_error_ptr_NULL);
00194         if (!png_ptr)
00195                 throw "Unable to create a PNG write struct.";
00196 
00197         png_infop info_ptr = png_create_info_struct (png_ptr);
00198         if (!info_ptr)
00199         {
00200                 png_destroy_read_struct (&png_ptr, 0, 0);
00201                 throw "Unable to create a PNG info struct.";
00202         }
00203 
00204         if (setjmp (png_jmpbuf (png_ptr)))
00205         {
00206                 png_destroy_read_struct (&png_ptr, &info_ptr, 0);
00207                 fclose (fp);
00208                 throw "An error occurred while reading the PNG file.";
00209         }
00210 
00211         png_init_io (png_ptr, fp);
00212         png_set_sig_bytes (png_ptr, 8);
00213 
00214         int png_transforms = PNG_TRANSFORM_STRIP_16 |
00215                 PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_PACKING |
00216                 PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_SHIFT;
00217         png_read_png (png_ptr, info_ptr, png_transforms, 0);
00218 
00219         unsigned width = png_get_image_width (png_ptr, info_ptr);
00220         unsigned height = png_get_image_height (png_ptr, info_ptr);
00221 
00222         if (png_get_rowbytes (png_ptr, info_ptr) != 3 * width)
00223                 throw "Wrong number of bytes per row in a PNG file.";
00224 
00225         png_bytep *row_pointers = png_get_rows (png_ptr, info_ptr);
00226         buffer = new unsigned char [3 * width * height];
00227         for (unsigned row = 0; row < height; ++ row)
00228         {
00229                 unsigned char *rowBuffer = buffer + 3 * row * width;
00230                 unsigned char *rowSource = row_pointers [row];
00231                 for (int i = 3 * width; i > 0; -- i)
00232                         *(rowBuffer ++) = *(rowSource ++);
00233         }
00234 
00235         png_destroy_read_struct (&png_ptr, &info_ptr, 0);
00236         fclose (fp);
00237 
00238         imgWidth = width;
00239         imgHeight = height;
00240 #else
00241         if (!filename)
00242                 return;
00243 #endif
00244         return;
00245 } /* PngImage::PngImage */
00246 
00247 inline void PngImage::save (const char *filename) const
00248 {
00249 #ifndef WITHOUT_PNG
00250         using namespace std;
00251 
00252         FILE *fp = fopen (filename, "wb");
00253         if (!fp)
00254                 throw "Unable to create a PNG file.";
00255 
00256         png_structp png_ptr = png_create_write_struct
00257                 (PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00258                 png_error_ptr_NULL, png_error_ptr_NULL);
00259         if (!png_ptr)
00260                 throw "Unable to create a PNG write struct.";
00261 
00262         png_infop info_ptr = png_create_info_struct (png_ptr);
00263         if (!info_ptr)
00264         {
00265                 png_destroy_write_struct (&png_ptr, (png_infopp) 0);
00266                 throw "Unable to create a PNG info struct.";
00267         }
00268 
00269         png_bytep *row_pointers = new png_bytep [imgHeight];
00270         for (int i = 0; i < imgHeight; ++ i)
00271                 row_pointers [i] = buffer + 3 * i * imgWidth;
00272 
00273         if (setjmp (png_jmpbuf (png_ptr)))
00274         {
00275                 png_destroy_write_struct (&png_ptr, &info_ptr);
00276                 delete [] row_pointers;
00277                 fclose (fp);
00278                 throw "An error occurred while writing the PNG file.";
00279         }
00280 
00281         png_init_io (png_ptr, fp);
00282         png_set_rows (png_ptr, info_ptr, row_pointers);
00283         png_set_IHDR (png_ptr, info_ptr, imgWidth, imgHeight,
00284                 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
00285                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00286 
00287         png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
00288 
00289         png_destroy_write_struct (&png_ptr, &info_ptr);
00290         delete [] row_pointers;
00291         fclose (fp);
00292 #else
00293         if (!filename)
00294                 return;
00295 #endif
00296         return;
00297 } /* PngImage::save */
00298 
00299 
00300 #endif // _PWP_PNGIMAGE_H_
00301 

Generated on Sun Mar 28 17:47:58 2010 for The Conley-Morse Graphs Software by  doxygen 1.5.3