/* $Id: qdfilt.c 3735 2010-08-11 00:12:39Z flaterco $
qdfilt -- quick and dirty image sharpening and smoothing
Copyright (C) 1997 David Flater.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You can obtain a copy of the GNU General Public License from
.
Description
-----------
This program follows in the footsteps of qdgamma in re-inventing
the wheel for simple image processing. This time it's linear
filtering of the sort that could be done with pnmconvol, but
restricted to just sharpening and smoothing.
qdfilt version 1 works ONLY on 8-bit rawbits pixmaps and
graymaps with maxval = 255, and ONLY on stdin and stdout.
Usage: qdfilt factor < input > output
Factor Result
------ ------
<-1.0 Super extra sharpening
-1.0 Heavy linear sharpening
-0.2 Light linear sharpening
0.0 No operation
0.2 Light linear smoothing
1.0 Max linear smoothing
>1.0 Meaningless blurring
Most of the time you will get better results smoothing with qdnlfilt.
The main utility of this program is for sharpening.
To compile: gcc -O2 -s -o qdfilt qdfilt.c
Version 3.1 2010-08-10
Minor cleanups.
Version 3 2010-07-18
Renamed getline to resolve clash with stdio.h.
Version 2 2000-02-21
Hastily added code to avoid choking on comments in PNM files.
Changes from version 1.1 to 1.2: added center pixel to mean so that
factor of 1.0 really is max smoothing. Need to use a slightly
higher sharpening factor to compensate.
Changes from version 1 to 1.1: code cleanups.
*/
#include
#include
#include
#include
#ifdef MSDOS
#include
#include
#endif
unsigned char *prev, *this, *next;
int linlen;
void
usage ()
{
fprintf (stderr, "Usage: qdfilt factor < input > output\n\
\n\
Factor Result\n\
------ ------\n\
<-1.0 Super extra sharpening\n\
-1.0 Heavy linear sharpening\n\
-0.2 Light linear sharpening\n\
0.0 No operation\n\
0.2 Light linear smoothing\n\
1.0 Max linear smoothing\n\
>1.0 Meaningless blurring\n");
exit (-1);
}
void
bogus ()
{
fprintf (stderr,
"qdfilt works ONLY on 8-bit rawbits pixmaps and\n");
fprintf (stderr,
"graymaps with maxval = 255, and ONLY on stdin and stdout.\n");
exit (-1);
}
int linterp (float a, float b, float x) {
float temp;
temp = (a + x*(b-a) + 0.5);
if (temp < 0.0)
temp = 0.0;
else if (temp > 255.0)
temp = 255.0;
return (int)temp;
}
void
qdgetline () {
unsigned char *temp;
temp = prev;
prev = this;
this = next;
next = temp;
assert (fread (next, 1, linlen, stdin) == linlen);
}
void
getnoncommentline (char buf[1000]) {
do
assert (fgets (buf, 1000, stdin));
while (buf[0] == '#');
}
int
main (int argc, char **argv)
{
int width, height, maxval, grayflag = 0, disp, x, y, mean;
float factor;
char magicnum[3], buf[1000];
if (argc != 2)
usage ();
if (sscanf (argv[1], "%f", &factor) != 1)
usage ();
#ifdef MSDOS
setmode (fileno (stdin), O_BINARY);
setmode (fileno (stdout), O_BINARY);
#endif
getnoncommentline (buf);
if (sscanf (buf, "%2s", magicnum) != 1) {
fprintf (stderr, "Error getting header data\n");
bogus();
}
getnoncommentline (buf);
if (sscanf (buf, "%d %d", &width, &height) != 2) {
fprintf (stderr, "Error getting header data\n");
bogus();
}
getnoncommentline (buf);
if (sscanf (buf, "%d", &maxval) != 1) {
fprintf (stderr, "Error getting header data\n");
bogus();
}
if (strcmp (magicnum, "P5") != 0 && strcmp (magicnum, "P6") != 0) {
fprintf (stderr, "Bad magic number\n");
bogus ();
}
if (maxval != 255) {
fprintf (stderr, "Maxval != 255\n");
bogus ();
}
if (magicnum[1] == '5')
grayflag = 1;
printf ("%s\n%d %d\n%d\n", magicnum, width, height, maxval);
if (width < 3 || height < 3) {
/* Too small to do anything with; echo stdin to stdout */
int tval;
while ((tval = getchar ()) != EOF)
assert (putchar (tval) != EOF);
fflush (stdout);
exit (0);
}
disp = (grayflag? 1 : 3);
linlen = width * disp;
assert (prev = malloc (linlen));
assert (this = malloc (linlen));
assert (next = malloc (linlen));
qdgetline();
qdgetline();
assert (fwrite (this, 1, linlen, stdout) == linlen);
for (y=1; y