📄 imfb44compressor.cpp
字号:
//
// We can support uncompressed data in the machine's native
// format only if all image channels are of type HALF.
//
assert (sizeof (unsigned short) == pixelTypeSize (HALF));
if (_numChans == numHalfChans)
_format = NATIVE;
}
B44Compressor::~B44Compressor ()
{
delete [] _tmpBuffer;
delete [] _outBuffer;
delete [] _channelData;
}
int
B44Compressor::numScanLines () const
{
return _numScanLines;
}
Compressor::Format
B44Compressor::format () const
{
return _format;
}
int
B44Compressor::compress (const char *inPtr,
int inSize,
int minY,
const char *&outPtr)
{
return compress (inPtr,
inSize,
Box2i (V2i (_minX, minY),
V2i (_maxX, minY + numScanLines() - 1)),
outPtr);
}
int
B44Compressor::compressTile (const char *inPtr,
int inSize,
Imath::Box2i range,
const char *&outPtr)
{
return compress (inPtr, inSize, range, outPtr);
}
int
B44Compressor::uncompress (const char *inPtr,
int inSize,
int minY,
const char *&outPtr)
{
return uncompress (inPtr,
inSize,
Box2i (V2i (_minX, minY),
V2i (_maxX, minY + numScanLines() - 1)),
outPtr);
}
int
B44Compressor::uncompressTile (const char *inPtr,
int inSize,
Imath::Box2i range,
const char *&outPtr)
{
return uncompress (inPtr, inSize, range, outPtr);
}
int
B44Compressor::compress (const char *inPtr,
int inSize,
Imath::Box2i range,
const char *&outPtr)
{
//
// Compress a block of pixel data: First copy the input pixels
// from the input buffer into _tmpBuffer, rearranging them such
// that blocks of 4x4 pixels of a single channel can be accessed
// conveniently. Then compress each 4x4 block of HALF pixel data
// and append the result to the output buffer. Copy UINT and
// FLOAT data to the output buffer without compressing them.
//
outPtr = _outBuffer;
if (inSize == 0)
{
//
// Special case - empty input buffer.
//
return 0;
}
//
// For each channel, detemine how many pixels are stored
// in the input buffer, and where those pixels will be
// placed in _tmpBuffer.
//
int minX = range.min.x;
int maxX = min (range.max.x, _maxX);
int minY = range.min.y;
int maxY = min (range.max.y, _maxY);
unsigned short *tmpBufferEnd = _tmpBuffer;
int i = 0;
for (ChannelList::ConstIterator c = _channels.begin();
c != _channels.end();
++c, ++i)
{
ChannelData &cd = _channelData[i];
cd.start = tmpBufferEnd;
cd.end = cd.start;
cd.nx = numSamples (c.channel().xSampling, minX, maxX);
cd.ny = numSamples (c.channel().ySampling, minY, maxY);
tmpBufferEnd += cd.nx * cd.ny * cd.size;
}
if (_format == XDR)
{
//
// The data in the input buffer are in the machine-independent
// Xdr format. Copy the HALF channels into _tmpBuffer and
// convert them back into native format for compression.
// Copy UINT and FLOAT channels verbatim into _tmpBuffer.
//
for (int y = minY; y <= maxY; ++y)
{
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
if (modp (y, cd.ys) != 0)
continue;
if (cd.type == HALF)
{
for (int x = cd.nx; x > 0; --x)
{
Xdr::read <CharPtrIO> (inPtr, *cd.end);
++cd.end;
}
}
else
{
int n = cd.nx * cd.size;
memcpy (cd.end, inPtr, n * sizeof (unsigned short));
inPtr += n * sizeof (unsigned short);
cd.end += n;
}
}
}
}
else
{
//
// The input buffer contains only HALF channels, and they
// are in native, machine-dependent format. Copy the pixels
// into _tmpBuffer.
//
for (int y = minY; y <= maxY; ++y)
{
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
#if defined (DEBUG)
assert (cd.type == HALF);
#endif
if (modp (y, cd.ys) != 0)
continue;
int n = cd.nx * cd.size;
memcpy (cd.end, inPtr, n * sizeof (unsigned short));
inPtr += n * sizeof (unsigned short);
cd.end += n;
}
}
}
//
// The pixels for each channel have been packed into a contiguous
// block in _tmpBuffer. HALF channels are in native format; UINT
// and FLOAT channels are in Xdr format.
//
#if defined (DEBUG)
for (int i = 1; i < _numChans; ++i)
assert (_channelData[i-1].end == _channelData[i].start);
assert (_channelData[_numChans-1].end == tmpBufferEnd);
#endif
//
// For each HALF channel, split the data in _tmpBuffer into 4x4
// pixel blocks. Compress each block and append the compressed
// data to the output buffer.
//
// UINT and FLOAT channels are copied from _tmpBuffer into the
// output buffer without further processing.
//
char *outEnd = _outBuffer;
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
if (cd.type != HALF)
{
//
// UINT or FLOAT channel.
//
int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
memcpy (outEnd, cd.start, n);
outEnd += n;
continue;
}
//
// HALF channel
//
for (int y = 0; y < cd.ny; y += 4)
{
//
// Copy the next 4x4 pixel block into array s.
// If the width, cd.nx, or the height, cd.ny, of
// the pixel data in _tmpBuffer is not divisible
// by 4, then pad the data by repeating the
// rightmost column and the bottom row.
//
unsigned short *row0 = cd.start + y * cd.nx;
unsigned short *row1 = row0 + cd.nx;
unsigned short *row2 = row1 + cd.nx;
unsigned short *row3 = row2 + cd.nx;
if (y + 3 >= cd.ny)
{
if (y + 1 >= cd.ny)
row1 = row0;
if (y + 2 >= cd.ny)
row2 = row1;
row3 = row2;
}
for (int x = 0; x < cd.nx; x += 4)
{
unsigned short s[16];
if (x + 3 >= cd.nx)
{
int n = cd.nx - x;
for (int i = 0; i < 4; ++i)
{
int j = min (i, n - 1);
s[i + 0] = row0[j];
s[i + 4] = row1[j];
s[i + 8] = row2[j];
s[i + 12] = row3[j];
}
}
else
{
memcpy (&s[ 0], row0, 4 * sizeof (unsigned short));
memcpy (&s[ 4], row1, 4 * sizeof (unsigned short));
memcpy (&s[ 8], row2, 4 * sizeof (unsigned short));
memcpy (&s[12], row3, 4 * sizeof (unsigned short));
}
row0 += 4;
row1 += 4;
row2 += 4;
row3 += 4;
//
// Compress the contents of array s and append the
// results to the output buffer.
//
if (cd.pLinear)
convertFromLinear (s);
outEnd += pack (s, (unsigned char *) outEnd,
_optFlatFields, !cd.pLinear);
}
}
}
return outEnd - _outBuffer;
}
int
B44Compressor::uncompress (const char *inPtr,
int inSize,
Imath::Box2i range,
const char *&outPtr)
{
//
// This function is the reverse of the compress() function,
// above. First all pixels are moved from the input buffer
// into _tmpBuffer. UINT and FLOAT channels are copied
// verbatim; HALF channels are uncompressed in blocks of
// 4x4 pixels. Then the pixels in _tmpBuffer are copied
// into the output buffer and rearranged such that the data
// for for each scan line form a contiguous block.
//
outPtr = _outBuffer;
if (inSize == 0)
{
return 0;
}
int minX = range.min.x;
int maxX = min (range.max.x, _maxX);
int minY = range.min.y;
int maxY = min (range.max.y, _maxY);
unsigned short *tmpBufferEnd = _tmpBuffer;
int i = 0;
for (ChannelList::ConstIterator c = _channels.begin();
c != _channels.end();
++c, ++i)
{
ChannelData &cd = _channelData[i];
cd.start = tmpBufferEnd;
cd.end = cd.start;
cd.nx = numSamples (c.channel().xSampling, minX, maxX);
cd.ny = numSamples (c.channel().ySampling, minY, maxY);
tmpBufferEnd += cd.nx * cd.ny * cd.size;
}
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
if (cd.type != HALF)
{
//
// UINT or FLOAT channel.
//
int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
if (inSize < n)
notEnoughData();
memcpy (cd.start, inPtr, n);
inPtr += n;
inSize -= n;
continue;
}
//
// HALF channel
//
for (int y = 0; y < cd.ny; y += 4)
{
unsigned short *row0 = cd.start + y * cd.nx;
unsigned short *row1 = row0 + cd.nx;
unsigned short *row2 = row1 + cd.nx;
unsigned short *row3 = row2 + cd.nx;
for (int x = 0; x < cd.nx; x += 4)
{
unsigned short s[16];
if (inSize < 3)
notEnoughData();
if (((const unsigned char *)inPtr)[2] == 0xfc)
{
unpack3 ((const unsigned char *)inPtr, s);
inPtr += 3;
inSize -= 3;
}
else
{
if (inSize < 14)
notEnoughData();
unpack14 ((const unsigned char *)inPtr, s);
inPtr += 14;
inSize -= 14;
}
if (cd.pLinear)
convertToLinear (s);
int n = (x + 3 < cd.nx)?
4 * sizeof (unsigned short) :
(cd.nx - x) * sizeof (unsigned short);
if (y + 3 < cd.ny)
{
memcpy (row0, &s[ 0], n);
memcpy (row1, &s[ 4], n);
memcpy (row2, &s[ 8], n);
memcpy (row3, &s[12], n);
}
else
{
memcpy (row0, &s[ 0], n);
if (y + 1 < cd.ny)
memcpy (row1, &s[ 4], n);
if (y + 2 < cd.ny)
memcpy (row2, &s[ 8], n);
}
row0 += 4;
row1 += 4;
row2 += 4;
row3 += 4;
}
}
}
char *outEnd = _outBuffer;
if (_format == XDR)
{
for (int y = minY; y <= maxY; ++y)
{
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
if (modp (y, cd.ys) != 0)
continue;
if (cd.type == HALF)
{
for (int x = cd.nx; x > 0; --x)
{
Xdr::write <CharPtrIO> (outEnd, *cd.end);
++cd.end;
}
}
else
{
int n = cd.nx * cd.size;
memcpy (outEnd, cd.end, n * sizeof (unsigned short));
outEnd += n * sizeof (unsigned short);
cd.end += n;
}
}
}
}
else
{
for (int y = minY; y <= maxY; ++y)
{
for (int i = 0; i < _numChans; ++i)
{
ChannelData &cd = _channelData[i];
#if defined (DEBUG)
assert (cd.type == HALF);
#endif
if (modp (y, cd.ys) != 0)
continue;
int n = cd.nx * cd.size;
memcpy (outEnd, cd.end, n * sizeof (unsigned short));
outEnd += n * sizeof (unsigned short);
cd.end += n;
}
}
}
#if defined (DEBUG)
for (int i = 1; i < _numChans; ++i)
assert (_channelData[i-1].end == _channelData[i].start);
assert (_channelData[_numChans-1].end == tmpBufferEnd);
#endif
if (inSize > 0)
tooMuchData();
outPtr = _outBuffer;
return outEnd - _outBuffer;
}
} // namespace Imf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -