/// 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; }
/// 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; }
/// 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);
/// 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; }