#include "includes.h"
 
/**************************************|****************************************
Routine   : Map2BitMap
Input  par: BitMap *SrcImg    (Pointer to the source image to copy.)
            BitMap *DstImg    (Pointer to the destination image.)
            int XStart        (The x position in the source image to start
                               copying from.)
            int YStart        (The y position in the source image to start
                               copying from.)
Output par: None
Function  : Copies a part of a BitMap to a new BitMap.
***************************************|***************************************/
 
 void Map2BitMap(BitMap *SrcImg,BitMap *DstImg,int XStart,int YStart)
  {
   register unsigned int x,y;
   const unsigned int Sizex=DstImg->XSize;
   const unsigned int Sizey=DstImg->YSize;

   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<Sizex;x++)    
   for(y=0;y<Sizey;y++) DstImg->Map[x][y]=SrcImg->Map[XStart+x][YStart+y];
  }
 
/**************************************|****************************************
Routine   : BitMap2Map
Input  par: BitMap *SrcImg      (Pointer to the bitmap to copy.)
            BitMap *DstImg      (Pointer to the image to copy the source image
                                 into.)
            int XStart,YStart   (The x and y location in the destination image
                                 to copy the source image into.)
Output par: None
Function  : Copies a the source bitmap into the specified location of the
            destination bitmap.
***************************************|***************************************/
 
 void BitMap2Map(BitMap *SrcImg,BitMap *DstImg,int XStart,int YStart)
  {
   register unsigned int x,y;
   const unsigned int Sizex=SrcImg->XSize;
   const unsigned int Sizey=SrcImg->YSize;

   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<Sizex;x++)     
   for(y=0;y<Sizey;y++) DstImg->Map[XStart+x][YStart+y]=SrcImg->Map[x][y];
  }
 
/**************************************|****************************************
Routine   : Map3D2BitMap3D
Input  par: BitMap3D *SrcImg (Pointer to the source image to copy.)
            BitMap3D *DstImg (Pointer to the destination image.)
            int XStart       (The x position in the source image to start
                              copying from.)
            int YStart       (The y position in the source image to start
                              copying from.)
Output par: None
Function  : Copies a part of a BitMap3D to a new BitMap3D. Analog to Map2BitMap
***************************************|***************************************/
 
 void Map3D2BitMap3D(BitMap3D *SrcImg,BitMap3D *DstImg,int XStart,int YStart,int ZStart)
  {
   register unsigned int x,y,z;
   const unsigned int Sizex=DstImg->XSize;
   const unsigned int Sizey=DstImg->YSize;
   const unsigned int Sizez=DstImg->ZSize;

   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<Sizex;x++)    
   for(y=0;y<Sizey;y++)
   for(z=0;z<Sizez;z++)
   DstImg->Map[x][y][z]=SrcImg->Map[XStart+x][YStart+y][ZStart+z];
  }
 
/**************************************|****************************************
Routine   : CopyBitMap
Input  par: BitMap *SrcImg (Pointer to the source image.)
            BitMap *DstImg (Pointer to the destination image.)
Output par: None
Function  : Copies a BitMap struct.
***************************************|***************************************/
 
 void CopyBitMap(BitMap *SrcImg,BitMap *DstImg)
  {
   register unsigned int x,y;
   if (SrcImg->ImgType!=DstImg->ImgType)   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<DstImg->XSize;x++)    
    {
     for(y=0;y<DstImg->YSize;y++) DstImg->Map[x][y]=SrcImg->Map[x][y];
    }
  }


/**************************************|****************************************
Routine   : BitMap3D2Map3D
Input  par: BitMap3D *SrcImg    (Pointer to the bitmap to copy.)
            BitMap3D *DstImg    (Pointer to the image to copy the source image
                                 into.)
            int XStart,YStart   (The x and y location in the destination image
                                 to copy the source image into.)
Output par: None
Function  : Copies a the source 3D bitmap into the specified location of the
            destination bitmap. Analog to BitMap2Map
***************************************|***************************************/
 
 void BitMap3D2Map3D(BitMap3D *SrcImg,BitMap3D *DstImg,int XStart,int YStart,int ZStart)
  {
   register unsigned int x,y,z;
   const unsigned int Sizex=SrcImg->XSize;
   const unsigned int Sizey=SrcImg->YSize;
   const unsigned int Sizez=SrcImg->ZSize;

   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");

   for(x=0;x<Sizex;x++)     
   for(y=0;y<Sizey;y++)
   for(z=0;z<Sizez;z++) 
   DstImg->Map[XStart+x][YStart+y][ZStart+z]=SrcImg->Map[x][y][z];
  }
 
/**************************************|****************************************
Routine   : CopyBitMap3D
Input  par: BitMap3D *SrcImg (source image to copy)
            BitMap3D *DstImg (dest to copy to)
Output par: none
Function  : Copies a 3d bitmap to another 3d bitmap.
***************************************|***************************************/
 
 void CopyBitMap3D(BitMap3D *SrcImg,BitMap3D *DstImg)
  {
   register unsigned int x,y,z;
   const unsigned int Sizex=DstImg->XSize;
   const unsigned int Sizey=DstImg->YSize;
   const unsigned int Sizez=DstImg->ZSize;

   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");

   for(x=0;x<Sizex;x++)    
   for(y=0;y<Sizey;y++)
   for(z=0;z<Sizez;z++) DstImg->Map[x][y][z]=SrcImg->Map[x][y][z];
  }
 
/**************************************|****************************************
Routine   : Frame2BitMap
Input  par: BitMap3D *SrcImg (3d bitmap from where a frame must be extracted)
            int z            (the number of the frame to be extracted)
            BitMap *DstImg   (2d bitmap to copy to)
Output par: none
Function  : Copies a single frame of a 3d image to a 2d image.
***************************************|***************************************/
 
 void Frame2BitMap(BitMap3D *SrcImg,int z,BitMap *DstImg)
  {
   register unsigned int x,y;
   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<DstImg->XSize;x++)    
   for(y=0;y<DstImg->YSize;y++) DstImg->Map[x][y]=SrcImg->Map[x][y][z];
  }
 
/**************************************|****************************************
Routine   : BitMap2Frame
Input  par: BitMap *SrcImg   (2d bitmap frame)
            BitMap3D *DstImg (3d bitmap image)
            int z            (frame number of the 3d sequence)
Output par: none
Function  : Copies a 2d frame into a 3d bitmap.
***************************************|***************************************/
 
 void BitMap2Frame(BitMap *SrcImg,BitMap3D *DstImg,int z)
  {
   register unsigned int x,y;
   if (SrcImg->ImgType!=DstImg->ImgType) 
   ErrorHandler(WRONG_FORMAT,"Images not of the same type");
   for(x=0;x<DstImg->XSize;x++)    
   for(y=0;y<DstImg->YSize;y++) DstImg->Map[x][y][z]=SrcImg->Map[x][y];
  }
 
/**************************************|****************************************
Routine   : T_CScaleAndLShift3D
Input  par: BitMap3D *SrcImg (3d bitmap image to be shifted and scaled)
            float Scale      (contrast scale parameter , i.e. alpha)
            int Shift        (luminance shift parameter, i.e. deltag)
Output par: none
Function  : Takes a 3d image and scale it (*) with Mul and the shifts it with (+)
            Shift. The order of the * and + is important!
***************************************|***************************************/
 
 void T_CScaleAndLShift(BitMap *SrcImg,float Scale,int Shift)
  {
   register unsigned int x=SrcImg->XSize,y;
   register int Val;
   
   while(x--)      
    {
     y=SrcImg->YSize;
     while(y--)        
      {
         Val = (int)(SrcImg->Map[x][y]*Scale+0.5)+Shift;
         if (Val>255) Val=255; /* limit the output */
         if (Val<0)   Val=0;   /* to the range 0-255 */
         SrcImg->Map[x][y]=Val;
      }
    }
  }
 
