⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imfb44compressor.cpp

📁 image converter source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas// Digital Ltd. LLC// // All rights reserved.// // Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:// *       Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// *       Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// *       Neither the name of Industrial Light & Magic nor the names of// its contributors may be used to endorse or promote products derived// from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.///////////////////////////////////////////////////////////////////////////////-----------------------------------------------------------------------------////	class B44Compressor////	This compressor is lossy for HALF channels; the compression rate//	is fixed at 32/14 (approximately 2.28).  FLOAT and UINT channels//	are not compressed; their data are preserved exactly.////	Each HALF channel is split into blocks of 4 by 4 pixels.  An//	uncompressed block occupies 32 bytes, which are re-interpreted//	as sixteen 16-bit unsigned integers, t[0] ... t[15].  Compression//	shrinks the block to 14 bytes.  The compressed 14-byte block//	contains////	 - t[0]////	 - a 6-bit shift value////	 - 15 densely packed 6-bit values, r[0] ... r[14], which are//         computed by subtracting adjacent pixel values and right-//	   shifting the differences according to the stored shift value.////	   Differences between adjacent pixels are computed according//	   to the following diagram:////		 0 -------->  1 -------->  2 -------->  3//               |     3            7           11//               |//               | 0//               |//               v //		 4 -------->  5 -------->  6 -------->  7//               |     4            8           12//               |//               | 1//               |//               v//		 8 -------->  9 --------> 10 --------> 11//               |     5            9           13//               |//               | 2//               |//               v//		12 --------> 13 --------> 14 --------> 15//                     6           10           14////	    Here////               5 ---------> 6//                     8////	    means that r[8] is the difference between t[5] and t[6].////	 - optionally, a 4-by-4 pixel block where all pixels have the//	   same value can be treated as a special case, where the//	   compressed block contains only 3 instead of 14 bytes://	   t[0], followed by an "impossible" 6-bit shift value and//	   two padding bits.////	This compressor can handle positive and negative pixel values.//	NaNs and infinities are replaced with zeroes before compression.////-----------------------------------------------------------------------------#include <ImfB44Compressor.h>#include <ImfHeader.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImathFun.h>#include <ImathBox.h>#include <Iex.h>#include <ImfIO.h>#include <ImfXdr.h>#include <string.h>#include <assert.h>#include <algorithm>namespace Imf {using Imath::divp;using Imath::modp;using Imath::Box2i;using Imath::V2i;using std::min;namespace {//// Lookup tables for//	y = exp (x / 8)// and //	x = 8 * log (y)//#include "b44ExpLogTable.h"inline voidconvertFromLinear (unsigned short s[16]){    for (int i = 0; i < 16; ++i)	s[i] = expTable[s[i]];}inline voidconvertToLinear (unsigned short s[16]){    for (int i = 0; i < 16; ++i)	s[i] = logTable[s[i]];}inline intshiftAndRound (int x, int shift){    //    // Compute    //    //     y = x * pow (2, -shift),    //    // then round y to the nearest integer.    // In case of a tie, where y is exactly    // halfway between two integers, round    // to the even one.    //    x <<= 1;    int a = (1 << shift) - 1;    shift += 1;    int b = (x >> shift) & 1;    return (x + a + b) >> shift;}intpack (const unsigned short s[16],      unsigned char b[14],      bool optFlatFields,      bool exactMax){    //    // Pack a block of 4 by 4 16-bit pixels (32 bytes) into    // either 14 or 3 bytes.    //    //    // Integers s[0] ... s[15] represent floating-point numbers    // in what is essentially a sign-magnitude format.  Convert    // s[0] .. s[15] into a new set of integers, t[0] ... t[15],    // such that if t[i] is greater than t[j], the floating-point    // number that corresponds to s[i] is always greater than    // the floating-point number that corresponds to s[j].    //    // Also, replace any bit patterns that represent NaNs or    // infinities with bit patterns that represent floating-point    // zeroes.    //    //	bit pattern	floating-point		bit pattern    //	in s[i]		value			in t[i]    //    //  0x7fff		NAN			0x8000    //  0x7ffe		NAN			0x8000    //	  ...					  ...    //  0x7c01		NAN			0x8000    //  0x7c00		+infinity		0x8000    //  0x7bff		+HALF_MAX		0xfbff    //  0x7bfe					0xfbfe    //  0x7bfd					0xfbfd    //	  ...					  ...    //  0x0002		+2 * HALF_MIN		0x8002    //  0x0001		+HALF_MIN		0x8001    //  0x0000		+0.0			0x8000    //  0x8000		-0.0			0x7fff    //  0x8001		-HALF_MIN		0x7ffe    //  0x8002		-2 * HALF_MIN		0x7ffd    //	  ...					  ...    //  0xfbfd					0x0f02    //  0xfbfe					0x0401    //  0xfbff		-HALF_MAX		0x0400    //  0xfc00		-infinity		0x8000    //  0xfc01		NAN			0x8000    //	  ...					  ...    //  0xfffe		NAN			0x8000    //  0xffff		NAN			0x8000    //    unsigned short t[16];    for (int i = 0; i < 16; ++i)    {	if ((s[i] & 0x7c00) == 0x7c00)	    t[i] = 0x8000;	else if (s[i] & 0x8000)	    t[i] = ~s[i];	else	    t[i] = s[i] | 0x8000;    }        //    // Find the maximum, tMax, of t[0] ... t[15].    //    unsigned short tMax = 0;    for (int i = 0; i < 16; ++i)	if (tMax < t[i])	    tMax = t[i];    //    // Compute a set of running differences, r[0] ... r[14]:    // Find a shift value such that after rounding off the    // rightmost bits and shifting all differenes are between    // -32 and +31.  Then bias the differences so that they    // end up between 0 and 63.    //    int shift = -1;    int d[16];    int r[15];    int rMin;    int rMax;    const int bias = 0x20;    do    {	shift += 1;	//	// Compute absolute differences, d[0] ... d[15],	// between tMax and t[0] ... t[15].	//	// Shift and round the absolute differences.	//	for (int i = 0; i < 16; ++i)	    d[i] = shiftAndRound (tMax - t[i], shift);	//	// Convert d[0] .. d[15] into running differences	//	r[ 0] = d[ 0] - d[ 4] + bias;	r[ 1] = d[ 4] - d[ 8] + bias;	r[ 2] = d[ 8] - d[12] + bias;	r[ 3] = d[ 0] - d[ 1] + bias;	r[ 4] = d[ 4] - d[ 5] + bias;	r[ 5] = d[ 8] - d[ 9] + bias;	r[ 6] = d[12] - d[13] + bias;	r[ 7] = d[ 1] - d[ 2] + bias;	r[ 8] = d[ 5] - d[ 6] + bias;	r[ 9] = d[ 9] - d[10] + bias;	r[10] = d[13] - d[14] + bias;	r[11] = d[ 2] - d[ 3] + bias;	r[12] = d[ 6] - d[ 7] + bias;	r[13] = d[10] - d[11] + bias;	r[14] = d[14] - d[15] + bias;	rMin = r[0];	rMax = r[0];	for (int i = 1; i < 15; ++i)	{	    if (rMin > r[i])		rMin = r[i];	    if (rMax < r[i])		rMax = r[i];	}    }    while (rMin < 0 || rMax > 0x3f);    if (rMin == bias && rMax == bias && optFlatFields)    {	//	// Special case - all pixels have the same value.	// We encode this in 3 instead of 14 bytes by	// storing the value 0xfc in the third output byte,	// which cannot occur in the 14-byte encoding.	//	b[0] = (t[0] >> 8);	b[1] =  t[0];	b[2] = 0xfc;	return 3;    }    if (exactMax)    {	//	// Adjust t[0] so that the pixel whose value is equal	// to tMax gets represented as accurately as possible.	//	t[0] = tMax - (d[0] << shift);    }    //    // Pack t[0], shift and r[0] ... r[14] into 14 bytes:    //    b[ 0] = (t[0] >> 8);    b[ 1] =  t[0];    b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4));    b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2));    b[ 4] = (unsigned char) ((r[ 1] << 6) |  r[ 2]      );    b[ 5] = (unsigned char) ((r[ 3] << 2) | (r[ 4] >> 4));    b[ 6] = (unsigned char) ((r[ 4] << 4) | (r[ 5] >> 2));    b[ 7] = (unsigned char) ((r[ 5] << 6) |  r[ 6]      );    b[ 8] = (unsigned char) ((r[ 7] << 2) | (r[ 8] >> 4));    b[ 9] = (unsigned char) ((r[ 8] << 4) | (r[ 9] >> 2));    b[10] = (unsigned char) ((r[ 9] << 6) |  r[10]      );    b[11] = (unsigned char) ((r[11] << 2) | (r[12] >> 4));    b[12] = (unsigned char) ((r[12] << 4) | (r[13] >> 2));    b[13] = (unsigned char) ((r[13] << 6) |  r[14]      );    return 14;}inlinevoidunpack14 (const unsigned char b[14], unsigned short s[16]){    //    // Unpack a 14-byte block into 4 by 4 16-bit pixels.    //    #if defined (DEBUG)	assert (b[2] != 0xfc);    #endif    s[ 0] = (b[0] << 8) | b[1];    unsigned short shift = (b[ 2] >> 2);    unsigned short bias = (0x20 << shift);    s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;    s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;    s[12] = s[ 8] +   ((b[ 4]                       & 0x3f) << shift) - bias;        s[ 1] = s[ 0] +   ((b[ 5] >> 2)                         << shift) - bias;    s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;    s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;    s[13] = s[12] +   ((b[ 7]                       & 0x3f) << shift) - bias;        s[ 2] = s[ 1] +   ((b[ 8] >> 2)                         << shift) - bias;    s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;    s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;    s[14] = s[13] +   ((b[10]                       & 0x3f) << shift) - bias;        s[ 3] = s[ 2] +   ((b[11] >> 2)                         << shift) - bias;    s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;    s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;    s[15] = s[14] +   ((b[13]                       & 0x3f) << shift) - bias;    for (int i = 0; i < 16; ++i)    {	if (s[i] & 0x8000)	    s[i] &= 0x7fff;	else	    s[i] = ~s[i];    }}inlinevoidunpack3 (const unsigned char b[3], unsigned short s[16]){    //    // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.    //    #if defined (DEBUG)	assert (b[2] == 0xfc);    #endif    s[0] = (b[0] << 8) | b[1];    if (s[0] & 0x8000)	s[0] &= 0x7fff;    else	s[0] = ~s[0];    for (int i = 1; i < 16; ++i)	s[i] = s[0];}voidnotEnoughData (){    throw Iex::InputExc ("Error decompressing data "			 "(input data are shorter than expected).");}voidtooMuchData (){    throw Iex::InputExc ("Error decompressing data "			 "(input data are longer than expected).");}} // namespacestruct B44Compressor::ChannelData{    unsigned short *	start;    unsigned short *	end;    int			nx;    int			ny;    int			ys;    PixelType		type;    bool		pLinear;    int			size;};B44Compressor::B44Compressor    (const Header &hdr,     int maxScanLineSize,     int numScanLines,     bool optFlatFields):    Compressor (hdr),    _maxScanLineSize (maxScanLineSize),    _optFlatFields (optFlatFields),    _format (XDR),    _numScanLines (numScanLines),    _tmpBuffer (0),    _outBuffer (0),    _numChans (0),    _channels (hdr.channels()),    _channelData (0){    //    // Allocate buffers for compressed an uncompressed pixel data,    // allocate a set of ChannelData structs to help speed up the    // compress() and uncompress() functions, below, and determine    // if uncompressed pixel data should be in native or Xdr format.    //    _tmpBuffer = new unsigned short [maxScanLineSize * numScanLines];    const ChannelList &channels = header().channels();    int numHalfChans = 0;    for (ChannelList::ConstIterator c = channels.begin();	 c != channels.end();	 ++c)    {	assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);	++_numChans;	if (c.channel().type == HALF)	    ++numHalfChans;    }    //    // Compressed data may be larger than the input data    //    int padding = 12 * numHalfChans * (numScanLines + 3) / 4;    _outBuffer = new char [maxScanLineSize * numScanLines + padding];    _channelData = new ChannelData[_numChans];    int i = 0;    for (ChannelList::ConstIterator c = channels.begin();	 c != channels.end();	 ++c, ++i)    {	_channelData[i].ys = c.channel().ySampling;	_channelData[i].type = c.channel().type;	_channelData[i].pLinear = c.channel().pLinear;	_channelData[i].size =	    pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);    }    const Box2i &dataWindow = hdr.dataWindow();    _minX = dataWindow.min.x;    _maxX = dataWindow.max.x;    _maxY = dataWindow.max.y;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -