Revision 073c5385
Added by David Sorber about 8 years ago
| software/packJPG_library/lib_src/packjpg.cpp | ||
|---|---|---|
|
// #define DEV_BUILD // uncomment to include developer functions
|
||
|
// #define DEV_INFOS // uncomment to include developer information
|
||
|
|
||
|
#define QUANT(cm, bp) (cmpnfo[cm].qtable[ bp ])
|
||
|
#define QUANT(cm, bp) (cmpnfo[cm].qtable[bp])
|
||
|
#define MAX_V(cm, bp) (( QUANT(cm,bp) > 0 ) ? ( ( freqmax[bp] + QUANT(cm,bp) - 1 ) / QUANT(cm,bp) ) : 0)
|
||
|
// #define QUN_V(v,cm,bp) ( ( QUANT(cm,bp) > 0 ) ? ( ( v > 0 ) ? ( v + (QUANT(cm,bp)/2) ) / QUANT(cm,bp) : ( v - (QUANT(cm,bp)/2) ) / QUANT(cm,bp) ) : 0 )
|
||
|
|
||
| ... | ... | |
|
static inline void* frealloc(void* ptr, size_t size)
|
||
|
{
|
||
|
void* n_ptr = realloc(ptr, (size) ? size : 1);
|
||
|
if (n_ptr == NULL)
|
||
|
if (n_ptr == nullptr)
|
||
|
{
|
||
|
free(ptr);
|
||
|
}
|
||
| ... | ... | |
|
|
||
|
#if defined(DEV_INFOS)
|
||
|
int dev_size_hdr = 0;
|
||
|
int dev_size_cmp[ 4 ] = { 0 };
|
||
|
int dev_size_zsr[ 4 ] = { 0 };
|
||
|
int dev_size_dc[ 4 ] = { 0 };
|
||
|
int dev_size_ach[ 4 ] = { 0 };
|
||
|
int dev_size_acl[ 4 ] = { 0 };
|
||
|
int dev_size_zdh[ 4 ] = { 0 };
|
||
|
int dev_size_zdl[ 4 ] = { 0 };
|
||
|
int dev_size_cmp[4] = { 0 };
|
||
|
int dev_size_zsr[4] = { 0 };
|
||
|
int dev_size_dc[4] = { 0 };
|
||
|
int dev_size_ach[4] = { 0 };
|
||
|
int dev_size_acl[4] = { 0 };
|
||
|
int dev_size_zdh[4] = { 0 };
|
||
|
int dev_size_zdl[4] = { 0 };
|
||
|
#endif
|
||
|
|
||
|
|
||
| ... | ... | |
|
return (const char*) v_name;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
|
||
|
/* ----------------------- Begin of library only functions -------------------------- */
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
DLL export converter function
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool pjglib_convert_stream2stream(char* msg)
|
||
|
bool packJPG::pjglib_convert_stream2stream(char* msg)
|
||
|
{
|
||
|
// process in main function
|
||
|
return pjglib_convert_stream2mem(NULL, NULL, msg);
|
||
|
return pjglib_convert_stream2mem(nullptr, nullptr, msg);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
DLL export converter function
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool pjglib_convert_file2file(char* in, char* out, char* msg)
|
||
|
bool packJPG::pjglib_convert_file2file(char* in, char* out, char* msg)
|
||
|
{
|
||
|
// init streams
|
||
|
pjglib_init_streams((void*) in, 0, 0, (void*) out, 0);
|
||
|
|
||
|
// process in main function
|
||
|
return pjglib_convert_stream2mem(NULL, NULL, msg);
|
||
|
return pjglib_convert_stream2mem(nullptr, nullptr, msg);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
DLL export converter function
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool pjglib_convert_stream2mem(unsigned char** out_file, unsigned int* out_size, char* msg)
|
||
|
bool packJPG::pjglib_convert_stream2mem(
|
||
|
unsigned char** out_file,
|
||
|
unsigned int* out_size,
|
||
|
char* msg)
|
||
|
{
|
||
|
clock_t begin, end;
|
||
|
int total;
|
||
|
float cr;
|
||
|
|
||
|
|
||
|
// use automatic settings
|
||
|
auto_set = true;
|
||
|
|
||
| ... | ... | |
|
|
||
|
// fetch pointer and size of output (only for memory output)
|
||
|
if ((errorlevel < err_tol) && (lib_out_type == 1) &&
|
||
|
(out_file != NULL) && (out_size != NULL))
|
||
|
(out_file != nullptr) && (out_size != nullptr))
|
||
|
{
|
||
|
*out_size = str_out->num_bytes_written();
|
||
|
*out_file = str_out->get_c_data();
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
}
|
||
|
if (msg != NULL)
|
||
|
if (msg != nullptr)
|
||
|
{
|
||
|
strcpy(msg, errormessage);
|
||
|
}
|
||
| ... | ... | |
|
cr = (jpgfilesize > 0) ? (100.0 * pjgfilesize / jpgfilesize) : 0;
|
||
|
|
||
|
// write success message else
|
||
|
if (msg != NULL)
|
||
|
if (msg != nullptr)
|
||
|
{
|
||
|
switch (filetype)
|
||
|
{
|
||
| ... | ... | |
|
/* -----------------------------------------------
|
||
|
DLL export init input (file/mem)
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
void pjglib_init_streams(void* in_src, int in_type, int in_size, void* out_dest, int out_type)
|
||
|
void packJPG::pjglib_init_streams(
|
||
|
void* in_src,
|
||
|
int in_type,
|
||
|
int in_size,
|
||
|
void* out_dest,
|
||
|
int out_type)
|
||
|
{
|
||
|
/* a short reminder about input/output stream types:
|
||
|
|
||
| ... | ... | |
|
|
||
|
vice versa for output streams! */
|
||
|
|
||
|
unsigned char buffer[ 2 ];
|
||
|
unsigned char buffer[2];
|
||
|
|
||
|
// (re)set errorlevel
|
||
|
errorfunction = NULL;
|
||
|
errorfunction = nullptr;
|
||
|
errorlevel = 0;
|
||
|
jpgfilesize = 0;
|
||
|
pjgfilesize = 0;
|
||
| ... | ... | |
|
lib_out_type = out_type;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ----------------------- End of libary only functions -------------------------- */
|
||
|
|
||
|
/* ----------------------- Begin of main interface functions -------------------------- */
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
reads in commandline arguments
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
UI for processing one file
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
gets statusmessage for function
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
shows help in case of wrong input
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
processes one file
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
void process_file(void)
|
||
|
void packJPG::process_file(void)
|
||
|
{
|
||
|
if (filetype == F_JPG)
|
||
|
{
|
||
|
switch (action)
|
||
|
{
|
||
|
case A_COMPRESS:
|
||
|
execute(read_jpeg);
|
||
|
execute(decode_jpeg);
|
||
|
execute(check_value_range);
|
||
|
execute(adapt_icos);
|
||
|
execute(predict_dc);
|
||
|
execute(calc_zdst_lists);
|
||
|
execute(pack_pjg);
|
||
|
read_jpeg();
|
||
|
decode_jpeg();
|
||
|
check_value_range();
|
||
|
adapt_icos();
|
||
|
predict_dc();
|
||
|
calc_zdst_lists();
|
||
|
pack_pjg();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
| ... | ... | |
|
switch (action)
|
||
|
{
|
||
|
case A_COMPRESS:
|
||
|
execute(unpack_pjg);
|
||
|
execute(adapt_icos);
|
||
|
execute(unpredict_dc);
|
||
|
execute(recode_jpeg);
|
||
|
execute(merge_jpeg);
|
||
|
unpack_pjg();
|
||
|
adapt_icos();
|
||
|
unpredict_dc();
|
||
|
recode_jpeg();
|
||
|
merge_jpeg();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// reset buffers
|
||
|
reset_buffers();
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
main-function execution routine
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
void execute(bool (*function)())
|
||
|
void packJPG::execute(bool (*function)())
|
||
|
{
|
||
|
if (errorlevel < err_tol)
|
||
|
{
|
||
| ... | ... | |
|
(*function)();
|
||
|
|
||
|
// store errorfunction if needed
|
||
|
if ((errorlevel > 0) && (errorfunction == NULL))
|
||
|
if ((errorlevel > 0) && (errorfunction == nullptr))
|
||
|
{
|
||
|
errorfunction = function;
|
||
|
}
|
||
| ... | ... | |
|
/* ----------------------- Begin of main functions -------------------------- */
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
check file and determine filetype
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
swap streams / init verification
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
comparison between input & output
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
set each variable to its initial value
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool reset_buffers(void)
|
||
|
bool packJPG::reset_buffers(void)
|
||
|
{
|
||
|
int cmp, bpos;
|
||
|
int i;
|
||
|
|
||
|
|
||
|
// -- free buffers --
|
||
|
|
||
|
// free buffers & set pointers NULL
|
||
|
if (hdrdata != NULL)
|
||
|
// free buffers & set pointers nullptr
|
||
|
if (hdrdata != nullptr)
|
||
|
{
|
||
|
free(hdrdata);
|
||
|
}
|
||
|
if (huffdata != NULL)
|
||
|
if (huffdata != nullptr)
|
||
|
{
|
||
|
free(huffdata);
|
||
|
}
|
||
|
if (grbgdata != NULL)
|
||
|
if (grbgdata != nullptr)
|
||
|
{
|
||
|
free(grbgdata);
|
||
|
}
|
||
|
if (rst_err != NULL)
|
||
|
if (rst_err != nullptr)
|
||
|
{
|
||
|
free(rst_err);
|
||
|
}
|
||
|
if (rstp != NULL)
|
||
|
if (rstp != nullptr)
|
||
|
{
|
||
|
free(rstp);
|
||
|
}
|
||
|
if (scnp != NULL)
|
||
|
if (scnp != nullptr)
|
||
|
{
|
||
|
free(scnp);
|
||
|
}
|
||
|
hdrdata = NULL;
|
||
|
huffdata = NULL;
|
||
|
grbgdata = NULL;
|
||
|
rst_err = NULL;
|
||
|
rstp = NULL;
|
||
|
scnp = NULL;
|
||
|
hdrdata = nullptr;
|
||
|
huffdata = nullptr;
|
||
|
grbgdata = nullptr;
|
||
|
rst_err = nullptr;
|
||
|
rstp = nullptr;
|
||
|
scnp = nullptr;
|
||
|
|
||
|
// free image arrays
|
||
|
for (cmp = 0; cmp < 4; cmp++)
|
||
|
{
|
||
|
if (zdstdata[ cmp ] != NULL)
|
||
|
if (zdstdata[cmp] != nullptr)
|
||
|
{
|
||
|
free(zdstdata[cmp]);
|
||
|
}
|
||
|
if (eobxhigh[ cmp ] != NULL)
|
||
|
if (eobxhigh[cmp] != nullptr)
|
||
|
{
|
||
|
free(eobxhigh[cmp]);
|
||
|
}
|
||
|
if (eobyhigh[ cmp ] != NULL)
|
||
|
if (eobyhigh[cmp] != nullptr)
|
||
|
{
|
||
|
free(eobyhigh[cmp]);
|
||
|
}
|
||
|
if (zdstxlow[ cmp ] != NULL)
|
||
|
if (zdstxlow[cmp] != nullptr)
|
||
|
{
|
||
|
free(zdstxlow[cmp]);
|
||
|
}
|
||
|
if (zdstylow[ cmp ] != NULL)
|
||
|
if (zdstylow[cmp] != nullptr)
|
||
|
{
|
||
|
free(zdstylow[cmp]);
|
||
|
}
|
||
|
zdstdata[ cmp ] = NULL;
|
||
|
eobxhigh[ cmp ] = NULL;
|
||
|
eobyhigh[ cmp ] = NULL;
|
||
|
zdstxlow[ cmp ] = NULL;
|
||
|
zdstylow[ cmp ] = NULL;
|
||
|
freqscan[ cmp ] = (unsigned char*) stdscan;
|
||
|
zdstdata[cmp] = nullptr;
|
||
|
eobxhigh[cmp] = nullptr;
|
||
|
eobyhigh[cmp] = nullptr;
|
||
|
zdstxlow[cmp] = nullptr;
|
||
|
zdstylow[cmp] = nullptr;
|
||
|
freqscan[cmp] = (unsigned char*) stdscan;
|
||
|
|
||
|
for (bpos = 0; bpos < 64; bpos++)
|
||
|
{
|
||
|
if (colldata[ cmp ][ bpos ] != NULL)
|
||
|
if (colldata[cmp][bpos] != nullptr)
|
||
|
{
|
||
|
free(colldata[cmp][bpos]);
|
||
|
}
|
||
|
colldata[ cmp ][ bpos ] = NULL;
|
||
|
colldata[cmp][bpos] = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// -- set variables --
|
||
|
|
||
|
// preset componentinfo
|
||
|
for (cmp = 0; cmp < 4; cmp++)
|
||
|
{
|
||
|
cmpnfo[ cmp ].sfv = -1;
|
||
|
cmpnfo[ cmp ].sfh = -1;
|
||
|
cmpnfo[ cmp ].mbs = -1;
|
||
|
cmpnfo[ cmp ].bcv = -1;
|
||
|
cmpnfo[ cmp ].bch = -1;
|
||
|
cmpnfo[ cmp ].bc = -1;
|
||
|
cmpnfo[ cmp ].ncv = -1;
|
||
|
cmpnfo[ cmp ].nch = -1;
|
||
|
cmpnfo[ cmp ].nc = -1;
|
||
|
cmpnfo[ cmp ].sid = -1;
|
||
|
cmpnfo[ cmp ].jid = -1;
|
||
|
cmpnfo[ cmp ].qtable = NULL;
|
||
|
cmpnfo[ cmp ].huffdc = -1;
|
||
|
cmpnfo[ cmp ].huffac = -1;
|
||
|
cmpnfo[cmp].sfv = -1;
|
||
|
cmpnfo[cmp].sfh = -1;
|
||
|
cmpnfo[cmp].mbs = -1;
|
||
|
cmpnfo[cmp].bcv = -1;
|
||
|
cmpnfo[cmp].bch = -1;
|
||
|
cmpnfo[cmp].bc = -1;
|
||
|
cmpnfo[cmp].ncv = -1;
|
||
|
cmpnfo[cmp].nch = -1;
|
||
|
cmpnfo[cmp].nc = -1;
|
||
|
cmpnfo[cmp].sid = -1;
|
||
|
cmpnfo[cmp].jid = -1;
|
||
|
cmpnfo[cmp].qtable = nullptr;
|
||
|
cmpnfo[cmp].huffdc = -1;
|
||
|
cmpnfo[cmp].huffac = -1;
|
||
|
}
|
||
|
|
||
|
// preset imgwidth / imgheight / component count
|
||
| ... | ... | |
|
// reset quantization / huffman tables
|
||
|
for (i = 0; i < 4; i++)
|
||
|
{
|
||
|
htset[ 0 ][ i ] = 0;
|
||
|
htset[ 1 ][ i ] = 0;
|
||
|
htset[0][i] = 0;
|
||
|
htset[1][i] = 0;
|
||
|
for (bpos = 0; bpos < 64; bpos++)
|
||
|
{
|
||
|
qtables[ i ][ bpos ] = 0;
|
||
|
qtables[i][bpos] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
// reset padbit
|
||
|
padbit = -1;
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
Read in header & image data
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool read_jpeg(void)
|
||
|
bool packJPG::read_jpeg(void)
|
||
|
{
|
||
|
unsigned char* segment = NULL; // storage for current segment
|
||
|
unsigned char* segment = nullptr; // storage for current segment
|
||
|
unsigned int ssize = 1024; // current size of segment array
|
||
|
unsigned char type = 0x00; // type of current marker segment
|
||
|
unsigned int len = 0; // length of current marker segment
|
||
| ... | ... | |
|
MemoryWriter* hdrw;
|
||
|
MemoryWriter* grbgw;
|
||
|
|
||
|
|
||
|
// preset count of scans
|
||
|
scnc = 0;
|
||
|
|
||
| ... | ... | |
|
|
||
|
// alloc memory for segment data first
|
||
|
segment = (unsigned char*) calloc(ssize, sizeof(char));
|
||
|
if (segment == NULL)
|
||
|
if (segment == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
// store number of wrongly set rst markers
|
||
|
if (crst > 0)
|
||
|
{
|
||
|
if (rst_err == NULL)
|
||
|
if (rst_err == nullptr)
|
||
|
{
|
||
|
rst_err = (unsigned char*) calloc(scnc + 1, sizeof(char));
|
||
|
if (rst_err == NULL)
|
||
|
if (rst_err == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
}
|
||
|
if (rst_err != NULL)
|
||
|
if (rst_err != nullptr)
|
||
|
{
|
||
|
// realloc and set only if needed
|
||
|
rst_err = (unsigned char*) frealloc(rst_err, (scnc + 1) * sizeof(char));
|
||
|
if (rst_err == NULL)
|
||
|
if (rst_err == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
errorlevel = 1;
|
||
|
crst = 255;
|
||
|
}
|
||
|
rst_err[ scnc ] = crst;
|
||
|
rst_err[scnc] = crst;
|
||
|
}
|
||
|
// end of current scan
|
||
|
scnc++;
|
||
|
// on with the header parser routines
|
||
|
segment[ 0 ] = 0xFF;
|
||
|
segment[ 1 ] = tmp;
|
||
|
segment[0] = 0xFF;
|
||
|
segment[1] = tmp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (segment[ 0 ] != 0xFF)
|
||
|
if (segment[0] != 0xFF)
|
||
|
{
|
||
|
// ugly fix for incorrect marker segment sizes
|
||
|
sprintf(errormessage, "size mismatch in marker segment FF %2X", type);
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (segment[ 0 ] == 0xFF)
|
||
|
if (segment[0] == 0xFF)
|
||
|
{
|
||
|
errorlevel = 1;
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
|
||
|
// read segment type
|
||
|
type = segment[ 1 ];
|
||
|
type = segment[1];
|
||
|
|
||
|
// if EOI is encountered make a quick exit
|
||
|
if (type == 0xD9)
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
len = 2 + B_SHORT(segment[ 2 ], segment[ 3 ]);
|
||
|
len = 2 + B_SHORT(segment[2], segment[3]);
|
||
|
if (len < 4)
|
||
|
{
|
||
|
break;
|
||
| ... | ... | |
|
if (ssize < len)
|
||
|
{
|
||
|
segment = (unsigned char*) frealloc(segment, len);
|
||
|
if (segment == NULL)
|
||
|
if (segment == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
// JPEG reader loop end
|
||
|
|
||
|
// free writers
|
||
|
delete (hdrw);
|
||
|
delete (huffw);
|
||
|
delete hdrw;
|
||
|
delete huffw;
|
||
|
|
||
|
// check if everything went OK
|
||
|
if ((hdrs == 0) || (hufs == 0))
|
||
| ... | ... | |
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
Merges header & image data to jpeg
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool merge_jpeg(void)
|
||
|
bool packJPG::merge_jpeg(void)
|
||
|
{
|
||
|
unsigned char SOI[ 2 ] = { 0xFF, 0xD8 }; // SOI segment
|
||
|
unsigned char EOI[ 2 ] = { 0xFF, 0xD9 }; // EOI segment
|
||
|
unsigned char SOI[2] = {0xFF, 0xD8}; // SOI segment
|
||
|
unsigned char EOI[2] = {0xFF, 0xD9}; // EOI segment
|
||
|
unsigned char mrk = 0xFF; // marker start
|
||
|
unsigned char stv = 0x00; // 0xFF stuff value
|
||
|
unsigned char rst = 0xD0; // restart marker
|
||
| ... | ... | |
|
unsigned int scan = 1; // number of current scan
|
||
|
unsigned int tmp; // temporary storage variable
|
||
|
|
||
|
|
||
|
// write SOI
|
||
|
str_out->write(SOI, 2);
|
||
|
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
type = hdrdata[ hpos + 1 ];
|
||
|
len = 2 + B_SHORT(hdrdata[ hpos + 2 ], hdrdata[ hpos + 3 ]);
|
||
|
type = hdrdata[hpos + 1];
|
||
|
len = 2 + B_SHORT(hdrdata[hpos + 2], hdrdata[hpos + 3]);
|
||
|
hpos += len;
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// (re)set corrected rst pos
|
||
|
cpos = 0;
|
||
|
|
||
|
// write & expand huffman coded image data
|
||
|
for (ipos = scnp[ scan - 1 ]; ipos < scnp[ scan ]; ipos++)
|
||
|
for (ipos = scnp[scan - 1]; ipos < scnp[scan]; ipos++)
|
||
|
{
|
||
|
// write current byte
|
||
|
str_out->write_byte(huffdata[ipos]);
|
||
|
// check current byte, stuff if needed
|
||
|
if (huffdata[ ipos ] == 0xFF)
|
||
|
if (huffdata[ipos] == 0xFF)
|
||
|
{
|
||
|
str_out->write_byte(stv);
|
||
|
}
|
||
|
// insert restart markers if needed
|
||
|
if (rstp != NULL)
|
||
|
if (rstp != nullptr)
|
||
|
{
|
||
|
if (ipos == rstp[ rpos ])
|
||
|
if (ipos == rstp[rpos])
|
||
|
{
|
||
|
rst = 0xD0 + (cpos % 8);
|
||
|
str_out->write_byte(mrk);
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
// insert false rst markers at end if needed
|
||
|
if (rst_err != NULL)
|
||
|
if (rst_err != nullptr)
|
||
|
{
|
||
|
while (rst_err[ scan - 1 ] > 0)
|
||
|
while (rst_err[scan - 1] > 0)
|
||
|
{
|
||
|
rst = 0xD0 + (cpos % 8);
|
||
|
str_out->write_byte(mrk);
|
||
|
str_out->write_byte(rst);
|
||
|
cpos++;
|
||
|
rst_err[ scan - 1 ]--;
|
||
|
rst_err[scan - 1]--;
|
||
|
}
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
// get filesize
|
||
|
jpgfilesize = str_out->num_bytes_written();
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
JPEG decoding routine
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool decode_jpeg(void)
|
||
|
bool packJPG::decode_jpeg(void)
|
||
|
{
|
||
|
BitReader* huffr; // bitwise reader for image data
|
||
|
|
||
| ... | ... | |
|
unsigned int len = 0; // length of current marker segment
|
||
|
unsigned int hpos = 0; // current position in header
|
||
|
|
||
|
int lastdc[ 4 ]; // last dc for each component
|
||
|
short block[ 64 ]; // store block for coeffs
|
||
|
int lastdc[4]; // last dc for each component
|
||
|
short block[64]; // store block for coeffs
|
||
|
int peobrun; // previous eobrun
|
||
|
int eobrun; // run of eobs
|
||
|
int rstw; // restart wait counter
|
||
| ... | ... | |
|
int mcu, sub, csc;
|
||
|
int eob, sta;
|
||
|
|
||
|
|
||
|
// open huffman coded image data for input in BitReader
|
||
|
huffr = new BitReader(huffdata, hufs);
|
||
|
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
type = hdrdata[ hpos + 1 ];
|
||
|
len = 2 + B_SHORT(hdrdata[ hpos + 2 ], hdrdata[ hpos + 3 ]);
|
||
|
type = hdrdata[hpos + 1];
|
||
|
len = 2 + B_SHORT(hdrdata[hpos + 2], hdrdata[hpos + 3]);
|
||
|
if ((type == 0xC4) || (type == 0xDA) || (type == 0xDD))
|
||
|
{
|
||
|
if (!jpg_parse_jfif(type, len, &(hdrdata[ hpos ])))
|
||
|
if (!jpg_parse_jfif(type, len, &(hdrdata[hpos])))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
| ... | ... | |
|
// check if huffman tables are available
|
||
|
for (csc = 0; csc < cs_cmpc; csc++)
|
||
|
{
|
||
|
cmp = cs_cmp[ csc ];
|
||
|
if (((cs_sal == 0) && (htset[ 0 ][ cmpnfo[cmp].huffdc ] == 0)) ||
|
||
|
((cs_sah > 0) && (htset[ 1 ][ cmpnfo[cmp].huffac ] == 0)))
|
||
|
cmp = cs_cmp[csc];
|
||
|
if (((cs_sal == 0) && (htset[0][cmpnfo[cmp].huffdc] == 0)) ||
|
||
|
((cs_sah > 0) && (htset[1][cmpnfo[cmp].huffac] == 0)))
|
||
|
{
|
||
|
sprintf(errormessage, "huffman table missing in scan%i", scnc);
|
||
|
delete huffr;
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// intial variables set for decoding
|
||
|
cmp = cs_cmp[ 0 ];
|
||
|
cmp = cs_cmp[0];
|
||
|
csc = 0;
|
||
|
mcu = 0;
|
||
|
sub = 0;
|
||
| ... | ... | |
|
while (true)
|
||
|
{
|
||
|
// (re)set last DCs for diff coding
|
||
|
lastdc[ 0 ] = 0;
|
||
|
lastdc[ 1 ] = 0;
|
||
|
lastdc[ 2 ] = 0;
|
||
|
lastdc[ 3 ] = 0;
|
||
|
lastdc[0] = 0;
|
||
|
lastdc[1] = 0;
|
||
|
lastdc[2] = 0;
|
||
|
lastdc[3] = 0;
|
||
|
|
||
|
// (re)set status
|
||
|
eob = 0;
|
||
| ... | ... | |
|
{
|
||
|
// decode block
|
||
|
eob = jpg_decode_block_seq(huffr,
|
||
|
&(htrees[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[ 1 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[0][cmpnfo[cmp].huffdc]),
|
||
|
&(htrees[1][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// check for non optimal coding
|
||
|
if ((eob > 1) && (block[ eob - 1 ] == 0))
|
||
|
if ((eob > 1) && (block[eob - 1] == 0))
|
||
|
{
|
||
|
sprintf(errormessage, "reconstruction of inefficient coding not supported");
|
||
|
errorlevel = 1;
|
||
|
}
|
||
|
|
||
|
// fix dc
|
||
|
block[ 0 ] += lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = block[ 0 ];
|
||
|
block[0] += lastdc[cmp];
|
||
|
lastdc[cmp] = block[0];
|
||
|
|
||
|
// copy to colldata
|
||
|
for (bpos = 0; bpos < eob; bpos++)
|
||
|
{
|
||
|
colldata[ cmp ][ bpos ][ dpos ] = block[ bpos ];
|
||
|
colldata[cmp][bpos][dpos] = block[bpos];
|
||
|
}
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
sta = jpg_decode_dc_prg_fs(huffr,
|
||
|
&(htrees[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[0][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// fix dc for diff coding
|
||
|
colldata[cmp][0][dpos] = block[0] + lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = colldata[cmp][0][dpos];
|
||
|
colldata[cmp][0][dpos] = block[0] + lastdc[cmp];
|
||
|
lastdc[cmp] = colldata[cmp][0][dpos];
|
||
|
|
||
|
// bitshift for succesive approximation
|
||
|
colldata[cmp][0][dpos] <<= cs_sal;
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// decode next bit
|
||
|
sta = jpg_decode_dc_prg_sa(huffr,
|
||
|
block);
|
||
|
sta = jpg_decode_dc_prg_sa(huffr, block);
|
||
|
|
||
|
// shift in next bit
|
||
|
colldata[cmp][0][dpos] += block[0] << cs_sal;
|
||
| ... | ... | |
|
{
|
||
|
// decode block
|
||
|
eob = jpg_decode_block_seq(huffr,
|
||
|
&(htrees[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[ 1 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[0][cmpnfo[cmp].huffdc]),
|
||
|
&(htrees[1][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// check for non optimal coding
|
||
|
if ((eob > 1) && (block[ eob - 1 ] == 0))
|
||
|
if ((eob > 1) && (block[eob - 1] == 0))
|
||
|
{
|
||
|
sprintf(errormessage, "reconstruction of inefficient coding not supported");
|
||
|
errorlevel = 1;
|
||
|
}
|
||
|
|
||
|
// fix dc
|
||
|
block[ 0 ] += lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = block[ 0 ];
|
||
|
block[0] += lastdc[cmp];
|
||
|
lastdc[cmp] = block[0];
|
||
|
|
||
|
// copy to colldata
|
||
|
for (bpos = 0; bpos < eob; bpos++)
|
||
|
{
|
||
|
colldata[ cmp ][ bpos ][ dpos ] = block[ bpos ];
|
||
|
colldata[cmp][bpos][dpos] = block[bpos];
|
||
|
}
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
sta = jpg_decode_dc_prg_fs(huffr,
|
||
|
&(htrees[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(htrees[0][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// fix dc for diff coding
|
||
|
colldata[cmp][0][dpos] = block[0] + lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = colldata[cmp][0][dpos];
|
||
|
colldata[cmp][0][dpos] = block[0] + lastdc[cmp];
|
||
|
lastdc[cmp] = colldata[cmp][0][dpos];
|
||
|
|
||
|
// bitshift for succesive approximation
|
||
|
colldata[cmp][0][dpos] <<= cs_sal;
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// decode next bit
|
||
|
sta = jpg_decode_dc_prg_sa(huffr,
|
||
|
block);
|
||
|
sta = jpg_decode_dc_prg_sa(huffr, block);
|
||
|
|
||
|
// shift in next bit
|
||
|
colldata[cmp][0][dpos] += block[0] << cs_sal;
|
||
| ... | ... | |
|
{
|
||
|
// decode block
|
||
|
eob = jpg_decode_ac_prg_fs(huffr,
|
||
|
&(htrees[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(htrees[1][cmpnfo[cmp].huffac]),
|
||
|
block, &eobrun, cs_from, cs_to);
|
||
|
|
||
|
if (eobrun > 0)
|
||
|
{
|
||
|
// check for non optimal coding
|
||
|
if ((eob == cs_from) && (peobrun > 0) &&
|
||
|
(peobrun < hcodes[ 1 ][ cmpnfo[cmp].huffac ].max_eobrun - 1))
|
||
|
(peobrun < hcodes[1][cmpnfo[cmp].huffac].max_eobrun - 1))
|
||
|
{
|
||
|
sprintf(errormessage,
|
||
|
"reconstruction of inefficient coding not supported");
|
||
| ... | ... | |
|
// copy to colldata
|
||
|
for (bpos = cs_from; bpos < eob; bpos++)
|
||
|
{
|
||
|
colldata[ cmp ][ bpos ][ dpos ] = block[ bpos ] << cs_sal;
|
||
|
colldata[cmp][bpos][dpos] = block[bpos] << cs_sal;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
| ... | ... | |
|
// copy from colldata
|
||
|
for (bpos = cs_from; bpos <= cs_to; bpos++)
|
||
|
{
|
||
|
block[ bpos ] = colldata[ cmp ][ bpos ][ dpos ];
|
||
|
block[bpos] = colldata[cmp][bpos][dpos];
|
||
|
}
|
||
|
|
||
|
if (eobrun == 0)
|
||
|
{
|
||
|
// decode block (long routine)
|
||
|
eob = jpg_decode_ac_prg_sa(huffr,
|
||
|
&(htrees[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(htrees[1][cmpnfo[cmp].huffac]),
|
||
|
block, &eobrun, cs_from, cs_to);
|
||
|
|
||
|
if (eobrun > 0)
|
||
|
{
|
||
|
// check for non optimal coding
|
||
|
if ((eob == cs_from) && (peobrun > 0) &&
|
||
|
(peobrun < hcodes[ 1 ][ cmpnfo[cmp].huffac ].max_eobrun - 1))
|
||
|
(peobrun < hcodes[1][cmpnfo[cmp].huffac].max_eobrun - 1))
|
||
|
{
|
||
|
sprintf(errormessage,
|
||
|
"reconstruction of inefficient coding not supported");
|
||
| ... | ... | |
|
// copy back to colldata
|
||
|
for (bpos = cs_from; bpos <= cs_to; bpos++)
|
||
|
{
|
||
|
colldata[ cmp ][ bpos ][ dpos ] += block[ bpos ] << cs_sal;
|
||
|
colldata[cmp][bpos][dpos] += block[bpos] << cs_sal;
|
||
|
}
|
||
|
|
||
|
// proceed only if no error encountered
|
||
| ... | ... | |
|
}
|
||
|
|
||
|
// clean up
|
||
|
delete (huffr);
|
||
|
|
||
|
delete huffr;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
JPEG encoding routine
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool recode_jpeg(void)
|
||
|
bool packJPG::recode_jpeg(void)
|
||
|
{
|
||
|
BitWriter* huffw; // bitwise writer for image data
|
||
|
|
||
| ... | ... | |
|
unsigned int len = 0; // length of current marker segment
|
||
|
unsigned int hpos = 0; // current position in header
|
||
|
|
||
|
int lastdc[ 4 ]; // last dc for each component0
|
||
|
short block[ 64 ]; // store block for coeffs
|
||
|
int lastdc[4]; // last dc for each component0
|
||
|
short block[64]; // store block for coeffs
|
||
|
int eobrun; // run of eobs
|
||
|
int rstw; // restart wait counter
|
||
|
|
||
| ... | ... | |
|
int eob, sta;
|
||
|
int tmp;
|
||
|
|
||
|
|
||
|
// open huffman coded image data in BitWriter
|
||
|
huffw = new BitWriter(padbit);
|
||
|
|
||
| ... | ... | |
|
{
|
||
|
break;
|
||
|
}
|
||
|
type = hdrdata[ hpos + 1 ];
|
||
|
len = 2 + B_SHORT(hdrdata[ hpos + 2 ], hdrdata[ hpos + 3 ]);
|
||
|
type = hdrdata[hpos + 1];
|
||
|
len = 2 + B_SHORT(hdrdata[hpos + 2], hdrdata[hpos + 3]);
|
||
|
if ((type == 0xC4) || (type == 0xDA) || (type == 0xDD))
|
||
|
{
|
||
|
if (!jpg_parse_jfif(type, len, &(hdrdata[ hpos ])))
|
||
|
if (!jpg_parse_jfif(type, len, &(hdrdata[hpos])))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
| ... | ... | |
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// (re)alloc scan positons array
|
||
|
if (scnp == NULL)
|
||
|
if (scnp == nullptr)
|
||
|
{
|
||
|
scnp = (unsigned int*) calloc(scnc + 2, sizeof(int));
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
scnp = (unsigned int*) frealloc(scnp, (scnc + 2) * sizeof(int));
|
||
|
}
|
||
|
if (scnp == NULL)
|
||
|
if (scnp == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
if (rsti > 0)
|
||
|
{
|
||
|
tmp = rstc + ((cs_cmpc > 1) ?
|
||
|
(mcuc / rsti) : (cmpnfo[ cs_cmp[ 0 ] ].bc / rsti));
|
||
|
if (rstp == NULL)
|
||
|
(mcuc / rsti) : (cmpnfo[cs_cmp[0]].bc / rsti));
|
||
|
if (rstp == nullptr)
|
||
|
{
|
||
|
rstp = (unsigned int*) calloc(tmp + 1, sizeof(int));
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
rstp = (unsigned int*) frealloc(rstp, (tmp + 1) * sizeof(int));
|
||
|
}
|
||
|
if (rstp == NULL)
|
||
|
if (rstp == nullptr)
|
||
|
{
|
||
|
sprintf(errormessage, MEM_ERRMSG);
|
||
|
errorlevel = 2;
|
||
| ... | ... | |
|
}
|
||
|
|
||
|
// intial variables set for encoding
|
||
|
cmp = cs_cmp[ 0 ];
|
||
|
cmp = cs_cmp[0];
|
||
|
csc = 0;
|
||
|
mcu = 0;
|
||
|
sub = 0;
|
||
|
dpos = 0;
|
||
|
|
||
|
// store scan position
|
||
|
scnp[ scnc ] = huffw->num_bytes_written();
|
||
|
scnp[scnc] = huffw->num_bytes_written();
|
||
|
|
||
|
// JPEG imagedata encoding routines
|
||
|
while (true)
|
||
|
{
|
||
|
// (re)set last DCs for diff coding
|
||
|
lastdc[ 0 ] = 0;
|
||
|
lastdc[ 1 ] = 0;
|
||
|
lastdc[ 2 ] = 0;
|
||
|
lastdc[ 3 ] = 0;
|
||
|
lastdc[0] = 0;
|
||
|
lastdc[1] = 0;
|
||
|
lastdc[2] = 0;
|
||
|
lastdc[3] = 0;
|
||
|
|
||
|
// (re)set status
|
||
|
sta = 0;
|
||
| ... | ... | |
|
// copy from colldata
|
||
|
for (bpos = 0; bpos < 64; bpos++)
|
||
|
{
|
||
|
block[ bpos ] = colldata[ cmp ][ bpos ][ dpos ];
|
||
|
block[bpos] = colldata[cmp][bpos][dpos];
|
||
|
}
|
||
|
|
||
|
// diff coding for dc
|
||
|
block[ 0 ] -= lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = colldata[ cmp ][ 0 ][ dpos ];
|
||
|
block[0] -= lastdc[cmp];
|
||
|
lastdc[cmp] = colldata[cmp][0][dpos];
|
||
|
|
||
|
// encode block
|
||
|
eob = jpg_encode_block_seq(huffw,
|
||
|
&(hcodes[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[0][cmpnfo[cmp].huffdc]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
block);
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// diff coding & bitshifting for dc
|
||
|
tmp = colldata[ cmp ][ 0 ][ dpos ] >> cs_sal;
|
||
|
block[ 0 ] = tmp - lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = tmp;
|
||
|
tmp = colldata[cmp][0][dpos] >> cs_sal;
|
||
|
block[0] = tmp - lastdc[cmp];
|
||
|
lastdc[cmp] = tmp;
|
||
|
|
||
|
// encode dc
|
||
|
sta = jpg_encode_dc_prg_fs(huffw,
|
||
|
&(hcodes[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(hcodes[0][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// next mcupos if no error happened
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// fetch bit from current bitplane
|
||
|
block[ 0 ] = BITN(colldata[ cmp ][ 0 ][ dpos ], cs_sal);
|
||
|
block[0] = BITN(colldata[cmp][0][dpos], cs_sal);
|
||
|
|
||
|
// encode dc correction bit
|
||
|
sta = jpg_encode_dc_prg_sa(huffw, block);
|
||
| ... | ... | |
|
// copy from colldata
|
||
|
for (bpos = 0; bpos < 64; bpos++)
|
||
|
{
|
||
|
block[ bpos ] = colldata[ cmp ][ bpos ][ dpos ];
|
||
|
block[bpos] = colldata[cmp][bpos][dpos];
|
||
|
}
|
||
|
|
||
|
// diff coding for dc
|
||
|
block[ 0 ] -= lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = colldata[ cmp ][ 0 ][ dpos ];
|
||
|
block[0] -= lastdc[cmp];
|
||
|
lastdc[cmp] = colldata[cmp][0][dpos];
|
||
|
|
||
|
// encode block
|
||
|
eob = jpg_encode_block_seq(huffw,
|
||
|
&(hcodes[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[0][cmpnfo[cmp].huffdc]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
block);
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// diff coding & bitshifting for dc
|
||
|
tmp = colldata[ cmp ][ 0 ][ dpos ] >> cs_sal;
|
||
|
block[ 0 ] = tmp - lastdc[ cmp ];
|
||
|
lastdc[ cmp ] = tmp;
|
||
|
tmp = colldata[cmp][0][dpos] >> cs_sal;
|
||
|
block[0] = tmp - lastdc[cmp];
|
||
|
lastdc[cmp] = tmp;
|
||
|
|
||
|
// encode dc
|
||
|
sta = jpg_encode_dc_prg_fs(huffw,
|
||
|
&(hcodes[ 0 ][ cmpnfo[cmp].huffdc ]),
|
||
|
&(hcodes[0][cmpnfo[cmp].huffdc]),
|
||
|
block);
|
||
|
|
||
|
// check for errors, increment dpos otherwise
|
||
| ... | ... | |
|
while (sta == 0)
|
||
|
{
|
||
|
// fetch bit from current bitplane
|
||
|
block[ 0 ] = BITN(colldata[ cmp ][ 0 ][ dpos ], cs_sal);
|
||
|
block[0] = BITN(colldata[cmp][0][dpos], cs_sal);
|
||
|
|
||
|
// encode dc correction bit
|
||
|
sta = jpg_encode_dc_prg_sa(huffw, block);
|
||
| ... | ... | |
|
{
|
||
|
// copy from colldata
|
||
|
for (bpos = cs_from; bpos <= cs_to; bpos++)
|
||
|
block[ bpos ] =
|
||
|
FDIV2(colldata[ cmp ][ bpos ][ dpos ], cs_sal);
|
||
|
block[bpos] =
|
||
|
FDIV2(colldata[cmp][bpos][dpos], cs_sal);
|
||
|
|
||
|
// encode block
|
||
|
eob = jpg_encode_ac_prg_fs(huffw,
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
block, &eobrun, cs_from, cs_to);
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
|
||
|
// encode remaining eobrun
|
||
|
jpg_encode_eobrun(huffw,
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
&eobrun);
|
||
|
}
|
||
|
else
|
||
| ... | ... | |
|
{
|
||
|
// copy from colldata
|
||
|
for (bpos = cs_from; bpos <= cs_to; bpos++)
|
||
|
block[ bpos ] =
|
||
|
FDIV2(colldata[ cmp ][ bpos ][ dpos ], cs_sal);
|
||
|
block[bpos] =
|
||
|
FDIV2(colldata[cmp][bpos][dpos], cs_sal);
|
||
|
|
||
|
// encode block
|
||
|
eob = jpg_encode_ac_prg_sa(huffw, storw,
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
block, &eobrun, cs_from, cs_to);
|
||
|
|
||
|
// check for errors, proceed if no error encountered
|
||
| ... | ... | |
|
|
||
|
// encode remaining eobrun
|
||
|
jpg_encode_eobrun(huffw,
|
||
|
&(hcodes[ 1 ][ cmpnfo[cmp].huffac ]),
|
||
|
&(hcodes[1][cmpnfo[cmp].huffac]),
|
||
|
&eobrun);
|
||
|
|
||
|
// encode remaining correction bits
|
||
| ... | ... | |
|
{
|
||
|
if (rsti > 0) // store rstp & stay in the loop
|
||
|
{
|
||
|
rstp[ rstc++ ] = huffw->num_bytes_written() - 1;
|
||
|
rstp[rstc++] = huffw->num_bytes_written() - 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
delete huffw;
|
||
|
|
||
|
// store last scan & restart positions
|
||
|
scnp[ scnc ] = hufs;
|
||
|
if (rstp != NULL)
|
||
|
scnp[scnc] = hufs;
|
||
|
if (rstp != nullptr)
|
||
|
{
|
||
|
rstp[ rstc ] = hufs;
|
||
|
rstp[rstc] = hufs;
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
adapt ICOS tables for quantizer tables
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool adapt_icos(void)
|
||
|
bool packJPG::adapt_icos(void)
|
||
|
{
|
||
|
unsigned short quant[ 64 ]; // local copy of quantization
|
||
|
unsigned short quant[64]; // local copy of quantization
|
||
|
int ipos;
|
||
|
int cmp;
|
||
|
|
||
|
|
||
|
for (cmp = 0; cmp < cmpc; cmp++)
|
||
|
{
|
||
|
// make a local copy of the quantization values, check
|
||
|
for (ipos = 0; ipos < 64; ipos++)
|
||
|
{
|
||
|
quant[ ipos ] = QUANT(cmp, zigzag[ ipos ]);
|
||
|
if (quant[ ipos ] >= 2048) // if this is true, it can be safely assumed (for 8 bit JPEG), that all coefficients are zero
|
||
|
quant[ipos] = QUANT(cmp, zigzag[ipos]);
|
||
|
if (quant[ipos] >= 2048) // if this is true, it can be safely assumed (for 8 bit JPEG), that all coefficients are zero
|
||
|
{
|
||
|
quant[ ipos ] = 0;
|
||
|
quant[ipos] = 0;
|
||
|
}
|
||
|
}
|
||
|
// adapt idct 8x8 table
|
||
|
for (ipos = 0; ipos < 64 * 64; ipos++)
|
||
|
{
|
||
|
adpt_idct_8x8[ cmp ][ ipos ] = icos_idct_8x8[ ipos ] * quant[ ipos % 64 ];
|
||
|
adpt_idct_8x8[cmp][ipos] = icos_idct_8x8[ipos] * quant[ipos % 64];
|
||
|
}
|
||
|
// adapt idct 1x8 table
|
||
|
for (ipos = 0; ipos < 8 * 8; ipos++)
|
||
|
{
|
||
|
adpt_idct_1x8[ cmp ][ ipos ] = icos_idct_1x8[ ipos ] * quant[(ipos % 8) * 8 ];
|
||
|
adpt_idct_1x8[cmp][ipos] = icos_idct_1x8[ipos] * quant[(ipos % 8) * 8];
|
||
|
}
|
||
|
// adapt idct 8x1 table
|
||
|
for (ipos = 0; ipos < 8 * 8; ipos++)
|
||
|
{
|
||
|
adpt_idct_8x1[ cmp ][ ipos ] = icos_idct_1x8[ ipos ] * quant[ ipos % 8 ];
|
||
|
adpt_idct_8x1[cmp][ipos] = icos_idct_1x8[ipos] * quant[ipos % 8];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
filter DC coefficients
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool predict_dc(void)
|
||
|
bool packJPG::predict_dc(void)
|
||
|
{
|
||
|
signed short* coef;
|
||
|
int absmaxp;
|
||
| ... | ... | |
|
int corr_f;
|
||
|
int cmp, dpos;
|
||
|
|
||
|
|
||
|
// apply prediction, store prediction error instead of DC
|
||
|
for (cmp = 0; cmp < cmpc; cmp++)
|
||
|
{
|
||
| ... | ... | |
|
for (dpos = cmpnfo[cmp].bc - 1; dpos > 0; dpos--)
|
||
|
{
|
||
|
coef = &(colldata[cmp][0][dpos]);
|
||
|
#if defined( USE_PLOCOI )
|
||
|
#if defined(USE_PLOCOI)
|
||
|
(*coef) -= dc_coll_predictor(cmp, dpos); // loco-i predictor
|
||
|
#else
|
||
|
(*coef) -= dc_1ddct_predictor(cmp, dpos); // 1d dct
|
||
| ... | ... | |
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
unpredict DC coefficients
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool unpredict_dc(void)
|
||
|
bool packJPG::unpredict_dc(void)
|
||
|
{
|
||
|
signed short* coef;
|
||
|
int absmaxp;
|
||
| ... | ... | |
|
int corr_f;
|
||
|
int cmp, dpos;
|
||
|
|
||
|
|
||
|
// remove prediction, store DC instead of prediction error
|
||
|
for (cmp = 0; cmp < cmpc; cmp++)
|
||
|
{
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
checks range of values, error if out of bounds
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool check_value_range(void)
|
||
|
bool packJPG::check_value_range(void)
|
||
|
{
|
||
|
int absmax;
|
||
|
int cmp, bpos, dpos;
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
calculate zero distribution lists
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool calc_zdst_lists(void)
|
||
|
bool packJPG::calc_zdst_lists(void)
|
||
|
{
|
||
|
int cmp, bpos, dpos;
|
||
|
int b_x, b_y;
|
||
|
|
||
|
|
||
|
// this functions counts, for each DCT block, the number of non-zero coefficients
|
||
|
for (cmp = 0; cmp < cmpc; cmp++)
|
||
|
{
|
||
| ... | ... | |
|
// calculate # on non-zeroes per block (separately for lower 7x7 block & first row/collumn)
|
||
|
for (bpos = 1; bpos < 64; bpos++)
|
||
|
{
|
||
|
b_x = unzigzag[ bpos ] % 8;
|
||
|
b_y = unzigzag[ bpos ] / 8;
|
||
|
b_x = unzigzag[bpos] % 8;
|
||
|
b_y = unzigzag[bpos] / 8;
|
||
|
if (b_x == 0)
|
||
|
{
|
||
|
for (dpos = 0; dpos < cmpnfo[cmp].bc; dpos++)
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -----------------------------------------------
|
||
|
packs all parts to compressed pjg
|
||
|
----------------------------------------------- */
|
||
|
|
||
|
bool pack_pjg(void)
|
||
|
bool packJPG::pack_pjg(void)
|
||
|
{
|
||
|
unsigned char hcode;
|
||
|
int cmp;
|
||
| ... | ... | |
|
int dev_size = 0;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// PJG-Header
|
||
|
str_out->write(reinterpret_cast<const unsigned char*>(pjg_magic), 2);
|
||
|
|
||
| ... | ... | |
|
return false;
|
||
|
}
|
||
|
// also encode one bit to signal false/correct use of RST markers
|
||
|
if (!pjg_encode_bit(encoder, (rst_err == NULL) ? 0 : 1))
|
||
|
if (!pjg_encode_bit(encoder, (rst_err == nullptr) ? 0 : 1))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
// encode # of false set RST markers per scan
|
||
|
if (rst_err != NULL)
|
||
|
if (rst_err != nullptr)
|
||
|
if (!pjg_encode_generic(encoder, rst_err, scnc))
|
||
|
{
|
||
|
return false;
|
||
| ... | ... | |
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_zsr[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_zsr[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size = str_out->getpos();
|
||
|
// encode zero-distribution-lists for higher (7x7) ACs
|
||
|
if (!pjg_encode_zdst_high(encoder, cmp))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_zdh[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_zdh[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size = str_out->getpos();
|
||
|
// encode coefficients for higher (7x7) ACs
|
||
|
if (!pjg_encode_ac_high(encoder, cmp))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_ach[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_ach[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size = str_out->getpos();
|
||
|
// encode zero-distribution-lists for lower ACs
|
||
|
if (!pjg_encode_zdst_low(encoder, cmp))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_zdl[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_zdl[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size = str_out->getpos();
|
||
|
// encode coefficients for first row / collumn ACs
|
||
|
if (!pjg_encode_ac_low(encoder, cmp))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_acl[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_acl[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size = str_out->getpos();
|
||
|
// encode coefficients for DC
|
||
|
if (!pjg_encode_dc(encoder, cmp))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
dev_size_dc[ cmp ] += str_out->getpos() - dev_size;
|
||
|
dev_size_cmp[ cmp ] =
|
||
|
dev_size_zsr[ cmp ] + dev_size_zdh[ cmp ] + dev_size_zdl[ cmp ] +
|
||
|
dev_size_ach[ cmp ] + dev_size_acl[ cmp ] + dev_size_dc[ cmp ];
|
||
|
dev_size_dc[cmp] += str_out->getpos() - dev_size;
|
||
|
dev_size_cmp[cmp] =
|
||
|
dev_size_zsr[cmp] + dev_size_zdh[cmp] + dev_size_zdl[cmp] +
|
||
|
dev_size_ach[cmp] + dev_size_acl[cmp] + dev_size_dc[cmp];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
}
|
||
|
|
||
|
// finalize arithmetic compression
|
||
|
delete (encoder);
|
||
|
|
||
|
delete encoder;
|
||
WIP for libpackjpg reorganization: moved all main interface and main
functions inside the wrapper class