Project

General

Profile

Download (16.1 KB) Statistics
| Branch: | Revision:
#ifndef PACKJPG_H
#define PACKJPG_H

#include <filesystem>
#include <memory>

#define MEM_ERRMSG "out of memory error"
#define FRD_ERRMSG "could not read file / file not found: %s"
#define FWR_ERRMSG "could not write file / file write-protected: %s"
#define MSG_SIZE 128
#define BARLEN 36

namespace sfs = std::filesystem;

// Forward declarations -- real includes are in the source file so we can use
// this header externally
class ArithmeticDecoder;
class ArithmeticEncoder;
class BitReader;
class BitWriter;
class Reader;
class Writer;

/* -----------------------------------------------
struct declarations
----------------------------------------------- */

struct componentInfo
{
unsigned short* qtable; // quantization table
int huffdc; // no of huffman table (DC)
int huffac; // no of huffman table (AC)
int sfv; // sample factor vertical
int sfh; // sample factor horizontal
int mbs; // blocks in mcu
int bcv; // block count vertical (interleaved)
int bch; // block count horizontal (interleaved)
int bc; // block count (all) (interleaved)
int ncv; // block count vertical (non interleaved)
int nch; // block count horizontal (non interleaved)
int nc; // block count (all) (non interleaved)
int sid; // statistical identity
int jid; // jpeg internal id
};

struct huffCodes
{
unsigned short cval[256];
unsigned short clen[256];
unsigned short max_eobrun;
};

struct huffTree
{
unsigned short l[256];
unsigned short r[256];
};

class packJPG
{
public:
packJPG();
~packJPG();
static const char* pjglib_version_info(void);
static const char* pjglib_short_name(void);

/* -----------------------------------------------
checks if a file exists
----------------------------------------------- */
inline bool file_exists(const char* filename)
{
return sfs::exists(filename);
}
/**************************************************************************
* Library functions
*************************************************************************/
bool pjglib_convert_stream2stream(char* msg);
bool pjglib_convert_file2file(char* in, char* out, char* msg);
bool pjglib_convert_stream2mem(
unsigned char** out_file,
unsigned int* out_size,
char* msg);
void pjglib_init_streams(
void* in_src,
int in_type,
int in_size,
void* out_dest,
int out_type);
/**************************************************************************
* Main interface functions
*************************************************************************/
void process_file(void);
void execute(bool (*function)());
/**************************************************************************
* Main functions
*************************************************************************/
bool reset_buffers(void);
bool read_jpeg(void);
bool merge_jpeg(void);
bool decode_jpeg(void);
bool recode_jpeg(void);
bool adapt_icos(void);
bool predict_dc(void);
bool unpredict_dc(void);
bool check_value_range(void);
bool calc_zdst_lists(void);
bool pack_pjg(void);
bool unpack_pjg(void);
/* -----------------------------------------------
global variables: info about program
----------------------------------------------- */
static const unsigned char appversion;
static const char* subversion;
static const char* apptitle;
static const char* appname;
static const char* versiondate;
static const char* author;
static const char pjg_magic[2];
private:

/**************************************************************************
* JPEG specific functions
*************************************************************************/
bool jpg_setup_imginfo(void);
bool jpg_parse_jfif(
unsigned char type,
unsigned int len,
unsigned char* segment);
bool jpg_rebuild_header(void);
int jpg_decode_block_seq(
BitReader* huffr,
huffTree* dctree,
huffTree* actree,
short* block);
int jpg_encode_block_seq(
BitWriter* huffw,
huffCodes* dctbl,
huffCodes* actbl,
short* block);

int jpg_decode_dc_prg_fs(
BitReader* huffr,
huffTree* dctree,
short* block);
int jpg_encode_dc_prg_fs(
BitWriter* huffw,
huffCodes* dctbl,
short* block);
int jpg_decode_ac_prg_fs(
BitReader* huffr,
huffTree* actree,
short* block,
int* eobrun,
int from,
int to);
int jpg_encode_ac_prg_fs(
BitWriter* huffw,
huffCodes* actbl,
short* block,
int* eobrun,
int from,
int to);

int jpg_decode_dc_prg_sa(BitReader* huffr, short* block);
int jpg_encode_dc_prg_sa(BitWriter* huffw, short* block);
int jpg_decode_ac_prg_sa(
BitReader* huffr,
huffTree* actree,
short* block,
int* eobrun,
int from,
int to);
int jpg_encode_ac_prg_sa(
BitWriter* huffw,
std::vector<std::uint8_t>& storw,
huffCodes* actbl,
short* block,
int* eobrun,
int from,
int to);
int jpg_decode_eobrun_sa(
BitReader* huffr,
short* block,
int* eobrun,
int from,
int to);
int jpg_encode_eobrun(
BitWriter* huffw,
huffCodes* actbl,
int* eobrun);
int jpg_encode_crbits(
BitWriter* huffw,
std::vector<std::uint8_t>& storw);
int jpg_next_huffcode(BitReader* huffw, huffTree* ctree);
int jpg_next_mcupos(
int* mcu,
int* cmp,
int* csc,
int* sub,
int* dpos,
int* rstw);
int jpg_next_mcuposn(int* cmp, int* dpos, int* rstw);
int jpg_skip_eobrun(int* cmp, int* dpos, int* rstw, int* eobrun);
void jpg_build_huffcodes(
unsigned char* clen,
unsigned char* cval,
huffCodes* hc,
huffTree* ht);
/**************************************************************************
* PJG specific functions
*************************************************************************/
bool pjg_encode_zstscan(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_zdst_high(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_zdst_low(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_dc(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_ac_high(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_ac_low(ArithmeticEncoder* enc, int cmp);
bool pjg_encode_generic(
ArithmeticEncoder* enc,
unsigned char* data,
int len);
bool pjg_encode_bit(ArithmeticEncoder* enc, unsigned char bit);
bool pjg_decode_zstscan(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_zdst_high(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_zdst_low(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_dc(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_ac_high(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_ac_low(ArithmeticDecoder* dec, int cmp);
bool pjg_decode_generic(
ArithmeticDecoder* dec,
unsigned char** data,
int* len);
bool pjg_decode_bit(ArithmeticDecoder* dec, unsigned char* bit);
void pjg_get_zerosort_scan(unsigned char* sv, int cmp);
bool pjg_optimize_header(void);
bool pjg_unoptimize_header(void);
void pjg_aavrg_prepare(
unsigned short** abs_coeffs,
int* weights,
unsigned short* abs_store,
int cmp);

int pjg_aavrg_context(
unsigned short** abs_coeffs,
int* weights,
int pos,
int p_y,
int p_x,
int r_x);
int pjg_lakh_context(
signed short** coeffs_x,
signed short** coeffs_a,
int* pred_cf,
int pos);

void get_context_nnb(int pos, int w, int* a, int* b);
/**************************************************************************
* DCT functions
*************************************************************************/

int idct_2d_fst_8x1(int cmp, int dpos, int ix, int iy);
int idct_2d_fst_1x8(int cmp, int dpos, int ix, int iy);

/**************************************************************************
* Prediction functions
*************************************************************************/

int dc_coll_predictor(int cmp, int dpos);
int dc_1ddct_predictor(int cmp, int dpos);
/* -----------------------------------------------
loco-i predictor
----------------------------------------------- */
inline int plocoi(int a, int b, int c)
{
// a -> left; b -> above; c -> above-left

int min = (a < b) ? a : b;
int max = (a > b) ? a : b;

if (c >= max)
{
return min;
}
if (c <= min)
{
return max;
}

return a + b - c;
}
/* -----------------------------------------------
calculates median out of an integer array
----------------------------------------------- */
inline int median_int(int* values, int size)
{
int middle = (size >> 1);
bool done;
int swap;
int i;

// sort data first
done = false;
while (!done)
{
done = true;
for (i = 1; i < size; i++)
{
if (values[i] < values[i - 1])
{
swap = values[i];
values[i] = values[i - 1];
values[i - 1] = swap;
done = false;
}
}
}

// return median
return ((size % 2) == 0) ?
(values[middle] + values[middle - 1]) / 2 : values[middle];
}

/* -----------------------------------------------
calculates median out of an float array
----------------------------------------------- */
inline float median_float(float* values, int size)
{
int middle = (size >> 1);
bool done;
float swap;
int i;


// sort data first
done = false;
while (!done)
{
done = true;
for (i = 1; i < size; i++)
{
if (values[i] < values[i - 1])
{
swap = values[i];
values[i] = values[i - 1];
values[i - 1] = swap;
done = false;
}
}
}

// return median
if ((size % 2) == 0)
{
return (values[middle] + values[middle - 1]) / 2.0;
}
else
{
return (values[middle]);
}
}

/**************************************************************************
* Member variables
*************************************************************************/
/* -----------------------------------------------
global variables: library only variables
----------------------------------------------- */
int lib_in_type;
int lib_out_type;
/* -----------------------------------------------
global variables: data storage
----------------------------------------------- */
unsigned short qtables[4][64]; // quantization tables
huffCodes hcodes[2][4]; // huffman codes
huffTree htrees[2][4]; // huffman decoding trees
unsigned char htset[2][4]; // 1 if huffman table is set
unsigned char* grbgdata; // garbage data
unsigned char* hdrdata ; // header data
unsigned char* huffdata; // huffman coded data
int hufs; // size of huffman data
int hdrs; // size of header
int grbs; // size of garbage
unsigned int* rstp; // restart markers positions in huffdata
unsigned int* scnp; // scan start positions in huffdata
int rstc; // count of restart markers
int scnc; // count of scans
int rsti; // restart interval
char padbit; // padbit (for huffman coding)
unsigned char* rst_err; // number of wrong-set RST markers per scan
unsigned char* zdstdata[4]; // zero distribution (# of non-zeroes) lists (for higher 7x7 block)
unsigned char* eobxhigh[4]; // eob in x direction (for higher 7x7 block)
unsigned char* eobyhigh[4]; // eob in y direction (for higher 7x7 block)
unsigned char* zdstxlow[4]; // # of non zeroes for first row
unsigned char* zdstylow[4]; // # of non zeroes for first collumn
signed short* colldata[4][64]; // collection sorted DCT coefficients
unsigned char* freqscan[4]; // optimized order for frequency scans (only pointers to scans)
unsigned char zsrtscan[4][64]; // zero optimized frequency scan
int adpt_idct_8x8[4][8 * 8 * 8 * 8]; // precalculated/adapted values for idct (8x8)
int adpt_idct_1x8[4][1 * 1 * 8 * 8]; // precalculated/adapted values for idct (1x8)
int adpt_idct_8x1[4][8 * 8 * 1 * 1]; // precalculated/adapted values for idct (8x1)
/* -----------------------------------------------
global variables: info about image
----------------------------------------------- */
componentInfo cmpnfo[4]; // seperate info for each color component
int cmpc; // component count
int imgwidth; // width of image
int imgheight; // height of image
int sfhm; // max horizontal sample factor
int sfvm; // max verical sample factor
int mcuv; // mcus per line
int mcuh; // mcus per collumn
int mcuc; // count of mcus
/* -----------------------------------------------
global variables: info about current scan
----------------------------------------------- */
int cs_cmpc; // component count in current scan
int cs_cmp[4]; // component numbers in current scan
int cs_from; // begin - band of current scan ( inclusive )
int cs_to; // end - band of current scan ( inclusive )
int cs_sah; // successive approximation bit pos high
int cs_sal; // successive approximation bit pos low
/* -----------------------------------------------
global variables: info about files
----------------------------------------------- */
char* jpgfilename; // name of JPEG file
char* pjgfilename; // name of PJG file
int jpgfilesize; // size of JPEG file
int pjgfilesize; // size of PJG file
int jpegtype; // type of JPEG coding: 0->unknown, 1->sequential, 2->progressive
int filetype; // type of current file
std::unique_ptr<Reader> str_in; // input stream
std::unique_ptr<Writer> str_out; // output stream
/* -----------------------------------------------
global variables: messages
----------------------------------------------- */
char errormessage[MSG_SIZE];
bool (*errorfunction)();
// meaning of errorlevel:
// -1 -> wrong input
// 0 -> no error
// 1 -> warning
// 2 -> fatal error
int errorlevel;
/* -----------------------------------------------
global variables: settings
----------------------------------------------- */
int err_tol; // error threshold ( proceed on warnings yes (2) / no (1) )
bool disc_meta; // discard meta-info yes / no
bool auto_set; // automatic find best settings yes/no
int action; // what to do with JPEG/PJG files
unsigned char nois_trs[4]; // bit pattern noise threshold
unsigned char segm_cnt[4]; // number of segments
};


#endif
(7-7/8)