⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpgencodercomponent.cpp

📁 Jpeg编解码器的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  Description:
//
//    This function is use to output a data unit for the first pass
//    DC progressive scan. The DC coefficients are encoded in the same manner
//    as in a sequential scan except for the point transform.
//
//    This function gets called twice for each data unit in the scan. The
//    first pass is used to gather Huffman statistics and the second is
//    used to Huffman-encode the data and write it to the output stream.
//    We use pointers to the statistics/output functions to ensure that
//    both passes are performed in the exact same manner.
//
//  Parameters:
//    row,col: Data unit position
//    dcfunction: Function for outputting DC coefficient values.
//    successiveapproximation: Successive Approximation
//
//    This function is of the type COMPONENTPASSFUNCTION.
//
void JpegEncoderComponent::progressiveDcFirst (
                          unsigned int row, unsigned int col,
                          DCOUTPUTFUNCTION dcfunction, ACOUTPUTFUNCTION,
                          unsigned int, unsigned int,
                          unsigned int successiveapproximation)
{
  // G.1.2.1

  // DC value calculation
  // A.4
  int value = dct_coefficients [row * du_cols + col][0]
            >> successiveapproximation ;

  // Section F.1.2
  int diff = value - last_dc_value ;
  last_dc_value = value ;

  // Break the difference into a category for Huffman coding and additional
  // raw bits for refinement.
  int bits ;
  if (diff >= 0)
  {
    bits = diff ;
  }
  else
  {
    diff = -diff ;
    bits = ~diff ;
  }
  int ssss = 0 ;  // Category
  while (diff != 0)
  {
    ++ ssss ;
    diff >>= 1 ;
  }
  (this->*dcfunction) (ssss, bits) ;

  return ;
}

//
//  Description:
//
//    This function outputs DC coefficient data for refining scans in a
//    progressive frame. This is the only thing simple about progressive
//    JPEG. In this scan we simply encode an additional bit for each
//    DC coefficient.
//
//    Since there is no Huffman coding for this refining DC scans this function
//    only gets called once per data unit in a scan. Therefore we do not
//    use the output function pararmeters.
//
//  Parameters:
//    row,col: Data unit position
//    ssa:  Successive Approximation
//
//    This function is of the type COMPONENTPASSFUNCTION.
//
void JpegEncoderComponent::progressiveDcRefine (
                            unsigned int row, unsigned int col,
                            DCOUTPUTFUNCTION, ACOUTPUTFUNCTION,
                            unsigned int, unsigned int,
                            unsigned int ssa)
{
  // Section G.1.2.1
  int value = (dct_coefficients [row * du_cols + col][0] >> ssa) & 0x1 ;
  output_stream->outputBits (value, 1) ;
  return ;
}

//
//  Description:
//
//    This function encodes a data unit for the first AC coefficient scan
//    for a spectral range in a progressive frame. The procedure here
//    is taken literally from the JPEG specification.
//
//    The AC encoding complexity is significantly increased over that of
//    sequential scans because End of Bands can span data units.
//
//  Parameters:
//    row,col: Data unit position
//    acfunction: Function for outputting AC coefficient values
//    sss:  Spectral Selection Start
//    sse:  Spectral Selection End
//    ssa:  Successive Approximation
//
void JpegEncoderComponent::progressiveAcFirst (
                            unsigned int row, unsigned int col,
                            ACOUTPUTFUNCTION acfunction,
                            unsigned int sss, unsigned int sse,
                            unsigned int ssa)
{
  JpegCoefficientBlock &du = dct_coefficients [row * du_cols + col] ;

  // G.1.2.2 Figure G.3
  unsigned int zerorun = 0 ;
  for (unsigned int ii = sss ; ii <= sse ; ++ ii)
  {
    int value = du [JpegZigZagInputOrder (ii)]  ;
    // Point Transform
    value = value / (1 << ssa) ;

    if (value == 0)
    {
      ++ zerorun ;
    }
    else
    {
      printEobRun (acfunction) ;
      // Figure G.5
      while (zerorun >= 16)
      {
        (this->*acfunction)(0xF0, 0, 0) ;
        zerorun -= 16 ;
      }

      int bits ;
      if (value >= 0)
      {
        bits = value ;
      }
      else
      {
        value = -value ;
        bits = ~value ;
      }
      int ssss = 0 ;
      while (value != 0)
      {
        ++ ssss ;
        value >>= 1 ;
      }
      unsigned int rrrrssss = (zerorun << 4) | ssss ;
      (this->*acfunction) (rrrrssss, bits, ssss) ;
      zerorun = 0 ;

      if (ii >= sse)
        return ;
    }
  }
  ++ eob_run ;

  // Do not allow the EOB run to exceed 0x7FFF.
  // G.1.2.2
  if (eob_run == 0x7FFF)
    printEobRun (acfunction) ;
  return ;
}

