/*
 * jdmcu.c
 *
 * Copyright (C) 1991, 1992, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains MCU disassembly and IDCT control routines.
 * These routines are invoked via the disassemble_MCU, reverse_DCT, and
 * disassemble_init/term methods.
 */

#include "jinclude.h"          

/*
 * Frankie
 */
#include "Time.h"            
#include "FastUtils.h"

/*
 * Fetch one MCU row from entropy_decode, build coefficient array.
 * This version is used for noninterleaved (single-component) scans.
 */

METHODDEF void
disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
                                JBLOCKIMAGE image_data)
{
  JBLOCKROW MCU_data[1];
  long mcuindex;

  /* this is pretty easy since there is one component and one block per MCU */

  /* Pre-zero the target area to speed up entropy decoder */
  /* (we assume wholesale zeroing is faster than retail) */
  jzero_far((void FAR *) image_data[0][0],
            (size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK)));

  for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
    /* Point to the proper spot in the image array for this MCU */
    MCU_data[0] = image_data[0][0] + mcuindex;
    /* Fetch the coefficient data */
    (*cinfo->methods->entropy_decode) (cinfo, MCU_data);
  }
}


/*
 * Fetch one MCU row from entropy_decode, build coefficient array.
 * This version is used for interleaved (multi-component) scans.
 */

METHODDEF void
disassemble_interleaved_MCU (decompress_info_ptr cinfo,
                             JBLOCKIMAGE image_data)
{
  JBLOCKROW MCU_data[MAX_BLOCKS_IN_MCU];
  long mcuindex;
  short blkn, ci, xpos, ypos;
  jpeg_component_info * compptr;
  JBLOCKROW image_ptr;

  /* Pre-zero the target area to speed up entropy decoder */
  /* (we assume wholesale zeroing is faster than retail) */
  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
    compptr = cinfo->cur_comp_info[ci];
    for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
      jzero_far((void FAR *) image_data[ci][ypos],
                (size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK)));
    }
  }

  for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
    /* Point to the proper spots in the image array for this MCU */
    blkn = 0;
    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
      compptr = cinfo->cur_comp_info[ci];
      for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
        image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width);
        for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
          MCU_data[blkn] = image_ptr;
          image_ptr++;
          blkn++;
        }
      }
    }

TIME_START(1,"entropy_decode")

    /* Fetch the coefficient data */
    (*cinfo->methods->entropy_decode) (cinfo, MCU_data);
TIME_END(1)
  }
}


/*
 * Perform inverse DCT on each block in an MCU row's worth of data;
 * output the results into a sample array starting at row start_row.
 * NB: start_row can only be nonzero when dealing with a single-component
 * scan; otherwise we'd have to pass different offsets for different
 * components, since the heights of interleaved MCU rows can vary.
 * But the pipeline controller logic is such that this is not necessary.
 */

extern void my_rev_dct(DCTELEM * input,JSAMPARRAY outarray,int offset,char * range_limit);

METHODDEF void reverse_DCT (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data,
   int start_row)
{
JBLOCKROW browptr;
JSAMPARRAY srowptr;
int blocksperrow, bi;
int numrows, ri;
int ci;
register short int * block;                  /* DCT block */
register JSAMPLE *range_limit = cinfo->sample_range_limit + CENTERJSAMPLE;
int i;
char moy;                     
jpeg_component_info * compptr;
boolean Preview;

TIME_START(2,"reverse_DCT")

   Preview = cinfo -> x_scale_mul == 1 && cinfo -> y_scale_mul == 1 && cinfo -> x_scale_div == 8 &&
      cinfo -> y_scale_div == 8;
                           
   for (ci = 0; ci < cinfo -> comps_in_scan ; ci++)
   {
      compptr = cinfo->cur_comp_info[ci];
      /* don't bother to IDCT an uninteresting component */
      if (! compptr->component_needed)
         continue;

      /* calculate size of an MCU row in this component */
      blocksperrow = (int)cinfo->cur_comp_info[ci]->downsampled_width / DCTSIZE;
      numrows = cinfo->cur_comp_info[ci]->MCU_height;
      /* iterate through all blocks in MCU row */
      for (ri = 0; ri < numrows; ri++)
      {
         browptr = coeff_data[ci][ri];
         srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
         for (bi = 0; bi < blocksperrow; bi++)
         {                      
            /* Block est un array 8*8 de short */
            block=(short int *)browptr[bi];      

            /* Fait on une preview au 1/8e ?? */
            if(Preview)
            {
               /* Cas preview , la moyenne d'un block est son premier coeff */
               moy=range_limit[block[0]/8];
               if(compptr->component_index == 0)
               {
                  /* Premier component = Y , on ne reproduit pas tout le bloc */
                  *(char *)(srowptr[0] + (bi * DCTSIZE))=moy; 
               }
               else 
               {
                  /* Component , U , V upsample , on reproduit tout */
                  for(i=0;i<DCTSIZE2;i++)
                     *(char *)(srowptr[i/8] + (bi * DCTSIZE) + i%8 )=moy; 
               };
            }
            else
            {
               /* Cas normal , dct + range limiting */
               my_rev_dct(block,srowptr,bi * DCTSIZE,range_limit);
            };
         }
      }
   }

TIME_END(2)
}



/*
 * Initialize for processing a scan.
 */

METHODDEF void
disassemble_init (decompress_info_ptr cinfo)
{
  /* no work for now */
}


/*
 * Clean up after a scan.
 */

METHODDEF void
disassemble_term (decompress_info_ptr cinfo)
{
  /* no work for now */
}



/*
 * The method selection routine for MCU disassembly.
 */

GLOBAL void
jseldmcu (decompress_info_ptr cinfo)
{
  if (cinfo->comps_in_scan == 1)
    cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
  else
    cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
  cinfo->methods->reverse_DCT = reverse_DCT;
  cinfo->methods->disassemble_init = disassemble_init;
  cinfo->methods->disassemble_term = disassemble_term;
}
