/*
 * predict.c --
 * 
 * Code for predictor calculation. Its macro version, predictor.h,
 * is used in non-debugging compilation.
 */
/*
 *
 */
#include <stdio.h>
#include "mcu.h"

#ifdef DEBUG
/*
 *--------------------------------------------------------------
 *
 * Predict --
 *
 *      Calculate the predictor for pixel[row][col][curComp],
 *      i.e. curRowBuf[col][curComp]. It handles the all special 
 *      cases at image edges, such as first row and first column
 *      of a scan.
 *
 * Results:
 *      predictor is passed out.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
void
Predict(int row,int col,  /* position of the pixel to be predicted */
        int curComp,      /* the pixel's component that is predicting */
        MCU *curRowBuf,MCU *prevRowBuf, /* current and previous row of image */
        int Pr,          /* data precision */
        int Pt,          /* point transformation */
        int psv,         /* predictor selection value */
        int *predictor)  /* preditor value (output) */
{
    register int left,upper,diag,leftcol;

    leftcol=col-1;
    if (row==0) {      

       /* 
        * The predictor of first pixel is (1<<(Pr-Pt-1), and the
        * predictors for rest of first row are left neighbors. 
        */
       if (col==0) {
          *predictor = (1<<(Pr-Pt-1));
       }
       else {
          *predictor = curRowBuf[leftcol][curComp];
       }
    }
    else {

       /*
        * The predictors of first column are upper neighbors. 
        * All other preditors are calculated according to psv. 
        */
       upper=prevRowBuf[col][curComp];
       if (col==0)
          *predictor = upper;
       else {
          left=curRowBuf[leftcol][curComp];
          diag=prevRowBuf[leftcol][curComp];
          switch (psv) {
             case 0:
                     *predictor = 0;
                     break;
             case 1:
                     *predictor = left;
                     break;
             case 2:
                     *predictor = upper;
                     break;
             case 3:
                     *predictor = diag;
                     break;
             case 4:
                     *predictor = left+upper-diag;
                     break;
             case 5:
                     *predictor = left+((upper-diag)>>1);
                     break;
             case 6:
                     *predictor = upper+((left-diag)>>1);
                     break;
             case 7:
                     *predictor = (left+upper)>>1;
                     break;
             default:
                     fprintf(stderr,"Warning: Undefined PSV\n");
                     *predictor = 0;
           }
        }
      }
}

/*
 *--------------------------------------------------------------
 *
 * QuickPredict --
 *
 *      Calculate the predictor for sample curRowBuf[col][curComp].
 *      It does not handle the special cases at image edges, such 
 *      as first row and first column of a scan. We put the special 
 *      case checkings outside so that the computations in main
 *      loop can be simpler. This has enhenced the performance
 *      significantly.
 *
 * Results:
 *      predictor is passed out.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
void
QuickPredict(int col   /* column # of the pixel to be predicted */,
         int curComp   /* the pixel's component that is predicting */,
         MCU *curRowBuf,MCU *prevRowBuf,/* current and previous row of image */
         int psv       /* predictor selection value */,
         int predictor /* preditor value (output) */)
{
    register int left,upper,diag,leftcol;

    /* 
     * All predictor are calculated according to psv.
     */ 
    switch (psv) {
      case 0:
              *predictor = 0;
              break;
      case 1:
              leftcol = col-1;
              left    = curRowBuf[leftcol][curComp];
              *predictor = left;
              break;
      case 2:
              upper = prevRowBuf[col][curComp];
              *predictor = upper;
              break;
      case 3:
              leftcol = col-1;
              diag    = prevRowBuf[leftcol][curComp];
              *predictor = diag;
              break;
      case 4:
              leftcol = col-1;
              upper   = prevRowBuf[col][curComp];
              left    = curRowBuf[leftcol][curComp];
              diag    = prevRowBuf[leftcol][curComp];
              *predictor = left + upper - diag;
              break;
      case 5:
              leftcol = col-1;
              upper   = prevRowBuf[col][curComp];
              left    = curRowBuf[leftcol][curComp];
              diag    = prevRowBuf[leftcol][curComp];
              *predictor = left+((upper-diag)>>1);
              break;
      case 6:
              leftcol = col-1;
              upper   = prevRowBuf[col][curComp];
              left    = curRowBuf[leftcol][curComp];
              diag    = prevRowBuf[leftcol][curComp];
              *predictor = upper+((left-diag)>>1);
              break;
      case 7:
              leftcol = col-1;
              upper   = prevRowBuf[col][curComp];
              left    = curRowBuf[leftcol][curComp];
              *predictor = (left+upper)>>1;
              break;
      default:
              fprintf(stderr,"Warning: Undefined PSV\n");
              *predictor = 0;
     }
}
#endif /*DEBUG*/
