/****************************************************************************
* *
* PrimeSense Sensor 5.x Alpha *
* Copyright (C) 2011 PrimeSense Ltd. *
* *
* This file is part of PrimeSense Sensor. *
* *
* PrimeSense Sensor is free software: you can redistribute it and/or modify*
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* PrimeSense Sensor is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with PrimeSense Sensor. If not, see .*
* *
****************************************************************************/
//---------------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------------
#include "Uncomp.h"
#include
#include
//---------------------------------------------------------------------------
// Macros
//---------------------------------------------------------------------------
#define XN_CHECK_UNC_IMAGE_OUTPUT(x, y) \
if (x > y) \
{ \
return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW); \
}
#define XN_IMAGE_OUTPUT(pOutput, pOutputEnd, nValue) \
XN_CHECK_UNC_IMAGE_OUTPUT(pOutput, pOutputEnd) \
*pOutput = nValue; \
++pOutput;
//---------------------------------------------------------------------------
// Code
//---------------------------------------------------------------------------
XnStatus XnStreamUncompressYUVImagePS(const XnUInt8* pInput, const XnUInt32 nInputSize,
XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize,
XnUInt32* pnActualRead, XnBool bLastPart)
{
// Input is made of 4-bit elements.
const XnUInt8* pInputOrig = pInput;
const XnUInt8* pInputEnd = pInput + nInputSize;
XnUInt8* pOrigOutput = pOutput;
XnUInt8* pOutputEnd = pOutput + (*pnOutputSize);
XnUInt8 nLastFullValue[4] = {0};
// NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage)
XnUInt32 nTempValue = 0;
XnUInt32 cInput = 0;
XnBool bReadByte = TRUE;
if (nInputSize < sizeof(XnUInt8))
{
printf("Buffer too small!\n");
return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL);
}
const XnUInt8* pInputLastPossibleStop = pInputOrig;
XnUInt8* pOutputLastPossibleStop = pOrigOutput;
*pnActualRead = 0;
*pnOutputSize = 0;
XnUInt32 nChannel = 0;
XnUInt32 nCurLineSize = 0;
while (pInput < pInputEnd)
{
cInput = *pInput;
if (bReadByte)
{
bReadByte = FALSE;
if (cInput < 0xd0) // 0x0 to 0xc are diffs
{
// take high_element only
// diffs are between -6 and 6 (0x0 to 0xc)
nLastFullValue[nChannel] += XnInt8((cInput >> 4) - 6);
}
else if (cInput < 0xe0) // 0xd is dummy
{
// Do nothing
continue;
}
else // 0xe is not used, so this must be 0xf - full
{
// take two more elements
nTempValue = (cInput & 0x0f) << 4;
if (++pInput == pInputEnd)
break;
nTempValue += (*pInput >> 4);
nLastFullValue[nChannel] = (XnUInt8)nTempValue;
}
}
else
{
// take low-element
cInput &= 0x0f;
bReadByte = TRUE;
pInput++;
if (cInput < 0xd) // 0x0 to 0xc are diffs
{
// diffs are between -6 and 6 (0x0 to 0xc)
nLastFullValue[nChannel] += (XnInt8)(cInput - 6);
}
else if (cInput < 0xe) // 0xd is dummy
{
// Do nothing
continue;
}
else // 0xe is not in use, so this must be 0xf - full
{
if (pInput == pInputEnd)
break;
// take two more elements
nLastFullValue[nChannel] = *pInput;
pInput++;
}
}
// write output
if (pOutput > pOutputEnd)
{
return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW);
}
*pOutput = nLastFullValue[nChannel];
pOutput++;
nChannel++;
switch (nChannel)
{
case 2:
nLastFullValue[3] = nLastFullValue[1];
break;
case 4:
nLastFullValue[1] = nLastFullValue[3];
nChannel = 0;
break;
}
nCurLineSize++;
if (nCurLineSize == nLineSize)
{
pInputLastPossibleStop = pInput;
pOutputLastPossibleStop = pOutput;
nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0;
nCurLineSize = 0;
}
}
if (bLastPart == TRUE)
{
*pnOutputSize = (XnUInt32)(pOutput - pOrigOutput) * sizeof(XnUInt8);
*pnActualRead += (XnUInt32)(pInput - pInputOrig) * sizeof(XnUInt8);
}
else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig))
{
*pnOutputSize = (XnUInt32)(pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8);
*pnActualRead += (XnUInt32)(pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8);
}
// All is good...
return (XN_STATUS_OK);
}
XnStatus XnStreamUncompressImageNew(const XnUInt8* pInput, const XnUInt32 nInputSize,
XnUInt8* pOutput, XnUInt32* pnOutputSize, XnUInt16 nLineSize,
XnUInt32* pnActualRead, XnBool bLastPart)
{
// Input is made of 4-bit elements.
const XnUInt8* pInputOrig = pInput;
const XnUInt8* pInputEnd = pInput + nInputSize;
XnUInt8* pOrigOutput = pOutput;
XnUInt8* pOutputEnd = pOutput + (*pnOutputSize);
XnUInt8 nLastFullValue[4] = {0};
// NOTE: we use variables of type uint32 instead of uint8 as an optimization (better CPU usage)
XnUInt32 nTempValue = 0;
XnUInt32 cInput = 0;
XnBool bReadByte = TRUE;
if (nInputSize < sizeof(XnUInt8))
{
printf("Buffer too small!\n");
return (XN_STATUS_IO_COMPRESSED_BUFFER_TOO_SMALL);
}
const XnUInt8* pInputLastPossibleStop = pInputOrig;
XnUInt8* pOutputLastPossibleStop = pOrigOutput;
*pnActualRead = 0;
*pnOutputSize = 0;
XnUInt32 nChannel = 0;
XnUInt32 nCurLineSize = 0;
while (pInput < pInputEnd)
{
cInput = *pInput;
if (bReadByte)
{
bReadByte = FALSE;
if (cInput < 0xd0) // 0x0 to 0xc are diffs
{
// take high_element only
// diffs are between -6 and 6 (0x0 to 0xc)
nLastFullValue[nChannel] += (XnInt8)((cInput >> 4) - 6);
}
else if (cInput < 0xe0) // 0xd is dummy
{
// Do nothing
continue;
}
else // 0xe is not used, so this must be 0xf - full
{
// take two more elements
nTempValue = (cInput & 0x0f) << 4;
if (++pInput == pInputEnd)
break;
nTempValue += (*pInput >> 4);
nLastFullValue[nChannel] = (XnUInt8)nTempValue;
}
}
else
{
// take low-element
cInput &= 0x0f;
bReadByte = TRUE;
pInput++;
if (cInput < 0xd) // 0x0 to 0xc are diffs
{
// diffs are between -6 and 6 (0x0 to 0xc)
nLastFullValue[nChannel] += (XnInt8)(cInput - 6);
}
else if (cInput < 0xe) // 0xd is dummy
{
// Do nothing
continue;
}
else // 0xe is not in use, so this must be 0xf - full
{
if (pInput == pInputEnd)
break;
// take two more elements
nLastFullValue[nChannel] = *pInput;
pInput++;
}
}
// write output
if (pOutput > pOutputEnd)
{
return (XN_STATUS_OUTPUT_BUFFER_OVERFLOW);
}
*pOutput = nLastFullValue[nChannel];
pOutput++;
nChannel++;
switch (nChannel)
{
case 2:
nChannel = 0;
break;
}
nCurLineSize++;
if (nCurLineSize == nLineSize)
{
pInputLastPossibleStop = pInput;
pOutputLastPossibleStop = pOutput;
nLastFullValue[0] = nLastFullValue[1] = nLastFullValue[2] = nLastFullValue[3] = 0;
nCurLineSize = 0;
}
}
if (bLastPart == TRUE)
{
*pnOutputSize = (XnUInt32)(pOutput - pOrigOutput) * sizeof(XnUInt8);
*pnActualRead += (XnUInt32)(pInput - pInputOrig) * sizeof(XnUInt8);
}
else if ((pOutputLastPossibleStop != pOrigOutput) && (pInputLastPossibleStop != pInputOrig))
{
*pnOutputSize = (XnUInt32)(pOutputLastPossibleStop - pOrigOutput) * sizeof(XnUInt8);
*pnActualRead += (XnUInt32)(pInputLastPossibleStop - pInputOrig) * sizeof(XnUInt8);
}
// All is good...
return (XN_STATUS_OK);
}