//
//  Description:
//
//    This function encodes the AC coefficients for a refining scan in a
//    progressive frame.
//
//    The JPEG standard is nebulous here (Section G.1.2.3). It is
//    unfortunate that for such a brain-damaged encoding method as
//    this that they should be unclear. In addition to the complexity
//    of having EOB runs span data units, data does not get written
//    out in the order it occurs.
//
//    This is why there are no section references in the code other than
//    the one above. I am simply guessing here, sorry. I created this code by
//    guessing and running the output through various applications that handle
//    progressive JPEG until I could find no complaints.
//
//    If you thing this is bad wait until you get to the part about decoding
//    progressive scans (G.2)!
//
//  Parameters:
//    row,col: Data unit position
//    acfunction: Function for outputting AC coefficient values
//    sss:  Spectral Selection Start
//    sse:  Spectral Selection End
//    ssa:  Successive Approximation
//
void JpegEncoderComponent::progressiveAcRefine (
                            unsigned int row, unsigned int col,
                            ACOUTPUTFUNCTION acfunction,
                            unsigned int sss, unsigned int sse,
                            unsigned int ssa)
{
  JpegCoefficientBlock &du = dct_coefficients [row * du_cols + col] ;
  // Number of zero coefficients - Note that existing non-zero coefficients
  // are not included in this count.
  unsigned int zerorun = 0 ;
  // The start of the zero run.
  unsigned int zerostart = sss ;
  // Number of existing non-zero coefficients - used only for error checking.
  unsigned int correctioncount = 0 ;

  for (unsigned int ii = sss ; ii <= sse ; ++ ii)
  {
    // Point Transform
    int value = du [JpegZigZagInputOrder (ii)] / (1 << ssa) ;

    // We have three types of values:
    //  o A Zero
    //  o A coefficient that was zero in all previous scan that we are
    //    going to make non-zero in this scan (value = +/-1)
    //  o An coefficient that was made non-zero in a previous scan
    //      (value > 1 OR value < -1)
    if (value == 0)
    {
      ++ zerorun ;
    }
    else if (value == 1 || value == -1)
    {
      // If way have an EOB run then print it out.
      printRefineEobRun (acfunction, sss, sse, ssa) ;

      // The longest zero run we can have is 16.
      while (zerorun >= 16)
      {
        (this->*acfunction)(0xF0, 0, 0) ;
        zerorun -= 16 ;

        // Refine all the existing coefficients skipped by the zero run.
        for (int zerocount = 0 ;
             zerocount < 16 ;
             ++ zerostart)
        {
          ASSERT (zerostart >= sss && zerostart <= sse && correctioncount <= JPEGSAMPLESIZE) ; // Invalid Zero Run

          int oldvalue = du [JpegZigZagInputOrder (zerostart)] / (1 << ssa) ;
          if (oldvalue < 0)
            oldvalue = - oldvalue ;
          if (oldvalue > 1)
          {
            (this->*acfunction)(-1, (oldvalue & 0x1), 1) ;
            -- correctioncount ;
          }
          else if (oldvalue == 0)
          {
            // Because we need to count only zero values we our loop counter
            // gets incremented here.
            ++ zerocount ;
          }
          else
          {
            // If the value is +/- 1 we should have already processed it.
            throw JpegEncoder::JpegError ("INTERNAL ERROR - Bad Value") ;
          }
        }
      }

      // This is the first time this value has been nonzero.
      int output = (zerorun << 0x4) | 1 ;
      if (value > 0)
        (this->*acfunction)(output, 1, 1) ;
      else
        (this->*acfunction)(output, 0, 1) ;
      zerorun = 0 ;

      // No go back and refine all the previously non-zero coefficients
      // skipped by this zero run.
      for (unsigned int jj = zerostart ; jj < ii ; ++ jj)
      {
        int oldvalue = du [JpegZigZagInputOrder (jj)] / (1 << ssa) ;
        if (oldvalue < 0)
          oldvalue = - oldvalue ;
        if (oldvalue > 1)
        {
          (this->*acfunction)(-1, (oldvalue & 0x1), 1) ;
          -- correctioncount ;
        }
      }
      zerostart = ii + 1 ;
      if (ii == sse)
        return ;  // All finished with this data unit.
    }
    else
    {
      // We only use this counter for error checking. It contains the
      // number of previously non-zero coefficients that we have skipped
      /// as part of a zero run.
      ++ correctioncount ;
    }
  }
  // If we get here then the data unit ends with a string of zero coefficients
  // or previously non-zero coefficients that we are skipping.
  if (eob_run == 0)
  {
    // We are beginning and End of Band run. Mark the starting position
    // including the spectral position.
    eob_start_du_row = row ;
    eob_start_du_col = col ;
    eob_start_position = zerostart ;
  }
  ++ eob_run ;
  // G.1.2.2
  if (eob_run == 0x7FFF)
    printRefineEobRun (acfunction, sss, sse, ssa) ;
  return ;
}

//
//  Description:
//
//    This function Resets the End of Band run counters. It should be called
//    before beginning to output a scan.
//
void JpegEncoderComponent::resetEobRun ()
{
  eob_run = 0 ;

  // We use values here that should make an error easier to detect.
  eob_start_du_row = du_cols * du_rows ;
  eob_start_du_col = du_cols * du_rows ;
  eob_start_position = JPEGSAMPLESIZE ;

  return ;
}

//
//  Description:
//
//    This function outputs an End of Band run in a refining AC ceofficient
//    scan of a progressive frame. As for the rest of the refining AC scan
//    data I am mostly guessing here. I have taken the process from
//    Figure G.4 and the vague description in Section G.1.2.3. It seems to
//    work.
//
//  Parameters:
//    acfunction: Function for outputting AC coefficient values
//    sss:  Spectral Selection Start
//    sse:  Spectral Selection End
//    ssa:  Successive Approximation
//
void JpegEncoderComponent::printRefineEobRun (ACOUTPUTFUNCTION acfunction,
                            unsigned int sss, unsigned int sse,
                            unsigned int ssa)
{
  if (eob_run != 0)
  {
    unsigned int bits = eob_run ;
    unsigned int value = bits >> 1 ;
    unsigned int ssss = 0 ; // Category (Table G.1)
    while (value != 0)
    {
      value >>= 1 ;
      ++ ssss ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -