pngsmall.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file pngsmall.cpp
00004 ///
00005 /// This is a small utility program which decreases in size a PNG file
00006 /// (if necessary) in order to make it fit within the given size.
00007 ///
00008 /// @author Pawel Pilarczyk
00009 ///
00010 /////////////////////////////////////////////////////////////////////////////
00011 
00012 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00013 //
00014 // This file is part of the Homology Library.  This library is free software;
00015 // you can redistribute it and/or modify it under the terms of the GNU
00016 // General Public License as published by the Free Software Foundation;
00017 // either version 2 of the License, or (at your option) any later version.
00018 //
00019 // This library is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 // GNU General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU General Public License along
00025 // with this software; see the file "license.txt".  If not, write to the
00026 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00027 // MA 02111-1307, USA.
00028 
00029 // Started on April 10, 2008. Last revision: April 10, 2008.
00030 
00031 
00032 // include some standard C++ header files
00033 #include <exception>
00034 #include <cstring>
00035 #include <cstdio>
00036 
00037 // include selected header files from the CHomP library
00038 #include "chomp/system/config.h"
00039 #include "chomp/system/textfile.h"
00040 #include "chomp/system/timeused.h"
00041 #include "chomp/system/arg.h"
00042 
00043 // include local header files
00044 #include "pngimage.h"
00045 
00046 
00047 // --------------------------------------------------
00048 // -------------------- OVERTURE --------------------
00049 // --------------------------------------------------
00050 
00051 /// The title of the program which is displayed every time
00052 /// the program is launcued.
00053 const char *title = "\
00054 PNGSMALL, ver. 0.01, 04/10/08. Copyright (C) 2008 by Pawel Pilarczyk.\n\
00055 This is free software. No warranty. Consult 'license.txt' for details.";
00056 
00057 /// The help information about the program which is displayed
00058 /// if the program is launched without command-line arguments
00059 /// or with incorrect arguments.
00060 const char *helpinfo = "\
00061 This program reads a given PNG images and writes another PNG image\n\
00062 which is the original one scaled down so that the provided width\n\
00063 and height are not exceeded. The down-scaling factors are limited\n\
00064 to the integer numbers for optimal efficiency. The colors of output\n\
00065 pixels are computed by means of an arithmetic average of the input ones.\n\
00066 Command line arguments:\n\
00067 input.png - the name of the input PNG image file to be down-scaled,\n\
00068 output.png - the name of the output PNG file (rewrites the input if none),\n\
00069 -w width - the maximal allowed width of the output PNG image,\n\
00070 -h height - the maximal allowed height of the output PNG image,\n\
00071 -s scaling - the downscaling factor (overrides max width/height settings),\n\
00072 --quiet - makes the program run quietly, without any output messages,\n\
00073 --help - shows this brief help information on the program's usage.\n\
00074 For more information consult the accompanying documentation (if available)\n\
00075 or ask the program's author at http://www.PawelPilarczyk.com/.";
00076 
00077 
00078 // --------------------------------------------------
00079 // -------------------- PNGSMALL --------------------
00080 // --------------------------------------------------
00081 
00082 /// The main function of the program "pngsmall".
00083 /// This function downscales the given PNG image and saves the result
00084 /// as another PNG image.
00085 /// The scaling factor is determined on the basis of the provided maximal
00086 /// allowed width and/or height of the image, unless specified explicitly.
00087 /// Returns 0, or throws an error message in case of failure.
00088 int pngSmall (const char *inName, const char *outName,
00089         int maxWidth, int maxHeight, int scalingFactor)
00090 {
00091         using chomp::homology::sout;
00092 
00093         // read the input PNG image
00094         PngImage inPng (inName);
00095         int inWidth = inPng. width ();
00096         int inHeight = inPng. height ();
00097 
00098         // determine the scaling factor if necessary
00099         if (scalingFactor <= 0)
00100         {
00101                 int widthFactor = 0;
00102                 if (maxWidth > 0)
00103                 {
00104                         widthFactor = (inWidth + maxWidth - 1) / maxWidth;
00105                 }
00106                 int heightFactor = 0;
00107                 if (maxHeight > 0)
00108                 {
00109                         heightFactor = (inHeight + maxHeight - 1) /
00110                                 maxHeight;
00111                 }
00112                 scalingFactor = (widthFactor < heightFactor) ?
00113                         heightFactor : widthFactor;
00114                 if (scalingFactor <= 0)
00115                         scalingFactor = 1;
00116         }
00117 
00118         // if the scaling factor equals 1 then just copy the PNG file
00119         if (scalingFactor == 1)
00120         {
00121                 using namespace std;
00122                 if (!outName || !strcmp (inName, outName))
00123                 {
00124                         sout << inWidth << " x " << inHeight <<
00125                                 ": No downscaling necessary. "
00126                                 "Leaving the file intact.\n";
00127                         return 0;
00128                 }
00129                 sout << inWidth << " x " << inHeight <<
00130                         ": No downscaling necessary. "
00131                         "Copying the file byte-for-byte.\n";
00132                 FILE *inFile = fopen (inName, "rb");
00133                 FILE *outFile = fopen (outName, "wb");
00134                 int ch = getc (inFile);
00135                 while (ch != EOF)
00136                 {
00137                         putc (ch, outFile);
00138                         ch = getc (inFile);
00139                 }
00140                 fclose (outFile);
00141                 fclose (inFile);
00142                 return 0;
00143         }
00144 
00145         // create a new PNG image in the memory
00146         int outWidth = inWidth / scalingFactor;
00147         if (outWidth <= 0)
00148                 outWidth = 1;
00149         int outHeight = inHeight / scalingFactor;
00150         if (outHeight <= 0)
00151                 outHeight = 1;
00152         PngImage outPng (outWidth, outHeight);
00153 
00154         // show the information on rescaling
00155         sout << "Downscaling " << inName;
00156         if (outName)
00157                 sout << " -> " << outName;
00158         sout << ":\n" << inWidth << " x " << inHeight << " -> " <<
00159                 outWidth << " x " << outHeight << " (" << scalingFactor <<
00160                 " times smaller).\n";
00161 
00162         // compute the pixels of the new PNG image as averages
00163         for (int outX = 0; outX < outWidth; ++ outX)
00164         {
00165                 for (int outY = 0; outY < outHeight; ++ outY)
00166                 {
00167                         // prepare variables to sum color components
00168                         int red = 0;
00169                         int green = 0;
00170                         int blue = 0;
00171 
00172                         // compute the sum of color components
00173                         int inX = outX * scalingFactor;
00174                         int inY = outY * scalingFactor;
00175                         for (int x = 0; x < scalingFactor; ++ x)
00176                         {
00177                                 for (int y = 0; y < scalingFactor; ++ y)
00178                                 {
00179                                         int color = inPng. getPixel
00180                                                 (inX + x, inY + y);
00181                                         red += (color >> 16) & 0xFF;
00182                                         green += (color >> 8) & 0xFF;
00183                                         blue += color & 0xFF;
00184                                 }
00185                         }
00186 
00187                         // compute the average of the color components
00188                         int n = scalingFactor * scalingFactor;
00189                         red = (red + (n >> 1)) / n;
00190                         green = (green + (n >> 1)) / n;
00191                         blue = (blue + (n >> 1)) / n;
00192 
00193                         // plot the pixel with the average colors
00194                         int color = (red << 16) | (green << 8) | blue;
00195                         outPng. putPixel (outX, outY, color);
00196                 }
00197         }       
00198 
00199         // save the output PNG image to a file
00200         outPng. save (outName ? outName : inName);
00201         return 0;
00202 } /* pngSmall */
00203 
00204 // --------------------------------------------------
00205 // ---------------------- MAIN ----------------------
00206 // --------------------------------------------------
00207 
00208 /// The main procedure of the program.
00209 /// Returns: 0 = Ok, -1 = Error, 1 = Help displayed, 2 = Wrong arguments.
00210 int main (int argc, char *argv [])
00211 {
00212         using namespace chomp::homology;
00213 
00214         // prepare user-configurable data
00215         char *inName = 0;
00216         char *outName = 0;
00217         int maxWidth = 0;
00218         int maxHeight = 0;
00219         int scalingFactor = 0;
00220 
00221         // interprete the command-line arguments
00222         arguments a;
00223         arg (a, 0, inName);
00224         arg (a, 0, outName);
00225         arg (a, "w", maxWidth);
00226         arg (a, "h", maxHeight);
00227         arg (a, "s", scalingFactor);
00228         arghelp (a);
00229 
00230         argstreamprepare (a);
00231         int argresult = a. analyze (argc, argv);
00232         argstreamset ();
00233 
00234         // if no input name has been provided then show the help information
00235         if (!inName)
00236                 argresult = 1;
00237 
00238         // show the program's main title
00239         if (argresult >= 0)
00240                 sout << title << '\n';
00241 
00242         // if something was incorrect, show an additional message and exit
00243         if (argresult < 0)
00244         {
00245                 sout << "Call with '--help' for help.\n";
00246                 return 2;
00247         }
00248 
00249         // if help requested, show help information
00250         if (argresult > 0)
00251         {
00252                 sout << helpinfo << '\n';
00253                 return 1;
00254         }
00255 
00256         // try running the main function and catch an error message if thrown
00257         try
00258         {
00259                 // set an appropriate program time message
00260                 program_time = "Aborted after:";
00261                 program_time = 1;
00262 
00263                 // run the conversion procedure
00264                 pngSmall (inName, outName, maxWidth, maxHeight,
00265                         scalingFactor);
00266 
00267                 // set an appropriate program time message
00268                 program_time = "Total time used:";
00269 
00270                 // finalize
00271                 return 0;
00272         }
00273         catch (const char *msg)
00274         {
00275                 sout << "ERROR: " << msg << '\n';
00276                 return -1;
00277         }
00278         catch (const std::exception &e)
00279         {
00280                 sout << "ERROR: " << e. what () << '\n';
00281                 return -1;
00282         }
00283         catch (...)
00284         {
00285                 sout << "ABORT: An unknown error occurred.\n";
00286                 return -1;
00287         }
00288 } /* main */
00289 

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