📄 jpxstream.cc
字号:
//========================================================================//// JPXStream.cc//// Copyright 2002-2003 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <limits.h>#include "gmem.h"#include "Error.h"#include "JArithmeticDecoder.h"#include "JPXStream.h"//~ to do:// - precincts// - ROI// - progression order changes// - packed packet headers// - support for palettes, channel maps, etc.// - make sure all needed JP2/JPX subboxes are parsed (readBoxes)// - can we assume that QCC segments must come after the QCD segment?// - skip EPH markers (readTilePartData)// - handle tilePartToEOC in readTilePartData// - deal with multiple codeword segments (readTilePartData,// readCodeBlockData)// - progression orders 2, 3, and 4// - in coefficient decoding (readCodeBlockData):// - termination pattern: terminate after every coding pass// - error resilience segmentation symbol// - selective arithmetic coding bypass// - vertically causal context formation// - coeffs longer than 31 bits (should just ignore the extra bits?)// - handle boxes larger than 2^32 bytes// - the fixed-point arithmetic won't handle 16-bit pixels//------------------------------------------------------------------------// number of contexts for the arithmetic decoder#define jpxNContexts 19#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup#define jpxContextSign 9 // 9 - 13: sign#define jpxContextMagRef 14 // 14 -16: magnitude refinement#define jpxContextRunLength 17 // cleanup: run length#define jpxContextUniform 18 // cleanup: first signif coeff//------------------------------------------------------------------------#define jpxPassSigProp 0#define jpxPassMagRef 1#define jpxPassCleanup 2//------------------------------------------------------------------------// arithmetic decoder context for the significance propagation and// cleanup passes:// [horiz][vert][diag][subband]// where subband = 0 for HL// = 1 for LH and LL// = 2 for HHstatic Guint sigPropContext[3][3][5][3] = { {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0 { 1, 1, 3 }, // horiz=0, vert=0, diag=1 { 2, 2, 6 }, // horiz=0, vert=0, diag=2 { 2, 2, 8 }, // horiz=0, vert=0, diag=3 { 2, 2, 8 }}, // horiz=0, vert=0, diag=4 {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0 { 6, 3, 4 }, // horiz=0, vert=1, diag=1 { 6, 3, 7 }, // horiz=0, vert=1, diag=2 { 6, 3, 8 }, // horiz=0, vert=1, diag=3 { 6, 3, 8 }}, // horiz=0, vert=1, diag=4 {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0 { 8, 4, 5 }, // horiz=0, vert=2, diag=1 { 8, 4, 7 }, // horiz=0, vert=2, diag=2 { 8, 4, 8 }, // horiz=0, vert=2, diag=3 { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4 {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0 { 3, 6, 4 }, // horiz=1, vert=0, diag=1 { 3, 6, 7 }, // horiz=1, vert=0, diag=2 { 3, 6, 8 }, // horiz=1, vert=0, diag=3 { 3, 6, 8 }}, // horiz=1, vert=0, diag=4 {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0 { 7, 7, 5 }, // horiz=1, vert=1, diag=1 { 7, 7, 7 }, // horiz=1, vert=1, diag=2 { 7, 7, 8 }, // horiz=1, vert=1, diag=3 { 7, 7, 8 }}, // horiz=1, vert=1, diag=4 {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0 { 8, 7, 5 }, // horiz=1, vert=2, diag=1 { 8, 7, 7 }, // horiz=1, vert=2, diag=2 { 8, 7, 8 }, // horiz=1, vert=2, diag=3 { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4 {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0 { 4, 8, 5 }, // horiz=2, vert=0, diag=1 { 4, 8, 7 }, // horiz=2, vert=0, diag=2 { 4, 8, 8 }, // horiz=2, vert=0, diag=3 { 4, 8, 8 }}, // horiz=2, vert=0, diag=4 {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0 { 7, 8, 5 }, // horiz=2, vert=1, diag=1 { 7, 8, 7 }, // horiz=2, vert=1, diag=2 { 7, 8, 8 }, // horiz=2, vert=1, diag=3 { 7, 8, 8 }}, // horiz=2, vert=1, diag=4 {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0 { 8, 8, 5 }, // horiz=2, vert=2, diag=1 { 8, 8, 7 }, // horiz=2, vert=2, diag=2 { 8, 8, 8 }, // horiz=2, vert=2, diag=3 { 8, 8, 8 }}} // horiz=2, vert=2, diag=4};// arithmetic decoder context and xor bit for the sign bit in the// significance propagation pass:// [horiz][vert][k]// where horiz/vert are offset by 2 (i.e., range is -2 .. 2)// and k = 0 for the context// = 1 for the xor bitstatic Guint signContext[5][5][2] = { {{ 13, 1 }, // horiz=-2, vert=-2 { 13, 1 }, // horiz=-2, vert=-1 { 12, 1 }, // horiz=-2, vert= 0 { 11, 1 }, // horiz=-2, vert=+1 { 11, 1 }}, // horiz=-2, vert=+2 {{ 13, 1 }, // horiz=-1, vert=-2 { 13, 1 }, // horiz=-1, vert=-1 { 12, 1 }, // horiz=-1, vert= 0 { 11, 1 }, // horiz=-1, vert=+1 { 11, 1 }}, // horiz=-1, vert=+2 {{ 10, 1 }, // horiz= 0, vert=-2 { 10, 1 }, // horiz= 0, vert=-1 { 9, 0 }, // horiz= 0, vert= 0 { 10, 0 }, // horiz= 0, vert=+1 { 10, 0 }}, // horiz= 0, vert=+2 {{ 11, 0 }, // horiz=+1, vert=-2 { 11, 0 }, // horiz=+1, vert=-1 { 12, 0 }, // horiz=+1, vert= 0 { 13, 0 }, // horiz=+1, vert=+1 { 13, 0 }}, // horiz=+1, vert=+2 {{ 11, 0 }, // horiz=+2, vert=-2 { 11, 0 }, // horiz=+2, vert=-1 { 12, 0 }, // horiz=+2, vert= 0 { 13, 0 }, // horiz=+2, vert=+1 { 13, 0 }}, // horiz=+2, vert=+2};//------------------------------------------------------------------------// constants used in the IDWT#define idwtAlpha -1.586134342059924#define idwtBeta -0.052980118572961#define idwtGamma 0.882911075530934#define idwtDelta 0.443506852043971#define idwtKappa 1.230174104914001#define idwtIKappa (1.0 / idwtKappa)// number of bits to the right of the decimal point for the fixed// point arithmetic used in the IDWT#define fracBits 16//------------------------------------------------------------------------// floor(x / y)#define jpxFloorDiv(x, y) ((x) / (y))// floor(x / 2^y)#define jpxFloorDivPow2(x, y) ((x) >> (y))// ceil(x / y)#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))// ceil(x / 2^y)#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))//------------------------------------------------------------------------#if 1 //----- disable coverage tracking#define cover(idx)#else //----- enable coverage trackingclass JPXCover {public: JPXCover(int sizeA); ~JPXCover(); void incr(int idx);private: int size, used; int *data;};JPXCover::JPXCover(int sizeA) { size = sizeA; used = -1; data = (int *)gmallocn(size, sizeof(int)); memset(data, 0, size * sizeof(int));}JPXCover::~JPXCover() { int i; printf("JPX coverage:\n"); for (i = 0; i <= used; ++i) { printf(" %4d: %8d\n", i, data[i]); } gfree(data);}void JPXCover::incr(int idx) { if (idx < size) { ++data[idx]; if (idx > used) { used = idx; } }}JPXCover jpxCover(150);#define cover(idx) jpxCover.incr(idx)#endif //----- coverage tracking//------------------------------------------------------------------------JPXStream::JPXStream(Stream *strA): FilterStream(strA){ nComps = 0; bpc = NULL; width = height = 0; haveCS = gFalse; havePalette = gFalse; haveCompMap = gFalse; haveChannelDefn = gFalse; img.tiles = NULL; bitBuf = 0; bitBufLen = 0; bitBufSkip = gFalse; byteCount = 0;}JPXStream::~JPXStream() { close(); delete str;}void JPXStream::reset() { str->reset(); if (readBoxes()) { curY = img.yOffset; } else { // readBoxes reported an error, so we go immediately to EOF curY = img.ySize; } curX = img.xOffset; curComp = 0; readBufLen = 0;}void JPXStream::close() { JPXTile *tile; JPXTileComp *tileComp; JPXResLevel *resLevel; JPXPrecinct *precinct; JPXSubband *subband; JPXCodeBlock *cb; Guint comp, i, k, r, pre, sb; gfree(bpc); bpc = NULL; if (havePalette) { gfree(palette.bpc); gfree(palette.c); havePalette = gFalse; } if (haveCompMap) { gfree(compMap.comp); gfree(compMap.type); gfree(compMap.pComp); haveCompMap = gFalse; } if (haveChannelDefn) { gfree(channelDefn.idx); gfree(channelDefn.type); gfree(channelDefn.assoc); haveChannelDefn = gFalse; } if (img.tiles) { for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { tile = &img.tiles[i]; if (tile->tileComps) { for (comp = 0; comp < img.nComps; ++comp) { tileComp = &tile->tileComps[comp]; gfree(tileComp->quantSteps); gfree(tileComp->data); gfree(tileComp->buf); if (tileComp->resLevels) { for (r = 0; r <= tileComp->nDecompLevels; ++r) { resLevel = &tileComp->resLevels[r]; if (resLevel->precincts) { for (pre = 0; pre < 1; ++pre) { precinct = &resLevel->precincts[pre]; if (precinct->subbands) { for (sb = 0; sb < (Guint)(r == 0 ? 1 : 3); ++sb) { subband = &precinct->subbands[sb]; gfree(subband->inclusion); gfree(subband->zeroBitPlane); if (subband->cbs) { for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { cb = &subband->cbs[k]; gfree(cb->coeffs); if (cb->arithDecoder) { delete cb->arithDecoder; } if (cb->stats) { delete cb->stats; } } gfree(subband->cbs); } } gfree(precinct->subbands); } } gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts); } } gfree(img.tiles[i].tileComps[comp].resLevels); } } gfree(img.tiles[i].tileComps); } } gfree(img.tiles); img.tiles = NULL; } FilterStream::close();}int JPXStream::getChar() { int c; if (readBufLen < 8) { fillReadBuf(); } if (readBufLen == 8) { c = readBuf & 0xff; readBufLen = 0; } else if (readBufLen > 8) { c = (readBuf >> (readBufLen - 8)) & 0xff; readBufLen -= 8; } else if (readBufLen == 0) { c = EOF; } else { c = (readBuf << (8 - readBufLen)) & 0xff; readBufLen = 0; } return c;}int JPXStream::lookChar() { int c; if (readBufLen < 8) { fillReadBuf(); } if (readBufLen == 8) { c = readBuf & 0xff; } else if (readBufLen > 8) { c = (readBuf >> (readBufLen - 8)) & 0xff; } else if (readBufLen == 0) { c = EOF; } else { c = (readBuf << (8 - readBufLen)) & 0xff; } return c;}void JPXStream::fillReadBuf() { JPXTileComp *tileComp; Guint tileIdx, tx, ty; int pix, pixBits; do { if (curY >= img.ySize) { return; } tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles + (curX - img.xTileOffset) / img.xTileSize;#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid tileComp = &img.tiles[tileIdx].tileComps[curComp];#else tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];#endif tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep); ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep); pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx]; pixBits = tileComp->prec;#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid if (++curComp == img.nComps) {#else if (havePalette) { if (pix >= 0 && pix < palette.nEntries) { pix = palette.c[pix * palette.nComps + curComp]; } else { pix = pixBits = palette.bpc[curComp]; } if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {#endif curComp = 0; if (++curX == img.xSize) { curX = img.xOffset; ++curY; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -