//
// Copyright (c) 1997,1998 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// See the README.TXT file that came with this software for restrictions
// on the use and redistribution of this file or send E-mail to
// info@colosseumbuilders.com
//

//
// JPEG Decoder Quantization Table Class Implementation
//
// Author:  John M. Miano  miano@colosseumbuilders.com
//

#include <iostream>
#include "jpgdecoderquantization.h"
#include "jpgdecoder.h"

using namespace std ;
using namespace Colosseum ;

#pragma comment (exestr, "Copyright 1997 Colosseum Builders Inc.")

namespace ColosseumPrivate
{

//
// This table consists of the values
//
//   F (i, j) = X (i) X (j) / 8 
// 
// where
// 
//  X (n) = 1, n = 0, 4
//  X (n) = 1 / sqrt(2) / cos (n*PI/16) 
//  

const double floatscaling [JPEGSAMPLESIZE] = 
{
 0.125,                  0.09011997775086849627, 0.09567085809127244544, 0.1063037618459070632,  0.125,                  0.159094822571604233,  0.2309698831278216846, 0.4530637231764438333, 
 0.09011997775086849627, 0.0649728831185362593,  0.0689748448207357645,  0.07664074121909414394, 0.09011997775086849627, 0.1147009749634507608, 0.1665200058287998886, 0.3266407412190940884, 
 0.09567085809127244544, 0.0689748448207357645,  0.0732233047033631207,  0.08136137691302557096, 0.09567085809127244544, 0.1217659055464329343, 0.1767766952966368932, 0.3467599613305368256, 
 0.1063037618459070632,  0.07664074121909414394, 0.08136137691302557096, 0.09040391826073060355, 0.1063037618459070632,  0.135299025036549253,  0.1964237395967755595, 0.3852990250365491698, 
 0.125,                  0.09011997775086849627, 0.09567085809127244544, 0.1063037618459070632,  0.125,                  0.159094822571604233,  0.2309698831278216846, 0.4530637231764438333, 
 0.159094822571604233,   0.1147009749634507608,  0.1217659055464329343,  0.135299025036549253,   0.159094822571604233,   0.2024893005527218515, 0.2939689006048396558, 0.5766407412190940329, 
 0.2309698831278216846,  0.1665200058287998886,  0.1767766952966368932,  0.1964237395967755595,  0.2309698831278216846,  0.2939689006048396558, 0.4267766952966368654, 0.8371526015321518744, 
 0.4530637231764438333,  0.3266407412190940884,  0.3467599613305368256,  0.3852990250365491698,  0.4530637231764438333,  0.5766407412190940329, 0.8371526015321518744, 1.642133898068010689,  
} ;

//
//  Description:
//
//    Class Default Constructor
//
JpegDecoderQuantizationTable::JpegDecoderQuantizationTable ()
{
  table_defined = false ;
  memset (data_values, 0, sizeof (data_values)) ;
  return ;
}

//
//  Description:
//
//    This function reads a quantization table from a JPEG stream.
//
//  Parameters:
//    decoder:  The JPEG decoder that owns the table and the JPEG stream.
//    precision: The quantization table precision
//
void JpegDecoderQuantizationTable::readTable (Colosseum::JpegInputStream &inputstream,
                                              unsigned int precision)
{
  // B 2.4.1
  // Determine if 16-bit or 8-bit precision is used for the quantization
  // values in the file.
  if (precision == 1)
  {
// Our source code only allows 8-bit data. The standard says
// 16-bit quantization tables are not allowed with 8-bit data.
// The commented code shows how 16-bit tables would be implemented.
//
//    // Read 16-bit values.
//    for (unsigned int ii = 0 ; ii < SampleSize ; ++ ii)
//    {
//      data_values[ii] = decoder.ReadWord () ;
//      if (data_values[ii] == 0)
//        throw EJpegBadData ("Zero value in quantization table") ;
//    }
    throw JpegDecoder::JpegBadStream ("Only 8-bit Data is Supported") ;
  }
  else if (precision == 0)
  {
    // Read 8-bit values.
    for (unsigned int ii = 0 ; ii < JPEGSAMPLESIZE ; ++ ii)
    {
      data_values[ii] = inputstream.getByte () ;
      if (data_values[ii] == 0)
        throw JpegDecoder::JpegBadStream ("Zero value in quantization table") ;
    }
  }
  else
  {
    throw JpegDecoder::JpegBadStream ("Invalid Quantization Table Precision") ;
  }

  buildScaledTables () ;

  table_defined = true ;
  return ;
}

//
//  Description:
//
//    This function creates scaled quantization tables that
//    allow quantization to be merged with the IDCT process.
//    We factor the DCT matrix so that the first step in the
//    IDCT is to multiply each value by a constant. Here we
//    merge that constant with the quantization table valus.
//
void JpegDecoderQuantizationTable::buildScaledTables ()
{
  unsigned int ii ;  // Overcome MSVC++ Wierdness
  for (ii = 0 ; ii < JPEGSAMPLESIZE ; ++ ii)
  {
    float_scaling [ii] = data_values [JpegZigZagOutputOrder (ii)] * floatscaling [ii] ;
  }
  for (ii = 0 ; ii < JPEGSAMPLESIZE ; ++ ii)
  {
    integer_scaling [ii] = (long) ((1 << QuantizationIntegerScale)
                                   * floatscaling [ii]
                                   * data_values  [JpegZigZagOutputOrder (ii)]) ;
  }
  return ;
}

//
//  Description:
//
//    This is a debugging function that prints the contents
//    of the quantization table to a stream.
//
//  Parameters:
//
//    strm:  The output stream
//
void JpegDecoderQuantizationTable::printOn (std::ostream &strm) const
{
  for (unsigned int ii = 0 ; ii < JPEGSAMPLEWIDTH ; ++ ii)
  {
    strm << endl << "        "  ;
    for (unsigned int jj = 0 ; jj < JPEGSAMPLEWIDTH ; ++ jj)
    {
      strm << dec
           << data_values [ii * JPEGSAMPLEWIDTH + jj]
           << " " ;
    }
  }

  strm << endl << " Integer Scaling " << endl << "        " ;
  for (unsigned int ii = 0 ; ii < JPEGSAMPLEWIDTH ; ++ ii)
  {
    for (unsigned int jj = 0 ; jj < JPEGSAMPLEWIDTH ; ++ jj)
    {
      strm << dec
           << integer_scaling [ii * JPEGSAMPLEWIDTH + jj]
           << " " ;
    }
    strm << endl << "        "  ;
  }

  return ;
}

}