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

📄 rangeencoder.cpp

📁 对浮点型数据进行压缩
💻 CPP
字号:
/*===============================================================================  FILE:  rangeencoder.cpp    CONTENTS:          see header file  PROGRAMMERS:      martin isenburg@cs.unc.edu    COPYRIGHT:      copyright (C) 2003 martin isenburg (isenburg@cs.unc.edu)        This software 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.    CHANGE HISTORY:      see header file  ===============================================================================*/#include "rangeencoder.h"#include <stdlib.h>#include <string.h>RangeEncoder::RangeEncoder(FILE* fp, bool store_chars){  if (fp)  {    this->fp = fp;    chars = 0;    number_chars = 0;  }  else  {    this->fp = 0;    if (store_chars)    {      chars = (unsigned char*)malloc(sizeof(unsigned char)*1000);      number_chars = 0;      allocated_chars = 1000;    }    else    {      chars = 0;      number_chars = 0;    }  }  low = 0;                /* Full code range */  range = TOP_VALUE;  /* this buffer is written as first byte in the datastream (header,...) */  buffer = HEADERBYTE;  help = 0;               /* No bytes to follow */  bytecount = 0;}void RangeEncoder::encode(RangeModel* rm, unsigned int sym){  unsigned int syfreq;  unsigned int ltfreq;  unsigned int r, tmp;  unsigned int lg_totf = rm->lg_totf;  rm->getfreq(sym,&syfreq,&ltfreq);  normalize();  r = range >> lg_totf;  tmp = r * ltfreq;  low += tmp;#ifdef EXTRAFAST  range = r * syfreq;#else  if ((ltfreq+syfreq) >> lg_totf)  {    range -= tmp;  }  else  {    range = r * syfreq;  }#endif  rm->update(sym);}void RangeEncoder::encode(unsigned int range, unsigned int sym){  if (range > 4194303) // 22 bits  {    encodeShort(sym&65535);    sym = sym >> 16;    range = range >> 16;    range++;  }  unsigned int r, tmp;  normalize();  r = this->range / range;  tmp = r * sym;  low += tmp;#ifdef EXTRAFAST  this->range = r;#else  if (sym+1 < range)  {    this->range = r;  }  else  {    this->range -= tmp;  }#endif}void RangeEncoder::encodeByte(unsigned char c){  unsigned int r, tmp;  normalize();  r = range >> 8;  tmp = r * (unsigned int)(c);  low += tmp;#ifdef EXTRAFAST  range = r;#else  if (((unsigned int)(c)+1) >> 8)  {    range -= tmp;  }  else  {    range = r;  }#endif}void RangeEncoder::encodeShort(unsigned short s){  unsigned int r, tmp;  normalize();  r = range >> 16;  tmp = r * (unsigned int)(s);  low += tmp;#ifdef EXTRAFAST  range = r;#else  if (((unsigned int)(s)+1) >> 16)  {    range -= tmp;  }  else  {    range = r;  }#endif}void RangeEncoder::encodeInt(unsigned int i){  encodeShort((unsigned short)(i % 65536)); // lower 16 bits  encodeShort((unsigned short)(i / 65536)); // UPPER 16 bits}void RangeEncoder::encodeFloat(float f){  encodeInt(*((unsigned int*)(&f)));}/* I do the normalization before I need a defined state instead of *//* after messing it up. This simplifies starting and ending.       */inline void RangeEncoder::normalize(){	//////////////////////////////////////////////////////////////////////////		//cout <<buffer <<endl;  while(range <= BOTTOM_VALUE) /* do we need renormalisation?  */  {    if (low < (unsigned int)0xff<<SHIFT_BITS)  /* no carry possible --> output */    {      outbyte(buffer);      for(; help; help--)      {        outbyte(0xff);      }      buffer = (unsigned char)(low >> SHIFT_BITS);    }    else if (low & TOP_VALUE) /* carry now, no future carry */    {      outbyte(buffer+1);      for(; help; help--)      {        outbyte(0);      }      buffer = (unsigned char)(low >> SHIFT_BITS);    }    else                      /* passes on a potential carry */    {      help++;    }    range <<= 8;    low = (low<<8) & (TOP_VALUE-1);    bytecount++;  }}/* Finish encoding                                           *//* actually not that many bytes need to be output, but who   *//* cares. I output them because decode will read them :)     *//* the return value is the number of bytes written           */unsigned int RangeEncoder::done(){  unsigned int tmp;  normalize();     /* now we have a normalized state */  bytecount += 5;  if ((low & (BOTTOM_VALUE-1)) < ((bytecount&0xffffffL)>>1))  {    tmp = low >> SHIFT_BITS;  }  else  {    tmp = (low >> SHIFT_BITS) + 1;  }  if (tmp > 0xff) /* we have a carry */  {    outbyte(buffer+1);    for(; help; help--)    {      outbyte(0);    }  }  else  /* no carry */  {    outbyte(buffer);    for(; help; help--)    {      outbyte(0xff);    }  }  outbyte(tmp & 0xff);  outbyte((bytecount>>16) & 0xff);  outbyte((bytecount>>8) & 0xff);  outbyte(bytecount & 0xff);  return bytecount;}RangeEncoder::~RangeEncoder(){  if (chars)  {    free(chars);  }}unsigned char* RangeEncoder::getChars(){  return chars;}  int RangeEncoder::getNumberChars(){  return number_chars;}long RangeEncoder::getNumberBits(){  return bytecount*8;}int RangeEncoder::getNumberBytes(){  return bytecount;}inline void RangeEncoder::outbyte(unsigned int c){	//cout <<c <<endl;  if (fp)  {    fputc(c, fp);	//cout <<c <<endl;  }  else  {    if (chars)    {      if (number_chars == allocated_chars)      {        unsigned char* newchars = (unsigned char*) malloc(sizeof(unsigned char)*allocated_chars*2);        memcpy(newchars,chars,sizeof(unsigned char)*allocated_chars);        free(chars);        chars = newchars;        allocated_chars = allocated_chars*2;      }      chars[number_chars++] = c;    }  }}

⌨️ 快捷键说明

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