/*  $Id: qdgamma.c 3735 2010-08-11 00:12:39Z flaterco $

    qdgamma -- quick and dirty replacement for pnmgamma

    Copyright (C) 1995  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
    <http://www.gnu.org/licenses/>.


    Description
    -----------

    At some point in my life, I lost the ability to get pnmgamma to
    work.  I do not know how, or why.  After living without it for a
    while and realizing that I couldn't live without it, I replaced it
    with this program, which does not depend on any of the pbmplus
    libraries.  If you _can_ use pnmgamma, then use it.  If you can't,
    then use this.

    qdgamma works ONLY on 8-bit rawbits pixmaps and graymaps with
    maxval = 255, and ONLY on stdin and stdout.

    Usage:  qdgamma gammaval < input > output

    To compile:  gcc -O2 -s -o qdgamma qdgamma.c -lm


    Version 2.1 2010-08-10
      Minor cleanups.

    Version 2 2000-02-21
      Hastily added code to avoid choking on comments in PNM files.

    Version 1 1995-03-19
*/

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#ifdef MSDOS
#include <io.h>
#include <fcntl.h>
#endif

void
usage ()
{
  fprintf (stderr, "Usage:  qdgamma gammaval < input > output\n");
  fprintf (stderr,
    "gammaval between 0 and 1 is darker; above 1 is brighter\n");
  exit (-1);
}

void
bogus ()
{
  fprintf (stderr,
  "qdgamma works ONLY on 8-bit rawbits pixmaps and\n");
  fprintf (stderr,
  "graymaps with maxval = 255, and ONLY on stdin and stdout.\n");
  exit (-1);
}

void
getnoncommentline (char buf[1000]) {
  do
    assert (fgets (buf, 1000, stdin));
  while (buf[0] == '#');
}

int
main (int argc, char **argv)
{
  int xlate[256], looper, tval, width, height, maxval;
  double gamma;
  char magicnum[3], buf[1000];
  if (argc != 2)
    usage ();
  if (sscanf (argv[1], "%lf", &gamma) != 1)
    usage ();
  if (gamma <= 0.0)
    usage ();
#ifdef MSDOS
  setmode (fileno (stdin), O_BINARY);
  setmode (fileno (stdout), O_BINARY);
#endif
  gamma = 1.0 / gamma;
  for (looper=0;looper<256;looper++) {
    tval = (int)(255.0*pow(((double)looper)/255.0, gamma) + 0.5);
    xlate[looper] = (255 > tval ? tval : 255);
  }

  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 ();
  }
  printf ("%s\n%d %d\n%d\n", magicnum, width, height, maxval);
  while ((tval = getchar ()) != EOF)
    assert (putchar (xlate[tval]) != EOF);
  fflush (stdout);
  exit (0);
}
