/*
 * judge.c
 *
 * judges the quality of jpeg files, output format similar to file(1)
 *
 * This uses code from the IJG JPEG library. The original copyright was:
 *
 * Copyright (C) 1994-1996, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README-jpeg6a
 * file.
 *
 * The estimate function and all the changes are copyright Marc Lehmann.
 * You can do anything with it *except* claim that you have written it.
 *
 */

#include "config.h"

#include <assert.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <jpeglib.h>

#include "estim.c"

static int
judge_quality (char *filename)
{
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  int scan_size;
  u8 *buffer, *scanline;
  FILE *input_file;
  JDIMENSION num_scanlines;
  estimate_stat stat;
  
  /* Initialize the JPEG decompression object with default error handling. */
  cinfo.err = jpeg_std_error (&jerr);
  cinfo.err->trace_level = 0;
  jpeg_create_decompress (&cinfo);

  if (filename)
    {
      /* Open the input file. */
      if ((input_file = fopen (filename, "rb")) == NULL)
	{
	  perror (filename);
	  return -1;
	}
    }
  else
    input_file = stdin;

  /* Specify data source for decompression */
  jpeg_stdio_src (&cinfo, input_file);

  /* Read file header, set default decompression parameters */
  (void) jpeg_read_header (&cinfo, TRUE);

  cinfo.dct_method = JDCT_ISLOW;
  cinfo.dither_mode = JDITHER_NONE;
  cinfo.do_fancy_upsampling = FALSE;
  cinfo.do_block_smoothing = FALSE;

  /* Start decompressor */
  (void) jpeg_start_decompress (&cinfo);

  scan_size = cinfo.output_width * cinfo.output_components;
  scanline = buffer = (u8 *) malloc (scan_size * DCTSIZE);
  assert (buffer);		// bad, bad...

  estimate_init (&stat);

  /* Process data */
  while (cinfo.output_height > cinfo.output_scanline)
    {
      num_scanlines = jpeg_read_scanlines (&cinfo, &scanline, 1);
      assert (num_scanlines == 1);
      if ((unsigned) cinfo.output_scanline % DCTSIZE == 0)
	{
	  scanline = buffer;
	  process_blocks (&stat, buffer, cinfo.output_width, cinfo.output_components);
	}
      else
	scanline += scan_size;

    }

  free (buffer);

  (void) jpeg_finish_decompress (&cinfo);
  jpeg_destroy_decompress (&cinfo);

  /* Close files, if we opened them */
  if (filename)
    fclose (input_file);

  /* All done. */
  if (jerr.num_warnings)
    printf ("jpeg read error\n");

  return estimate_quality (&stat);
}

static void
usage (char *prog, int ec)
{
  fprintf (stderr, "Usage: %s [ -vb ] file ...\n", prog);
  exit (ec);
}

int
main (int argc, char **argv)
{
  int display_filenames = 1;
  int retcode = 0;
  
  for (;;)
    {
      switch (getopt (argc, argv, "hvb"))
	{
	case 'h':
	  usage (argv[0], 0);
	  
	case 'v':
	  printf ("%s version %s\n", PACKAGE, VERSION);
	  exit (0);
	
	case 'b':
	  display_filenames = 0;
	  break;
	  
	case '?':
	  usage (argv[0], 2);
	
	default:
	  goto noodle;
	}
    }
  
  noodle:
  
  if (optind == argc)
    usage (argv[0], 2);
  
  while (optind < argc)
    {
      int quality;
      char *filename = argv[optind];
      
      quality = judge_quality (strcmp (filename, "-") ? filename : 0);
      
      if (quality<0)
        retcode = 1;
      else if (display_filenames)
        printf ("%s: %3d\n", filename, quality);
      else
        printf ("%3d\n", quality);
      
      optind++;
    }
  
  return retcode;
}
