📄 spihtencode.c
字号:
/*
*
* QccPack: Quantization, compression, and coding utilities
* Copyright (C) 1997-2001 James E. Fowler
*
*/
/*
* ----------------------------------------------------------------------------
*
* Public License for the SPIHT Algorithm
* Version 1.0, September 22, 1999
*
* ----------------------------------------------------------------------------
*
* The Set Partitioning In Hierarchical Trees (SPIHT) algorithm is protected
* by US Patent #5,764,807 (issued June 9, 1998) and other international
* patents and patents pending. An implementation of the SPIHT algorithm is
* included herein with the permission of PrimaComp, Inc., exclusive holder
* of patent rights. PrimaComp has gracioulsy granted the following license
* governing the terms and conditions for use, copying, distribution, and
* modification of the SPIHT algorithm implementation contained herein
* (hereafter referred to as "the SPIHT source code").
*
* 0. Use of the SPIHT source code, including any executable-program or
* linkable-library form resulting from its compilation, is restricted to
* solely academic or non-commercial research activities.
*
* 1. Any other use, including, but not limited to, use in the development
* of a commercial product, use in a commercial application, or commercial
* distribution, is prohibited by this license. Such acts require a separate
* license directly from PrimaComp, Inc.
*
* 2. For academic and non-commercial purposes, this license does not restrict
* use; copying, distribution, and modification are permitted under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, with the further restriction that the terms of the present
* license shall also apply to all subsequent copies, distributions,
* or modifications of the SPIHT source code.
*
* NO WARRANTY
*
* 3. PrimaComp dislaims all warranties, expressed or implied, including
* without limitation any warranty whatsoever as to the fitness for a
* particular use or the merchantability of the SPIHT source code.
*
* 4. In no event shall PrimaComp be liable for any loss of profits, loss of
* business, loss of use or loss of data, nor for indirect, special,
* incidental or consequential damages of any kind related to use of the
* SPIHT source code.
*
*
* END OF TERMS AND CONDITIONS
*
*
* Persons desiring to license the SPIHT algorithm for commercial purposes or
* for uses otherwise prohibited by this license may wish to contact
* PrimaComp, Inc., regarding the possibility of negotiating such licenses:
*
* PrimaComp, Inc.
* 1223 Peoples Ave.
* Troy, New York 12180
* USA
* +1 (518) 276-8276
* inquire@primacomp.com
* http://www.primacomp.com
*
* ----------------------------------------------------------------------------
*/
#include "spihtencode.h"
#define USG_STRING "[-w %s:wavelet] [-b %s:boundary] [-pw %: %s:pcpfile] [-nl %d:num_levels] [-noac %:] [-m %: %s:mask] [-vo %:] %f:rate %s:imgfile %s:bitstream"
QccWAVWavelet Wavelet;
QccString WaveletFilename = QCCWAVWAVELET_DEFAULT_WAVELET;
QccString Boundary = "symmetric";
QccWAVPerceptualWeights PerceptualWeights;
int UsePerceptualWeights = 0;
int NumLevels = 5;
int NumSubbands;
QccIMGImage InputImage;
int ImageNumRows, ImageNumCols;
QccIMGImage Mask;
int MaskSpecified = 0;
int MaskNumRows, MaskNumCols;
QccBitBuffer OutputBuffer;
int NoArithmeticCoding = 0;
int ValueOnly = 0;
float TargetRate;
float ActualRate;
int NumPixels;
int TargetBitCnt;
int main(int argc, char *argv[])
{
int row, col;
QccInit(argc, argv);
QccSPIHTHeader();
QccWAVWaveletInitialize(&Wavelet);
QccWAVPerceptualWeightsInitialize(&PerceptualWeights);
QccIMGImageInitialize(&InputImage);
QccIMGImageInitialize(&Mask);
QccBitBufferInitialize(&OutputBuffer);
if (QccParseParameters(argc, argv,
USG_STRING,
WaveletFilename,
Boundary,
&UsePerceptualWeights,
PerceptualWeights.filename,
&NumLevels,
&NoArithmeticCoding,
&MaskSpecified,
Mask.filename,
&ValueOnly,
&TargetRate,
InputImage.filename,
OutputBuffer.filename))
QccErrorExit();
if (NumLevels < 0)
{
QccErrorAddMessage("%s: Number of levels of decomposition must be nonnegative",
argv[0]);
QccErrorExit();
}
NumSubbands = QccWAVSubbandPyramidNumLevelsToNumSubbands(NumLevels);
if (QccWAVWaveletCreate(&Wavelet, WaveletFilename, Boundary))
{
QccErrorAddMessage("%s: Error calling QccWAVWaveletCreate()",
argv[0]);
QccErrorExit();
}
if (UsePerceptualWeights)
{
if (QccWAVPerceptualWeightsRead(&PerceptualWeights))
{
QccErrorAddMessage("%s: Error calling QccWAVPerceptualWeightsRead()",
argv[0]);
QccErrorExit();
}
if (PerceptualWeights.num_subbands != NumSubbands)
{
QccErrorAddMessage("%s: Number of subbands in %s does not match specified number of levels (%d)",
argv[0],
PerceptualWeights.filename,
NumLevels);
}
}
if (QccIMGImageRead(&InputImage))
{
QccErrorAddMessage("%s: Error calling QccIMGImageRead()",
argv[0]);
QccErrorExit();
}
if (QccIMGImageColor(&InputImage))
{
QccErrorAddMessage("%s: Color images not supported",
argv[0]);
QccErrorExit();
}
if (QccIMGImageGetResolution(&InputImage,
&ImageNumRows, &ImageNumCols))
{
QccErrorAddMessage("%s: Error calling QccIMGImageGetResolution()",
argv[0]);
QccErrorExit();
}
if (ImageNumCols !=
((int)(ImageNumCols >> (NumLevels + 1)) << (NumLevels + 1)))
{
QccErrorAddMessage("%s: Image resolution (%d x %d) is not a multiple of %d (as needed for a decomposition of %d levels)",
argv[0],
ImageNumCols, ImageNumRows,
(1 << (NumLevels + 1)), NumLevels);
QccErrorExit();
}
if (ImageNumRows !=
((int)(ImageNumRows >> (NumLevels + 1)) << (NumLevels + 1)))
{
QccErrorAddMessage("%s: Image resolution (%d x %d) is not a multiple of %d (as needed for a decomposition of %d levels",
argv[0],
ImageNumCols, ImageNumRows,
(1 << (NumLevels + 1)), NumLevels);
QccErrorExit();
}
if (MaskSpecified)
{
if (QccIMGImageRead(&Mask))
{
QccErrorAddMessage("%s: Error calling QccIMGImageRead()",
argv[0]);
QccErrorExit();
}
if (QccIMGImageColor(&Mask))
{
QccErrorAddMessage("%s: Mask must be grayscale",
argv[0]);
QccErrorExit();
}
if (QccIMGImageGetResolution(&Mask,
&MaskNumRows, &MaskNumCols))
{
QccErrorAddMessage("%s: Error calling QccIMGImageGetResolution()",
argv[0]);
QccErrorExit();
}
if ((MaskNumRows != ImageNumRows) ||
(MaskNumCols != ImageNumCols))
{
QccErrorAddMessage("%s: Mask must be same size as image",
argv[0]);
QccErrorExit();
}
NumPixels = 0;
for (row = 0; row < MaskNumRows; row++)
for (col = 0; col < MaskNumCols; col++)
if (!QccAlphaTransparent(Mask.Y.image[row][col]))
NumPixels++;
}
else
NumPixels = ImageNumRows * ImageNumCols;
OutputBuffer.type = QCCBITBUFFER_OUTPUT;
if (QccBitBufferStart(&OutputBuffer))
{
QccErrorAddMessage("%s: Error calling QccBitBufferStart()",
argv[0]);
QccErrorExit();
}
TargetBitCnt = (int)(ceil((NumPixels * TargetRate)/8.0))*8;
if (QccSPIHTEncode(&(InputImage.Y),
(MaskSpecified ? &(Mask.Y) : NULL),
&OutputBuffer,
NumLevels,
&Wavelet,
((UsePerceptualWeights) ? &PerceptualWeights : NULL),
TargetBitCnt,
!NoArithmeticCoding))
{
QccErrorAddMessage("%s: Error calling QccSPIHTEncode()",
argv[0]);
QccErrorExit();
}
ActualRate =
(double)OutputBuffer.bit_cnt / ImageNumRows / ImageNumCols;
if (QccBitBufferEnd(&OutputBuffer))
{
QccErrorAddMessage("%s: Error calling QccBitBufferEnd()",
argv[0]);
QccErrorExit();
}
if (ValueOnly)
printf("%f\n", ActualRate);
else
{
printf("SPIHT coding of %s:\n",
InputImage.filename);
printf(" Target rate: %f bpp\n", TargetRate);
printf(" Actual rate: %f bpp\n", ActualRate);
}
QccExit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -