Example #1
0
static CPLErr DecompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img)
{
    CntZImage zImg;
    Byte *ptr = (Byte *)src.buffer;
    if (!zImg.read(&ptr, 1e12))
    {
	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC decompression");
	return CE_Failure;
    }

// Unpack from zImg to dst buffer, calling the right type
#define UFILL(T) CntZImgUFill(zImg, (T *)(dst.buffer), img)
    switch (img.dt) {
    case GDT_Byte:	UFILL(GByte);	break;
    case GDT_UInt16:	UFILL(GUInt16); break;
    case GDT_Int16:	UFILL(GInt16);	break;
    case GDT_Int32:	UFILL(GInt32);	break;
    case GDT_UInt32:	UFILL(GUInt32); break;
    case GDT_Float32:	UFILL(float);	break;
    case GDT_Float64:	UFILL(double);	break;
    default: break;
    }
#undef UFILL

    return CE_None;
}
Example #2
0
bool Lerc::DecodeTempl(T* pData,    // outgoing data bands
  const Byte* pLercBlob,
  size_t numBytesBlob,
  int nCols, int nRows, int nBands,
  BitMask* pBitMask) const    // gets filled if not 0, even if all valid
{
  if (!pLercBlob || !pData)
    return false;

  const Byte* pByte = pLercBlob;
  Byte* pByte1 = const_cast<Byte*>(pLercBlob);

  Lerc2 lerc2;
  CntZImage zImg;

  for (int iBand = 0; iBand < nBands; iBand++)
  {
    // first try Lerc2
    unsigned int numBytesHeader = lerc2.ComputeNumBytesHeader();
    Lerc2::HeaderInfo hdInfo;
    if (((size_t)(pByte - pLercBlob) + numBytesHeader <= numBytesBlob) && lerc2.GetHeaderInfo(pByte, hdInfo))
    {
      if (hdInfo.nCols != nCols || hdInfo.nRows != nRows)
        return false;

      if ((pByte - pLercBlob) + (size_t)hdInfo.blobSize > numBytesBlob)
        return false;

      // init bitMask
      if (pBitMask && iBand == 0)
        pBitMask->SetSize(nCols, nRows);

      T* arr = pData + nCols * nRows * iBand;

      if (!lerc2.Decode(&pByte, arr, (pBitMask && iBand == 0) ? pBitMask->Bits() : 0))
        return false;
    }
    else    // then try Lerc1
    {
      unsigned int numBytesHeader = CntZImage::computeNumBytesNeededToReadHeader();

      if ((size_t)(pByte - pLercBlob) + numBytesHeader > numBytesBlob)
        return false;

      bool onlyZPart = iBand > 0;
      if (!zImg.read(&pByte1, 1e12, false, onlyZPart))
        return false;

      if (zImg.getWidth() != nCols || zImg.getHeight() != nRows)
        return false;

      T* arr = pData + nCols * nRows * iBand;

      if (!Convert(zImg, arr, pBitMask))
        return false;
    }
  }  // iBand

  return true;
}
Example #3
0
bool Lerc::GetLercInfo(const Byte* pLercBlob, size_t numBytesBlob, struct LercInfo& lercInfo) const
{
  lercInfo.RawInit();

  // first try Lerc2

  Lerc2 lerc2;
  unsigned int numBytesHeader = lerc2.ComputeNumBytesHeader();

  struct Lerc2::HeaderInfo lerc2Info;
  if (numBytesHeader <= numBytesBlob && lerc2.GetHeaderInfo(pLercBlob, lerc2Info))
  {
    lercInfo.version = lerc2Info.version;
    lercInfo.nCols = lerc2Info.nCols;
    lercInfo.nRows = lerc2Info.nRows;
    lercInfo.numValidPixel = lerc2Info.numValidPixel;
    lercInfo.nBands = 1;
    lercInfo.blobSize = lerc2Info.blobSize;
    lercInfo.dt = (DataType)lerc2Info.dt;
    lercInfo.zMin = lerc2Info.zMin;
    lercInfo.zMax = lerc2Info.zMax;
    lercInfo.maxZError = lerc2Info.maxZError;

    if (lercInfo.blobSize > (int)numBytesBlob)    // truncated blob, we won't be able to read this band
      return false;

    while (lercInfo.blobSize + numBytesHeader < numBytesBlob)    // means there could be another band
    {
      struct Lerc2::HeaderInfo hdInfo;
      if (!lerc2.GetHeaderInfo(pLercBlob + lercInfo.blobSize, hdInfo))
        return true;    // no other band, we are done

      if (hdInfo.nCols != lercInfo.nCols
        || hdInfo.nRows != lercInfo.nRows
        || hdInfo.numValidPixel != lercInfo.numValidPixel
        || (int)hdInfo.dt != (int)lercInfo.dt
        || hdInfo.maxZError != lercInfo.maxZError)
      {
        return false;
      }

      lercInfo.blobSize += hdInfo.blobSize;

      if (lercInfo.blobSize > (int)numBytesBlob)    // truncated blob, we won't be able to read this band
        return false;

      lercInfo.nBands++;
      lercInfo.zMin = min(lercInfo.zMin, hdInfo.zMin);
      lercInfo.zMax = max(lercInfo.zMax, hdInfo.zMax);
    }

    return true;
  }

  // then try Lerc1
  numBytesHeader = CntZImage::computeNumBytesNeededToReadHeader();
  Byte* pByte = const_cast<Byte*>(pLercBlob);

  CntZImage cntZImg;
  if (numBytesHeader <= numBytesBlob && cntZImg.read(&pByte, 1e12, true))    // read just the header
  {
    size_t nBytesRead = pByte - pLercBlob;
    size_t nBytesNeeded = 10 + 4 * sizeof(int) + 1 * sizeof(double);

    if (nBytesRead < nBytesNeeded)
      return false;

    Byte* ptr = const_cast<Byte*>(pLercBlob);
    ptr += 10 + 2 * sizeof(int);

    int height = *((const int*)ptr);  ptr += sizeof(int);
    int width  = *((const int*)ptr);  ptr += sizeof(int);
    double maxZErrorInFile = *((const double*)ptr);

    if (height > 20000 || width > 20000)    // guard against bogus numbers
      return false;

    lercInfo.nCols = width;
    lercInfo.nRows = height;
    lercInfo.dt = Lerc::DT_Float;
    lercInfo.maxZError = maxZErrorInFile;

    Byte* pByte = const_cast<Byte*>(pLercBlob);
    bool onlyZPart = false;

    while (lercInfo.blobSize + numBytesHeader < numBytesBlob)    // means there could be another band
    {
      if (!cntZImg.read(&pByte, 1e12, false, onlyZPart))
        return (lercInfo.nBands > 0);    // no other band, we are done

      onlyZPart = true;

      lercInfo.nBands++;
      lercInfo.blobSize = (int)(pByte - pLercBlob);

      // now that we have decoded it, we can go the extra mile and collect some extra info
      int numValidPixels = 0;
      float zMin =  FLT_MAX;
      float zMax = -FLT_MAX;

      for (int i = 0; i < height; i++)
      {
        for (int j = 0; j < width; j++)
          if (cntZImg(i, j).cnt > 0)
          {
            numValidPixels++;
            float z = cntZImg(i, j).z;
            zMax = max(zMax, z);
            zMin = min(zMin, z);
          }
      }

      lercInfo.numValidPixel = numValidPixels;
      lercInfo.zMin = min(lercInfo.zMin, zMin);
      lercInfo.zMax = max(lercInfo.zMax, zMax);
    }

    return true;
  }

  return false;
}