/**************************************|****************************************
Routine   : T_AbsorbGrey3D
Input  par: BitMap3D *SrcImg  (3d image to be absorbed)
            unsigned char Par (absorbtion parameter)
Output par: none
Function  : Converts a 3d image to a homogeneous block of level Par.
***************************************|***************************************/
 
 void T_AbsorbGrey(BitMap *SrcImg, unsigned char Par)
  {
   register unsigned int x,y;
   const unsigned int Sizex=SrcImg->XSize;
   const unsigned int Sizey=SrcImg->YSize;
   
   for(x=0;x<Sizex;x++)      
   for(y=0;y<Sizey;y++)
   SrcImg->Map[x][y]=Par;
  }
 
/**************************************|****************************************
Routine   : Sample3D
Input  par: BitMap3D *SrcImg (image to sample from)
            BitMap3D *DstImg (destination image)
            int XPos,int YPos,int ZPos (the position in the source image)
Output par: none
Function  : Takes a 3d image 
***************************************|***************************************/
 
 void Sample(BitMap *SrcImg,BitMap *DstImg,int XPos,int YPos)
  {
   register unsigned int x,y,i,j;
   register unsigned int Sum;
   const unsigned int Sizex=DstImg->XSize<<1;
   const unsigned int Sizey=DstImg->YSize<<1;
   
   for(x=0;x<Sizex;x+=2)      
    {
     for(y=0;y<Sizey;y+=2)        
      {
       Sum=0;
       for(i=0;i<2;i++)          
       for(j=0;j<2;j++)
       Sum+=SrcImg->Map[XPos+x+i][YPos+y+j];
       
       DstImg->Map[x>>1][y>>1]=Sum>>2;
      }
    }
  }
 
/**************************************|****************************************
Routine   : *Expand23D
Input  par: BitMap3D *SrcImg (image to be expanded)
Output par: BitMap3D * (pointer to expanded image)
Function  : Takes an image and expand it with a factor two.
***************************************|***************************************/
 
 BitMap *Expand2(BitMap *SrcImg)
  {
   BitMap *DstImg=GimmeABitMap((SrcImg->XSize)<<1,(SrcImg->YSize)<<1,
                         SrcImg->ImgType);
   register unsigned int x,y;
   const unsigned int Sizex=DstImg->XSize;
   const unsigned int Sizey=DstImg->YSize;

   for(x=0;x<Sizex;x++)    
   for(y=0;y<Sizey;y++) 
   DstImg->Map[x][y]=SrcImg->Map[x>>1][y>>1];
   
   FreeMeABitMap(SrcImg);
   return DstImg;
  }
 
/**************************************|****************************************
Routine   : PSNR3D
Input  par: BitMap3D *ImgA,BitMap3D *ImgB (images to be comparred)
Output par: float (PSNR value)
Function  : Calculates the PSNR value of two 3d images.
***************************************|***************************************/
 
 float PSNR(BitMap *ImgA,BitMap *ImgB)
  {
   float ret;
   unsigned long mse=0;
   
   mse=dl2(ImgA,0,0,ImgB);
   ret=10.0*log10((float)(255*255)/(float)mse*(float)(ImgB->XSize*ImgB->YSize));
   return ret;
  }
 
/**************************************|****************************************
Routine   : dl23D
Input  par: BitMap3D *ImgA (first image)
            int AXPos,int AYPos, int AZPos (postion in first image)
            BitMap3D *ImgB (second image)
Output par: unsigned long
Function  : Calculates the dl2 distance between two images.
            Notice: no division with volume!
***************************************|***************************************/
 
 unsigned long dl2(BitMap *ImgA,int AXPos,int AYPos,BitMap *ImgB)
  {
   register unsigned int x,y;
   register unsigned long Distortion=0;
   register int tmp;
   const unsigned int Sizex=ImgB->XSize;
   const unsigned int Sizey=ImgB->YSize;

   for(x=0;x<Sizex;x++)    
   for(y=0;y<Sizey;y++)      
    {
     tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[x][y];
     Distortion +=tmp*tmp;
    }
   /* no div with volume ! */
   
   return Distortion;
  }
 
