📄 hpbit_stream_out.c
字号:
}
/*****************************************************************************/
/* STATIC get_tile_component_bands */
/*****************************************************************************/
static int
get_tile_component_bands(hpbit_stream_out_ref self, int tnum, int comp_idx,
int num_levels)
/* This function computes the total number of bands for the relevant
tile-component based on the number of decomposition levels and any
special decomposition structure. */
{
int length, hp_descent, num_bands, n;
length = (int)
self->base.size_marker_elt(&(self->base),tnum,MARKER_COC_DECOMP,comp_idx);
if (length == 0)
return(3*num_levels+1); /* Mallat decomposition. */
num_bands = 1;
hp_descent = 0;
for (n=0; n < num_levels; n++)
{
if (n < length)
hp_descent = (int)
self->base.get_marker_val(&(self->base),tnum,MARKER_COC_DECOMP,
comp_idx,n);
if (hp_descent == 1)
num_bands += 3;
else if (hp_descent == 2)
num_bands += 12;
else if (hp_descent == 3)
num_bands += 48;
else
num_bands += 3; /* Error; use Mallat as default. */
}
return(num_bands);
}
/*****************************************************************************/
/* STATIC translate_cod_coc_markers */
/*****************************************************************************/
static void
translate_cod_coc_markers(hpbit_stream_out_ref self,
hpbit_markers_ptr markers)
/* Converts COD/COD markers onto the `markers->pre_markers' list into
codestream markers, which it adds to the `markers->codestream_markers'
list. Attempts to form a minimal number of COC codestream markers by
creating a COD marker whose parameters are common to as many components
as possible. If translation is successful, the function sets the
`translated' flag in the relevant `hpbit_pre_marker' structure.
Otherwise, the function returns without creating the codestream markers
and an appropriate non-standard generic marker will be created instead.
Note: all coding parameters collected in `markers->params' are accurate
and available for error checking and codestream marker formation. There
should be no need to store further coding parameters. Note also that
redundancies between the global and tile headers should already have
been removed. In fact, you will find that the COD and COC pre-markers
are all connected via the `link_next' and `link_prev' fields, although
not in any particular order. */
{
/* MJG - need to find all COD/COC premarkers and handle jointly*/
/* if we can't write a COC we should not write the COD because
the decoder isn't designed to get some info from a COD and some
from a premarker */
hpbit_pre_marker_ptr pm;
hpbit_marker_elt_ptr elt, cod_ppx, cod_ppy, coc_ppx, coc_ppy;
cod_marker cod;
coc_marker coc;
std_byte *buf, *bp, ppxy;
int length, i;
int valid;
cod_ppx = NULL;
cod_ppy = NULL;
coc_ppx = NULL;
coc_ppy = NULL;
/* first check */
for (pm=markers->pre_markers; pm != NULL; pm = pm->next)
{
if (pm->translated)
continue;
if (pm->id == (MARKER_COD & 0x00FF)) {
valid = 1;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_COD_PROG:
case ELTID_COD_LAYERS:
valid = (elt->size == 1); break;
case ELTID_COD_SOP:
valid = (elt->size <= 1); break;
case ELTID_COD_EPH:
valid = (elt->size <= 1); break;
case ELTID_COD_CXFORM:
valid = (elt->size <= 1); break;
default: valid = 0;
local_printf(5,72,"Got COD %d will use premarker",elt->element_id);
}
if (!valid)
return;
} else if (pm->id == (MARKER_COC & 0x00FF)) {
valid = 1;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_COC_LEVELS:
valid = (elt->size == 1); break;
case ELTID_COC_XCB:
valid = (elt->size == 1); break;
case ELTID_COC_YCB:
valid = (elt->size == 1); break;
case ELTID_COC_MOD:
valid = (elt->size == 1); break;
case ELTID_COC_REV:
valid = (elt->size == 1); break;
case ELTID_COC_PPX:
valid = 1; break;
case ELTID_COC_PPY:
valid = 1; break;
default: valid = 0;
local_printf(5,72,"Got COC %d will use premarker",elt->element_id);
}
if (!valid)
return;
}
}
/* Now Encode */
/* Grab cod only info */
for (pm=markers->pre_markers; pm != NULL; pm = pm->next)
{
if (pm->translated)
continue;
if (pm->id == (MARKER_COD & 0x00FF)) {
memset(&cod,0,sizeof(cod_marker));
valid = 1;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_COD_PROG:
valid = (elt->size == 1); cod.prog = (std_byte)(elt->buf[0]);
break;
case ELTID_COD_LAYERS:
valid = (elt->size == 1); cod.layers = (std_ushort)(elt->buf[0]);
break;
case ELTID_COD_SOP:
if (elt->size && elt->buf[0])
cod.Scod |= 2;
else
cod.Scod &= ~2;
break;
case ELTID_COD_EPH:
if (elt->size && elt->buf[0])
cod.Scod |= 4;
else
cod.Scod &= ~4;
break;
case ELTID_COD_CXFORM:
if (elt->size) {
cod.cxform = (std_byte)(elt->buf[0]);
if(cod.cxform == 2) cod.cxform = 1;
}
break;
default: valid = 0;
local_printf(5,72,"Got COD %d don't understand it",elt->element_id);
}
if (!valid)
return;
pm->translated = 1; /* not yet, but it will be */
}
}
/* Now write a COD with component 0 parameters */
for (pm=markers->pre_markers; pm != NULL; pm = pm->next)
{
if (pm->translated)
continue;
else if (pm->id == (MARKER_COC & 0x00FF)) {
memset(&coc,0,sizeof(coc_marker));
if (pm->instance != 0) continue;
valid = 1;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_COC_LEVELS:
valid = (elt->size == 1); cod.level = (std_byte)(elt->buf[0]); break;
case ELTID_COC_XCB:
valid = (elt->size == 1); cod.xcb = (std_byte)(elt->buf[0]); break;
case ELTID_COC_YCB:
valid = (elt->size == 1); cod.ycb = (std_byte)(elt->buf[0]); break;
case ELTID_COC_MOD:
valid = (elt->size == 1); cod.mod = (std_byte)(elt->buf[0]); break;
case ELTID_COC_REV:
valid = (elt->size == 1); cod.rev = (std_byte)(elt->buf[0]); break;
case ELTID_COC_PPX:
cod.Scod |= 1;
valid = (elt->size == cod.level + 1);
cod_ppx = elt; break;
case ELTID_COC_PPY:
cod.Scod |= 1;
valid = (elt->size == cod.level + 1);
cod_ppy = elt; break;
default: valid = 0;
local_printf(5,72,"Got COC %d don't understand it",elt->element_id);
}
length = 14;
if (cod.Scod & 1)
length += (cod.level + 1);
cod.COD = MARKER_COD;
cod.Lcod = length - 2;
bp = buf = (std_byte *) local_malloc(HPBIT_MEM_KEY,length);
copy_to_big_endian(&(cod.COD),bp,2,2); bp += 2*2;
*(bp++) = cod.Scod;
*(bp++) = cod.prog;
copy_to_big_endian(&(cod.layers),bp,1,2); bp += 1*2;
*(bp++) = cod.cxform;
*(bp++) = cod.level;
*(bp++) = cod.xcb;
*(bp++) = cod.ycb;
*(bp++) = cod.mod;
*(bp++) = cod.rev;
if (cod.Scod & 1) {
for(i=0;i<cod.level + 1;i++){
ppxy = (std_byte) (cod_ppy->buf[i] << 4);
ppxy |= (std_byte) (cod_ppx->buf[i] & 0x0f);
*(bp++) = (std_byte) ppxy;
}
}
add_codestream_marker(markers,buf,length,pm->instance,0);
pm->translated = 1;
}
}
/* Now encode each component COC that is different*/
for (pm=markers->pre_markers; pm != NULL; pm = pm->next)
{
if (pm->translated)
continue;
else if (pm->id == (MARKER_COC & 0x00FF)) {
memset(&coc,0,sizeof(coc_marker));
valid = 1;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_COC_LEVELS:
valid = (elt->size == 1); coc.level = (std_byte)(elt->buf[0]); break;
case ELTID_COC_XCB:
valid = (elt->size == 1); coc.xcb = (std_byte)(elt->buf[0]); break;
case ELTID_COC_YCB:
valid = (elt->size == 1); coc.ycb = (std_byte)(elt->buf[0]); break;
case ELTID_COC_MOD:
valid = (elt->size == 1); coc.mod = (std_byte)(elt->buf[0]); break;
case ELTID_COC_REV:
valid = (elt->size == 1); coc.rev = (std_byte)(elt->buf[0]); break;
case ELTID_COC_PPX:
coc.Scoc |= 1;
valid = (elt->size == coc.level + 1);
coc_ppx = elt; break;
case ELTID_COC_PPY:
coc.Scoc |= 1;
valid = (elt->size == coc.level + 1);
coc_ppy = elt; break;
default: valid = 0;
local_printf(5,72,"Got COC %d don't understand it",elt->element_id);
}
if (!valid)
return;
if ( (coc.level != cod.level) ||
(coc.xcb != cod.xcb) ||
(coc.ycb != cod.ycb) ||
(coc.mod != cod.mod) ||
(coc.rev != cod.rev) ||
((coc_ppx != NULL) && (coc_ppx != cod_ppx)) || /* Ricoh PPX bug fix */
((coc_ppy != NULL) && (coc_ppy != cod_ppy)) || /* Ricoh PPY bug fix */
((coc.Scoc&1) != (cod.Scod&1)) )
{
length = 11;
if (coc.Scoc & 1 ) /* packet partition */
length += coc.level + 1; /* Ricoh PPX/PPY bug fix */
if (markers->params.num_components > 255)
length++;
coc.COC = MARKER_COC;
coc.Lcoc = length -2;
coc.Ccoc = pm->instance;
bp = buf = (std_byte *) local_malloc(HPBIT_MEM_KEY,length);
copy_to_big_endian(&(coc.COC),bp,2,2); bp += 2*2;
if (markers->params.num_components > 255)
{
*(bp++) = (std_byte) (coc.Ccoc >> 8); /* J. Kasner fix w/ () */
}
*(bp++) = (std_byte) (coc.Ccoc & 0xff); /* J. Kasner fix w/ () */
*(bp++) = coc.Scoc;
*(bp++) = coc.level;
*(bp++) = coc.xcb;
*(bp++) = coc.ycb;
*(bp++) = coc.mod;
*(bp++) = coc.rev;
if (coc.Scoc & 1) {
for(i=0;i<coc.level+1;i++){ /* Ricoh PPX/PPY bug fix */
ppxy = (std_byte) (coc_ppy->buf[i] << 4);
ppxy |= (std_byte) (coc_ppx->buf[i] & 0x0f);
*(bp++) = (std_byte) ppxy;
}
}
add_codestream_marker(markers,buf,length,pm->instance,0);
}
/* mark translated even if we didn't write because it matches COD */
pm->translated = 1;
}
}
}
/*****************************************************************************/
/* STATIC translate_qcd_qcc_markers */
/*****************************************************************************/
static void
translate_qcd_qcc_markers(hpbit_stream_out_ref self,
hpbit_markers_ptr markers)
/* Converts QCD/QCC markers onto the `markers->pre_markers' list into
codestream markers, which it adds to the `markers->codestream_markers'
list. Attempts to form a minimal number of QCCC codestream markers by
creating a QCD marker whose parameters are common to as many components
as possible. If translation is successful, the function sets the
`translated' flag in the relevant `hpbit_pre_marker' structure.
Otherwise, the function returns without creating the codestream markers
and an appropriate non-standard generic marker will be created instead.
Note: all coding parameters collected in `markers->params' are accurate
and available for error checking and codestream marker formation. There
should be no need to store further coding parameters. Note also that
redundancies between the global and tile headers should already have
been removed. In fact, you will find that the QCD and QCC pre-markers
are all connected via the `link_next' and `link_prev' fields, although
not in any particular order. */
{
hpbit_pre_marker_ptr pm;
qcc_marker qcc;
/* RSV mjg - Make sure QCD/QCC data is part I */
int valid = 1;
/* J. Kasner fix #components > 256 fix */
int short_components;
short_components = (markers->params.num_components >= 256)? 1:0;
for (pm=markers->pre_markers; pm != NULL; pm = pm->next)
{
if (pm->translated)
continue;
else if (pm->id == (MARKER_QCD & 0x00FF)) {
hpbit_marker_elt_ptr elt;
for (elt=pm->elements; elt != NULL && valid; elt=elt->next)
switch ((char)(elt->element_id)) {
case ELTID_QCD_WHICH:
valid = (elt->size == 1) && (elt->buf[0] == 0);
break;
default: valid = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -