The Conley-Morse Graphs Software
pngsmall.cpp
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file pngsmall.cpp
4///
5/// This is a small utility program which decreases in size a PNG file
6/// (if necessary) in order to make it fit within the given size.
7///
8/// @author Pawel Pilarczyk
9///
10/////////////////////////////////////////////////////////////////////////////
11
12// Copyright (C) 1997-2014 by Pawel Pilarczyk.
13//
14// This file is part of my research software package. This is free software:
15// you can redistribute it and/or modify it under the terms of the GNU
16// General Public License as published by the Free Software Foundation,
17// either version 3 of the License, or (at your option) any later version.
18//
19// This software is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License
25// along with this software; see the file "license.txt". If not,
26// please, see <https://www.gnu.org/licenses/>.
27
28// Started on April 10, 2008. Last revision: April 10, 2008.
29
30
31// include some standard C++ header files
32#include <exception>
33#include <cstring>
34#include <cstdio>
35
36// include selected header files from the CHomP library
37#include "chomp/system/config.h"
38#include "chomp/system/textfile.h"
39#include "chomp/system/timeused.h"
40#include "chomp/system/arg.h"
41
42// include local header files
43#include "pngimage.h"
44
45
46// --------------------------------------------------
47// -------------------- OVERTURE --------------------
48// --------------------------------------------------
49
50/// The title of the program which is displayed every time
51/// the program is launched.
52const char *title = "\
53PNGSMALL, ver. 0.01, 04/10/08. Copyright (C) 1997-2014 by Pawel Pilarczyk.\n\
54This is free software. No warranty. Consult 'license.txt' for details.";
55
56/// The help information about the program which is displayed
57/// if the program is launched without command-line arguments
58/// or with incorrect arguments.
59const char *helpinfo = "\
60This program reads a given PNG image and writes another PNG image\n\
61which is the original one scaled down so that the provided width\n\
62and height are not exceeded. The down-scaling factors are limited\n\
63to the integer numbers for optimal efficiency. The colors of output\n\
64pixels are computed by means of an arithmetic average of the input ones.\n\
65Command line arguments:\n\
66input.png - the name of the input PNG image file to be down-scaled,\n\
67output.png - the name of the output PNG file (rewrites the input if none),\n\
68-w width - the maximal allowed width of the output PNG image,\n\
69-h height - the maximal allowed height of the output PNG image,\n\
70-s scaling - the downscaling factor (overrides max width/height settings),\n\
71--quiet - makes the program run quietly, without any output messages,\n\
72--help - shows this brief help information on the program's usage.\n\
73For more information consult the accompanying documentation (if available)\n\
74or ask the program's author at http://www.PawelPilarczyk.com/.";
75
76
77// --------------------------------------------------
78// -------------------- PNGSMALL --------------------
79// --------------------------------------------------
80
81/// The main function of the program "pngsmall".
82/// This function downscales the given PNG image and saves the result
83/// as another PNG image.
84/// The scaling factor is determined on the basis of the provided maximal
85/// allowed width and/or height of the image, unless specified explicitly.
86/// Returns 0, or throws an error message in case of failure.
87int pngSmall (const char *inName, const char *outName,
88 int maxWidth, int maxHeight, int scalingFactor)
89{
90 using chomp::homology::sout;
91
92 // read the input PNG image
93 PngImage inPng (inName);
94 int inWidth = inPng. width ();
95 int inHeight = inPng. height ();
96
97 // determine the scaling factor if necessary
98 if (scalingFactor <= 0)
99 {
100 int widthFactor = 0;
101 if (maxWidth > 0)
102 {
103 widthFactor = (inWidth + maxWidth - 1) / maxWidth;
104 }
105 int heightFactor = 0;
106 if (maxHeight > 0)
107 {
108 heightFactor = (inHeight + maxHeight - 1) /
109 maxHeight;
110 }
111 scalingFactor = (widthFactor < heightFactor) ?
112 heightFactor : widthFactor;
113 if (scalingFactor <= 0)
114 scalingFactor = 1;
115 }
116
117 // if the scaling factor equals 1 then just copy the PNG file
118 if (scalingFactor == 1)
119 {
120 using namespace std;
121 if (!outName || !strcmp (inName, outName))
122 {
123 sout << inWidth << " x " << inHeight <<
124 ": No downscaling necessary. "
125 "Leaving the file intact.\n";
126 return 0;
127 }
128 sout << inWidth << " x " << inHeight <<
129 ": No downscaling necessary. "
130 "Copying the file byte-for-byte.\n";
131 FILE *inFile = fopen (inName, "rb");
132 FILE *outFile = fopen (outName, "wb");
133 int ch = getc (inFile);
134 while (ch != EOF)
135 {
136 putc (ch, outFile);
137 ch = getc (inFile);
138 }
139 fclose (outFile);
140 fclose (inFile);
141 return 0;
142 }
143
144 // create a new PNG image in the memory
145 int outWidth = inWidth / scalingFactor;
146 if (outWidth <= 0)
147 outWidth = 1;
148 int outHeight = inHeight / scalingFactor;
149 if (outHeight <= 0)
150 outHeight = 1;
151 PngImage outPng (outWidth, outHeight);
152
153 // show the information on rescaling
154 sout << "Downscaling " << inName;
155 if (outName)
156 sout << " -> " << outName;
157 sout << ":\n" << inWidth << " x " << inHeight << " -> " <<
158 outWidth << " x " << outHeight << " (" << scalingFactor <<
159 " times smaller).\n";
160
161 // compute the pixels of the new PNG image as averages
162 for (int outX = 0; outX < outWidth; ++ outX)
163 {
164 for (int outY = 0; outY < outHeight; ++ outY)
165 {
166 // prepare variables to sum color components
167 int red = 0;
168 int green = 0;
169 int blue = 0;
170
171 // compute the sum of color components
172 int inX = outX * scalingFactor;
173 int inY = outY * scalingFactor;
174 for (int x = 0; x < scalingFactor; ++ x)
175 {
176 for (int y = 0; y < scalingFactor; ++ y)
177 {
178 int color = inPng. getPixel
179 (inX + x, inY + y);
180 red += (color >> 16) & 0xFF;
181 green += (color >> 8) & 0xFF;
182 blue += color & 0xFF;
183 }
184 }
185
186 // compute the average of the color components
187 int n = scalingFactor * scalingFactor;
188 red = (red + (n >> 1)) / n;
189 green = (green + (n >> 1)) / n;
190 blue = (blue + (n >> 1)) / n;
191
192 // plot the pixel with the average colors
193 int color = (red << 16) | (green << 8) | blue;
194 outPng. putPixel (outX, outY, color);
195 }
196 }
197
198 // save the output PNG image to a file
199 outPng. save (outName ? outName : inName);
200 return 0;
201} /* pngSmall */
202
203
204// --------------------------------------------------
205// ---------------------- MAIN ----------------------
206// --------------------------------------------------
207
208/// The main procedure of the program.
209/// Returns: 0 = Ok, -1 = Error, 1 = Help displayed, 2 = Wrong arguments.
210int main (int argc, char *argv [])
211{
212 using namespace chomp::homology;
213
214 // prepare user-configurable data
215 char *inName = 0;
216 char *outName = 0;
217 int maxWidth = 0;
218 int maxHeight = 0;
219 int scalingFactor = 0;
220
221 // interprete the command-line arguments
222 arguments a;
223 arg (a, 0, inName);
224 arg (a, 0, outName);
225 arg (a, "w", maxWidth);
226 arg (a, "h", maxHeight);
227 arg (a, "s", scalingFactor);
228 arghelp (a);
229
230 argstreamprepare (a);
231 int argresult = a. analyze (argc, argv);
232 argstreamset ();
233
234 // if no input name has been provided then show the help information
235 if (!inName)
236 argresult = 1;
237
238 // show the program's main title
239 if (argresult >= 0)
240 sout << title << '\n';
241
242 // if something was incorrect, show an additional message and exit
243 if (argresult < 0)
244 {
245 sout << "Call with '--help' for help.\n";
246 return 2;
247 }
248
249 // if help requested, show help information
250 if (argresult > 0)
251 {
252 sout << helpinfo << '\n';
253 return 1;
254 }
255
256 // try running the main function and catch an error message if thrown
257 try
258 {
259 // set an appropriate program time message
260 program_time = "Aborted after:";
261 program_time = 1;
262
263 // run the conversion procedure
264 pngSmall (inName, outName, maxWidth, maxHeight,
265 scalingFactor);
266
267 // set an appropriate program time message
268 program_time = "Total time used:";
269
270 // finalize
271 return 0;
272 }
273 catch (const char *msg)
274 {
275 sout << "ERROR: " << msg << '\n';
276 return -1;
277 }
278 catch (const std::exception &e)
279 {
280 sout << "ERROR: " << e. what () << '\n';
281 return -1;
282 }
283 catch (...)
284 {
285 sout << "ABORT: An unknown error occurred.\n";
286 return -1;
287 }
288} /* main */
289
An interface to the PNG library.
Definition: pngimage.h:52
Writing PNG images.
int main(int argc, char *argv[])
The main procedure of the program.
Definition: pngsmall.cpp:210
const char * helpinfo
The help information about the program which is displayed if the program is launched without command-...
Definition: pngsmall.cpp:59
int pngSmall(const char *inName, const char *outName, int maxWidth, int maxHeight, int scalingFactor)
The main function of the program "pngsmall".
Definition: pngsmall.cpp:87
const char * title
The title of the program which is displayed every time the program is launched.
Definition: pngsmall.cpp:52