// // // Return the current line of the given component index. struct Line *CurrentLine(UBYTE c) { class Component *comp = ComponentOf(c); struct Line *line = m_pLineCtrl->CurrentLineOf(comp->IndexOf()); return line; }
/// 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; }
/// LosslessScan::ParseMCU // Parse 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::ParseMCU(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 { bool startofline = true; do { if (BeginReadMCU(m_Stream.ByteStreamOf())) { ParseMCU(prev,top); } else { // Only if this is not due to a DNL marker that has been detected. if (m_ulPixelHeight != 0 && !hasFoundDNL()) { ClearMCU(top); } else if (!startofline) { // The problem is here that the DNL marker might have been detected, even though decoding // is not yet done completely. This may be because there are still just enough bits in the // bitream present to run a single decode. Big Outch! Just continue decoding in this case. ParseMCU(prev,top); } else break; } startofline = false; } while(AdvanceToTheRight()); // // Advance to the next line. } while(AdvanceToTheNextLine(prev,top) && --lines); #endif return false; // no further blocks here. }
/// Frame::InstallDefaultParameters // Define default scan parameters. Returns the scan for further refinement if required. class Scan *Frame::InstallDefaultParameters(ULONG width,ULONG height,UBYTE depth,UBYTE prec, bool writednl,const UBYTE *psubx,const UBYTE *psuby, const struct JPG_TagItem *tags) { int i; if (m_pScan || m_ucDepth != 0 || m_ucPrecision != 0) JPG_THROW(OBJECT_EXISTS,"Frame::InstallDefaultScanParameters","the scan has already been installed"); if (width > MAX_UWORD) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultScanParameters","image dimensions must be < 65536"); m_ulWidth = width; if (height > MAX_UWORD) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultScanParameters","image dimensions must be < 65535"); m_ulHeight = height; if (depth < 1 || depth > 4) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultScanParameters","image depth must be between 1 and 4"); m_ucDepth = depth; // // Potentially clamp the precision to be in range. Only for the DCT operations. m_ucPrecision = prec; // // Check the validity of the precision. switch(m_Type) { case Baseline: case Sequential: case Progressive: case DifferentialSequential: case DifferentialProgressive: case ACSequential: case ACProgressive: case ACDifferentialSequential: case ACDifferentialProgressive: // if (m_ucPrecision != 8 && m_ucPrecision != 12) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultScanParameters","image precision must be 8 or 12"); break; default: // lossless if (m_ucPrecision < 2 || m_ucPrecision > 16) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultScanParameters","image precision must be between 2 and 16"); break; } m_bWriteDNL = writednl; // // // Define the components. This call here does not support subsampling. for(i = 0;i < m_ucDepth;i++) { // Get subsampling parameters UBYTE sx = (psubx)?(*psubx++):(1); UBYTE sy = (psuby)?(*psuby++):(1); // // End of the array - fall back to one. if (sx == 0) { sx = 1;psubx = NULL; } if (sy == 0) { sy = 1;psuby = NULL; } // class Component *comp = DefineComponent(i,sx,sy); comp->SetComponentID(i); // simple 1-1 mapping. if (m_pTables->UseColortrafo()) { comp->SetQuantizer(i == 0?0:1); // one lume and one chroma quantizer } else { comp->SetQuantizer(0); // only one quantizer } } ComputeMCUSizes(); assert(m_pScan == NULL); // If this is only the DHP marker segment, do not create a scan. if (m_Type == Dimensions) return NULL; if (m_Type == Progressive || m_Type == ACProgressive || m_Type == DifferentialProgressive || m_Type == ACDifferentialProgressive) { if (m_ucDepth > 4) JPG_THROW(OVERFLOW_PARAMETER,"Frame::InstallDefaultParameters", "progressive mode allows only up to four components"); // while(tags && (tags = tags->FindTagItem(JPGTAG_IMAGE_SCAN))) { const struct JPG_TagItem *scantags = (struct JPG_TagItem *)(tags->ti_Data.ti_pPtr); if (scantags) { if (scantags->FindTagItem(JPGTAG_SCAN_COMPONENTS_CHROMA)) { // This actually creates a group of tags if the spectral selection contains // AC bands. if (m_ucDepth > 1) { if (scantags->GetTagData(JPGTAG_SCAN_SPECTRUM_START) > 0) { UBYTE i; struct JPG_TagItem ctags[] = { JPG_ValueTag(JPGTAG_SCAN_COMPONENT0,0), JPG_Continue(scantags) }; for(i = 1; i < m_ucDepth;i++) { class Scan *scan = new(m_pEnviron) class Scan(this); if (m_pScan == NULL) { m_pScan = scan; } else { m_pLast->TagOn(scan); } m_pLast = scan; ctags[0].ti_Data.ti_lData = i; scan->InstallDefaults(1,ctags); } } else { struct JPG_TagItem ctags[] = { JPG_ValueTag((m_ucDepth > 1)?JPGTAG_SCAN_COMPONENT0:JPGTAG_TAG_IGNORE,1), JPG_ValueTag((m_ucDepth > 2)?JPGTAG_SCAN_COMPONENT1:JPGTAG_TAG_IGNORE,2), JPG_ValueTag((m_ucDepth > 3)?JPGTAG_SCAN_COMPONENT2:JPGTAG_TAG_IGNORE,3), JPG_Continue(scantags) }; class Scan *scan = new(m_pEnviron) class Scan(this); if (m_pScan == NULL) { m_pScan = scan; } else { m_pLast->TagOn(scan); } m_pLast = scan; scan->InstallDefaults(m_ucDepth - 1,ctags); } } // Nothing to do if chroma channels are not present. } else { UBYTE depth = m_ucDepth; if (scantags->FindTagItem(JPGTAG_SCAN_COMPONENT0)) depth = 1; if (scantags->FindTagItem(JPGTAG_SCAN_COMPONENT1)) depth = 2; if (scantags->FindTagItem(JPGTAG_SCAN_COMPONENT2)) depth = 3; if (scantags->FindTagItem(JPGTAG_SCAN_COMPONENT3)) depth = 4; // // If this is an AC scan, and there is more than one component, separate // into several scans. if (depth > 1 && scantags->GetTagData(JPGTAG_SCAN_SPECTRUM_START) > 0) { UBYTE i; struct JPG_TagItem ctags[] = { JPG_ValueTag(JPGTAG_SCAN_COMPONENT0,0), JPG_ValueTag(JPGTAG_SCAN_COMPONENT1,0), JPG_ValueTag(JPGTAG_SCAN_COMPONENT2,0), JPG_ValueTag(JPGTAG_SCAN_COMPONENT3,0), JPG_Continue(scantags) }; for(i = 0;i < depth;i++) { const struct JPG_TagItem *comp = scantags->FindTagItem(JPGTAG_SCAN_COMPONENT0 + i); ctags[0].ti_Data.ti_lData = (comp)?(comp->ti_Data.ti_lData):(i); class Scan *scan = new(m_pEnviron) class Scan(this); if (m_pScan == NULL) { m_pScan = scan; } else { m_pLast->TagOn(scan); } m_pLast = scan; scan->InstallDefaults(1,ctags); } } else { class Scan *scan = new(m_pEnviron) class Scan(this); if (m_pScan == NULL) { m_pScan = scan; } else { m_pLast->TagOn(scan); } m_pLast = scan; scan->InstallDefaults(depth,scantags); } } } tags = tags->NextTagItem(); } } else { UBYTE maxdepth = 4; if (m_Type == JPEG_LS) { if (tags->GetTagData(JPGTAG_SCAN_LS_INTERLEAVING,JPGFLAG_SCAN_LS_INTERLEAVING_NONE) == JPGFLAG_SCAN_LS_INTERLEAVING_NONE) maxdepth = 1; } UBYTE depth = m_ucDepth; UBYTE comp = 0; // // Create multiple scans for more than maxdepth components. while(depth) { class Scan *scan; UBYTE curdepth = (depth > maxdepth)?(maxdepth):(depth); struct JPG_TagItem ctags[] = { JPG_ValueTag((curdepth > 0)?JPGTAG_SCAN_COMPONENT0:JPGTAG_TAG_IGNORE,comp + 0), JPG_ValueTag((curdepth > 1)?JPGTAG_SCAN_COMPONENT1:JPGTAG_TAG_IGNORE,comp + 1), JPG_ValueTag((curdepth > 2)?JPGTAG_SCAN_COMPONENT2:JPGTAG_TAG_IGNORE,comp + 2), JPG_ValueTag((curdepth > 3)?JPGTAG_SCAN_COMPONENT3:JPGTAG_TAG_IGNORE,comp + 3), JPG_Continue(tags) }; scan = new(m_pEnviron) class Scan(this); if (m_pScan == NULL) { assert(m_pScan == NULL && m_pLast == NULL); m_pScan = scan; } else { assert(m_pScan && m_pLast); m_pLast->TagOn(scan); } m_pLast = scan; scan->InstallDefaults(curdepth,ctags); comp += maxdepth; depth-= curdepth; } } // // Create a residual scan? if (m_pTables->UseResiduals()) { switch(m_Type) { case Lossless: case ACLossless: case JPEG_LS: JPG_THROW(INVALID_PARAMETER,"Frame::InstallDefaultScanParameters", "the lossless scans do not create residuals, no need to code them"); break; case DifferentialSequential: case DifferentialProgressive: case DifferentialLossless: case ACDifferentialSequential: case ACDifferentialProgressive: case ACDifferentialLossless: // Hmm. At this time, simply disallow. There is probably a way how to fit this into // the highest hierarchical level, but not now. JPG_THROW(NOT_IMPLEMENTED,"Frame::InstallDefaultScanParameters", "the hierarchical mode does not yet allow residual coding"); break; default: // Make the first scan a residual scan. { UBYTE component = m_ucDepth; class Scan *scan; do { component--; scan = new(m_pEnviron) class Scan(this); scan->TagOn(m_pScan); m_pScan = scan; scan->MakeResidualScan(ComponentOf(component)); } while(component); } break; } } if (m_pTables->UseRefinements()) { switch(m_Type) { case Lossless: case ACLossless: case JPEG_LS: JPG_THROW(INVALID_PARAMETER,"Frame::InstallDefaultScanParameters", "the lossless scans do not support hidden refinement scans"); break; case DifferentialSequential: case DifferentialProgressive: case DifferentialLossless: case ACDifferentialSequential: case ACDifferentialProgressive: case ACDifferentialLossless: // Hmm. At this time, simply disallow. There is probably a way how to fit this into // the highest hierarchical level, but not now. JPG_THROW(NOT_IMPLEMENTED,"Frame::InstallDefaultScanParameters", "the hierarchical mode does not yet allow hidden refinement coding"); break; default: // Create hidden refinement scans. { UBYTE hiddenbits; UBYTE component; class Scan *scan; for(hiddenbits = 0;hiddenbits < m_pTables->HiddenDCTBitsOf();hiddenbits++) { component = m_ucDepth; do { component--; scan = new(m_pEnviron) class Scan(this); scan->TagOn(m_pScan); m_pScan = scan; scan->MakeHiddenRefinementACScan(hiddenbits,ComponentOf(component)); } while(component); scan = new(m_pEnviron) class Scan(this); scan->TagOn(m_pScan); m_pScan = scan; scan->MakeHiddenRefinementDCScan(hiddenbits); } } break; } } m_pCurrent = m_pScan; return m_pScan; }
// // Return the Y position of the current topmost line to process, // given the index of the component in the scan. ULONG CurrentYOf(UBYTE c) { return m_pLineCtrl->CurrentYOf(ComponentOf(c)->IndexOf()); }
/// JPEGLSScan::FindComponentDimensions // Collect the component information. void JPEGLSScan::FindComponentDimensions(void) { class Thresholds *thres; LONG a0; unsigned int i; m_ulPixelWidth = m_pFrame->WidthOf(); m_ulPixelHeight = m_pFrame->HeightOf(); for(i = 0;i < m_ucCount;i++) { class Component *comp = ComponentOf(i); UBYTE subx = comp->SubXOf(); UBYTE suby = comp->SubYOf(); m_ulWidth[i] = (m_ulPixelWidth + subx - 1) / subx; m_ulHeight[i] = (m_ulPixelHeight + suby - 1) / suby; m_ulRemaining[i] = m_ulHeight[i]; } thres = m_pScan->FindThresholds(); if (thres == NULL) { if (m_pDefaultThresholds == NULL) m_pDefaultThresholds = new(m_pEnviron) class Thresholds(m_pEnviron); m_pDefaultThresholds->InstallDefaults(m_pFrame->PrecisionOf(),m_lNear); thres = m_pDefaultThresholds; } m_lMaxVal = thres->MaxValOf(); m_lT1 = thres->T1Of(); m_lT2 = thres->T2Of(); m_lT3 = thres->T3Of(); m_lReset = thres->ResetOf(); // // The bucket size. m_lDelta = 2 * m_lNear + 1; if (m_lNear == 0) { // Lossless m_lRange = m_lMaxVal + 1; } else { m_lRange = (m_lMaxVal + 2 * m_lNear) / m_lDelta + 1; } // Compute qbpp for (m_lQbpp = 1; (1 << m_lQbpp) < m_lRange; m_lQbpp++) { } // Compute bpp for (m_lBpp = 1; (1 << m_lBpp) < (m_lMaxVal + 1);m_lBpp++) { } if (m_lBpp < 2) m_lBpp = 2; m_lLimit = ((m_lBpp + ((m_lBpp < 8)?(8):(m_lBpp))) << 1) - m_lQbpp - 1; m_lMaxErr = (m_lRange + 1) >> 1; m_lMinErr = m_lMaxErr - m_lRange; // // Compute minimum and maximum reconstruction values. m_lMinReconstruct = -m_lNear; m_lMaxReconstruct = m_lMaxVal + m_lNear; // // Init the state variables N,A,B,C for(i = 0;i < sizeof(m_lN) / sizeof(LONG);i++) m_lN[i] = 1; for(i = 0;i < sizeof(m_lB) / sizeof(LONG);i++) m_lB[i] = m_lC[i] = 0; a0 = (m_lRange + (1 << 5)) >> 6; if (a0 < 2) a0 = 2; for(i = 0;i < sizeof(m_lA) / sizeof(LONG);i++) m_lA[i] = a0; // // Runlength data. memset(m_lRunIndex,0,sizeof(m_lRunIndex)); // Allocate the line buffers if not yet there. for(i = 0;i < m_ucCount;i++) { if (m_Top[i].m_pData == NULL) m_Top[i].m_pData = (LONG *)m_pEnviron->AllocMem((2 + m_ulWidth[i]) * sizeof(LONG)); memset(m_Top[i].m_pData,0,(2 + m_ulWidth[i]) * sizeof(LONG)); if (m_AboveTop[i].m_pData == NULL) m_AboveTop[i].m_pData = (LONG *)m_pEnviron->AllocMem((2 + m_ulWidth[i]) * sizeof(LONG)); memset(m_AboveTop[i].m_pData,0,(2 + m_ulWidth[i]) * sizeof(LONG)); if (m_ucMapIdx[i]) { // FIXME: Find the mapping table. JPG_THROW(NOT_IMPLEMENTED,"JPEGLSSScan::FindComponentDimensions", "mapping tables are not implemented by this code, sorry"); } } }