typedefstruct { struct jpeg_d_main_controller pub; /* public fields */
/* Pointer to allocated workspace (M or M+2 row groups). */
JSAMPARRAY buffer[MAX_COMPONENTS];
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
/* Remaining fields are only used in the context case. */
/* These are the master pointers to the funny-order pointer lists. */
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
} my_main_controller;
typedef my_main_controller * my_main_ptr;
/* context_state values: */ #define CTX_PREPARE_FOR_IMCU 0/* need to prepare for MCU row */ #define CTX_PROCESS_IMCU 1/* feeding iMCU to postprocessor */ #define CTX_POSTPONED_ROW 2/* feeding postponed row group */
LOCAL(void)
alloc_funny_pointers (j_decompress_ptr cinfo) /* Allocate space for the funny pointer lists. *Thisisdoneonlyonce,notonceperpass.
*/
{
my_main_ptr _main = (my_main_ptr) cinfo->main; int ci, rgroup; int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
/* Get top-level space for component array pointers. *Weallocbotharrayswithonecalltosaveafewcycles.
*/
_main->xbuffer[0] = (JSAMPIMAGE)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
_main->xbuffer[1] = _main->xbuffer[0] + cinfo->num_components;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. *Weallocbothpointerlistswithonecalltosaveafewcycles.
*/
xbuf = (JSAMPARRAY)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
xbuf += rgroup; /* want one row group at negative offsets */
_main->xbuffer[0][ci] = xbuf;
xbuf += rgroup * (M + 4);
_main->xbuffer[1][ci] = xbuf;
}
}
LOCAL(void)
make_funny_pointers (j_decompress_ptr cinfo) /* Create the funny pointer lists discussed in the comments above. *Theactualworkspaceisalreadyallocated(inmain->buffer), *andthespaceforthepointerlistsisallocatedtoo. *Thisroutinejustfillsinthecuriouslyorderedlists. *Thiswillberepeatedatthebeginningofeachpass.
*/
{
my_main_ptr _main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY buf, xbuf0, xbuf1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
xbuf0 = _main->xbuffer[0][ci];
xbuf1 = _main->xbuffer[1][ci]; /* First copy the workspace pointers as-is */
buf = _main->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) {
xbuf0[i] = xbuf1[i] = buf[i];
} /* In the second list, put the last four row groups in swapped order */ for (i = 0; i < rgroup * 2; i++) {
xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
} /* The wraparound pointers at top and bottom will be filled later *(seeset_wraparound_pointers,below).Initiallywewantthe"above" *pointerstoduplicatethefirstactualdataline.Thisonlyneeds *tohappeninxbuffer[0].
*/ for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[0];
}
}
}
LOCAL(void)
set_wraparound_pointers (j_decompress_ptr cinfo) /* Set up the "wraparound" pointers at top and bottom of the pointer lists. *Thischangesthepointerliststatefromtop-of-imagetothenormalstate.
*/
{
my_main_ptr _main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY xbuf0, xbuf1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
xbuf0 = _main->xbuffer[0][ci];
xbuf1 = _main->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
}
}
}
LOCAL(void)
set_bottom_pointers (j_decompress_ptr cinfo) /* Change the pointer lists to duplicate the last sample row at the bottom *oftheimage.whichptrindicateswhichxbufferholdsthefinaliMCUrow. *Alsosetsrowgroups_availtoindicatenumberofnondummyrowgroupsinrow.
*/
{
my_main_ptr _main = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) { /* Count sample rows in one iMCU row and in one row group */
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
rgroup = iMCUheight / cinfo->min_DCT_scaled_size; /* Count nondummy sample rows remaining for this component */
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; /* Count nondummy row groups. Should get same answer for each component, *soweneedonlydoitonce.
*/ if (ci == 0) {
_main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
} /* Duplicate the last real sample row rgroup*2 times; this pads out the *lastpartialrowgroupandensuresatleastonefullrowgroupofcontext.
*/
xbuf = _main->xbuffer[_main->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) {
xbuf[rows_left + i] = xbuf[rows_left-1];
}
}
}
/* Read input data if we haven't filled the main buffer yet */ if (! _main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, _main->buffer)) return; /* suspension forced, can do nothing more */
_main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; /* Note: at the bottom of the image, we may pass extra garbage row groups *tothepostprocessor.Thepostprocessorhastocheckforbottom *ofimageanyway(atrowresolution),sonopointinusdoingittoo.
*/
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (_main->rowgroup_ctr >= rowgroups_avail) {
_main->buffer_full = FALSE;
_main->rowgroup_ctr = 0;
}
}
/* Read input data if we haven't filled the _main buffer yet */ if (! _main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo,
_main->xbuffer[_main->whichptr])) return; /* suspension forced, can do nothing more */
_main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
_main->iMCU_row_ctr++; /* count rows received */
}
/* Postprocessor typically will not swallow all the input data it is handed *inonecall(duetofillingtheoutputbufferfirst).Mustbeprepared *toexitandrestart.Thisswitchletsuskeeptrackofhowfarwegot. *Notethateachcasefallsthroughtothenextonsuccessfulcompletion.
*/ switch (_main->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */
(*cinfo->post->post_process_data) (cinfo, _main->xbuffer[_main->whichptr],
&_main->rowgroup_ctr, _main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail); if (_main->rowgroup_ctr < _main->rowgroups_avail) return; /* Need to suspend */
_main->context_state = CTX_PREPARE_FOR_IMCU; if (*out_row_ctr >= out_rows_avail) return; /* Postprocessor exactly filled output buf */ /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */
_main->rowgroup_ctr = 0;
_main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" *thelastsamplerow,andadjustrowgroups_availtoignorepaddingrows.
*/ if (_main->iMCU_row_ctr == cinfo->total_iMCU_rows)
set_bottom_pointers(cinfo);
_main->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */
(*cinfo->post->post_process_data) (cinfo, _main->xbuffer[_main->whichptr],
&_main->rowgroup_ctr, _main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail); if (_main->rowgroup_ctr < _main->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ if (_main->iMCU_row_ctr == 1)
set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */
_main->whichptr ^= 1; /* 0=>1 or 1=>0 */
_main->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */
_main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
_main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
_main->context_state = CTX_POSTPONED_ROW;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.