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::Convert(const CntZImage& zImg, T* arr, BitMask* pBitMask) const
{
  if (!arr || !zImg.getSize())
    return false;

  const bool fltPnt = (typeid(*arr) == typeid(double)) || (typeid(*arr) == typeid(float));

  int h = zImg.getHeight();
  int w = zImg.getWidth();

  if (pBitMask)
  {
    pBitMask->SetSize(w, h);
    pBitMask->SetAllValid();
  }

  const CntZ* srcPtr = zImg.getData();
  T* dstPtr = arr;
  int num = w * h;
  for (int k = 0; k < num; k++)
  {
    if (srcPtr->cnt > 0)
      *dstPtr = fltPnt ? (T)srcPtr->z : (T)floor(srcPtr->z + 0.5);
    else if (pBitMask)
      pBitMask->SetInvalid(k);

    srcPtr++;
    dstPtr++;
  }

  return true;
}
Example #3
0
//  LERC 1 compression
static CPLErr CompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img, double precision)
{
    CntZImage zImg;
    // Fill data into zImg
#define FILL(T) CntZImgFill(zImg, (T *)(src.buffer), img)
    switch (img.dt) {
    case GDT_Byte:	FILL(GByte);	break;
    case GDT_UInt16:	FILL(GUInt16);	break;
    case GDT_Int16:	FILL(GInt16);	break;
    case GDT_Int32:	FILL(GInt32);	break;
    case GDT_UInt32:	FILL(GUInt32);	break;
    case GDT_Float32:	FILL(float);	break;
    case GDT_Float64:	FILL(double);	break;
    default: break;
    }
#undef FILL

    Byte *ptr = (Byte *)dst.buffer;

    // if it can't compress in output buffer it will crash
    if (!zImg.write(&ptr, precision)) {
	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC compression");
	return CE_Failure;
    }

    // write changes the value of the pointer, we can find the size by testing how far it moved
    dst.size = ptr - (Byte *)dst.buffer;
    CPLDebug("MRF_LERC","LERC Compressed to %d\n", (int)dst.size);
    return CE_None;
}
Example #4
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 #5
0
// Unload a zImg into a buffer
template <typename T> void CntZImgUFill(CntZImage &zImg, T *dst, const ILImage &img)
{
    int h = static_cast<int>(zImg.getHeight());
    int w = static_cast<int>(zImg.getWidth());
    T *ptr = dst;
    T ndv = (T)(img.NoDataValue);
    // Use 0 if nodata is not defined
    if (!img.hasNoData) ndv = 0;
    for (int i = 0; i < h; i++)
	for (int j = 0; j < w; j++)
	    *ptr++ = (zImg(i, j).cnt == 0) ? ndv : (T)(zImg(i, j).z);
}
Example #6
0
unsigned int CntZImage::computeNumBytesNeededToWriteVoidImage()
{
  unsigned int cnt = 0;

  CntZImage zImg;
  cnt += (unsigned int)zImg.getTypeString().length();    // "CntZImage ", 10 bytes
  cnt += 2 * sizeof(int);
  cnt += 2 * sizeof(int);
  cnt += 1 * sizeof(double);

  // cnt part
  cnt += 3 * sizeof(int);
  cnt += sizeof(float);

  // z part
  cnt += 3 * sizeof(int);
  cnt += sizeof(float);
  cnt += 1;

  return cnt;
}
Example #7
0
// Load a buffer into a zImg
template <typename T> void CntZImgFill(CntZImage &zImg, T *src, const ILImage &img)
{
    int w = img.pagesize.x;
    int h = img.pagesize.y;

    zImg.resize(w, h);
    T *ptr = src;

    // No data value
    float ndv = float(img.NoDataValue);
    if (!img.hasNoData) ndv = 0;

    for (int i = 0; i < h; i++)
	for (int j = 0; j < w; j++) {
	    zImg(i, j).z = float(*ptr++);
	    zImg(i, j).cnt = !CPLIsEqual(zImg(i, j).z, ndv);
	}
    return;
}
Example #8
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;
}