/* 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 2 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. If you cannot find a copy of the GNU General Public License, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 -O3 -o qdfilt qdfilt.c 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 #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 getline () { 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], junk, 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)); getline(); getline(); assert (fwrite (this, 1, linlen, stdout) == linlen); for (y=1; y