Exemple #1
0
  //
  // 
  // 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;
  }
Exemple #2
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;
}
Exemple #3
0
/// 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.
}
Exemple #4
0
/// 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;
}
Exemple #5
0
 //
 // 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());
 }
Exemple #6
0
/// 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");
    }
  }
}