home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 44
/
Amiga_Dream_44.iso
/
Linux
/
Apps
/
xanim.tgz
/
xanim
/
xanim27064
/
xa_jpg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-01-26
|
49KB
|
1,634 lines
/*
* xa_jpg.c
*
* Copyright (C) 1994,1995,1996,1997 by Mark Podlipec.
* All rights reserved.
*
* This software may be freely copied, modified and redistributed without
* fee for non-commerical purposes provided that this copyright notice is
* preserved intact on all copies and modified copies.
*
* There is no warranty or other guarantee of fitness of this software.
* It is provided solely "as is". The author(s) disclaim(s) all
* responsibility and liability with respect to this software's usage
* or its effect upon hardware or computer systems.
*
*/
/* Revision History
*
* 22Aug95 - +F dithering to MPEG.
*/
#include "xa_jpg.h"
#include "xa_color.h"
YUVBufs jpg_YUVBufs;
extern YUVTabs def_yuv_tabs;
extern xaLONG xa_dither_flag;
/* JPEG Specific Variables */
xaUBYTE *jpg_buff = 0;
xaLONG jpg_bsize = 0;
xaLONG jpg_h_bnum; /* this must be signed */
xaULONG jpg_h_bbuf;
xaUBYTE *jpg_samp_limit = 0;
xaUBYTE *xa_byte_limit = 0;
xaULONG jpg_init_flag = xaFALSE;
xaLONG *jpg_quant_tables[JJ_NUM_QUANT_TBLS];
xaULONG jpg_marker = 0;
xaULONG jpg_saw_SOI,jpg_saw_SOF,jpg_saw_SOS;
xaULONG jpg_saw_DHT,jpg_saw_DQT,jpg_saw_EOI;
xaULONG jpg_std_DHT_flag = 0;
xaLONG jpg_dprec,jpg_height,jpg_width;
xaLONG jpg_num_comps,jpg_comps_in_scan;
xaLONG jpg_nxt_rst_num;
xaLONG jpg_rst_interval;
xaULONG xa_mjpg_kludge;
JJ_HUFF_TBL jpg_ac_huff[JJ_NUM_HUFF_TBLS];
JJ_HUFF_TBL jpg_dc_huff[JJ_NUM_HUFF_TBLS];
#define JPG_MAX_COMPS 4
#define JPG_DUMMY_COMP (JPG_MAX_COMPS + 1)
COMPONENT_HDR jpg_comps[JPG_MAX_COMPS + 1];
#define JJ_INPUT_CHECK(val) ((jpg_bsize >= (val))?(xaTRUE):(xaFALSE))
#define JJ_INPUT_xaBYTE(var) { var = *jpg_buff++; jpg_bsize--; }
#define JJ_INPUT_xaSHORT(var) \
{ var = (*jpg_buff++) << 8; var |= (*jpg_buff++); jpg_bsize -= 2; }
xaLONG JJ_ZAG[DCTSIZE2+16] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63,
0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
0, 0, 0, 0, 0, 0, 0, 0
};
xaULONG jpg_MCUbuf_size = 0;
xaUBYTE *jpg_Ybuf = 0;
xaUBYTE *jpg_Ubuf = 0;
xaUBYTE *jpg_Vbuf = 0;
xaSHORT jpg_dct_buf[DCTSIZE2];
/* FUNCTIONS */
xaULONG JFIF_Decode_JPEG();
xaULONG jpg_read_markers();
xaULONG jpg_decode_111111();
xaULONG jpg_decode_211111();
xaULONG jpg_decode_221111();
xaULONG jpg_decode_411111();
void jpg_huff_build();
xaULONG jpg_huffparse();
extern void j_rev_dct();
extern void j_rev_dct_sparse();
void JPG_Setup_Samp_Limit_Table();
void JPG_Free_Samp_Limit_Table();
xaULONG jpg_read_EOI_marker();
xaULONG jpg_std_DHT();
void JPG_Alloc_MCU_Bufs();
void JPG_Free_MCU_Bufs();
xaULONG jpg_search_marker();
xaULONG jpg_read_SOF();
xaULONG jpg_skip_marker();
xaULONG jpg_get_marker();
void jpg_init_input();
void jpg_huff_reset();
void JFIF_Read_IJPG_Tables();
void JFIF_Init_IJPG_Tables();
char IJPG_Tab1[64];
char IJPG_Tab2[64];
/* external */
extern void XA_Gen_YUV_Tabs();
extern void XA_MCU111111_To_Gray();
extern void *XA_MCU111111_Func();
extern void *XA_MCU211111_Func();
extern void *XA_MCU221111_Func();
extern void *XA_MCU411111_Func();
extern void XA_Add_Func_To_Free_Chain();
/******* JFIF extern stuff and variables ***************/
xaULONG JFIF_Read_File();
XA_ACTION *ACT_Get_Action();
XA_CHDR *ACT_Get_CMAP();
XA_CHDR *CMAP_Create_332();
XA_CHDR *CMAP_Create_Gray();
XA_CHDR *CMAP_Create_CHDR_From_True();
xaUBYTE *UTIL_RGB_To_Map();
xaUBYTE *UTIL_RGB_To_FS_Map();
xaULONG UTIL_Get_LSB_Short();
void ACT_Setup_Mapped();
void ACT_Add_CHDR_To_Action();
xaULONG CMAP_Find_Closest();
extern XA_ANIM_SETUP *XA_Get_Anim_Setup();
extern void XA_Free_Anim_Setup();
extern void ACT_Setup_Delta();
/*******
*
*/
void jpg_init_stuff()
{ xaLONG i;
DEBUG_LEVEL1 fprintf(stderr,"JJINIT\n");
if (jpg_init_flag==xaTRUE) return;
for(i=0; i < JJ_NUM_QUANT_TBLS; i++) jpg_quant_tables[i] = 0;
if (jpg_samp_limit==0) JPG_Setup_Samp_Limit_Table(0);
jpg_init_flag = xaTRUE;
jpg_std_DHT_flag = 0;
}
/*******
*
*/
void jpg_free_stuff()
{ xaLONG i;
DEBUG_LEVEL1 fprintf(stderr,"JJFREE\n");
if (jpg_init_flag == xaFALSE) return;
for(i=0; i < JJ_NUM_QUANT_TBLS; i++)
if (jpg_quant_tables[i]) { free(jpg_quant_tables[i]); jpg_quant_tables[i]=0; }
if (jpg_samp_limit) { free(jpg_samp_limit); jpg_samp_limit = 0; }
jpg_init_flag = xaFALSE;
jpg_std_DHT_flag = 0;
}
#define JFIF_APP0_LEN 14
/*****
*
*/
xaULONG JFIF_Read_File(fname,anim_hdr)
char *fname;
XA_ANIM_HDR *anim_hdr;
{ XA_INPUT *xin = anim_hdr->xin;
ACT_DLTA_HDR *dlta_hdr = 0;
XA_ACTION *act = 0;
xaULONG jfif_flen;
xaUBYTE *inbuff = 0;
XA_ANIM_SETUP *jfif;
jfif = XA_Get_Anim_Setup();
jfif->cmap_frame_num = 1; /* always 1 image per file */
jfif->vid_time = XA_GET_TIME( 200 );
/* find file size */
xin->Seek_FPos(xin,0L,2);
jfif_flen = xin->Get_FPos(xin); /* POD may not be portable */
xin->Seek_FPos(xin,0L,0);
if (xa_file_flag==xaTRUE)
{ xaLONG ret;
dlta_hdr = (ACT_DLTA_HDR *) malloc(sizeof(ACT_DLTA_HDR));
if (dlta_hdr == 0) TheEnd1("JFIF: malloc failed");
dlta_hdr->flags = 0;
dlta_hdr->fpos = xin->Get_FPos(xin);
dlta_hdr->fsize = jfif_flen;
jfif->max_fvid_size = jfif_flen + 16;
inbuff = (xaUBYTE *)malloc(jfif_flen);
ret = xin->Read_Block(xin,inbuff,jfif_flen);
if (ret < jfif_flen)
{fprintf(stderr,"JFIF: inbuff read failed\n"); return(xaFALSE);}
}
else
{ xaLONG ret,d;
d = jfif_flen + (sizeof(ACT_DLTA_HDR));
dlta_hdr = (ACT_DLTA_HDR *) malloc( d );
if (dlta_hdr == 0) TheEnd1("JFIF: malloc failed");
dlta_hdr->flags = DLTA_DATA;
dlta_hdr->fpos = 0; dlta_hdr->fsize = jfif_flen;
ret = xin->Read_Block(xin, dlta_hdr->data, jfif_flen);
if (ret < jfif_flen)
{fprintf(stderr,"JFIF: read failed\n"); return(xaFALSE);}
inbuff = dlta_hdr->data;
}
/******** EXTRACT IMAGE SIZE ****************/
jpg_init_input(inbuff,jfif_flen);
jpg_saw_SOF = xaFALSE;
while(jpg_get_marker() == xaTRUE)
{
if ( (jpg_marker == M_SOF0) || (jpg_marker == M_SOF1) )
{
if (jpg_read_SOF()==xaTRUE) jpg_saw_SOF = xaTRUE;
break;
}
else if ((jpg_marker == M_SOI) || (jpg_marker == M_TEM)) continue;
else if ((jpg_marker >= M_RST0) && (jpg_marker <= M_RST7)) continue;
else jpg_skip_marker();
}
if (jpg_saw_SOF == xaFALSE)
{
fprintf(stderr,"JPEG: not recognized as a JPEG file\n");
return(xaFALSE);
}
jfif->imagex = 4 * ((jpg_width + 3)/4);
jfif->imagey = 2 * ((jpg_height + 1)/2);
JPG_Alloc_MCU_Bufs(anim_hdr,jfif->imagex,0,xaFALSE);
XA_Gen_YUV_Tabs(anim_hdr);
if (xa_verbose)
{
fprintf(stderr,"JFIF: size %d by %d\n",jfif->imagex,jfif->imagey);
}
/* Allocate Colors */
if (jpg_num_comps == 1) /* assume grayscale */
{ int i;
jfif->imagec = 256; jfif->depth = 8;
for(i=0;i<jfif->imagec;i++)
{ jfif->cmap[i].red = jfif->cmap[i].green = jfif->cmap[i].blue = i; }
jfif->chdr = ACT_Get_CMAP(jfif->cmap,jfif->imagec,0,jfif->imagec,0,8,8,8);
}
else if (jpg_num_comps == 3)
{
jfif->depth = 24;
if ( (cmap_true_map_flag == xaFALSE) /* depth 24 and not true_map */
|| (xa_buffer_flag == xaFALSE) )
{
if (cmap_true_to_332 == xaTRUE)
jfif->chdr = CMAP_Create_332(jfif->cmap,&jfif->imagec);
else jfif->chdr = CMAP_Create_Gray(jfif->cmap,&jfif->imagec);
}
}
else
{
fprintf(stderr,"JFIF: unsupported number of components %d\n",jpg_num_comps);
return(xaFALSE);
}
act = ACT_Get_Action(anim_hdr,ACT_DELTA);
act->data = (xaUBYTE *)dlta_hdr;
dlta_hdr->xpos = dlta_hdr->ypos = 0;
dlta_hdr->xsize = jfif->imagex;
dlta_hdr->ysize = jfif->imagey;
dlta_hdr->special = 0;
dlta_hdr->extra = (void *)(0);
dlta_hdr->xapi_rev = 0x0002;
dlta_hdr->delta = JFIF_Decode_JPEG;
jfif->pic = 0;
ACT_Setup_Delta(jfif,act,dlta_hdr,xin);
xin->Close_File(xin);
/* free up buffer in necessary */
if (xa_file_flag==xaTRUE) {free(inbuff); inbuff = 0; }
anim_hdr->imagex = jfif->imagex;
anim_hdr->imagey = jfif->imagey;
anim_hdr->imagec = jfif->imagec;
anim_hdr->imaged = 8; /* nop */
anim_hdr->frame_lst = (XA_FRAME *) malloc( sizeof(XA_FRAME) * 2);
anim_hdr->frame_lst[0].time_dur = jfif->vid_time;
anim_hdr->frame_lst[0].zztime = 0;
anim_hdr->frame_lst[0].act = act;
anim_hdr->frame_lst[1].time_dur = 0;
anim_hdr->frame_lst[1].zztime = -1;
anim_hdr->frame_lst[1].act = 0;
anim_hdr->loop_frame = 0;
anim_hdr->last_frame = 0;
anim_hdr->total_time = anim_hdr->frame_lst[0].time_dur;
if (xa_buffer_flag == xaFALSE) anim_hdr->anim_flags |= ANIM_SNG_BUF;
if (xa_file_flag == xaTRUE) anim_hdr->anim_flags |= ANIM_USE_FILE;
anim_hdr->anim_flags |= ANIM_FULL_IM;
anim_hdr->max_fvid_size = jfif->max_fvid_size;
anim_hdr->max_faud_size = 0;
anim_hdr->fname = anim_hdr->name;
XA_Free_Anim_Setup(jfif);
return(xaTRUE);
}
/********* END OF JFIF Code *************************************************/
/*******
*
*/
xaULONG jpg_read_SOI()
{
DEBUG_LEVEL1 fprintf(stderr,"SOI: \n");
jpg_rst_interval = 0;
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_read_SOF()
{
xaLONG len,ci;
COMPONENT_HDR *comp;
JJ_INPUT_xaSHORT(len);
if (xa_mjpg_kludge) len -= 6;
else len -= 8;
JJ_INPUT_xaBYTE(jpg_dprec);
JJ_INPUT_xaSHORT(jpg_height);
JJ_INPUT_xaSHORT(jpg_width);
JJ_INPUT_xaBYTE(jpg_num_comps);
DEBUG_LEVEL1 fprintf(stderr,"SOF: dprec %x res %d x %d comps %x\n",jpg_dprec,jpg_width,jpg_height,jpg_num_comps);
for(ci = 0; ci < jpg_num_comps; ci++)
{ xaULONG c;
if (ci > JPG_MAX_COMPS) comp = &jpg_comps[JPG_DUMMY_COMP];
else comp = &jpg_comps[ci];
JJ_INPUT_xaBYTE(comp->id);
JJ_INPUT_xaBYTE(c);
comp->hvsample = c;
JJ_INPUT_xaBYTE(comp->qtbl_num);
DEBUG_LEVEL1 fprintf(stderr," id %x hvsamp %x qtbl %x\n",comp->id,c,comp->qtbl_num);
}
return(JJ_INPUT_CHECK(0));
}
/*******
*
*/
xaULONG jpg_read_SOS()
{ xaLONG len,i;
xaLONG jpg_Ss, jpg_Se, jpg_AhAl;
JJ_INPUT_xaSHORT(len);
/* if (xa_mjpg_kludge) len += 2; length ignored */
JJ_INPUT_xaBYTE(jpg_comps_in_scan);
for (i = 0; i < jpg_comps_in_scan; i++)
{ xaLONG j,comp_id,htbl_num;
COMPONENT_HDR *comp = 0;
JJ_INPUT_xaBYTE(comp_id);
j = 0;
while(j < jpg_num_comps)
{ comp = &jpg_comps[j];
if (comp->id == comp_id) break;
j++;
}
if (j > jpg_num_comps)
{ fprintf(stderr,"JJ: bad id %x",comp_id); return(xaFALSE); }
JJ_INPUT_xaBYTE(htbl_num);
comp->dc_htbl_num = (htbl_num >> 4) & 0x0f;
comp->ac_htbl_num = (htbl_num ) & 0x0f;
DEBUG_LEVEL1 fprintf(stderr," id %x dc/ac %x\n",comp_id,htbl_num);
}
JJ_INPUT_xaBYTE(jpg_Ss);
JJ_INPUT_xaBYTE(jpg_Se);
JJ_INPUT_xaBYTE(jpg_AhAl);
return(JJ_INPUT_CHECK(0));
}
/*******
*
*/
xaULONG jpg_read_DQT()
{ xaLONG len;
JJ_INPUT_xaSHORT(len);
if ( !xa_mjpg_kludge ) len -= 2;
DEBUG_LEVEL1 fprintf(stderr,"DQT:\n");
while(len > 0)
{ xaLONG i,tbl_num,prec;
xaLONG *quant_table;
JJ_INPUT_xaBYTE(tbl_num); len -= 1;
DEBUG_LEVEL1 fprintf(stderr," prec/tnum %02x\n",tbl_num);
prec = (tbl_num >> 4) & 0x0f;
prec = (prec)?(2 * DCTSIZE2):(DCTSIZE2); /* 128 or 64 */
tbl_num &= 0x0f;
if (tbl_num > 4)
{ fprintf(stderr,"JJ: bad DQT tnum %x\n",tbl_num); return(xaFALSE); }
if (jpg_quant_tables[tbl_num] == 0)
{
jpg_quant_tables[tbl_num] = (xaLONG *)malloc(64 * sizeof(xaLONG));
if (jpg_quant_tables[tbl_num] == 0)
{ fprintf(stderr,"JJ: DQT alloc err %x \n",tbl_num); return(xaFALSE); }
}
len -= prec;
if (JJ_INPUT_CHECK(prec)==xaFALSE) return(xaFALSE);
quant_table = jpg_quant_tables[tbl_num];
if (prec==128)
{ xaULONG tmp;
for (i = 0; i < DCTSIZE2; i++)
{ JJ_INPUT_xaSHORT(tmp); quant_table[ JJ_ZAG[i] ] = (xaLONG) tmp; }
}
else
{ xaULONG tmp;
for (i = 0; i < DCTSIZE2; i++)
{ JJ_INPUT_xaBYTE(tmp); quant_table[ JJ_ZAG[i] ] = (xaLONG) tmp; }
}
}
return(xaTRUE);
}
/*******
* Handle DRI chunk
*/
xaULONG jpg_read_DRI()
{ xaLONG len;
JJ_INPUT_xaSHORT(len);
JJ_INPUT_xaSHORT(jpg_rst_interval);
DEBUG_LEVEL1 fprintf(stderr,"DRI: int %x\n",jpg_rst_interval);
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_skip_marker()
{ xaLONG len,tmp;
JJ_INPUT_xaSHORT(len);
DEBUG_LEVEL1 fprintf(stderr,"SKIP: marker %x len %x\n",jpg_marker,len);
len -= 2; if (JJ_INPUT_CHECK(len)==xaFALSE) return(xaFALSE);
while(len--) JJ_INPUT_xaBYTE(tmp); /* POD improve this */
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_read_DHT()
{
xaLONG len;
JJ_HUFF_TBL *htable;
xaUBYTE *hbits;
xaUBYTE *hvals;
jpg_std_DHT_flag = 0;
JJ_INPUT_xaSHORT(len);
if (xa_mjpg_kludge) len += 2;
len -= 2;
if (JJ_INPUT_CHECK(len)==xaFALSE) return(xaFALSE);
while(len > 0)
{ xaLONG i,index,count;
JJ_INPUT_xaBYTE(index);
/* POD index check */
if (index & 0x10) /* AC Table */
{
index &= 0x0f;
htable = &(jpg_ac_huff[index]);
hbits = jpg_ac_huff[index].bits;
hvals = jpg_ac_huff[index].vals;
}
else /* DC Table */
{
htable = &(jpg_dc_huff[index]);
hbits = jpg_dc_huff[index].bits;
hvals = jpg_dc_huff[index].vals;
}
hbits[0] = 0; count = 0;
for (i = 1; i <= 16; i++)
{
JJ_INPUT_xaBYTE(hbits[i]);
count += hbits[i];
}
len -= 17;
if (count > 256)
{ fprintf(stderr,"JJ: DHT bad count %d\n",count); return(xaFALSE); }
for (i = 0; i < count; i++) JJ_INPUT_xaBYTE(hvals[i]);
len -= count;
jpg_huff_build(htable,hbits,hvals);
} /* end of len */
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_get_marker()
{
xaLONG c;
for(;;)
{
JJ_INPUT_xaBYTE(c);
while(c != 0xFF) /* look for FF */
{
if (JJ_INPUT_CHECK(1)==xaFALSE) return(xaFALSE);
JJ_INPUT_xaBYTE(c);
}
/* now we've got 1 0xFF, keep reading until next 0xFF */
do
{
if (JJ_INPUT_CHECK(1)==xaFALSE) return(xaFALSE);
JJ_INPUT_xaBYTE(c);
} while (c == 0xFF);
if (c != 0) break; /* ignore FF/00 sequences */
}
jpg_marker = c;
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_read_markers()
{
for(;;)
{
if (jpg_get_marker() == xaFALSE) return(xaFALSE);
DEBUG_LEVEL1 fprintf(stderr,"JJ: marker %x\n",jpg_marker);
switch(jpg_marker)
{
case M_SOI:
if (jpg_read_SOI()==xaFALSE) return(xaFALSE);
jpg_saw_SOI = xaTRUE;
break;
case M_SOF0:
case M_SOF1:
if (jpg_read_SOF()==xaFALSE) return(xaFALSE);
jpg_saw_SOF = xaTRUE;
break;
case M_SOS:
if (jpg_read_SOS()==xaFALSE) return(xaFALSE);
jpg_saw_SOS = xaTRUE;
jpg_nxt_rst_num = 0;
return(xaTRUE);
break;
case M_DHT:
if (jpg_read_DHT()==xaFALSE) return(xaFALSE);
jpg_saw_DHT = xaTRUE;
break;
case M_DQT:
if (jpg_read_DQT()==xaFALSE) return(xaFALSE);
jpg_saw_DQT = xaTRUE;
break;
case M_DRI:
if (jpg_read_DRI()==xaFALSE) return(xaFALSE);
break;
case M_EOI:
fprintf(stderr,"JJ: reached EOI without data\n");
return(xaFALSE);
break;
case M_RST0: /* these are all parameterless */
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
case M_TEM:
break;
default:
if (jpg_skip_marker()==xaFALSE) return(xaFALSE);
DEBUG_LEVEL1 fprintf(stderr,"JJ: skipped marker %x\n",jpg_marker);
break;
} /* end of switch */
} /* end of forever */
}
/*****
*
*/
void jpg_huff_build(htbl,hbits,hvals)
JJ_HUFF_TBL *htbl;
xaUBYTE *hbits,*hvals;
{ xaULONG clen,num_syms,p,i,si,code,lookbits;
xaULONG l,ctr;
xaUBYTE huffsize[257];
xaULONG huffcode[257];
/*** generate code lengths for each symbol */
num_syms = 0;
for(clen = 1; clen <= 16; clen++)
{
for(i = 1; i <= (xaULONG)(hbits[clen]); i++)
huffsize[num_syms++] = (xaUBYTE)(clen);
}
huffsize[num_syms] = 0;
/*** generate codes */
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p])
{
while ( ((xaULONG)huffsize[p]) == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
/* Init mincode/maxcode/valptr arrays */
p = 0;
for (l = 1; l <= 16; l++)
{
if (htbl->bits[l])
{
htbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
p += (xaULONG)(htbl->bits[l]);
htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
}
else
{
htbl->valptr[l] = 0; /* not needed */
htbl->mincode[l] = 0; /* not needed */
htbl->maxcode[l] = 0; /* WAS -1; */ /* -1 if no codes of this length */
}
}
htbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
/* Init huffman cache */
memset((char *)htbl->cache, 0, ((1<<HUFF_LOOKAHEAD) * sizeof(xaUSHORT)) );
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++)
{
for (i = 1; i <= (xaULONG) htbl->bits[l]; i++, p++)
{ xaSHORT the_code = (xaUSHORT)((l << 8) | htbl->vals[p]);
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--)
{
htbl->cache[lookbits] = the_code;
lookbits++;
}
}
}
}
/*******
*
*/
void jpg_init_input(buff,buff_size)
xaUBYTE *buff;
xaLONG buff_size;
{
jpg_buff = buff;
jpg_bsize = buff_size;
}
/*******
*
*/
xaULONG
JFIF_Decode_JPEG(image,delta,dsize,dec_info)
xaUBYTE *image; /* Image Buffer. */
xaUBYTE *delta; /* delta data. */
xaULONG dsize; /* delta size */
XA_DEC2_INFO *dec_info; /* Decoder Info Header */
{ xaULONG imagex = dec_info->imagex; xaULONG imagey = dec_info->imagey;
xaULONG map_flag = dec_info->map_flag;
void *extra = dec_info->extra;
xaLONG base_y;
xaULONG jpg_type;
xaULONG interleave,row_offset;
dec_info->xs = dec_info->ys = 0;
dec_info->xe = imagex; dec_info->ye = imagey;
/* Indicate we can drop these frames */
if (dec_info->skip_flag > 0) return(ACT_DLTA_DROP);
jpg_type = (xaULONG)(extra);
xa_mjpg_kludge = (jpg_type & 0x40)?(0x40):(0x00);
if (jpg_init_flag==xaFALSE) jpg_init_stuff();
/* init buffer stuff */
jpg_init_input(delta,dsize);
base_y = 0;
while(base_y < imagey)
{
jpg_saw_EOI = jpg_saw_DHT = xaFALSE;
if (jpg_type & 0x10) /* IJPG/JMOV File */
{ xaLONG ci,*qtbl0,*qtbl1;
jpg_saw_SOI = jpg_saw_SOF = jpg_saw_SOS = jpg_saw_DQT = xaTRUE;
jpg_saw_EOI = xaTRUE;
if (base_y == 0) /* 1st time through */
{
jpg_huff_reset(); /* only 1st time */
jpg_width = imagex;
if (jpg_type & 0x01)
jpg_height = (imagey + 1) >> 1;/* interleaved */
else jpg_height = imagey;
jpg_comps_in_scan = jpg_num_comps = 3;
jpg_rst_interval = 0;
jpg_comps[0].hvsample = 0x21;
jpg_comps[0].ac_htbl_num = 0;
jpg_comps[0].dc_htbl_num = 0;
jpg_comps[0].qtbl_num = 0;
jpg_comps[1].hvsample = jpg_comps[2].hvsample = 0x11;
jpg_comps[1].ac_htbl_num = jpg_comps[2].ac_htbl_num = 1;
jpg_comps[1].dc_htbl_num = jpg_comps[2].dc_htbl_num = 1;
jpg_comps[1].qtbl_num = jpg_comps[2].qtbl_num = 1;
jpg_comps[0].id = 0;
jpg_comps[1].id = 1;
jpg_comps[2].id = 2;
/* IJPG set up quant tables */
if (jpg_quant_tables[0] == 0)
{
jpg_quant_tables[0] = (xaLONG *)malloc(64 * sizeof(xaLONG));
if (jpg_quant_tables[0] == 0)
{ fprintf(stderr,"JJ: IJPG DQT0 alloc err \n"); return(xaFALSE); }
}
if (jpg_quant_tables[1] == 0)
{
jpg_quant_tables[1] = (xaLONG *)malloc(64 * sizeof(xaLONG));
if (jpg_quant_tables[1] == 0)
{ fprintf(stderr,"JJ: IJPG DQT1 alloc err \n"); return(xaFALSE); }
}
qtbl0 = jpg_quant_tables[0];
qtbl1 = jpg_quant_tables[1];
for(ci=0; ci < DCTSIZE2; ci++)
{
qtbl0[ JJ_ZAG[ci] ] = (xaLONG)IJPG_Tab1[ci];
qtbl1[ JJ_ZAG[ci] ] = (xaLONG)IJPG_Tab2[ci];
}
} else jpg_saw_DHT = xaTRUE; /* 2nd time through IJPG */
if (jpg_type & 0x01) { interleave = 2; row_offset = (base_y)?(1):(0); }
else { interleave = 1; row_offset = 0; }
} else
{
/* read markers */
jpg_saw_SOI = jpg_saw_SOF = jpg_saw_SOS = jpg_saw_DHT = jpg_saw_DQT = xaFALSE;
if (jpg_read_markers() == xaFALSE) { jpg_free_stuff();
fprintf(stderr,"JPG: rd marker err\n"); return(ACT_DLTA_NOP); }
jpg_huff_reset();
interleave = (jpg_height <= ((imagey>>1)+1) )?(2):(1);
row_offset = ((interleave == 2) && (base_y == 0))?(1):(0);
}
jpg_marker = 0x00;
if (jpg_width > imagex) JPG_Alloc_MCU_Bufs(0,jpg_width,0,xaFALSE);
if ((jpg_saw_DHT != xaTRUE) && (jpg_std_DHT_flag==0))
{
DEBUG_LEVEL1 fprintf(stderr,"standard DHT tables\n");
jpg_std_DHT();
}
DEBUG_LEVEL1 fprintf(stderr,"JJ: imagexy %d %d jjxy %d %d basey %d\n",imagex,imagey,jpg_width,jpg_height,base_y);
if ( (jpg_num_comps == 3) && (jpg_comps_in_scan == 3)
&& (jpg_comps[1].hvsample == 0x11) && (jpg_comps[2].hvsample== 0x11) )
{
if (jpg_comps[0].hvsample == 0x41) /* 411 */
{ jpg_decode_411111(image,jpg_width,jpg_height,interleave,row_offset,
imagex,imagey,dec_info); }
else if (jpg_comps[0].hvsample == 0x22) /* 411 */
{ jpg_decode_221111(image,jpg_width,jpg_height,interleave,row_offset,
imagex,imagey,dec_info); }
else if (jpg_comps[0].hvsample == 0x21) /* 211 */
{ jpg_decode_211111(image,jpg_width,jpg_height,interleave,row_offset,
imagex,imagey,dec_info); }
else if (jpg_comps[0].hvsample == 0x11) /* 111 */
{ jpg_decode_111111(image,jpg_width,jpg_height,interleave,row_offset,
imagex,imagey,dec_info,0); }
else
{ fprintf(stderr,"JPG: cmps %d %d mcu %04x %04x %04x unsupported\n",
jpg_num_comps,jpg_comps_in_scan,jpg_comps[0].hvsample,
jpg_comps[1].hvsample,jpg_comps[2].hvsample);
break;
}
}
else if ( (jpg_num_comps == 1) || (jpg_comps_in_scan == 1) )
{
jpg_decode_111111(image,jpg_width,jpg_height,interleave,row_offset,
imagex,imagey,dec_info,1);
}
else
{ fprintf(stderr,"JPG: cmps %d %d mcu %04x %04x %04x unsupported.\n",
jpg_num_comps,jpg_comps_in_scan,jpg_comps[0].hvsample,
jpg_comps[1].hvsample,jpg_comps[2].hvsample);
break;
}
base_y += ((interleave == 1)?(imagey):(jpg_height));
if (jpg_marker == M_EOI) { jpg_saw_EOI = xaTRUE; jpg_marker = 0x00; }
else if (jpg_saw_EOI==xaFALSE) if (jpg_read_EOI_marker() == xaFALSE) break;
}
if (map_flag==xaTRUE) return(ACT_DLTA_MAPD);
else return(ACT_DLTA_NORM);
}
/*******
*
*/
void jpg_huff_reset()
{
jpg_comps[0].dc = 0;
jpg_comps[1].dc = 0;
jpg_comps[2].dc = 0;
jpg_h_bbuf = 0; /* clear huffman bit buffer */
jpg_h_bnum = 0;
}
/*******
*
*/
xaULONG jpg_read_EOI_marker()
{
/* POD make sure previous code restores bit buffer to input stream */
while( jpg_get_marker() == xaTRUE)
{
if (jpg_marker == M_EOI) {jpg_saw_EOI = xaTRUE; return(xaTRUE); }
}
return(xaFALSE);
}
/*******
*
*/
xaULONG jpg_read_RST_marker()
{
if ( (jpg_marker >= M_RST0) && (jpg_marker <= M_RST7) )
{
DEBUG_LEVEL1 fprintf(stderr,"JJ: RST marker %x found\n",jpg_marker);
return(xaTRUE);
}
else
{
fprintf(stderr,"JJ: NON-restart marker found %x\n",jpg_marker);
fprintf(stderr,"JJ: should resync-to-restart\n");
}
return(xaTRUE); /* POD NOTE just for now */
}
void JPG_Free_MCU_Bufs()
{
if (jpg_Ybuf) { free(jpg_Ybuf); jpg_Ybuf = 0; }
if (jpg_Ubuf) { free(jpg_Ubuf); jpg_Ubuf = 0; }
if (jpg_Vbuf) { free(jpg_Vbuf); jpg_Vbuf = 0; }
jpg_YUVBufs.Ybuf = 0; jpg_YUVBufs.Ubuf = 0; jpg_YUVBufs.Vbuf = 0;
}
/*******
*
*/
void JPG_Alloc_MCU_Bufs(anim_hdr,width,height,full_flag)
XA_ANIM_HDR *anim_hdr;
xaULONG width, height, full_flag;
{ xaULONG twidth = (width + 15) / 16;
xaULONG theight = (height + 15) / 16; if (theight & 1) theight++;
if (full_flag==xaTRUE) twidth *= (theight << 2);
else twidth <<= 2; /* four dct's deep */
DEBUG_LEVEL1 fprintf(stderr,"Alloc_MCU: wh %d %d twid %d act %d\n",
width,height,twidth,(twidth * DCTSIZE2) );
if (anim_hdr) XA_Add_Func_To_Free_Chain(anim_hdr,JPG_Free_MCU_Bufs);
if (jpg_init_flag==xaFALSE) jpg_init_stuff();
if (jpg_Ybuf == 0)
{ jpg_MCUbuf_size = twidth;
jpg_Ybuf = (xaUBYTE *)malloc(twidth * DCTSIZE2);
jpg_Ubuf = (xaUBYTE *)malloc(twidth * DCTSIZE2);
jpg_Vbuf = (xaUBYTE *)malloc(twidth * DCTSIZE2);
}
else if (twidth > jpg_MCUbuf_size)
{ jpg_MCUbuf_size = twidth;
jpg_Ybuf = (xaUBYTE *)realloc( jpg_Ybuf,(twidth * DCTSIZE2) );
jpg_Ubuf = (xaUBYTE *)realloc( jpg_Ubuf,(twidth * DCTSIZE2) );
jpg_Vbuf = (xaUBYTE *)realloc( jpg_Vbuf,(twidth * DCTSIZE2) );
}
jpg_YUVBufs.Ybuf = jpg_Ybuf;
jpg_YUVBufs.Ubuf = jpg_Ubuf;
jpg_YUVBufs.Vbuf = jpg_Vbuf;
}
#define jpg_huff_EXTEND(val,sz) \
((val) < (1<<((sz)-1)) ? (val) + (((-1)<<(sz)) + 1) : (val))
/*
* IF marker is read then jpg_marker is set and nothing more is read in.
*/
#define JJ_HBBUF_FILL8(hbbuf,hbnum) \
{ register xaULONG _tmp; \
hbbuf <<= 8; \
if (jpg_marker) return(xaFALSE); \
else { _tmp = *jpg_buff++; jpg_bsize--; } \
while(_tmp == 0xff) \
{ register xaULONG _t1; _t1 = *jpg_buff++; jpg_bsize--; \
if (_t1 == 0x00) break; \
else if (_t1 == 0xff) continue; \
else {jpg_marker = _t1; _tmp = 0x00; break;} \
} \
hbbuf |= _tmp; hbnum += 8; \
}
#define JJ_HBBUF_FILL8_1(hbbuf,hbnum) \
{ register xaULONG __tmp; \
hbbuf <<= 8; hbnum += 8; \
if (jpg_marker) __tmp = 0x00; \
else { __tmp = *jpg_buff++; jpg_bsize--; } \
while(__tmp == 0xff) \
{ register xaULONG _t1; _t1 = *jpg_buff++; jpg_bsize--; \
if (_t1 == 0x00) break; \
else if (_t1 == 0xff) continue; \
else {jpg_marker = _t1; __tmp = 0x00; break;} \
} \
hbbuf |= __tmp; \
}
#define JJ_HUFF_DECODE(huff_hdr,htbl, hbnum, hbbuf, result) \
{ register xaULONG _tmp, _hcode; \
while(hbnum < 16) JJ_HBBUF_FILL8_1(hbbuf,hbnum); \
_tmp = (hbbuf >> (hbnum - 8)) & 0xff; \
_hcode = (htbl)[_tmp]; \
if (_hcode) { hbnum -= (_hcode >> 8); (result) = _hcode & 0xff; } \
else \
{ register xaULONG _hcode, _shift, _minbits = 9; \
_tmp = (hbbuf >> (hbnum - 16)) & 0xffff; /* get 16 bits */ \
_shift = 16 - _minbits; _hcode = _tmp >> _shift; \
while(_hcode > huff_hdr->maxcode[_minbits]) \
{ _minbits++; _shift--; _hcode = _tmp >> _shift; } \
if (_minbits > 16) { fprintf(stderr,"JHDerr\n"); return(xaFALSE); } \
else \
{ hbnum -= _minbits; _hcode -= huff_hdr->mincode[_minbits]; \
result = huff_hdr->vals[ (huff_hdr->valptr[_minbits] + _hcode) ]; } \
} \
}
#define JJ_HUFF_MASK(s) ((1 << (s)) - 1)
#define JJ_GET_BITS(n, hbnum, hbbuf, result) \
{ hbnum -= n; \
while(hbnum < 0) { JJ_HBBUF_FILL8_1(hbbuf,hbnum); } \
(result) = ((hbbuf >> hbnum) & JJ_HUFF_MASK(n)); \
}
/* clears dctbuf to zeroes.
* fills from huffman encode stream
*/
xaULONG jpg_huffparse(comp, dct_buf, qtab, OBuf)
register COMPONENT_HDR *comp;
register xaSHORT *dct_buf;
xaULONG *qtab;
xaUBYTE *OBuf;
{ xaLONG i,dcval;
xaULONG size;
JJ_HUFF_TBL *huff_hdr = &(jpg_dc_huff[ comp->dc_htbl_num ]);
xaUSHORT *huff_tbl = huff_hdr->cache;
xaUBYTE *rnglimit = jpg_samp_limit + (CENTERJSAMPLE + MAXJSAMPLE + 1);
xaULONG c_cnt,pos = 0;
JJ_HUFF_DECODE(huff_hdr,huff_tbl,jpg_h_bnum,jpg_h_bbuf,size);
DEBUG_LEVEL2 fprintf(stderr," HUFF DECODE: size %d\n",size);
if (size)
{ xaULONG bits;
JJ_GET_BITS(size,jpg_h_bnum,jpg_h_bbuf,bits);
dcval = jpg_huff_EXTEND(bits, size);
comp->dc += dcval;
DEBUG_LEVEL2 fprintf(stderr," dcval %d -dc %d\n",dcval,comp->dc);
}
dcval = comp->dc;
/* clear reset of dct buffer */
memset((char *)(dct_buf),0,(DCTSIZE2 * sizeof(xaSHORT)));
dcval *= (xaLONG)qtab[0];
dct_buf[0] = (xaSHORT)dcval;
c_cnt = 0;
huff_hdr = &(jpg_ac_huff[ comp->ac_htbl_num ]);
huff_tbl = huff_hdr->cache;
i = 1;
while(i < 64)
{ xaLONG level; xaULONG run,tmp;
JJ_HUFF_DECODE(huff_hdr,huff_tbl,jpg_h_bnum,jpg_h_bbuf,tmp);
size = tmp & 0x0f;
run = (tmp >> 4) & 0x0f; /* leading zeroes */
DEBUG_LEVEL2 fprintf(stderr," %d) tmp %x size %x run %x\n",
i,tmp,size,run);
if (size)
{ xaLONG coeff;
i += run; /* skip zeroes */
JJ_GET_BITS(size, jpg_h_bnum,jpg_h_bbuf,level);
coeff = (xaLONG)jpg_huff_EXTEND(level, size);
DEBUG_LEVEL2 fprintf(stderr," size %d coeff %x\n",size,coeff);
pos = JJ_ZAG[i];
coeff *= (xaLONG)qtab[ pos ];
if (coeff)
{ c_cnt++;
dct_buf[ pos ] = (xaSHORT)(coeff);
}
i++;
}
else
{
if (run != 15) break; /* EOB */
i += 16;
}
}
if (c_cnt) j_rev_dct(dct_buf, OBuf, rnglimit);
else
{ register xaUBYTE *op = OBuf;
register int jj = 8;
xaSHORT v = *dct_buf;
register xaUBYTE dc;
v = (v < 0)?( (v-3)>>3 ):( (v+4)>>3 );
dc = rnglimit[ (int) (v & RANGE_MASK) ];
while(jj--)
{ op[0] = op[1] = op[2] = op[3] = op[4] = op[5] = op[6] = op[7] = dc;
op += 8;
}
}
return(xaTRUE);
}
/* POD since these are fixed, possibly eliminate */
#define FIX_0_298631336 ((xaLONG) 2446) /* FIX(0.298631336) */
#define FIX_0_390180644 ((xaLONG) 3196) /* FIX(0.390180644) */
#define FIX_0_541196100 ((xaLONG) 4433) /* FIX(0.541196100) */
#define FIX_0_765366865 ((xaLONG) 6270) /* FIX(0.765366865) */
#define FIX_0_899976223 ((xaLONG) 7373) /* FIX(0.899976223) */
#define FIX_1_175875602 ((xaLONG) 9633) /* FIX(1.175875602) */
#define FIX_1_501321110 ((xaLONG) 12299) /* FIX(1.501321110) */
#define FIX_1_847759065 ((xaLONG) 15137) /* FIX(1.847759065) */
#define FIX_1_961570560 ((xaLONG) 16069) /* FIX(1.961570560) */
#define FIX_2_053119869 ((xaLONG) 16819) /* FIX(2.053119869) */
#define FIX_2_562915447 ((xaLONG) 20995) /* FIX(2.562915447) */
#define FIX_3_072711026 ((xaLONG) 25172) /* FIX(3.072711026) */
/***********************************************************************
* For most steps we can mathematically guarantee that the initial value
* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
* limiting step (just after the IDCT), a wildly out-of-range value is
* possible if the input data is corrupt. To avoid any chance of indexing
* off the end of memory and getting a bad-pointer trap, we perform the
* post-IDCT limiting thus:
* x = range_limit[x & MASK];
* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
* samples. Under normal circumstances this is more than enough range and
* a correct output will be generated; with bogus input data the mask will
* cause wraparound, and we will safely generate a bogus-but-in-range output.
* For the post-IDCT step, we want to convert the data from signed to unsigned
* representation by adding CENTERJSAMPLE at the same time that we limit it.
* So the post-IDCT limiting table ends up looking like this:
* CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
* MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0,1,...,CENTERJSAMPLE-1
* Negative inputs select values from the upper half of the table after
* masking.
*
* We can save some space by overlapping the start of the post-IDCT table
* with the simpler range limiting table. The post-IDCT table begins at
* sample_range_limit + CENTERJSAMPLE.
*
* Note that the table is allocated in near data space on PCs; it's small
* enough and used often enough to justify this.
*/
void JPG_Free_Samp_Limit_Table()
{
if (jpg_samp_limit) { free(jpg_samp_limit); jpg_samp_limit = 0; }
}
void JPG_Setup_Samp_Limit_Table(anim_hdr)
XA_ANIM_HDR *anim_hdr;
{
xaUBYTE *table;
xaLONG i;
if (jpg_samp_limit==0)
{
jpg_samp_limit = (xaUBYTE *)malloc((5 * (MAXJSAMPLE+1) + CENTERJSAMPLE));
if (jpg_samp_limit==0)
{ fprintf(stderr,"JJ: samp limit malloc err\n");
return;
} /*POD note improve this */
}
else return; /* already done */
if (anim_hdr) XA_Add_Func_To_Free_Chain(anim_hdr,JPG_Free_Samp_Limit_Table);
xa_byte_limit = jpg_samp_limit + (MAXJSAMPLE + 1);
table = jpg_samp_limit;
table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
memset(table - (MAXJSAMPLE+1), 0, (MAXJSAMPLE+1));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (xaUBYTE) i;
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
memset(table + (2 * (MAXJSAMPLE+1)), 0, (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE));
memcpy(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
(char *)(jpg_samp_limit+(MAXJSAMPLE+1)), CENTERJSAMPLE);
}
/*******
*
*/
xaULONG jpg_std_DHT()
{
xaLONG ttt,len;
JJ_HUFF_TBL *htable;
xaUBYTE *hbits,*Sbits;
xaUBYTE *hvals,*Svals;
static xaUBYTE dc_luminance_bits[17] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
static xaUBYTE dc_luminance_vals[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static xaUBYTE dc_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static xaUBYTE dc_chrominance_vals[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static xaUBYTE ac_luminance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static xaUBYTE ac_luminance_vals[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static xaUBYTE ac_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static xaUBYTE ac_chrominance_vals[] =
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
for(ttt=0;ttt<4;ttt++)
{ xaULONG index = ttt & 1;
xaLONG i,count;
if (ttt <= 1) /* DC tables */
{
htable = &(jpg_dc_huff[index]);
hbits = jpg_dc_huff[index].bits;
hvals = jpg_dc_huff[index].vals;
if (index==0) { Sbits = dc_luminance_bits; Svals = dc_luminance_vals; }
else { Sbits = dc_chrominance_bits; Svals = dc_chrominance_vals; }
}
else /* AC tables */
{
htable = &(jpg_ac_huff[index]);
hbits = jpg_ac_huff[index].bits;
hvals = jpg_ac_huff[index].vals;
if (index==0) { Sbits = ac_luminance_bits; Svals = ac_luminance_vals; }
else { Sbits = ac_chrominance_bits; Svals = ac_chrominance_vals; }
}
hbits[0] = 0; count = 0;
for (i = 1; i <= 16; i++)
{
hbits[i] = Sbits[i];
count += hbits[i];
}
len -= 17;
if (count > 256)
{ fprintf(stderr,"JJ: STD DHT bad count %d\n",count); return(xaFALSE); }
for (i = 0; i < count; i++) hvals[i] = Svals[i];
len -= count;
jpg_huff_build(htable,hbits,hvals);
} /* end of i */
jpg_std_DHT_flag = 1;
return(xaTRUE);
}
xaULONG jpg_search_marker(marker,data_ptr,data_size)
xaULONG marker;
xaUBYTE **data_ptr;
xaLONG *data_size;
{ xaULONG d = 0;
xaUBYTE *dptr = *data_ptr;
xaLONG dsize = *data_size;
while( dsize )
{
if (d == 0xff) /* potential marker */
{
d = *dptr++; dsize--;
if (d == marker)
{
*data_size = dsize; *data_ptr = dptr;
return(xaTRUE); /* found marker */
}
} else { d = *dptr++; dsize--; }
}
*data_size = dsize; *data_ptr = dptr;
return(xaFALSE);
}
void JFIF_Read_IJPG_Tables(xin)
XA_INPUT *xin;
{ int i;
for(i=0;i<64;i++) IJPG_Tab1[i] = xin->Read_U8(xin);
for(i=0;i<64;i++) IJPG_Tab2[i] = xin->Read_U8(xin);
}
static char std_luminance_quant_tbl[64] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static char std_chrominance_quant_tbl[64] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
void JFIF_Init_IJPG_Tables(qfactor)
int qfactor;
{ int i;
for(i=0;i<64;i++) IJPG_Tab1[i] = qfactor * std_luminance_quant_tbl[i];
for(i=0;i<64;i++) IJPG_Tab2[i] = qfactor * std_chrominance_quant_tbl[i];
}
#define JPG_HANDLE_RST(rst_int,rst_cnt) { \
if ( ((rst_int) && (rst_cnt==0)) /* || (jpg_marker)*/ ) \
{ jpg_h_bbuf = 0; jpg_h_bnum = 0; \
DEBUG_LEVEL1 fprintf(stderr," jRST_INT %d rst_cnt %d\n", rst_int,rst_cnt);\
if (jpg_marker) \
{ DEBUG_LEVEL1 fprintf(stderr," jpg_marker(%x)\n",jpg_marker); \
if (jpg_marker == M_EOI) { jpg_saw_EOI = xaTRUE; return(xaTRUE); } \
else if ( !((jpg_marker >= M_RST0) && (jpg_marker <= M_RST7))) \
{fprintf(stderr,"JPEG: unexp marker(%x)\n",jpg_marker); return(xaFALSE);}\
jpg_marker = 0; \
} else if (jpg_read_RST_marker()==xaFALSE) \
{ fprintf(stderr,"RST marker false\n"); return(xaFALSE); } \
jpg_comps[0].dc = jpg_comps[1].dc = jpg_comps[2].dc = 0; \
rst_cnt = rst_int; \
} else rst_cnt--; }
#define JPG_TST_MARKER(rst_int,rst_cnt) { \
if (jpg_marker) \
{ DEBUG_LEVEL1 fprintf(stderr," jpg_marker(%x)\n",jpg_marker); \
if (jpg_marker == M_EOI) { jpg_saw_EOI = xaTRUE; \
/* return(xaTRUE); */ } \
else if ( !((jpg_marker >= M_RST0) && (jpg_marker <= M_RST7))) \
{fprintf(stderr,"JPEG: unexp marker(%x)\n",jpg_marker); return(xaFALSE);}\
else { \
jpg_comps[0].dc = jpg_comps[1].dc = jpg_comps[2].dc = 0; \
rst_cnt = rst_int; \
jpg_marker = 0; \
jpg_h_bbuf = 0; jpg_h_bnum = 0; } \
} }
/*******
*
*/
xaULONG jpg_decode_111111(image,width,height,interleave,row_offset,
imagex,imagey,dec_info,gray)
xaUBYTE *image;
xaULONG width,height,interleave,row_offset;
xaULONG imagex,imagey;
XA_DEC2_INFO *dec_info;
xaULONG gray;
{
xaUBYTE *iptr = image;
xaULONG map_flag = dec_info->map_flag;
xaULONG *map = dec_info->map;
XA_CHDR *chdr = dec_info->chdr;
xaULONG x,mcu_cols,mcu_rows;
xaLONG *qtab0,*qtab1,*qtab2;
xaUBYTE *Ybuf,*Ubuf,*Vbuf;
xaULONG rst_count;
xaULONG orow_size = imagex * dec_info->bytes_pixel;
void (*color_func)();
if (chdr) { if (chdr->new_chdr) chdr = chdr->new_chdr; }
if (gray) color_func = XA_MCU111111_To_Gray;
else color_func = (void (*)())XA_MCU111111_Func(dec_info->image_type);
if (row_offset) iptr += row_offset * orow_size;
orow_size *= interleave;
if (interleave == 2) imagey >>= 1;
qtab0 = jpg_quant_tables[ jpg_comps[0].qtbl_num ];
qtab1 = jpg_quant_tables[ jpg_comps[1].qtbl_num ];
qtab2 = jpg_quant_tables[ jpg_comps[2].qtbl_num ];
mcu_cols = (width + 7) / 8;
mcu_rows = (height + 7) / 8;
DEBUG_LEVEL1 fprintf(stderr,"111111 begin MCUS(%d,%d)\n",mcu_cols,mcu_rows);
jpg_marker = 0x00;
rst_count = jpg_rst_interval;
while(mcu_rows--)
{
Ybuf = jpg_YUVBufs.Ybuf; Ubuf = jpg_YUVBufs.Ubuf; Vbuf = jpg_YUVBufs.Vbuf;
x = mcu_cols;
while(x--)
{
DEBUG_LEVEL1 fprintf(stderr," MCU XY(%d,%d)\n",x,mcu_rows);
JPG_HANDLE_RST(jpg_rst_interval,rst_count);
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
if (gray==0)
{
jpg_huffparse(&jpg_comps[1],jpg_dct_buf,qtab1,Ubuf); Ubuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[2],jpg_dct_buf,qtab2,Vbuf); Vbuf += DCTSIZE2;
}
JPG_TST_MARKER(jpg_rst_interval,rst_count);
} /* end of mcu_cols */
DEBUG_LEVEL1 fprintf(stderr,"imagey %d\n",imagey);
(void)(color_func)(iptr,imagex,xaMIN(imagey,8),(mcu_cols * DCTSIZE2),
orow_size, &jpg_YUVBufs,&def_yuv_tabs, map_flag,map,chdr);
imagey -= 8; iptr += (orow_size << 3);
} /* end of mcu_rows */
if (jpg_marker) { jpg_h_bbuf = 0; jpg_h_bnum = 0; }
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_decode_211111(image,width,height,interleave,row_offset,
imagex,imagey,dec_info)
xaUBYTE *image;
xaULONG width,height,interleave,row_offset;
xaULONG imagex,imagey;
XA_DEC2_INFO *dec_info;
{
xaUBYTE *iptr = image;
xaULONG map_flag = dec_info->map_flag;
xaULONG *map = dec_info->map;
XA_CHDR *chdr = dec_info->chdr;
xaULONG x,mcu_cols,mcu_rows;
xaLONG *qtab0,*qtab1,*qtab2;
xaUBYTE *Ybuf,*Ubuf,*Vbuf;
xaULONG rst_count;
xaULONG orow_size = imagex * dec_info->bytes_pixel;
void (*color_func)() = (void (*)())XA_MCU211111_Func(dec_info->image_type);
if (chdr) { if (chdr->new_chdr) chdr = chdr->new_chdr; }
if (row_offset) iptr += row_offset * orow_size;
orow_size *= interleave;
if (interleave == 2) imagey >>= 1;
imagex++; imagex >>= 1;
qtab0 = jpg_quant_tables[ jpg_comps[0].qtbl_num ];
qtab1 = jpg_quant_tables[ jpg_comps[1].qtbl_num ];
qtab2 = jpg_quant_tables[ jpg_comps[2].qtbl_num ];
mcu_cols = (width + 15) / 16;
mcu_rows = (height + 7) / 8;
DEBUG_LEVEL1 fprintf(stderr,"211111 begin MCUS(%d,%d)\n",mcu_cols,mcu_rows);
jpg_marker = 0x00;
rst_count = jpg_rst_interval;
while(mcu_rows--)
{
Ybuf = jpg_YUVBufs.Ybuf; Ubuf = jpg_YUVBufs.Ubuf; Vbuf = jpg_YUVBufs.Vbuf;
x = mcu_cols;
while(x--)
{ /* DEBUG_LEVEL1 fprintf(stderr,"MCU XY(%d,%d)\n", x,mcu_rows); */
JPG_HANDLE_RST(jpg_rst_interval,rst_count);
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[1],jpg_dct_buf,qtab1,Ubuf); Ubuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[2],jpg_dct_buf,qtab2,Vbuf); Vbuf += DCTSIZE2;
JPG_TST_MARKER(jpg_rst_interval,rst_count);
} /* end of mcu_cols */
(void)(color_func)(iptr,imagex,xaMIN(imagey,8),(mcu_cols * DCTSIZE2),
orow_size, &jpg_YUVBufs,&def_yuv_tabs, map_flag,map,chdr);
imagey -= 8; iptr += (orow_size << 3);
} /* end of mcu_rows */
if (jpg_marker) { jpg_h_bbuf = 0; jpg_h_bnum = 0; }
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_decode_221111(image,width,height,interleave,row_offset,
imagex,imagey,dec_info)
xaUBYTE *image;
xaULONG width,height,interleave,row_offset;
xaLONG imagex,imagey;
XA_DEC2_INFO *dec_info;
{ xaUBYTE *iptr = image;
xaULONG map_flag = dec_info->map_flag;
xaULONG *map = dec_info->map;
XA_CHDR *chdr = dec_info->chdr;
xaLONG x,mcu_cols,mcu_rows;
xaLONG *qtab0,*qtab1,*qtab2;
xaUBYTE *Ybuf,*Ubuf,*Vbuf;
xaULONG rst_count;
void (*color_func)() = (void (*)())XA_MCU221111_Func(dec_info->image_type);
xaULONG orow_size = imagex * dec_info->bytes_pixel;
if (chdr) { if (chdr->new_chdr) chdr = chdr->new_chdr; }
if (row_offset) iptr += row_offset * orow_size;
orow_size *= interleave;
if (interleave == 2) imagey >>= 1;
imagex++; imagex >>= 1; /* 2h */
qtab0 = jpg_quant_tables[ jpg_comps[0].qtbl_num ];
qtab1 = jpg_quant_tables[ jpg_comps[1].qtbl_num ];
qtab2 = jpg_quant_tables[ jpg_comps[2].qtbl_num ];
mcu_cols = (width + 15) / 16;
mcu_rows = (height + 15) / 16;
DEBUG_LEVEL1 fprintf(stderr,"221111 begin MCUS(%d,%d)\n",mcu_cols,mcu_rows);
jpg_marker = 0x00;
rst_count = jpg_rst_interval;
while(mcu_rows--)
{ Ybuf = jpg_YUVBufs.Ybuf; Ubuf = jpg_YUVBufs.Ubuf; Vbuf = jpg_YUVBufs.Vbuf;
x = mcu_cols; while(x--)
{ DEBUG_LEVEL1 fprintf(stderr," MCU XY(%d,%d)\n",x,mcu_rows);
JPG_HANDLE_RST(jpg_rst_interval,rst_count);
/* Y0 Y1 Y2 Y3 U V */
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[1],jpg_dct_buf,qtab1,Ubuf); Ubuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[2],jpg_dct_buf,qtab2,Vbuf); Vbuf += DCTSIZE2;
JPG_TST_MARKER(jpg_rst_interval,rst_count);
} /* end of mcu_cols */
(void)(color_func)(iptr,imagex,xaMIN(imagey,16),(mcu_cols * DCTSIZE2),orow_size,
&jpg_YUVBufs,&def_yuv_tabs,map_flag,map,chdr);
imagey -= 16; iptr += (orow_size << 4);
} /* end of mcu_rows */
if (jpg_marker) { jpg_h_bbuf = 0; jpg_h_bnum = 0; }
DEBUG_LEVEL1 fprintf(stderr,"411: done\n");
return(xaTRUE);
}
/*******
*
*/
xaULONG jpg_decode_411111(image,width,height,interleave,row_offset,
imagex,imagey,dec_info)
xaUBYTE *image;
xaULONG width,height,interleave,row_offset;
xaLONG imagex,imagey;
XA_DEC2_INFO *dec_info;
{ xaUBYTE *iptr = image;
xaULONG map_flag = dec_info->map_flag;
xaULONG *map = dec_info->map;
XA_CHDR *chdr = dec_info->chdr;
xaLONG x,mcu_cols,mcu_rows;
xaLONG *qtab0,*qtab1,*qtab2;
xaUBYTE *Ybuf,*Ubuf,*Vbuf;
xaULONG rst_count;
xaULONG orow_size = imagex * dec_info->bytes_pixel;
void (*color_func)() = (void (*)())XA_MCU411111_Func(dec_info->image_type);
if (chdr) { if (chdr->new_chdr) chdr = chdr->new_chdr; }
if (row_offset) iptr += row_offset * orow_size;
orow_size *= interleave;
if (interleave == 2) imagey >>= 1;
imagex +=3; imagex >>= 2; /* 4h */
qtab0 = jpg_quant_tables[ jpg_comps[0].qtbl_num ];
qtab1 = jpg_quant_tables[ jpg_comps[1].qtbl_num ];
qtab2 = jpg_quant_tables[ jpg_comps[2].qtbl_num ];
mcu_cols = (width + 31) / 32;
mcu_rows = (height + 7) / 8;
DEBUG_LEVEL1 fprintf(stderr,"411111 begin MCUS(%d,%d)\n",mcu_cols,mcu_rows);
jpg_marker = 0x00;
rst_count = jpg_rst_interval;
while(mcu_rows--)
{ Ybuf = jpg_YUVBufs.Ybuf; Ubuf = jpg_YUVBufs.Ubuf; Vbuf = jpg_YUVBufs.Vbuf;
x = mcu_cols; while(x--)
{ DEBUG_LEVEL1 fprintf(stderr," MCU XY(%d,%d)\n",x,mcu_rows);
JPG_HANDLE_RST(jpg_rst_interval,rst_count);
/* Y0 Y1 Y2 Y3 U V */
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[0],jpg_dct_buf,qtab0,Ybuf); Ybuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[1],jpg_dct_buf,qtab1,Ubuf); Ubuf += DCTSIZE2;
jpg_huffparse(&jpg_comps[2],jpg_dct_buf,qtab2,Vbuf); Vbuf += DCTSIZE2;
JPG_TST_MARKER(jpg_rst_interval,rst_count);
} /* end of mcu_cols */
(void)(color_func)(iptr,imagex,xaMIN(imagey,8),(mcu_cols * DCTSIZE2),orow_size,
&jpg_YUVBufs,&def_yuv_tabs,map_flag,map,chdr);
imagey -= 8; iptr += (orow_size << 3);
} /* end of mcu_rows */
if (jpg_marker) { jpg_h_bbuf = 0; jpg_h_bnum = 0; }
DEBUG_LEVEL1 fprintf(stderr,"411: done\n");
return(xaTRUE);
}