Beispiel #1
0
/// LosslessScan::WriteMCU
// Write a single MCU in this scan. Actually, this is not quite true,
// as we write an entire group of eight lines of pixels, as a MCU is
// here a group of pixels. But it is more practical this way.
bool LosslessScan::WriteMCU(void)
{
#if ACCUSOFT_CODE
  int i;
  struct Line *top[4],*prev[4];
  int lines      = 8; // total number of MCU lines processed.
  
  for(i = 0;i < m_ucCount;i++) {
    class Component *comp = ComponentOf(i);
    UBYTE idx       = comp->IndexOf();
    top[i]          = m_pLineCtrl->CurrentLineOf(idx);
    prev[i]         = m_pLineCtrl->PreviousLineOf(idx);
    m_ulX[i]        = 0;
    m_ulY[i]        = m_pLineCtrl->CurrentYOf(idx);
  }
  
  // Loop over lines and columns
  do {
    do {
      BeginWriteMCU(m_Stream.ByteStreamOf());    
      //
      if (m_bMeasure) {
        MeasureMCU(prev,top);
      } else {
        WriteMCU(prev,top);
      }
    } while(AdvanceToTheRight());
    //
    // Advance to the next line.
  } while(AdvanceToTheNextLine(prev,top) && --lines);
#endif
  return false;
}
Beispiel #2
0
/// RefinementScan::WriteMCU
// Write a single MCU in this scan. Return true if there are more blocks in this row.
bool RefinementScan::WriteMCU(void)
{ 
  bool more = true;
  int c;

  assert(m_pBlockCtrl);
  
  BeginWriteMCU(m_bMeasure?NULL:m_Stream.ByteStreamOf());

  for(c = 0;c < m_ucCount;c++) {
    class Component *comp           = m_pComponent[c];
    class QuantizedRow *q           = m_pBlockCtrl->CurrentQuantizedRow(comp->IndexOf());
    class HuffmanCoder *ac          = m_pACCoder[c];
    class HuffmanStatistics *acstat = m_pACStatistics[c];
    UWORD &skip                     = m_usSkip[c];
    UBYTE mcux                      = (m_ucCount > 1)?(comp->MCUWidthOf() ):(1);
    UBYTE mcuy                      = (m_ucCount > 1)?(comp->MCUHeightOf()):(1);
    ULONG xmin                      = m_ulX[c];
    ULONG xmax                      = xmin + mcux;
    ULONG x,y; 
    if (xmax >= q->WidthOf()) {
      more     = false;
    }
    for(y = 0;y < mcuy;y++) {
      for(x = xmin;x < xmax;x++) {
        LONG *block,dummy[64];
        if (q && x < q->WidthOf()) {
          block  = q->BlockAt(x)->m_Data;
        } else {
          block  = dummy;
          memset(dummy ,0,sizeof(dummy) );
        }
        if (m_bMeasure) {
          MeasureBlock(block,acstat,skip);
        } else {
          EncodeBlock(block,ac,skip);
        }
      }
      if (q) q = q->NextOf();
    }
    // Done with this component, advance the block.
    m_ulX[c] = xmax;
  }

  return more;
}
Beispiel #3
0
/// ACRefinementScan::WriteMCU
// Write a single MCU in this scan. Return true if there are more blocks in this row.
bool ACRefinementScan::WriteMCU(void)
{ 
#if ACCUSOFT_CODE
  bool more = true;
  int c;

  assert(m_pBlockCtrl);

  BeginWriteMCU(m_Coder.ByteStreamOf());

  for(c = 0;c < m_ucCount;c++) {
    class Component *comp    = m_pComponent[c];
    class QuantizedRow *q    = m_pBlockCtrl->CurrentQuantizedRow(comp->IndexOf());
    UBYTE mcux               = (m_ucCount > 1)?(comp->MCUWidthOf() ):(1);
    UBYTE mcuy               = (m_ucCount > 1)?(comp->MCUHeightOf()):(1);
    ULONG xmin               = m_ulX[c];
    ULONG xmax               = xmin + mcux;
    ULONG x,y; 
    if (xmax >= q->WidthOf()) {
      more     = false;
    }
    for(y = 0;y < mcuy;y++) {
      for(x = xmin;x < xmax;x++) {
        LONG *block,dummy[64];
        if (q && x < q->WidthOf()) {
          block  = q->BlockAt(x)->m_Data;
        } else {
          block  = dummy;
          memset(dummy ,0,sizeof(dummy) );
        }
        EncodeBlock(block);
      }
      if (q) q = q->NextOf();
    }
    // Done with this component, advance the block.
    m_ulX[c] = xmax;
  }

  return more;
#else
  return false;
#endif
}
/// SingleComponentLSScan::WriteMCU
// Write a single MCU in this scan.
bool SingleComponentLSScan::WriteMCU(void)
{
#if ACCUSOFT_CODE
  int lines             = m_ulRemaining[0]; // total number of MCU lines processed.
  UBYTE preshift        = m_ucLowBit + FractionalColorBitsOf();
  struct Line *line     = CurrentLine(0);
  
  assert(m_ucCount == 1);

  //
  // A "MCU" in respect to the code organization is eight lines.
  if (lines > 8) {
    lines = 8;
  }
  m_ulRemaining[0] -= lines;
  assert(lines > 0);

  // Loop over lines and columns
  do {
    LONG length = m_ulWidth[0];
    LONG *lp    = line->m_pData;

    BeginWriteMCU(m_Stream.ByteStreamOf()); // MCU is a single line.
    StartLine(0);
    do {
      LONG a,b,c,d,x; // neighbouring values.
      LONG d1,d2,d3;  // local gradients.
      
      GetContext(0,a,b,c,d);
      x   = *lp >> preshift;
      
      d1  = d - b;    // compute local gradients
      d2  = b - c;
      d3  = c - a;

      if (isRunMode(d1,d2,d3)) {
        LONG runval = a;
        LONG runcnt = 0;
        do {
          x  = *lp >> preshift;
          if (x - runval < -m_lNear || x - runval > m_lNear)
            break;
          // Update so that the next process gets the correct value.
          // Also updates the line pointers.
          UpdateContext(0,runval);
        } while(lp++,runcnt++,--length);
        // Encode the run. Depends on whether the run was interrupted
        // by the end of the line.
        EncodeRun(runcnt,length == 0,m_lRunIndex[0]);
        // Continue the encoding of the end of the run if there are more
        // samples to encode.
        if (length) {
          bool negative; // the sign variable
          bool rtype;    // run interruption type
          LONG errval;   // the prediction error
          LONG merr;     // the mapped error (symbol)
          LONG rx;       // the reconstructed value
          UBYTE k;       // golomb parameter
          // Get the neighbourhood.
          GetContext(0,a,b,c,d);
          // Get the prediction mode.
          rtype  = InterruptedPredictionMode(negative,a,b);
          // Compute the error value.
          errval = x - ((rtype)?(a):(b));
          if (negative)
            errval = -errval;
          // Quantize the error.
          errval = QuantizePredictionError(errval);
          // Compute the reconstructed value.
          rx     = Reconstruct(negative,rtype?a:b,errval);
          // Update so that the next process gets the correct value.
          UpdateContext(0,rx);
          // Get the golomb parameter for run interruption coding.
          k      = GolombParameter(rtype);
          // Map the error into a symbol.
          merr   = ErrorMapping(errval,ErrorMappingOffset(rtype,errval != 0,k)) - rtype;
          // Golomb-coding of the error.
          GolombCode(k,merr,m_lLimit - m_lJ[m_lRunIndex[0]] - 1);
          // Update the variables of the run mode.
          UpdateState(rtype,errval);
          // Update the run index now. This is not part of
          // EncodeRun because the non-reduced run-index is
          // required for the golomb coder length limit.
          if (m_lRunIndex[0] > 0)
            m_lRunIndex[0]--;
        } else break; // Line ended, abort the loop over the line.
      } else { 
        UWORD ctxt;
        bool  negative; // the sign variable.
        LONG  px;       // the predicted variable.
        LONG  rx;       // the reconstructed value.
        LONG  errval;   // the error value.
        LONG  merr;     // the mapped error value.
        UBYTE k;        // the Golomb parameter.
        // Quantize the gradients.
        d1     = QuantizedGradient(d1);
        d2     = QuantizedGradient(d2);
        d3     = QuantizedGradient(d3);
        // Compute the context.
        ctxt   = Context(negative,d1,d2,d3); 
        // Compute the predicted value.
        px     = Predict(a,b,c);
        // Correct the prediction.
        px     = CorrectPrediction(ctxt,negative,px);
        // Compute the error value.
        errval = x - px;
        if (negative)
          errval = -errval;
        // Quantize the prediction error if NEAR > 0
        errval = QuantizePredictionError(errval);
        // Compute the reconstructed value.
        rx     = Reconstruct(negative,px,errval);
        // Update so that the next process gets the correct value.
        UpdateContext(0,rx);
        // Compute the golomb parameter k from the context.
        k      = GolombParameter(ctxt);
        // Map the error into a symbol
        merr   = ErrorMapping(errval,ErrorMappingOffset(ctxt,k));
        // Golomb-coding of the error.
        GolombCode(k,merr,m_lLimit);
        // Update the variables.
        UpdateState(ctxt,errval);
      }
    } while(++lp,--length);
    EndLine(0);
    line = line->m_pNext;
  } while(--lines);
Beispiel #5
0
/// SequentialScan::WriteMCU
// Write a single MCU in this scan. Return true if there are more blocks in this row.
bool SequentialScan::WriteMCU(void)
{ 
  bool more = true;
  int c;

  assert(m_pBlockCtrl);

  BeginWriteMCU(m_Stream.ByteStreamOf());
  
  for(c = 0;c < m_ucCount;c++) {
    class Component *comp           = m_pComponent[c];
    class QuantizedRow *q           = m_pBlockCtrl->CurrentQuantizedRow(comp->IndexOf());
    class HuffmanCoder *dc          = m_pDCCoder[c];
    class HuffmanCoder *ac          = m_pACCoder[c];
    class HuffmanStatistics *dcstat = m_pDCStatistics[c];
    class HuffmanStatistics *acstat = m_pACStatistics[c];
    LONG &prevdc                    = m_lDC[c];
    UWORD &skip                     = m_usSkip[c];
    UBYTE mcux                      = (m_ucCount > 1)?(comp->MCUWidthOf() ):(1);
    UBYTE mcuy                      = (m_ucCount > 1)?(comp->MCUHeightOf()):(1);
    ULONG xmin                      = m_ulX[c];
    ULONG xmax                      = xmin + mcux;
    ULONG x,y; 
    if (xmax >= q->WidthOf()) {
      more     = false;
    }
    for(y = 0;y < mcuy;y++) {
      for(x = xmin;x < xmax;x++) {
        LONG *block,dummy[64];
        if (q && x < q->WidthOf()) {
          block  = q->BlockAt(x)->m_Data;
        } else {
          block  = dummy;
          memset(dummy ,0,sizeof(dummy) );
          block[0] = prevdc;
        }
#if HIERARCHICAL_HACK
        // A nice hack for the hierarchical scan: If this is not the last frame
        // in the hierarchy, remove all coefficients below the diagonal to allow a
        // fast "EOB", they can be encoded by the level above.
        if (m_pFrame->NextOf()) {
          LONG i,j;
          for(j = 0;j < 8;j++) {
            for(i = 0;i < 8;i++) {
              if (i+j > 4) {
                block[i + (j << 3)] = 0;
              }
            }
          }
        }
#endif
        if (m_bMeasure) {
          MeasureBlock(block,dcstat,acstat,prevdc,skip);
        } else {
          EncodeBlock(block,dc,ac,prevdc,skip);
        }
      }
      if (q) q = q->NextOf();
    }
    // Done with this component, advance the block.
    m_ulX[c] = xmax;
  }

  return more;
}