/* read_face.c -- read the Facesaver format from uunet. */

/* Copyright (C) 1988, 1990, 1992 Free Software Foundation, Inc.

   This file is part of GNU Finger.

   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, 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 should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include <stdio.h>
#include <config.h>
#include <general.h>
#include <bitmap.h>

/* If non-zero, this is the amount to magnify the face image by. */
int mag_factor = 5;

BITMAP *
read_face (user)
     char *user;
{
  register int i;
  FILE *file;
  BITMAP *face = (BITMAP *)NULL;
  char *filename = mugshot_filename (user);
  char line[128], *res;
  int size, width = 0, height = 0, depth = 0;

  file = fopen (filename, "r");
  free (filename);

  if (!file)
    return (BITMAP *)NULL;

  /* Get info about this file.  The file format is several lines, each one
     containing a label and a value, followed by the image data itself in
     an ASCII representation of hex. */
  while (1)
    {
      char *field_end;

      res = fgets (line, sizeof (line), file);

      if (res == (char *)NULL)
	break;

      /* Skip leading whitespace. */
      while (whitespace (*res))
	res++;

      /* Ignore blank lines. */
      if (!*res)
	continue;

      /* If this is a field, then parse out it's value. */
      field_end = rindex (res, ':');

      if (field_end)
	{
	  char *identifier = res;

	  *field_end = '\0';
	  res = field_end + 1;

	  if (strcmp (identifier, "PicData") == 0)
	    {
	      sscanf (res, "%d %d %d", &width, &height, &depth);
	    }
	}
      else
	break;
    }

  /* If we scanned in the width, height and depth, we can read the bits
     now. */
  if (depth)
    {
      int row, offset, tem;
      byte *image_row, *buffer;

      face = (BITMAP *)xmalloc (sizeof (BITMAP));

      face->width = width;
      face->height = height;

      if (depth == 8)
	face->rowlen = width;
      else
	face->rowlen = (width + 7) / 8;

      size = face->rowlen * height;

      buffer = (byte *)xmalloc (size);

      offset = 0;
      row = height - 1;

      while (res = fgets (line, sizeof (line), file))
	{
	  char hex_rep[3];

	  hex_rep[2] = '\0';

	next_row:
	  /* Protect against malformed input files. */
	  if (row < 0)
	    break;

	  image_row = buffer + (row * face->rowlen);

	next_byte:

	  /* Skip leading whitespace. */
	  while (whitespace (*res) || *res == ',')
	    res++;

	  if (!*res)
	    continue;

	  hex_rep[0] = *res++;
	  hex_rep[1] = *res++;
	  
	  sscanf (hex_rep, "%x", &tem);

	  image_row[offset++] = tem;

	  if (offset == face->rowlen)
	    {
	      offset = 0;
	      row--;
	      goto next_row;
	    }
	  goto next_byte;
	}

      if (depth == 8)
	{
	  byte *dither ();

	  /* Before we dither the face, expand it in place so that we can
	     at least have a larger image. */
	  {
	    byte *newface;
	    int newrowlen = face->rowlen * mag_factor;

	    newface = (byte *)xmalloc (newrowlen
				       * (mag_factor * face->height));

	    for (row = 0; row < face->height; row++)
	      {
		register int q, z;
		byte pixel, *newrow;

		for (offset = 0; offset < face->width; offset++)
		  {
		    newrow = newface
		      + ((row * mag_factor) * newrowlen);

		    pixel = buffer[(row * (face->rowlen)) + offset];

		    for (z = 0; z < mag_factor; z++)
		      {
			int newoffset = offset * mag_factor;

			for (q = 0; q < mag_factor; q++)
			  newrow[newoffset + q] = pixel;

			newrow += newrowlen;
		      }
		  }
	      }
	    free (buffer);
	    buffer = newface;
	    face->width *= mag_factor;
	    face->rowlen = face->width;
	    face->height *= mag_factor;
	  }

	  face->bits =
	    dither (buffer, face->width, face->height, face->rowlen);

	  face->rowlen = ROWBYTES (face->width);

	  reverse_image_bit_order (face);
	  free (buffer);
	}
      else
	face->bits = buffer;
    }

  fclose (file);
  
  return (face);
}

#ifdef TEST
#define MAGARG_PREFIX "-mag-factor="

/* Load a Facesaver file from disk and display it. */

main (argc, argv)
     int argc;
     char **argv;
{
  int arg_index = 1;

  while (arg_index != argc)
    {
      char *file = argv[arg_index++];
      BITMAP *face;

      if (strncmp (file, MAGARG_PREFIX, strlen (MAGARG_PREFIX)) == 0)
	{
	  sscanf (file + strlen (MAGARG_PREFIX), "%d", &mag_factor);
	  continue;
	}

      face = read_face (file);
      
      if (face)
	{
	  x_show_face (file, face);
	  free (face->bits);
	  free (face);
	}
      else
	fprintf (stderr, "No face bits for `%s'.\n", file);
    }
}

site_save_face ()
{}

#endif
/*
 * Local variables:
 * compile-command: "gcc -DTEST -o showface read_face.c x_show_face.o bitmap.o util.o dither.o -lXaw -lXt -lXmu -lXext -lX11 -lm -I../include -g"
 * end.
 */