/**************************************|****************************************
Routine   : Isometri3D
Input  par: BitMap3D *SrcImg (bitmap to be rotated)
            BitMap3D *DstImg (output from manipulation)
            int type (the isometri type: 1-8)
Output par: none.
Function  : Isometric transformaition of a 3d image. 
***************************************|***************************************/
 
 void Isometri(BitMap *SrcImg,BitMap *DstImg, int type)
  {
   register unsigned int y,x;
   const unsigned int Sizex=SrcImg->XSize;
   const unsigned int Sizey=SrcImg->YSize;

   switch(type)    
    {
     case 1:
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[x][y];
     break;
     case 2: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[x][Sizey-1-y];
     break;
     case 3: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[Sizex-1-x][y];
     break;
     case 4: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[y][x];
     break;
     case 5: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[Sizex-1-y][Sizey-1-x];
     break;
     case 6: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[y][Sizey-1-x];
     break;
     case 7: 
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[Sizex-1-x][Sizey-1-y];
     break;
     case 8:
     for(x=0;x<Sizex;x++)      
     for(y=0;y<Sizey;y++)
     DstImg->Map[x][y]=SrcImg->Map[Sizex-1-y][x];
     break;
    }
  }
 
/**************************************|****************************************
Routine   : IsoAnddl23D
Input  par: BitMap3D *ImgA (image to be transformed)
            int AXPos, int AYPos, int AZPos (position in original image)
            BitMap3D *ImgB (image to compare to)
            int Size       (size (side length) of comparation volumen)
            int type       (type of isometrie)
Output par: unsigned long  (dl2 distortion)
Function  : A combined version of dl2 and isometri. It takes an image and calcs
            the dl23d distortion to another image with repect to a given 
            isometri tranfromation. This is done to reduce encoding time!
            Notice: no division with volume!
***************************************|***************************************/
 
 unsigned long IsoAnddl2(BitMap *ImgA, int AXPos, int AYPos,
                         BitMap *ImgB, int Size, int type)
  {
   register int x,y;
   register unsigned long Distortion=0;
   register int tmp;
   const unsigned int Sizex=ImgB->XSize;
   const unsigned int Sizey=ImgB->YSize;

   x=Sizex;
   switch(type)    
    {
     case 1:
     while(x--)
      {
       y=Sizey;
       while(y--)
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[x][y];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 2:
     while(x--)      
      {
       y=Sizey;
       while(y--)
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[x][Sizey-1-y];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 3:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[Sizex-1-x][y];
           Distortion+=tmp*tmp;
        }
      }
     
     break;
     case 4:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[y][x];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 5:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[Sizex-1-y][Sizey-1-x];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 6:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[y][Sizey-1-x];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 7:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[Sizex-1-x][Sizey-1-y];
           Distortion+=tmp*tmp;
        }
      }
     break;
     case 8:
     while(x--)      
      {
       y=Sizey;
       while(y--)        
        {
           tmp=ImgA->Map[AXPos+x][AYPos+y]-ImgB->Map[Sizex-1-y][x];
           Distortion+=tmp*tmp;
        }
      }
     break;
    }
   
   return Distortion; /* notice no div with Size*Size*Size! */
  }
 
/**************************************|****************************************
Routine   : MakeRange
Input  par: float p (float to be conveted)
            Parameter *pa (pointer to the parameters)
Output par: unsigned char (output from the quantization)
Function  : Converts a float to an unsigned char according to the range given
            in the parameters. The float is quantizied asymetric.
            Range:  {pa->AMin,pa->AMax} 
            Bits used: pa->ABits
***************************************|***************************************/
 
 unsigned char MakeRange(float p,Parameter *pa) /* asymetric quant */
  {
   if (p>pa->AMax) p=pa->AMax;
   if (p<pa->AMin) p=pa->AMin;
   return (unsigned char)((p-pa->AMin)/(pa->AMax-pa->AMin)*(float)((1<<pa->ABits)-1)+0.5);
  }
 
/**************************************|****************************************
Routine   : MakeFloat
Input  par: unsigned char conv (bitarray to be converted)
            Parameter *pa (poiter to parameters)
Output par: float (converted integer)
Function  : Converts an unsiged char (or bitarray) to a float. See MakeRange.
***************************************|***************************************/
 
 
 float MakeFloat(unsigned char conv,Parameter *pa)
  {
   return (float)((conv)*(pa->AMax-pa->AMin)/(float)((1<<pa->ABits)-1)+pa->AMin);
  }
