📄 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;}intB44Compressor::numScanLines () const{ return _numScanLines;}Compressor::FormatB44Compressor::format () const{ return _format;}intB44Compressor::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);}intB44Compressor::compressTile (const char *inPtr, int inSize, Imath::Box2i range, const char *&outPtr){ return compress (inPtr, inSize, range, outPtr);}intB44Compressor::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);}intB44Compressor::uncompressTile (const char *inPtr, int inSize, Imath::Box2i range, const char *&outPtr){ return uncompress (inPtr, inSize, range, outPtr);}intB44Compressor::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;}intB44Compressor::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 + -