📄 jpc_dec.c
字号:
/* * Copyright (c) 1999-2000 Image Power, Inc. and the University of * British Columbia. * Copyright (c) 2001-2003 Michael David Adams. * All rights reserved. *//* __START_OF_JASPER_LICENSE__ * * JasPer License Version 2.0 * * Copyright (c) 1999-2000 Image Power, Inc. * Copyright (c) 1999-2000 The University of British Columbia * Copyright (c) 2001-2003 Michael David Adams * * All rights reserved. * * Permission is hereby granted, free of charge, to any person (the * "User") obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * 1. The above copyright notices and this permission notice (which * includes the disclaimer below) shall be included in all copies or * substantial portions of the Software. * * 2. The name of a copyright holder shall not be used to endorse or * promote products derived from the Software without specific prior * written permission. * * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. * * __END_OF_JASPER_LICENSE__ *//* * $Id: jpc_dec.c 1918 2005-07-24 14:12:08Z baford $ *//******************************************************************************\* Includes.\******************************************************************************/#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "jasper/jas_types.h"#include "jasper/jas_math.h"#include "jasper/jas_tvp.h"#include "jasper/jas_malloc.h"#include "jasper/jas_debug.h"#include "jpc_fix.h"#include "jpc_dec.h"#include "jpc_cs.h"#include "jpc_mct.h"#include "jpc_t2dec.h"#include "jpc_t1dec.h"#include "jpc_math.h"/******************************************************************************\*\******************************************************************************/#define JPC_MHSOC 0x0001 /* In the main header, expecting a SOC marker segment. */#define JPC_MHSIZ 0x0002 /* In the main header, expecting a SIZ marker segment. */#define JPC_MH 0x0004 /* In the main header, expecting "other" marker segments. */#define JPC_TPHSOT 0x0008 /* In a tile-part header, expecting a SOT marker segment. */#define JPC_TPH 0x0010 /* In a tile-part header, expecting "other" marker segments. */#define JPC_MT 0x0020 /* In the main trailer. */typedef struct { uint_fast16_t id; /* The marker segment type. */ int validstates; /* The states in which this type of marker segment can be validly encountered. */ int (*action)(jpc_dec_t *dec, jpc_ms_t *ms); /* The action to take upon encountering this type of marker segment. */} jpc_dec_mstabent_t;/******************************************************************************\*\******************************************************************************//* COD/COC parameters have been specified. */#define JPC_CSET 0x0001/* QCD/QCC parameters have been specified. */#define JPC_QSET 0x0002/* COD/COC parameters set from a COC marker segment. */#define JPC_COC 0x0004/* QCD/QCC parameters set from a QCC marker segment. */#define JPC_QCC 0x0008/******************************************************************************\* Local function prototypes.\******************************************************************************/static int jpc_dec_dump(jpc_dec_t *dec, FILE *out);jpc_ppxstab_t *jpc_ppxstab_create(void);void jpc_ppxstab_destroy(jpc_ppxstab_t *tab);int jpc_ppxstab_grow(jpc_ppxstab_t *tab, int maxents);int jpc_ppxstab_insert(jpc_ppxstab_t *tab, jpc_ppxstabent_t *ent);jpc_streamlist_t *jpc_ppmstabtostreams(jpc_ppxstab_t *tab);int jpc_pptstabwrite(jas_stream_t *out, jpc_ppxstab_t *tab);jpc_ppxstabent_t *jpc_ppxstabent_create(void);void jpc_ppxstabent_destroy(jpc_ppxstabent_t *ent);int jpc_streamlist_numstreams(jpc_streamlist_t *streamlist);jpc_streamlist_t *jpc_streamlist_create(void);int jpc_streamlist_insert(jpc_streamlist_t *streamlist, int streamno, jas_stream_t *stream);jas_stream_t *jpc_streamlist_remove(jpc_streamlist_t *streamlist, int streamno);void jpc_streamlist_destroy(jpc_streamlist_t *streamlist);jas_stream_t *jpc_streamlist_get(jpc_streamlist_t *streamlist, int streamno);static void jpc_dec_cp_resetflags(jpc_dec_cp_t *cp);static jpc_dec_cp_t *jpc_dec_cp_create(uint_fast16_t numcomps);static int jpc_dec_cp_isvalid(jpc_dec_cp_t *cp);static jpc_dec_cp_t *jpc_dec_cp_copy(jpc_dec_cp_t *cp);static int jpc_dec_cp_setfromcod(jpc_dec_cp_t *cp, jpc_cod_t *cod);static int jpc_dec_cp_setfromcoc(jpc_dec_cp_t *cp, jpc_coc_t *coc);static int jpc_dec_cp_setfromcox(jpc_dec_cp_t *cp, jpc_dec_ccp_t *ccp, jpc_coxcp_t *compparms, int flags);static int jpc_dec_cp_setfromqcd(jpc_dec_cp_t *cp, jpc_qcd_t *qcd);static int jpc_dec_cp_setfromqcc(jpc_dec_cp_t *cp, jpc_qcc_t *qcc);static int jpc_dec_cp_setfromqcx(jpc_dec_cp_t *cp, jpc_dec_ccp_t *ccp, jpc_qcxcp_t *compparms, int flags);static int jpc_dec_cp_setfromrgn(jpc_dec_cp_t *cp, jpc_rgn_t *rgn);static int jpc_dec_cp_prepare(jpc_dec_cp_t *cp);static void jpc_dec_cp_destroy(jpc_dec_cp_t *cp);static int jpc_dec_cp_setfrompoc(jpc_dec_cp_t *cp, jpc_poc_t *poc, int reset);static int jpc_pi_addpchgfrompoc(jpc_pi_t *pi, jpc_poc_t *poc);static int jpc_dec_decode(jpc_dec_t *dec);static jpc_dec_t *jpc_dec_create(jpc_dec_importopts_t *impopts, jas_stream_t *in);static void jpc_dec_destroy(jpc_dec_t *dec);static void jpc_dequantize(jas_matrix_t *x, jpc_fix_t absstepsize);static void jpc_undo_roi(jas_matrix_t *x, int roishift, int bgshift, int numbps);static jpc_fix_t jpc_calcabsstepsize(int stepsize, int numbits);static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile);static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile);static int jpc_dec_tilefini(jpc_dec_t *dec, jpc_dec_tile_t *tile);static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_eoc(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_siz(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_cod(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_coc(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_rgn(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_qcd(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_qcc(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_poc(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_ppm(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_ppt(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_com(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_unk(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms);static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts);static jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id);/******************************************************************************\* Global data.\******************************************************************************/jpc_dec_mstabent_t jpc_dec_mstab[] = { {JPC_MS_SOC, JPC_MHSOC, jpc_dec_process_soc}, {JPC_MS_SOT, JPC_MH | JPC_TPHSOT, jpc_dec_process_sot}, {JPC_MS_SOD, JPC_TPH, jpc_dec_process_sod}, {JPC_MS_EOC, JPC_TPHSOT, jpc_dec_process_eoc}, {JPC_MS_SIZ, JPC_MHSIZ, jpc_dec_process_siz}, {JPC_MS_COD, JPC_MH | JPC_TPH, jpc_dec_process_cod}, {JPC_MS_COC, JPC_MH | JPC_TPH, jpc_dec_process_coc}, {JPC_MS_RGN, JPC_MH | JPC_TPH, jpc_dec_process_rgn}, {JPC_MS_QCD, JPC_MH | JPC_TPH, jpc_dec_process_qcd}, {JPC_MS_QCC, JPC_MH | JPC_TPH, jpc_dec_process_qcc}, {JPC_MS_POC, JPC_MH | JPC_TPH, jpc_dec_process_poc}, {JPC_MS_TLM, JPC_MH, 0}, {JPC_MS_PLM, JPC_MH, 0}, {JPC_MS_PLT, JPC_TPH, 0}, {JPC_MS_PPM, JPC_MH, jpc_dec_process_ppm}, {JPC_MS_PPT, JPC_TPH, jpc_dec_process_ppt}, {JPC_MS_SOP, 0, 0}, {JPC_MS_CRG, JPC_MH, jpc_dec_process_crg}, {JPC_MS_COM, JPC_MH | JPC_TPH, jpc_dec_process_com}, {0, JPC_MH | JPC_TPH, jpc_dec_process_unk}};/******************************************************************************\* The main entry point for the JPEG-2000 decoder.\******************************************************************************/jas_image_t *jpc_decode(jas_stream_t *in, char *optstr){ jpc_dec_importopts_t opts; jpc_dec_t *dec; jas_image_t *image; dec = 0; if (jpc_dec_parseopts(optstr, &opts)) { goto error; } jpc_initluts(); if (!(dec = jpc_dec_create(&opts, in))) { goto error; } /* Do most of the work. */ if (jpc_dec_decode(dec)) { goto error; } if (jas_image_numcmpts(dec->image) >= 3) { jas_image_setclrspc(dec->image, JAS_CLRSPC_SRGB); jas_image_setcmpttype(dec->image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); jas_image_setcmpttype(dec->image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); jas_image_setcmpttype(dec->image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); } else { jas_image_setclrspc(dec->image, JAS_CLRSPC_SGRAY); jas_image_setcmpttype(dec->image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); } /* Save the return value. */ image = dec->image; /* Stop the image from being discarded. */ dec->image = 0; /* Destroy decoder. */ jpc_dec_destroy(dec); return image;error: if (dec) { jpc_dec_destroy(dec); } return 0;}typedef enum { OPT_MAXLYRS, OPT_MAXPKTS, OPT_DEBUG} optid_t;jas_taginfo_t decopts[] = { {OPT_MAXLYRS, "maxlyrs"}, {OPT_MAXPKTS, "maxpkts"}, {OPT_DEBUG, "debug"}, {-1, 0}};static int jpc_dec_parseopts(char *optstr, jpc_dec_importopts_t *opts){ jas_tvparser_t *tvp; opts->debug = 0; opts->maxlyrs = JPC_MAXLYRS; opts->maxpkts = -1; if (!(tvp = jas_tvparser_create(optstr ? optstr : ""))) { return -1; } while (!jas_tvparser_next(tvp)) { switch (jas_taginfo_nonull(jas_taginfos_lookup(decopts, jas_tvparser_gettag(tvp)))->id) { case OPT_MAXLYRS: opts->maxlyrs = atoi(jas_tvparser_getval(tvp)); break; case OPT_DEBUG: opts->debug = atoi(jas_tvparser_getval(tvp)); break; case OPT_MAXPKTS: opts->maxpkts = atoi(jas_tvparser_getval(tvp)); break; default: fprintf(stderr, "warning: ignoring invalid option %s\n", jas_tvparser_gettag(tvp)); break; } } jas_tvparser_destroy(tvp); return 0;}/******************************************************************************\* Code for table-driven code stream decoder.\******************************************************************************/static jpc_dec_mstabent_t *jpc_dec_mstab_lookup(uint_fast16_t id){ jpc_dec_mstabent_t *mstabent; for (mstabent = jpc_dec_mstab; mstabent->id != 0; ++mstabent) { if (mstabent->id == id) { break; } } return mstabent;}static int jpc_dec_decode(jpc_dec_t *dec){ jpc_ms_t *ms; jpc_dec_mstabent_t *mstabent; int ret; jpc_cstate_t *cstate; if (!(cstate = jpc_cstate_create())) { return -1; } dec->cstate = cstate; /* Initially, we should expect to encounter a SOC marker segment. */ dec->state = JPC_MHSOC; for (;;) { /* Get the next marker segment in the code stream. */ if (!(ms = jpc_getms(dec->in, cstate))) { fprintf(stderr, "cannot get marker segment\n"); return -1; } mstabent = jpc_dec_mstab_lookup(ms->id); assert(mstabent); /* Ensure that this type of marker segment is permitted at this point in the code stream. */ if (!(dec->state & mstabent->validstates)) { fprintf(stderr, "unexpected marker segment type\n"); jpc_ms_destroy(ms); return -1; } /* Process the marker segment. */ if (mstabent->action) { ret = (*mstabent->action)(dec, ms); } else { /* No explicit action is required. */ ret = 0; } /* Destroy the marker segment. */ jpc_ms_destroy(ms); if (ret < 0) { return -1; } else if (ret > 0) { break; } } return 0;}static int jpc_dec_process_crg(jpc_dec_t *dec, jpc_ms_t *ms){ int cmptno; jpc_dec_cmpt_t *cmpt; jpc_crg_t *crg; crg = &ms->parms.crg; for (cmptno = 0, cmpt = dec->cmpts; cmptno < dec->numcomps; ++cmptno, ++cmpt) { /* Ignore the information in the CRG marker segment for now. This information serves no useful purpose for decoding anyhow. Some other parts of the code need to be changed if these lines are uncommented. cmpt->hsubstep = crg->comps[cmptno].hoff; cmpt->vsubstep = crg->comps[cmptno].voff; */ } return 0;}static int jpc_dec_process_soc(jpc_dec_t *dec, jpc_ms_t *ms){ /* Eliminate warnings about unused variables. */ ms = 0; /* We should expect to encounter a SIZ marker segment next. */ dec->state = JPC_MHSIZ; return 0;}static int jpc_dec_process_sot(jpc_dec_t *dec, jpc_ms_t *ms){ jpc_dec_tile_t *tile; jpc_sot_t *sot = &ms->parms.sot; jas_image_cmptparm_t *compinfos; jas_image_cmptparm_t *compinfo; jpc_dec_cmpt_t *cmpt; int cmptno; if (dec->state == JPC_MH) { compinfos = jas_malloc(dec->numcomps * sizeof(jas_image_cmptparm_t)); assert(compinfos); for (cmptno = 0, cmpt = dec->cmpts, compinfo = compinfos; cmptno < dec->numcomps; ++cmptno, ++cmpt, ++compinfo) { compinfo->tlx = 0; compinfo->tly = 0; compinfo->prec = cmpt->prec; compinfo->sgnd = cmpt->sgnd; compinfo->width = cmpt->width; compinfo->height = cmpt->height; compinfo->hstep = cmpt->hstep; compinfo->vstep = cmpt->vstep; } if (!(dec->image = jas_image_create(dec->numcomps, compinfos, JAS_CLRSPC_UNKNOWN))) { return -1; } jas_free(compinfos); /* Is the packet header information stored in PPM marker segments in the main header? */ if (dec->ppmstab) { /* Convert the PPM marker segment data into a collection of streams (one stream per tile-part). */ if (!(dec->pkthdrstreams = jpc_ppmstabtostreams(dec->ppmstab))) { abort(); } jpc_ppxstab_destroy(dec->ppmstab); dec->ppmstab = 0; } } if (sot->len > 0) { dec->curtileendoff = jas_stream_getrwcount(dec->in) - ms->len - 4 + sot->len; } else { dec->curtileendoff = 0; } if (JAS_CAST(int, sot->tileno) > dec->numtiles) { fprintf(stderr, "invalid tile number in SOT marker segment\n"); return -1; } /* Set the current tile. */ dec->curtile = &dec->tiles[sot->tileno]; tile = dec->curtile; /* Ensure that this is the expected part number. */ if (sot->partno != tile->partno) { return -1; } if (tile->numparts > 0 && sot->partno >= tile->numparts) { return -1; } if (!tile->numparts && sot->numparts > 0) { tile->numparts = sot->numparts; } tile->pptstab = 0; switch (tile->state) { case JPC_TILE_INIT: /* This is the first tile-part for this tile. */ tile->state = JPC_TILE_ACTIVE; assert(!tile->cp); if (!(tile->cp = jpc_dec_cp_copy(dec->cp))) { return -1; } jpc_dec_cp_resetflags(dec->cp); break; default: if (sot->numparts == sot->partno - 1) { tile->state = JPC_TILE_ACTIVELAST; } break; } /* Note: We do not increment the expected tile-part number until all processing for this tile-part is complete. */ /* We should expect to encounter other tile-part header marker segments next. */ dec->state = JPC_TPH; return 0;}static int jpc_dec_process_sod(jpc_dec_t *dec, jpc_ms_t *ms){ jpc_dec_tile_t *tile; int pos; /* Eliminate compiler warnings about unused variables. */ ms = 0; if (!(tile = dec->curtile)) { return -1; } if (!tile->partno) { if (!jpc_dec_cp_isvalid(tile->cp)) { return -1; } jpc_dec_cp_prepare(tile->cp); if (jpc_dec_tileinit(dec, tile)) { return -1; } } /* Are packet headers stored in the main header or tile-part header? */ if (dec->pkthdrstreams) { /* Get the stream containing the packet header data for this tile-part. */ if (!(tile->pkthdrstream = jpc_streamlist_remove(dec->pkthdrstreams, 0))) { return -1; } } if (tile->pptstab) { if (!tile->pkthdrstream) { if (!(tile->pkthdrstream = jas_stream_memopen(0, 0))) { return -1; } } pos = jas_stream_tell(tile->pkthdrstream); jas_stream_seek(tile->pkthdrstream, 0, SEEK_END); if (jpc_pptstabwrite(tile->pkthdrstream, tile->pptstab)) { return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -