原创 C ARM JPEG 解码

2008-12-19 23:15 5053 9 9 分类: MCU/ 嵌入式

#ifndef _JPEG_H_
#define _JPEG_H_


typedef signed char shortint;
typedef signed short smallint;
typedef signed int longint;


typedef unsigned char byte;
typedef signed int integer;


typedef unsigned short word;
typedef unsigned int dword;
//typedef unsigned int long;


typedef shortint * pshortint;
typedef smallint * psmallint;
typedef longint * plongint;
typedef byte * pbyte;
typedef integer * pint;
typedef integer myint[8][8];
typedef unsigned char * pchar;



typedef unsigned int boolean;
typedef byte * pointer;


#define false 0
#define true  1


#define func_ok       0
#define func_memory_error  1
#define func_file_error   2
#define func_format_error  3


#define   m_sof0 0xc0
#define   m_dht  0xc4
#define   m_eoi  0xd9
#define   m_sos  0xda
#define   m_dqt  0xdb
#define   m_dri  0xdd
#define   m_app0 0xe0


#define   w1     2841 // 2048*sqrt(2)*cos(1*pi/16)
#define   w2     2676 // 2048*sqrt(2)*cos(2*pi/16)
#define   w3     2408 // 2048*sqrt(2)*cos(3*pi/16)
#define   w5     1609 // 2048*sqrt(2)*cos(5*pi/16)
#define   w6     1108 // 2048*sqrt(2)*cos(6*pi/16)
#define   w7     565  // 2048*sqrt(2)*cos(7*pi/16)


extern pchar jpeg_source;
extern pointer bmp_dest;
extern dword bmp_size;


boolean jpeg_decode(void);


/*


integer inittag(void);
void inittable(void);
integer decode(void);
integer decodemcublock(void);
integer hufblock(byte dchufindex, byte achufindex);
integer decodeelement(void);
void iqtizzmcucomponent(smallint flag);
void iqtizzblock(psmallint s, pint d, smallint flag);
void getyuv(smallint flag);
void storebuffer(void);
byte readbyte(void);
void initialize_fast_idct(void);
void fast_idct(myint block);
void idctrow(myint block);
void idctcol(myint block);


*/


#endif // _JPEG_H_


 


#include <jpeg.h>


const byte myand[9] = {  0, 1, 3, 7, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };


const byte zig_zag[8][8] = {
  {    0, 1, 5, 6, 14, 15, 27, 28  }  ,
  {    2, 4, 7, 13, 16, 26, 29, 42  }  ,
  {    3, 8, 12, 17, 25, 30, 41, 43  }  ,
  {    9, 11, 18, 24, 31, 40, 44, 53  }  ,
  {    10, 19, 23, 32, 39, 45, 52, 54  }  ,
  {    20, 22, 33, 38, 46, 51, 55, 60  }  ,
  {    21, 34, 37, 47, 50, 56, 59, 61  }  ,
  {    35, 36, 48, 49, 57, 58, 62, 63  }
};


 


pchar jpeg_source;
pointer bmp_dest;
dword bmp_size;


dword imgwidth = 0;
dword imgheight = 0;
smallint interval = 0;


boolean intervalflag;


byte comp_index[4];
byte ydcindex, yacindex, uvdcindex, uvacindex, huftabindex;


smallint restart;
smallint comp_num;
smallint samprate_y_h, samprate_y_v, samprate_u_h, samprate_u_v, samprate_v_h,
  samprate_v_v;
smallint h_ytou, v_ytou, h_ytov, v_ytov, y_in_mcu, u_in_mcu, v_in_mcu;
smallint bitpos, curbyte, rrun, vvalue;
smallint ycoef, ucoef, vcoef;


dword sizei, sizej;
dword linebytes, numcolors;


smallint qt_table[3][64];
smallint code_pos_table[4][16];
smallint code_len_table[4][16];
smallint blockbuffer[64];
smallint mcubuffer[10 *64];


word code_value_table[4][256];
word huf_max_value[4][16];
word huf_min_value[4][16];


pchar lpimgdata, lp;
psmallint yqttable, uqttable, vqttable;



integer y[4 *64];
integer u[4 *64];
integer v[4 *64];
integer qtzzmcubuffer[10 *64];


longint iclip[1024];


integer inittag(void);
void inittable(void);
integer decode(void);
integer decodemcublock(void);
integer hufblock(byte dchufindex, byte achufindex);
integer decodeelement(void);
void iqtizzmcucomponent(smallint flag);
void iqtizzblock(psmallint s, pint d, smallint flag);
void getyuv(smallint flag);
void storebuffer(void);
byte readbyte(void);
void initialize_fast_idct(void);
void fast_idct(myint block);
void idctrow(myint block);
void idctcol(myint block);


//------------------------------------------------------------------------------
// width = 800
// height = 480
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
boolean jpeg_decode(void)
{
  inittable();


  if (inittag())
  {
    if ((samprate_y_h != 0) && (samprate_y_v != 0))
    {
      numcolors = 0;


      if ( ( imgwidth != 800) || ( imgheight != 480 ) ) return 0;
      //linebytes = ((imgwidth *24+31) / 32) *4;
      linebytes = imgwidth * 2;


      bmp_size = linebytes * imgheight;


      if (decode() == func_ok)
        return 1;
    }
  }


  return 0;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
integer inittag(void)
{
  boolean finish;
  byte id;
  smallint llength;
  smallint i, j, k;
  smallint huftab1, huftab2;
  smallint huftabindex;


  byte hf_table_index;
  byte qt_table_index;
  byte comnum;
  pchar lptemp;
  smallint ccount;


  finish = false;
  lp = jpeg_source + 2;


  while (!finish)
  {
    id = lp[1];
    lp+=2;


    switch (id)
    {
      case m_app0:
        {
          llength = (lp[0] << 8) + lp[1];
          lp += llength; //skip jfif segment marker
          break;
        }


      case m_dqt:
        {
          llength = (lp[0] << 8) + lp[1];
          qt_table_index = lp[2] & 0x0F;


          lptemp = lp + 3;


          if (llength < 80)
          {
            for (i = 0; i < 64; i++)
            {
              qt_table[qt_table_index] =  *lptemp;
              lptemp++;
            }
          }


          else
          {
            for (i = 0; i < 64; i++)
            {
              qt_table[qt_table_index] =  *lptemp;
              lptemp++;
            }


            qt_table_index =  (*lptemp) & 0x0F;
            lptemp++;


            for (i = 0; i < 64; i++)
            {
              qt_table[qt_table_index] =  *lptemp;
              lptemp++;
            }


          }


          lp = lp + llength;
          break;
        }


      case m_sof0:
        {
          llength = (lp[0] << 8) + lp[1];


          imgheight = (lp[3] << 8) + lp[4];
          imgwidth = (lp[5] << 8) + lp[6];
          comp_num = lp[7];


          if (((comp_num != 1) && (comp_num != 3)))
            return func_format_error;


          if (comp_num == 3)
          {
            comp_index[0] = lp[8];
            samprate_y_h = lp[9] >> 4;
            samprate_y_v = lp[9] & 0x0f;


            yqttable = &qt_table[lp[10]][0];
            comp_index[1] = lp[11];
            samprate_u_h = lp[12] >> 4;
            samprate_u_v = lp[12] & 0x0f;


            uqttable = &qt_table[lp[13]][0];
            comp_index[2] = lp[14];
            samprate_v_h = lp[15] >> 4;
            samprate_v_v = lp[15] & 0x0f;
            vqttable = &qt_table[lp[16]][0];


          }
          else
          // if (comp_num == 1)
          {
            comp_index[0] = lp[8];
            samprate_y_h = lp[9] >> 4;
            samprate_y_v = lp[9] & 0x0f;
            yqttable = &qt_table[lp[10]][0];


            comp_index[1] = lp[8];
            samprate_u_h = 1;
            samprate_u_v = 1;
            uqttable = &qt_table[lp[10]][0];


            comp_index[2] = lp[8];
            samprate_v_h = 1;
            samprate_v_v = 1;
            vqttable = &qt_table[lp[10]][0];


          }
          lp = lp + llength;
          break;
        }



      case m_dht:
        {


          llength = (lp[0] << 8) + lp[1];


          if (llength < 0xd0)
          {
            huftab1 = lp[2] >> 4;
            huftab2 = lp[2] & 0x0f;
            huftabindex = huftab1*2 + huftab2;


            lptemp = lp + 3;


            for (i = 0; i < 16; i++)
            {
              code_len_table[huftabindex] =  *lptemp;
              lptemp++;
            }



            j = 0;
            for (i = 0; i < 16; i++)
            {
              if (code_len_table[huftabindex] != 0)
              {
                k = 0;
                while (k < code_len_table[huftabindex])
                {
                  code_value_table[huftabindex][k + j] =  *lptemp;
                  lptemp = lptemp + 1;
                  k = k + 1;
                }
                j = j + k;
              }
            }



            i = 0;
            while (code_len_table[huftabindex] == 0)
              i = i + 1;


            for (j = 0; j < i; j++)
            {
              huf_min_value[huftabindex][j] = 0;
              huf_max_value[huftabindex][j] = 0;
            }


            huf_min_value[huftabindex] = 0;
            huf_max_value[huftabindex] = code_len_table[huftabindex] - 1;


            for (j = i + 1; j < 16; j++)
            {
              huf_min_value[huftabindex][j] = (huf_max_value[huftabindex][j -
                1] + 1) << 1;


              huf_max_value[huftabindex][j] = huf_min_value[huftabindex][j] +
                code_len_table[huftabindex][j] - 1;
            }


            code_pos_table[huftabindex][0] = 0;


            for (j = 1; j < 16; j++)
              code_pos_table[huftabindex][j] = code_len_table[huftabindex][j -
                1] + code_pos_table[huftabindex][j - 1];
            lp = lp + llength;
          }


          else
          {
            hf_table_index = lp[2];
            lp = lp + 2;


            while (hf_table_index != 0xff)
            {
              huftab1 = hf_table_index >> 4;
              huftab2 = hf_table_index & 0x0F;
              huftabindex = huftab1 * 2+huftab2;


              lptemp = lp;
              lptemp++;


              ccount = 0;
              for (i = 0; i < 16; i++)
              {
                code_len_table[huftabindex] =  *lptemp;
                lptemp++;
                ccount = ccount + code_len_table[huftabindex];
              }


              ccount = ccount + 17;


              j = 0;
              for (i = 0; i < 16; i++)
              {
                if (code_len_table[huftabindex] != 0)
                {
                  k = 0;
                  while (k < code_len_table[huftabindex])
                  {
                    code_value_table[huftabindex][k + j] =  *lptemp;
                    lptemp++;
                    k++;
                  }
                  j = j + k;
                }
              }


              i = 0;
              while (code_len_table[huftabindex] == 0)
                i++;


              for (j = 0; j < i; j++)
              {
                huf_min_value[huftabindex][j] = 0;
                huf_max_value[huftabindex][j] = 0;
              }


              huf_min_value[huftabindex] = 0;
              huf_max_value[huftabindex] = code_len_table[huftabindex] - 1;


              for (j = i + 1; j < 16; j++)
              {
                huf_min_value[huftabindex][j] = (huf_max_value[huftabindex][j - 1] + 1) << 1;
                huf_max_value[huftabindex][j] = huf_min_value[huftabindex][j] + code_len_table[huftabindex][j] - 1;
              }


              code_pos_table[huftabindex][0] = 0;


              for (j = 1; j < 16; j++)
                code_pos_table[huftabindex][j] = code_len_table[huftabindex][j- 1] + code_pos_table[huftabindex][j - 1];


              lp = lp + ccount;


              hf_table_index =  *lp;
            }
          }
          break;
        }



      case m_dri:
        {
          llength = (lp[0] << 8) + lp[1];
          restart = (lp[2] << 8) + lp[3];
          lp = lp + llength;
          break;
        }


 


      case m_sos:
        {
          llength = (lp[0] << 8) + lp[1];
          comnum = lp[2];


          if (comnum != comp_num)
            return func_format_error;


          lptemp = lp + 3;
          for (i = 0; i < comp_num; i++)
          {
            if (*lptemp == comp_index[0])
            {
              ydcindex = lptemp[1] >> 4;
              yacindex = (lptemp[1] & 0x0f) + 2;
            }
            else
            {
              uvdcindex = lptemp[1] >> 4;
              uvacindex = (lptemp[1] & 0x0f) + 2;
            }


            lptemp = lptemp + 2;
          }
          lp = lp + llength;
          finish = true;
          break;
        }


      case m_eoi:
        {
          return func_format_error;
        }


      default:
        {
          if ((id &0xf0) != 0xd0)
          {
           llength = (lp[0] << 8) + lp[1];
            lp = lp + llength;
          }
          else
          {
            lp = lp + 2;
          }
        }
    }
  }
  return 1;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void inittable(void)
{
  smallint i, j;
  sizei = 0;
  sizej = 0;
  imgwidth = 0;
  imgheight = 0;
  interval = 0;
  rrun = 0;
  vvalue = 0;
  bitpos = 0;
  curbyte = 0;
  intervalflag = false;
  restart = 0;


  for (i = 0; i < 3; i++)
    for (j = 0; j < 64; j++)
      qt_table[j] = 0;


  comp_num = 0;
  huftabindex = 0;


  for (i = 0; i < 3; i++)
    comp_index = 0;


  for (i = 0; i < 4; i++)
  {
    for (j = 0; j < 16; j++)
    {
      code_len_table[j] = 0;
      code_pos_table[j] = 0;
      huf_max_value[j] = 0;
      huf_min_value[j] = 0;
    }
  }


  for (i = 0; i < 4; i++)
  {
    for (j = 0; j < 256; j++)
    {
      code_value_table[j] = 0;
    }
  }


 


  for (i = 0; i < 10 *64; i++)
  {
    mcubuffer = 0;
    qtzzmcubuffer = 0;
  }


  for (i = 0; i < 64; i++)
  {
    y = 0;
    u = 0;
    v = 0;
    blockbuffer = 0;
  }


  ycoef = 0;
  ucoef = 0;
  vcoef = 0;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
integer decode(void)
{
  integer funcret;


  y_in_mcu = samprate_y_h * samprate_y_v;
  u_in_mcu = samprate_u_h * samprate_u_v;
  v_in_mcu = samprate_v_h * samprate_v_v;
  h_ytou   = samprate_y_h / samprate_u_h;
  v_ytou   = samprate_y_v / samprate_u_v;
  h_ytov   = samprate_y_h / samprate_v_h;
  v_ytov   = samprate_y_v / samprate_v_v;


  initialize_fast_idct();


  funcret = decodemcublock();


  while (funcret == func_ok)
  {
    interval++;


    if ((restart != 0) && ((interval % restart) == 0))
      intervalflag = true;
    else
      intervalflag = false;


    iqtizzmcucomponent(0);
    iqtizzmcucomponent(1);
    iqtizzmcucomponent(2);


    getyuv(0);
    getyuv(1);
    getyuv(2);
    storebuffer();


    sizej = sizej + (dword)(samprate_y_h *8);


    if (sizej >= imgwidth)
    {
      sizej = 0;
      sizei = sizei + (dword)(samprate_y_v *8);
    }


    if ((sizej == 0) && (sizei >= imgheight))
      break;


    funcret = decodemcublock();


  }


  return funcret;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void getyuv(smallint flag)
{
  smallint h, vv;
  integer temp;
  smallint i, j, k, hk;
  pint buf, tempbuf;
  pint pqtzzmcu;


  switch (flag)
  {
    case 0:
      {
        h = samprate_y_h;
        vv = samprate_y_v;
        buf = y;
        pqtzzmcu = qtzzmcubuffer;
        break;
      }


    case 1:
      {
        h = samprate_u_h;
        vv = samprate_u_v;
        buf = u;
        pqtzzmcu = qtzzmcubuffer;
        pqtzzmcu += (y_in_mcu * 64);
        break;
      }


    case 2:
      {
        h = samprate_v_h;
        vv = samprate_v_v;
        buf = v;
        pqtzzmcu = qtzzmcubuffer;
        pqtzzmcu += ( (y_in_mcu + u_in_mcu) *64 );
        break;
      }


    default:
      {
        h = 0;
        vv = 0;
        buf = 0;
        pqtzzmcu = 0;
      }
  }


  for (i = 0; i < vv; i++)
    for (j = 0; j < h; j++)
      for (k = 0; k < 8; k++)
  for (hk = 0; hk < 8; hk++)
  {
    temp = (i *8+k) *samprate_y_h * 8 + j * 8 + hk;
    tempbuf = buf;
    tempbuf += temp;
    *tempbuf =  *pqtzzmcu;
    pqtzzmcu++;
  }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void storebuffer16(void)
{
  smallint i, j;
  pchar lpbmp;
  byte r, g, b;
  integer yy, uu, vv, rr, gg, bb;


  for (i = 0; i < samprate_y_v *8; i++)
  {
    if ((sizei + (dword)(i)) < imgheight)
    {
      lpbmp = bmp_dest + (dword)((imgheight - sizei - (dword)(i) - 1) *linebytes + sizej * 2);    // 2 bytes for RGB565


      for (j = 0; j < samprate_y_h *8; j++)
      {
        if ((sizej + (dword)(j)) < imgwidth)
        {
          yy = y[i *8 * samprate_y_h + j];
          uu = u[(i / v_ytou) *8 * samprate_y_h + j / h_ytou];
          vv = v[(i / v_ytov) *8 * samprate_y_h + j / h_ytov];


          rr = ((yy << 8) + 18 * uu + 367 * vv);
          if (rr < 0)
            rr = (rr >> 8) | (0xFFFFFFFF << (32-8));
          else
            rr = rr >> 8;


          gg = ((yy << 8) - 159 * uu - 220 * vv);
          if (gg < 0)
            gg = (gg >> 8) | (0xFFFFFFFF << (32-8));
          else
            gg = gg >> 8;


          bb = ((yy << 8) + 411 * uu - 29 * vv);
          if (bb < 0)
            bb = (bb >> 8) | (0xFFFFFFFF << (32-8));
          else
            bb = bb >> 8;


          r = (byte)(rr);
          g = (byte)(gg);
          b = (byte)(bb);


          if ((rr &0xffffff00) != 0)
            if (rr > 255)
              r = 255;
            else if (rr < 0)
              r = 0;


          if (gg &0xffffff00 != 0)
            if (gg > 255)
              g = 255;
            else if (gg < 0)
              g = 0;


          if (bb &0xffffff00 != 0)
            if (bb > 255)
              b = 255;
            else if (bb < 0)
              b = 0;


//          *lpbmp = b;
//          lpbmp++;
//          *lpbmp = g;
//          lpbmp++;
//          *lpbmp = r;
//          lpbmp++;


          *lpbmp = b;
          lpbmp++;
          *lpbmp = g;
          lpbmp++;
          *lpbmp = r;
          lpbmp++;
        }
        else
          break;
      }
    }
    else
      break;
  }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void storebuffer24(void)
{
  smallint i, j;
  pchar lpbmp;
  byte r, g, b;
  integer yy, uu, vv, rr, gg, bb;


  for (i = 0; i < samprate_y_v *8; i++)
  {
    if ((sizei + (dword)(i)) < imgheight)
    {
      lpbmp = bmp_dest + (dword)((imgheight - sizei - (dword)(i) - 1) *linebytes + sizej * 3);


      for (j = 0; j < samprate_y_h *8; j++)
      {
        if ((sizej + (dword)(j)) < imgwidth)
        {
          yy = y[i *8 * samprate_y_h + j];
          uu = u[(i / v_ytou) *8 * samprate_y_h + j / h_ytou];
          vv = v[(i / v_ytov) *8 * samprate_y_h + j / h_ytov];
          rr = ((yy << 8) + 18 * uu + 367 * vv);


          if (rr < 0)
            rr = (rr >> 8) | (0xFFFFFFFF << (32-8));
          else
            rr = rr >> 8;


          gg = ((yy << 8) - 159 * uu - 220 * vv);
          if (gg < 0)
            gg = (gg >> 8) | (0xFFFFFFFF << (32-8));
          else
            gg = gg >> 8;


          bb = ((yy << 8) + 411 * uu - 29 * vv);
          if (bb < 0)
            bb = (bb >> 8) | (0xFFFFFFFF << (32-8));
          else
            bb = bb >> 8;


          r = (byte)(rr);
          g = (byte)(gg);
          b = (byte)(bb);


          if ((rr &0xffffff00) != 0)
            if (rr > 255)
              r = 255;
            else if (rr < 0)
              r = 0;


          if (gg &0xffffff00 != 0)
            if (gg > 255)
              g = 255;
            else if (gg < 0)
              g = 0;


          if (bb &0xffffff00 != 0)
            if (bb > 255)
              b = 255;
            else if (bb < 0)
              b = 0;


          *lpbmp = b;
          lpbmp++;
          *lpbmp = g;
          lpbmp++;
          *lpbmp = r;
          lpbmp++;


        }
        else
          break;
      }
    }
    else
      break;
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void storebuffer(void)
{
  smallint i, j;
  pchar lpbmp;
  byte r, g, b;
  word color16;
  integer yy, uu, vv, rr, gg, bb;


  for (i = 0; i < samprate_y_v *8; i++)
  {
    if ((sizei + (dword)(i)) < imgheight)
    {
     //for bmp
      lpbmp = bmp_dest + (dword)((imgheight - sizei - (dword)(i) - 1) *linebytes + sizej * 2);


   // for LCD
      lpbmp = bmp_dest + (dword)((sizei + (dword)(i)) *linebytes + sizej * 2);


      for (j = 0; j < samprate_y_h *8; j++)
      {
        if ((sizej + (dword)(j)) < imgwidth)
        {
          yy = y[i *8 * samprate_y_h + j];
          uu = u[(i / v_ytou) *8 * samprate_y_h + j / h_ytou];
          vv = v[(i / v_ytov) *8 * samprate_y_h + j / h_ytov];


          rr = ((yy << 8) + 18 * uu + 367 * vv);
          gg = ((yy << 8) - 159 * uu - 220 * vv);
          bb = ((yy << 8) + 411 * uu - 29 * vv);


          if (rr < 0)
            rr = (rr >> 8) | (0xFFFFFFFF << (32-8));
          else
            rr = rr >> 8;


          if (gg < 0)
            gg = (gg >> 8) | (0xFFFFFFFF << (32-8));
          else
            gg = gg >> 8;


          if (bb < 0)
            bb = (bb >> 8) | (0xFFFFFFFF << (32-8));
          else
            bb = bb >> 8;


          r = (byte)(rr);
          g = (byte)(gg);
          b = (byte)(bb);


          if ((rr &0xffffff00) != 0)
            if (rr > 255)
              r = 255;
            else if (rr < 0)
              r = 0;


          if (gg &0xffffff00 != 0)
            if (gg > 255)
              g = 255;
            else if (gg < 0)
              g = 0;


          if (bb &0xffffff00 != 0)
            if (bb > 255)
              b = 255;
            else if (bb < 0)
              b = 0;


          color16 = ( (r>>3) << 11) + ( (g>>2) << 5) + (b>>3);



          *lpbmp = color16;
          lpbmp++;
          *lpbmp = color16>>8;
          lpbmp++;


        }
        else
          break;
      }
    }
    else
      break;
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
integer decodemcublock(void)
{
  psmallint lpmcubuffer;
  smallint i, j;
  integer funcret;


  if (intervalflag)
  {
    lp += 2;
    ycoef = 0;
    ucoef = 0;
    vcoef = 0;
    bitpos = 0;
    curbyte = 0;
  }


  switch (comp_num)
  {
    case 3:
      {
        lpmcubuffer = mcubuffer;
        for (i = 0; i < samprate_y_h *samprate_y_v; i++)
        {
          funcret = hufblock(ydcindex, yacindex); //????4 * (8*8)
          if (funcret != func_ok)
          {
            return funcret;
          }
          blockbuffer[0] = blockbuffer[0] + ycoef;
          ycoef = blockbuffer[0];
          for (j = 0; j < 64; j++)
          {
            *lpmcubuffer = blockbuffer[j];
            lpmcubuffer++;
          }
        }


        for (i = 0; i < samprate_u_h *samprate_u_v; i++)
        {
          funcret = hufblock(uvdcindex, uvacindex);
          if (funcret != func_ok)
          {
            return funcret;
          }
          blockbuffer[0] = blockbuffer[0] + ucoef;
          ucoef = blockbuffer[0];
          for (j = 0; j < 64; j++)
          {
            *lpmcubuffer = blockbuffer[j];
            lpmcubuffer++;
          }
        }


        for (i = 0; i < samprate_v_h *samprate_v_v; i++)
        {
          funcret = hufblock(uvdcindex, uvacindex);
          if (funcret != func_ok)
          {
            return funcret;
          }
          blockbuffer[0] = blockbuffer[0] + vcoef;
          vcoef = blockbuffer[0];
          for (j = 0; j < 64; j++)
          {
            *lpmcubuffer = blockbuffer[j];
            lpmcubuffer++;
          }
        }
        break;
      }


    case 1:
      {
        lpmcubuffer = mcubuffer;
        funcret = hufblock(ydcindex, yacindex);
        if (funcret != func_ok)
        {
          return funcret;
        }
        blockbuffer[0] = blockbuffer[0] + ycoef;
        ycoef = blockbuffer[0];
        for (j = 0; j < 64; j++)
        {
          *lpmcubuffer = blockbuffer[j];
          lpmcubuffer++;
        }
        for (i = 0; i < 128; i++)
        {
          *lpmcubuffer = 0;
          lpmcubuffer++;
        }
        break;
      }


    default:
      {
        return func_format_error;
      }


  }


  return func_ok;
}


 


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
integer hufblock(byte dchufindex, byte achufindex)
{
  smallint count, i;
  integer funcret;


  count = 0;
  huftabindex = dchufindex;


  funcret = decodeelement();
  if (funcret != func_ok)
    return funcret;


  blockbuffer[count] = vvalue;
  count++;


  //ac
  huftabindex = achufindex;
  while (count < 64)
  {
    funcret = decodeelement();
    if (funcret != func_ok)
      return funcret;


    if ((rrun == 0) && (vvalue == 0))
    {
      for (i = count; i < 64; i++)
        blockbuffer = 0;
      count = 64;
    }
    else
    {
      for (i = 0; i < rrun; i++)
      {
        blockbuffer[count] = 0;
        count++;
      }
      blockbuffer[count] = vvalue;
      count++;
    }
  }
  return func_ok;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
integer decodeelement(void)
{
  integer thiscode, tempcode;
  word temp, valueex;
  smallint codelen;
  byte hufexbyte, runsize, tempsize, sign;
  byte newbyte, lastbyte;


  if (bitpos >= 1)
  {
    bitpos--;
    thiscode = (byte)(curbyte >> bitpos);
    curbyte = curbyte & myand[bitpos];
  }
  else
  {
    lastbyte = readbyte();
    bitpos--;
    newbyte = curbyte &myand[bitpos];
    thiscode = lastbyte >> 7;
    curbyte = newbyte;
  }


  codelen = 1;


  while ((thiscode < huf_min_value[huftabindex][codelen - 1]) ||
    (code_len_table[huftabindex][codelen - 1] == 0) ||
    (thiscode > huf_max_value[huftabindex][codelen - 1]))
  {
    if (bitpos >= 1)
    {
      bitpos--;
      tempcode = (byte)(curbyte >> bitpos);
      curbyte = curbyte &myand[bitpos];
    }
    else
    {
      lastbyte = readbyte();
      bitpos--;
      newbyte = curbyte &myand[bitpos];
      tempcode = (byte)(lastbyte >> 7);
      curbyte = newbyte;
    }


    thiscode = (thiscode << 1) + tempcode;
    codelen++;


    if (codelen > 16)
      return func_format_error;
  } //while


  temp = thiscode - huf_min_value[huftabindex][codelen - 1] +
    code_pos_table[huftabindex][codelen - 1];


  hufexbyte = (byte)(code_value_table[huftabindex][temp]);


  rrun = (smallint)(hufexbyte >> 4);


  runsize = hufexbyte &0x0f;


  if (runsize == 0)
  {
    vvalue = 0;
    return func_ok;
  }


  tempsize = runsize;
  if (bitpos >= runsize)
  {
    bitpos = bitpos - runsize;
    valueex = (byte)(curbyte >> bitpos);
    curbyte = curbyte &myand[bitpos];
  }
  else
  {
    valueex = curbyte;
    tempsize = tempsize - bitpos;
    while (tempsize > 8)
    {
      lastbyte = readbyte();
      valueex = (valueex << 8) + (byte)(lastbyte);
      tempsize = tempsize - 8;
    }


    lastbyte = readbyte();
    bitpos = bitpos - tempsize;
    valueex = (valueex << tempsize) + (lastbyte >> bitpos);
    curbyte = lastbyte &myand[bitpos];
  }


  sign = valueex >> (runsize - 1);


  if (sign != 0)
    vvalue = valueex;
  else
  {
    valueex = valueex ^ 0xffff;
    temp = 0xffff << runsize;
    vvalue =  - ((smallint)(valueex ^ temp));
  }
  return func_ok;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void iqtizzmcucomponent(smallint flag)
{
  smallint h, vv, i, j;
  pint pqtzzmcubuffer, tempbuf1;
  psmallint pmcubuffer, tempbuf2;


  switch (flag)
  {
    case 0:
      {
        h = samprate_y_h;
        vv = samprate_y_v;
        pmcubuffer = (psmallint)(mcubuffer);
        pqtzzmcubuffer = qtzzmcubuffer;
        break;
      }


    case 1:
      {
        h = samprate_u_h;
        vv = samprate_u_v;
        pmcubuffer = (psmallint)(mcubuffer);
        pmcubuffer += y_in_mcu * 64;
        pqtzzmcubuffer = qtzzmcubuffer;
        pqtzzmcubuffer += y_in_mcu * 64;
        break;
      }


    case 2:
      {
        h = samprate_v_h;
        vv = samprate_v_v;
        pmcubuffer = (psmallint)(mcubuffer);
        pmcubuffer += (y_in_mcu + u_in_mcu) *64;
        pqtzzmcubuffer = qtzzmcubuffer;
        pqtzzmcubuffer += (y_in_mcu + u_in_mcu) *64;
        break;
      }


    default:
      {
        h = 0;
        pqtzzmcubuffer = 0;
        pmcubuffer = 0;
        vv = 0;
        break;
      }
  }


  for (i = 0; i < vv; i++)
  {
    for (j = 0; j < h; j++)
    {
      tempbuf2 = pmcubuffer;
      tempbuf2 += (i *h + j) *64;
      tempbuf1 = pqtzzmcubuffer;
      tempbuf1 += (i *h + j) *64;


      iqtizzblock(tempbuf2, tempbuf1, flag);
    }
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void iqtizzblock(psmallint s, pint d, smallint flag)
{
  smallint i, j, tag, offset;
  psmallint pqt, temp1, temp3;
  myint buffer2;
  pint temp2;


  switch (flag)
  {
    case 0:
      {
        pqt = yqttable;
        offset = 128;
        break;
      }


    case 1:
      {
        pqt = uqttable;
        offset = 0;
        break;
      }
    case 2:
      {
        pqt = vqttable;
        offset = 0;
        break;
      }
    default:
      {
        pqt = 0;
        offset = 0;
        break;
      }
  }


  for (i = 0; i < 8; i++)
  for (j = 0; j < 8; j++)
  {
    tag = zig_zag[j];


    temp1 = s;
    temp1 += tag;


    temp3 = pqt;
    temp3 += tag;


    buffer2[j] = (integer)( (*temp1) * (*temp3) );
  }


  fast_idct(buffer2); //??dct


  for (i = 0; i < 8; i++)
  for (j = 0; j < 8; j++)
  {
    temp2 = d;
    temp2 += (i *8+j);
    *temp2 = buffer2[j] + offset;
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void fast_idct(myint block)
{
  idctrow(block);
  idctcol(block);
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
byte readbyte(void)
{
  byte i;


  i =  *lp;
  lp = lp + 1;


  if (i == 0xff)
    lp = lp + 1;


  bitpos = 8;
  curbyte = i;
  return i;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void initialize_fast_idct(void)
{
  smallint i;


  for (i =  - 512; i < 512; i++)
  {
    if (i <  - 256)
      iclip[512+i] =  - 256;


    if (i > 255)
      iclip[512+i] = 255;


    if ((i >=  - 256) && (i <= 255))
      iclip[512+i] = i;
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void idctrow(myint blk)
{
  integer i, x0, x1, x2, x3, x4, x5, x6, x7, x8;


  //intcut
  for (i = 0; i < 8; i++)
  {
    x1 = blk[4] << 11;
    x2 = blk[6];
    x3 = blk[2];
    x4 = blk[1];
    x5 = blk[7];
    x6 = blk[5];
    x7 = blk[3];
    if ((x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
    {
      blk[1] = blk[0] << 3;
      blk[2] = blk[0] << 3;
      blk[3] = blk[0] << 3;
      blk[4] = blk[0] << 3;
      blk[5] = blk[0] << 3;
      blk[6] = blk[0] << 3;
      blk[7] = blk[0] << 3;
      blk[0] = blk[0] << 3;
      continue;
    }


    x0 = (blk[0] << 11) + 128; // for proper rounding in the fourth stage


    //first stage
    x8 = w7 *(x4 + x5);
    x4 = x8 + (w1 - w7) *x4;
    x5 = x8 - (w1 + w7) *x5;
    x8 = w3 *(x6 + x7);
    x6 = x8 - (w3 - w5) *x6;
    x7 = x8 - (w3 + w5) *x7;


    //second stage
    x8 = x0 + x1;
    x0 = x0 - x1;
    x1 = w6 *(x3 + x2);
    x2 = x1 - (w2 + w6) *x2;
    x3 = x1 + (w2 - w6) *x3;
    x1 = x4 + x6;
    x4 = x4 - x6;
    x6 = x5 + x7;
    x5 = x5 - x7;


    //third stage
    x7 = x8 + x3;
    x8 = x8 - x3;
    x3 = x0 + x2;
    x0 = x0 - x2;


    if ((181 *(x4 + x5) + 128) < 0)
      x2 = ((181 *(x4 + x5) + 128) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      x2 = (181 *(x4 + x5) + 128) >> 8;


    if ((181 *(x4 - x5) + 128) < 0)
      x4 = ((181 *(x4 - x5) + 128) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      x4 = (181 *(x4 - x5) + 128) >> 8;



    //fourth stage
    if (x7 + x1 < 0)
      blk[0] = ((x7 + x1) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[0] = (x7 + x1) >> 8;


    if (x3 + x2 < 0)
      blk[1] = ((x3 + x2) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[1] = (x3 + x2) >> 8;


    if (x0 + x4 < 0)
      blk[2] = ((x0 + x4) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[2] = (x0 + x4) >> 8;


    if (x8 + x6 < 0)
      blk[3] = ((x8 + x6) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[3] = (x8 + x6) >> 8;


    if (x8 - x6 < 0)
      blk[4] = ((x8 - x6) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[4] = (x8 - x6) >> 8;


    if (x0 - x4 < 0)
      blk[5] = ((x0 - x4) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[5] = (x0 - x4) >> 8;


    if (x3 - x2 < 0)
      blk[6] = ((x3 - x2) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[6] = (x3 - x2) >> 8;


    if (x7 - x1 < 0)
      blk[7] = ((x7 - x1) >> 8) | (((0xFFFFFFFF)) << (32-8));
    else
      blk[7] = (x7 - x1) >> 8;
  }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void idctcol(myint blk)
{
  integer j, x0, x1, x2, x3, x4, x5, x6, x7, x8;
  integer temp;


  //intcut
  for (j = 0; j < 8; j++)
  {
    x1 = blk[4][j] << 8;
    x2 = blk[6][j];
    x3 = blk[2][j];
    x4 = blk[1][j];
    x5 = blk[7][j];
    x6 = blk[5][j];
    x7 = blk[3][j];


    if ((x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
    {
      if ((blk[0][j] + 32) < 0)
        temp = ((blk[0][j] + 32) >> 6) | (0xFFFFFFFF << (32-6));
      else
        temp = (blk[0][j] + 32) >> 6;


      blk[1][j] = iclip[512+temp];
      blk[2][j] = iclip[512+temp];
      blk[3][j] = iclip[512+temp];
      blk[4][j] = iclip[512+temp];
      blk[5][j] = iclip[512+temp];
      blk[6][j] = iclip[512+temp];
      blk[7][j] = iclip[512+temp];
      blk[0][j] = iclip[512+temp];
      continue;
    }


    x0 = (blk[0][j] << 8) + 8192;


    //first stage
    x8 = w7 *(x4 + x5) + 4;
    if ((x8 + (w1 - w7) *x4) < 0)
      x4 = ((x8 + (w1 - w7) *x4) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x4 = (x8 + (w1 - w7) *x4) >> 3;


    if ((x8 - (w1 + w7) *x5) < 0)
      x5 = ((x8 - (w1 + w7) *x5) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x5 = (x8 - (w1 + w7) *x5) >> 3;


    x8 = w3 *(x6 + x7) + 4;
    if ((x8 - (w3 - w5) *x6) < 0)
      x6 = ((x8 - (w3 - w5) *x6) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x6 = (x8 - (w3 - w5) *x6) >> 3;


    if ((x8 - (w3 + w5) *x7) < 0)
      x7 = ((x8 - (w3 + w5) *x7) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x7 = (x8 - (w3 + w5) *x7) >> 3;


    //second stage
    x8 = x0 + x1;
    x0 = x0 - x1;
    x1 = w6 *(x3 + x2) + 4;
    if ((x1 - (w2 + w6) *x2) < 0)
      x2 = ((x1 - (w2 + w6) *x2) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x2 = (x1 - (w2 + w6) *x2) >> 3;


    if ((x1 + (w2 - w6) *x3) < 0)
      x3 = ((x1 + (w2 - w6) *x3) >> 3) | (0xFFFFFFFF << (32-3));
    else
      x3 = (x1 + (w2 - w6) *x3) >> 3;
    x1 = x4 + x6;
    x4 = x4 - x6;
    x6 = x5 + x7;
    x5 = x5 - x7;


    //third stage
    x7 = x8 + x3;
    x8 = x8 - x3;
    x3 = x0 + x2;
    x0 = x0 - x2;
    if ((181 *(x4 + x5) + 128) < 0)
      x2 = ((181 *(x4 + x5) + 128) >> 8) | (0xFFFFFFFF << (32-8));
    else
      x2 = (181 *(x4 + x5) + 128) >> 8;


    if ((181 *(x4 - x5) + 128) < 0)
      x4 = ((181 *(x4 - x5) + 128) >> 8) | (0xFFFFFFFF << (32-8));
    else
      x4 = (181 *(x4 - x5) + 128) >> 8;


    //fourth stage
    if (x7 + x1 < 0)
      temp = ((x7 + x1) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x7 + x1) >> 14;


    blk[0][j] = iclip[512+temp];
    if (x3 + x2 < 0)
      temp = ((x3 + x2) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x3 + x2) >> 14;


    blk[1][j] = iclip[512+temp];
    if (x0 + x4 < 0)
      temp = ((x0 + x4) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x0 + x4) >> 14;


    blk[2][j] = iclip[512+temp];
    if (x8 + x6 < 0)
      temp = ((x8 + x6) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x8 + x6) >> 14;


    blk[3][j] = iclip[512+temp];
    if (x8 - x6 < 0)
      temp = ((x8 - x6) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x8 - x6) >> 14;


    blk[4][j] = iclip[512+temp];
    if (x0 - x4 < 0)
      temp = ((x0 - x4) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x0 - x4) >> 14;


    blk[5][j] = iclip[512+temp];
    if (x3 - x2 < 0)
      temp = ((x3 - x2) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x3 - x2) >> 14;


    blk[6][j] = iclip[512+temp];
    if (x7 - x1 < 0)
      temp = ((x7 - x1) >> 14) | (0xFFFFFFFF << (32-14));
    else
      temp = (x7 - x1) >> 14;


    blk[7][j] = iclip[512+temp];
  }
}



 

文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /2 下一条