MODULE JPEG2000DecoderCS;
IMPORT
SYSTEM, J2KU := JPEG2000DecoderUtil, KernelLog, Machine, Streams;
CONST
MAX_IMG_WIDTH = MAX(LONGINT);
MAX_IMG_HEIGHT = MAX(LONGINT);
MAX_TILES = 65535;
MAX_COMPONENTS = 16384;
MAX_LAYERS = 65535;
CODESTREAM_READER* = 0;
BUF_CODESTREAM_READER* = 1;
REBUILD_TILEPART* = MAX(LONGINT);
SOC = 0000FF4FH;
SOT = 0000FF90H;
SOD = 0000FF93H;
EOC = 0000FFD9H;
SIZ = 0000FF51H;
COD = 0000FF52H;
COC = 0000FF53H;
RGN = 0000FF5EH;
QCD = 0000FF5CH;
QCC = 0000FF5DH;
POC = 0000FF5FH;
TLM = 0000FF55H;
PLM = 0000FF57H;
PLT = 0000FF58H;
PPM = 0000FF60H;
PPT = 0000FF61H;
SOP = 0000FF91H;
EPH = 0000FF92H;
CRG = 0000FF63H;
COM = 0000FF64H;
ENTROPY_NUM_PASSES = 3;
ENTROPY_FIRST_BYPASS_IDX = 3 * ENTROPY_NUM_PASSES + 1;
NOQUANT* = 00000000H;
QUANT_DER* = 00000001H;
QUANT_EXP* = 00000002H;
TRANS_9X7_IRREV* = 00000000H;
TRANS_5X3_REV* = 00000001H;
PROG_LRCP = 00000000H;
PROG_RLCP = 00000001H;
PROG_RPCL = 00000002H;
PROG_PCRL = 00000003H;
PROG_CPRL = 00000004H;
MAX_PREC_SIZ = 15;
TYPE
PrecinctExp = RECORD
ppx : LONGINT;
ppy : LONGINT;
END;
CodingStyle = OBJECT
VAR
maxps : BOOLEAN;
ndec : LONGINT;
cblw : LONGINT;
cblh : LONGINT;
selcb : BOOLEAN;
rescp : BOOLEAN;
term : BOOLEAN;
vert : BOOLEAN;
pred : BOOLEAN;
segs : BOOLEAN;
trans : LONGINT;
precs : POINTER TO ARRAY OF PrecinctExp;
END CodingStyle;
CICodingStyle = OBJECT
VAR
po : LONGINT;
nl : LONGINT;
mct : LONGINT;
sop : BOOLEAN;
eph : BOOLEAN;
END CICodingStyle;
Component = OBJECT
VAR
signed : BOOLEAN;
depth : LONGINT;
subsx : LONGINT;
subsy : LONGINT;
END Component;
Quantization = OBJECT
VAR
style : LONGINT;
nguardb : LONGINT;
nstepsiz : LONGINT;
stepsiz : POINTER TO ARRAY OF QuantStep;
END Quantization;
QuantStep = OBJECT
VAR
mant : LONGINT;
exp : LONGINT;
END QuantStep;
ImageInfo* = OBJECT
VAR
xsiz, ysiz : LONGINT;
xos, yos : LONGINT;
nt : LONGINT;
nxt, nyt : LONGINT;
xt, yt : LONGINT;
xtos, ytos : LONGINT;
ncomp : LONGINT;
comps : POINTER TO ARRAY OF Component;
PROCEDURE GetImgWidth* (declevel : LONGINT) : LONGINT;
VAR
tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
RETURN SYSTEM.LSH(xsiz + tmp, -declevel) - SYSTEM.LSH(xos + tmp, -declevel);
END GetImgWidth;
PROCEDURE GetImgHeight* (declevel : LONGINT) : LONGINT;
VAR
tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
RETURN SYSTEM.LSH(ysiz + tmp, -declevel) - SYSTEM.LSH(yos + tmp, -declevel);
END GetImgHeight;
PROCEDURE GetImgULX* (declevel : LONGINT) : LONGINT;
VAR
tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
RETURN SYSTEM.LSH(xos + tmp, -declevel);
END GetImgULX;
PROCEDURE GetImgULY* (declevel : LONGINT) : LONGINT;
VAR
tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
RETURN SYSTEM.LSH(yos + tmp, -declevel);
END GetImgULY;
PROCEDURE GetCompImgWidth* (component, declevel : LONGINT) : LONGINT;
VAR
subsx, tmp, cx0, cx1 : LONGINT;
BEGIN
subsx := comps[component].subsx;
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
cx0 := (xos + subsx - 1) DIV subsx;
cx1 := (xsiz + subsx - 1) DIV subsx;
RETURN SYSTEM.LSH(cx1 + tmp, -declevel) - SYSTEM.LSH(cx0 + tmp, -declevel);
END GetCompImgWidth;
PROCEDURE GetCompImgHeight* (component, declevel : LONGINT) : LONGINT;
VAR
subsy, tmp, cy0, cy1 : LONGINT;
BEGIN
subsy := comps[component].subsy;
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
cy0 := (yos + subsy - 1) DIV subsy;
cy1 := (ysiz + subsy - 1) DIV subsy;
RETURN SYSTEM.LSH(cy1 + tmp, -declevel) - SYSTEM.LSH(cy0 + tmp, -declevel);
END GetCompImgHeight;
PROCEDURE GetNumTiles* () : LONGINT;
BEGIN
RETURN nt;
END GetNumTiles;
PROCEDURE GetNumTilesX* () : LONGINT;
BEGIN
RETURN nxt;
END GetNumTilesX;
PROCEDURE GetNumTilesY* () : LONGINT;
BEGIN
RETURN nyt;
END GetNumTilesY;
PROCEDURE GetTileWidth* (tile, declevel : LONGINT) : LONGINT;
VAR
tx0, tx1, p, tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
p := tile MOD nxt;
tx0 := xtos + p*xt;
tx1 := tx0 + xt;
IF xos > tx0 THEN
tx0 := xos;
END;
IF xsiz < tx1 THEN
tx1 := xsiz;
END;
RETURN SYSTEM.LSH(tx1 + tmp, -declevel) - SYSTEM.LSH(tx0 + tmp, -declevel);
END GetTileWidth;
PROCEDURE GetTileHeight* (tile, declevel : LONGINT) : LONGINT;
VAR
ty0, ty1, q, tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
q := tile DIV nxt;
ty0 := ytos + q*yt;
ty1 := ty0 + yt;
IF yos > ty0 THEN
ty0 := yos;
END;
IF ysiz < ty1 THEN
ty1 := ysiz;
END;
RETURN SYSTEM.LSH(ty1 + tmp, -declevel) - SYSTEM.LSH(ty0 + tmp, -declevel);
END GetTileHeight;
PROCEDURE GetTileULX* (tile, declevel : LONGINT) : LONGINT;
VAR
tx0, p, tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
p := tile MOD nxt;
tx0 := xtos + p*xt;
IF xos > tx0 THEN
tx0 := xos;
END;
RETURN SYSTEM.LSH(tx0 + tmp, -declevel);
END GetTileULX;
PROCEDURE GetTileULY* (tile, declevel : LONGINT) : LONGINT;
VAR
ty0, q, tmp : LONGINT;
BEGIN
tmp := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), declevel) - 1;
q := tile DIV nxt;
ty0 := ytos + q*yt;
IF yos > ty0 THEN
ty0 := yos;
END;
RETURN SYSTEM.LSH(ty0 + tmp, -declevel);
END GetTileULY;
PROCEDURE GetNumComponents* () : LONGINT;
BEGIN
RETURN ncomp;
END GetNumComponents;
PROCEDURE GetSubsX* (component : LONGINT) : LONGINT;
BEGIN
RETURN comps[component].subsx;
END GetSubsX;
PROCEDURE GetSubsY* (component : LONGINT) : LONGINT;
BEGIN
RETURN comps[component].subsy;
END GetSubsY;
PROCEDURE GetBitDepth* (component : LONGINT) : LONGINT;
BEGIN
RETURN comps[component].depth;
END GetBitDepth;
END ImageInfo;
DecoderSpecs* = OBJECT
VAR
imgInfo : ImageInfo;
cstyle : POINTER TO ARRAY OF ARRAY OF CodingStyle;
cics : POINTER TO ARRAY OF CICodingStyle;
quant : POINTER TO ARRAY OF ARRAY OF Quantization;
roiShift : POINTER TO ARRAY OF ARRAY OF LONGINT;
PROCEDURE &InitNew*;
BEGIN
imgInfo := NIL;
cstyle := NIL;
cics := NIL;
quant := NIL;
roiShift := NIL;
END InitNew;
PROCEDURE GetImageInfo* () : ImageInfo;
BEGIN
RETURN imgInfo;
END GetImageInfo;
PROCEDURE BypassCoding* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].selcb;
END BypassCoding;
PROCEDURE RegularTermination* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].term;
END RegularTermination;
PROCEDURE VerticallyCausalContext* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].vert;
END VerticallyCausalContext;
PROCEDURE PredictableTermination* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].pred;
END PredictableTermination;
PROCEDURE ResetContexts* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].rescp;
END ResetContexts;
PROCEDURE SegmentationSymbols* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].segs;
END SegmentationSymbols;
PROCEDURE GetWavTransType* (tile, component : LONGINT) : LONGINT;
BEGIN
RETURN cstyle[tile][component].trans;
END GetWavTransType;
PROCEDURE IsReversibleWavTrans* (tile, component : LONGINT) : BOOLEAN;
BEGIN
RETURN cstyle[tile][component].trans = TRANS_5X3_REV;
END IsReversibleWavTrans;
PROCEDURE CompTransUsed* (tile : LONGINT) : BOOLEAN;
BEGIN
RETURN cics[tile].mct # 0;
END CompTransUsed;
PROCEDURE GetNumDecLevels* (tile, component : LONGINT) : LONGINT;
BEGIN
RETURN cstyle[tile][component].ndec;
END GetNumDecLevels;
PROCEDURE GetImgMinDecLevels* () : LONGINT;
VAR
min, i, j : LONGINT;
BEGIN
min := cstyle[0][0].ndec;
FOR j := 0 TO imgInfo.nt - 1 DO
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[j][i].ndec < min THEN
min := cstyle[j][i].ndec;
END;
END;
END;
RETURN min;
END GetImgMinDecLevels;
PROCEDURE GetImgMaxDecLevels* () : LONGINT;
VAR
max, i, j : LONGINT;
BEGIN
max := cstyle[0][0].ndec;
FOR j := 0 TO imgInfo.nt - 1 DO
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[j][i].ndec > max THEN
max := cstyle[j][i].ndec;
END;
END;
END;
RETURN max;
END GetImgMaxDecLevels;
PROCEDURE GetMinDecLevels* (tile : LONGINT) : LONGINT;
VAR
min, i : LONGINT;
BEGIN
min := cstyle[tile][0].ndec;
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[tile][i].ndec < min THEN
min := cstyle[tile][i].ndec;
END;
END;
RETURN min;
END GetMinDecLevels;
PROCEDURE GetMaxDecLevels* (tile : LONGINT) : LONGINT;
VAR
max, i : LONGINT;
BEGIN
max := cstyle[tile][0].ndec;
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[tile][i].ndec > max THEN
max := cstyle[tile][i].ndec;
END;
END;
RETURN max;
END GetMaxDecLevels;
PROCEDURE GetNumLayers* (tile : LONGINT) : LONGINT;
BEGIN
RETURN cics[tile].nl;
END GetNumLayers;
PROCEDURE GetMinNumLayers* () : LONGINT;
VAR
i, min : LONGINT;
BEGIN
min := cics[0].nl;
FOR i := 0 TO imgInfo.nt - 1 DO
IF cics[i].nl < min THEN
min := cics[i].nl;
END;
END;
RETURN min;
END GetMinNumLayers;
PROCEDURE GetPPX (tile, comp, reslevel : LONGINT) : LONGINT;
BEGIN
IF cstyle[tile][comp].maxps THEN
RETURN MAX_PREC_SIZ;
ELSE
RETURN cstyle[tile][comp].precs[reslevel].ppx;
END;
END GetPPX;
PROCEDURE GetPPY (tile, comp, reslevel : LONGINT) : LONGINT;
BEGIN
IF cstyle[tile][comp].maxps THEN
RETURN MAX_PREC_SIZ;
ELSE
RETURN cstyle[tile][comp].precs[reslevel].ppy;
END;
END GetPPY;
PROCEDURE GetMaxCblkWidthExp* (tile : LONGINT) : LONGINT;
VAR
i, maxw : LONGINT;
BEGIN
maxw := cstyle[tile][0].cblw;
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[tile][i].cblw > maxw THEN
maxw := cstyle[tile][i].cblw;
END;
END;
RETURN maxw;
END GetMaxCblkWidthExp;
PROCEDURE GetMaxCblkHeightExp* (tile : LONGINT) : LONGINT;
VAR
i, maxh : LONGINT;
BEGIN
maxh := cstyle[tile][0].cblh;
FOR i := 1 TO imgInfo.ncomp - 1 DO
IF cstyle[tile][i].cblh > maxh THEN
maxh := cstyle[tile][i].cblh;
END;
END;
RETURN maxh;
END GetMaxCblkHeightExp;
PROCEDURE GetQuantStyle* (tile, comp : LONGINT) : LONGINT;
BEGIN
RETURN quant[tile][comp].style;
END GetQuantStyle;
PROCEDURE GetQuantExponent* (tile, comp, reslevel, subband : LONGINT) : LONGINT;
BEGIN
IF reslevel = 0 THEN
RETURN quant[tile][comp].stepsiz[0].exp
ELSE
RETURN quant[tile][comp].stepsiz[3*(reslevel-1) + subband].exp;
END;
END GetQuantExponent;
PROCEDURE GetQuantMantissa* (tile, comp, reslevel, subband : LONGINT) : LONGINT;
BEGIN
IF reslevel = 0 THEN
RETURN quant[tile][comp].stepsiz[0].mant;
ELSE
RETURN quant[tile][comp].stepsiz[3*(reslevel-1) + subband].mant;
END;
END GetQuantMantissa;
PROCEDURE ROIUsed* (tile, comp : LONGINT) : BOOLEAN;
BEGIN
RETURN (roiShift # NIL) & (roiShift[tile][comp] >= 0);
END ROIUsed;
PROCEDURE GetROIShift* (tile, comp : LONGINT) : LONGINT;
BEGIN
IF (roiShift = NIL) THEN
RETURN -1;
ELSE
RETURN roiShift[tile][comp];
END;
END GetROIShift;
END DecoderSpecs;
ProgState = RECORD
progNr : LONGINT;
progOrder : LONGINT;
curLay : LONGINT;
startLay : J2KU.LongInt2DArrayPtr;
endLay : LONGINT;
startRes : LONGINT;
curRes : LONGINT;
endRes : LONGINT;
startComp : LONGINT;
curComp : LONGINT;
endComp : LONGINT;
curPrec : J2KU.LongInt3DArrayPtr;
curX : LONGINT;
curY : LONGINT;
END;
ProgChange = RECORD
progOrder : LONGINT;
startRes : LONGINT;
startComp : LONGINT;
endLay : LONGINT;
endRes : LONGINT;
endComp : LONGINT;
END;
ProgChangeArrayPtr = POINTER TO ARRAY OF ProgChange;
DataListElement = OBJECT
VAR
data : J2KU.ByteArrayPtr;
next : DataListElement;
END DataListElement;
PrecinctInfo = RECORD
nblocks : POINTER TO ARRAY OF ARRAY OF ARRAY 2 OF LONGINT;
nprecx : LONGINT;
nprecy : LONGINT;
END;
PacketDecoder = OBJECT(J2KU.BitSource)
VAR
cr : CodestreamReader;
curTile : LONGINT;
curByte : LONGINT;
curBytePos : LONGINT;
decSpec : DecoderSpecs;
pph : DataListElement;
pphPos : LONGINT;
pphTileFirstLast : POINTER TO ARRAY OF ARRAY OF DataListElement;
pphTilePos : J2KU.LongIntArrayPtr;
pphMainUsed : BOOLEAN;
pphTileUsed : POINTER TO ARRAY OF BOOLEAN;
sopUsed, ephUsed : BOOLEAN;
incStep : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF ARRAY 2 OF LONGINT;
minIncStep : POINTER TO ARRAY OF ARRAY OF ARRAY 2 OF LONGINT;
sotEot : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF ARRAY 2, 2 OF LONGINT;
maxSotEot : POINTER TO ARRAY OF ARRAY OF ARRAY 2, 2 OF LONGINT;
inclTrees : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF J2KU.TagTree;
zeroTrees : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF J2KU.TagTree;
lblock : POINTER TO ARRAY OF ARRAY OF J2KU.LongInt4DArrayPtr;
cblkInfo : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF J2KU.CblkInfo;
precInfo : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF PrecinctInfo;
PROCEDURE &InitNew *( cr : CodestreamReader;
decSpec : DecoderSpecs;
pphMain : DataListElement);
BEGIN
ReInit(cr, decSpec, pphMain);
END InitNew;
PROCEDURE ReInit ( cr : CodestreamReader;
decSpec : DecoderSpecs;
pphMain : DataListElement);
VAR
nt, ncomp : LONGINT;
BEGIN
SELF.cr := cr;
SELF.decSpec := decSpec;
curByte := 0;
curBytePos := 0;
curTile := 0;
nt := decSpec.imgInfo.GetNumTiles();
ncomp := decSpec.imgInfo.GetNumComponents();
NEW(precInfo, nt, ncomp);
NEW(lblock, nt, ncomp);
NEW(inclTrees, nt, ncomp);
NEW(zeroTrees, nt, ncomp);
NEW(cblkInfo, nt, ncomp);
NEW(incStep, nt, ncomp);
NEW(minIncStep, nt, ncomp);
NEW(sotEot, nt, ncomp);
NEW(maxSotEot, nt, ncomp);
IF pphMain # NIL THEN
NEW(pph);
NEW(pph.data, 1);
pphPos := 1;
pph.next := pphMain;
pphMainUsed := TRUE;
ELSE
pph := NIL;
pphMainUsed := FALSE;
END;
pphTileFirstLast := NIL;
pphTileUsed := NIL;
END ReInit;
PROCEDURE SetAndInitTile(t : LONGINT);
VAR
c, r, ndec : LONGINT;
BEGIN
BuildIncSotEotArrays(t);
FOR c := 0 TO decSpec.imgInfo.ncomp - 1 DO
ndec := decSpec.cstyle[t][c].ndec;
NEW(precInfo[t][c], ndec + 1);
NEW(lblock[t][c], ndec + 1);
NEW(zeroTrees[t][c], ndec + 1);
NEW(inclTrees[t][c], ndec + 1);
NEW(cblkInfo[t][c], ndec + 1);
FOR r := 0 TO ndec DO
CreatePrecinctInfo(t, c, r, precInfo[t][c][r]);
InitSubbands(t, c, r, precInfo[t][c][r]);
END;
END;
SetTile(t);
END SetAndInitTile;
PROCEDURE SetTile (t : LONGINT);
BEGIN
IF pphTileUsed # NIL THEN
IF pph # NIL THEN
pphTileFirstLast[curTile][0] := pph;
pphTilePos[curTile] := pphPos;
END;
IF pphTileUsed[t] THEN
pph := pphTileFirstLast[t][0];
pphPos := pphTilePos[t];
ELSE
pph := NIL;
END;
END;
IF (pph # NIL) & (pphPos >= LEN(pph.data^)) THEN
pph := pph.next;
pphPos := 0;
END;
sopUsed := decSpec.cics[t].sop;
ephUsed := decSpec.cics[t].eph;
SELF.curTile := t;
END SetTile;
PROCEDURE BuildIncSotEotArrays (tile : LONGINT);
VAR
c, r, subsX, subsY, ndec, ppx, ppy, shift : LONGINT;
tileCompULX, tileCompWidth, tileCompULY, tileCompHeight : LONGINT;
subbInfo : J2KU.SubbandInfo;
BEGIN
FOR c := 0 TO decSpec.imgInfo.ncomp - 1 DO
ndec := decSpec.cstyle[tile][c].ndec;
subsX := decSpec.imgInfo.comps[c].subsx;
subsY := decSpec.imgInfo.comps[c].subsy;
minIncStep[tile][c][0] := MAX(LONGINT);
minIncStep[tile][c][1] := MAX(LONGINT);
NEW(incStep[tile][c], ndec + 1);
NEW(sotEot[tile][c], ndec + 1);
subbInfo := cr.GetSubbandInfo(tile, c, ndec, J2KU.SUB_LL);
tileCompULX := subbInfo.ulcx;
tileCompWidth := subbInfo.width;
tileCompULY := subbInfo.ulcy;
tileCompHeight := subbInfo.height;
FOR r := 0 TO ndec DO
ppx := decSpec.GetPPX(tile, c, r);
ppy := decSpec.GetPPY(tile, c, r);
shift := ndec - r;
incStep[tile][c][r][0] := SYSTEM.LSH(SYSTEM.LSH(subsX, shift), ppx);
IF incStep[tile][c][r][0] < minIncStep[tile][c][0] THEN
minIncStep[tile][c][0] := incStep[tile][c][r][0];
END;
incStep[tile][c][r][1] := SYSTEM.LSH(SYSTEM.LSH(subsY, shift), ppy);
IF incStep[tile][c][r][1] < minIncStep[tile][c][1] THEN
minIncStep[tile][c][1] := incStep[tile][c][r][1];
END;
IF incStep[tile][c][r][0] = 0 THEN
sotEot[tile][c][r][0][0] := 0;
sotEot[tile][c][r][0][1] := 1;
incStep[tile][c][r][0] := 1;
ELSE
sotEot[tile][c][r][0][0] := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, tileCompULX)
* (SYSTEM.VAL(SET, incStep[tile][c][r][0] - 1) / SYSTEM.VAL(SET, J2KU.SWAP_MASK))
);
sotEot[tile][c][r][0][1] := tileCompULX + tileCompWidth;
END;
IF incStep[tile][c][r][1] = 0 THEN
sotEot[tile][c][r][1][0] := 0;
sotEot[tile][c][r][1][1] := 1;
incStep[tile][c][r][1] := 1;
ELSE
sotEot[tile][c][r][1][0] := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, tileCompULY)
* (SYSTEM.VAL(SET, incStep[tile][c][r][1] - 1) / SYSTEM.VAL(SET, J2KU.SWAP_MASK))
);
sotEot[tile][c][r][1][1] := tileCompULY + tileCompHeight;
END;
END;
IF minIncStep[tile][c][0] = 0 THEN
maxSotEot[tile][c][0][0] := 0;
maxSotEot[tile][c][0][1] := 1;
minIncStep[tile][c][0] := 1;
ELSE
maxSotEot[tile][c][0][0] := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, tileCompULX)
* (SYSTEM.VAL(SET, minIncStep[tile][c][0] - 1) / SYSTEM.VAL(SET, J2KU.SWAP_MASK))
);
maxSotEot[tile][c][0][1] := tileCompULX + tileCompWidth;
END;
IF minIncStep[tile][c][1] = 0 THEN
maxSotEot[tile][c][1][0] := 0;
maxSotEot[tile][c][1][1] := 1;
minIncStep[tile][c][1] := 1;
ELSE
maxSotEot[tile][c][1][0] := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, tileCompULY)
* (SYSTEM.VAL(SET, minIncStep[tile][c][1] - 1) / SYSTEM.VAL(SET, J2KU.SWAP_MASK))
);
maxSotEot[tile][c][1][1] := tileCompULY + tileCompHeight;
END;
END;
END BuildIncSotEotArrays;
PROCEDURE CreatePrecinctInfo(tile, comp, reslevel : LONGINT; VAR precInfo : PrecinctInfo);
VAR
incX, incY, incXR, incYR, maxSotX, maxSotY, maxEotX, maxEotY, sotX, sotY, xr, yr : LONGINT;
ppx, ppy, nprecx, nprecy, nprec, curPrec, px, py, width, height : LONGINT;
cblkw, cblkh : LONGINT;
nband, subband : LONGINT;
subbInfo : J2KU.SubbandInfo;
cblkwCeil, cblkhCeil : LONGINT;
precw, prech : LONGINT;
ndec : LONGINT;
maxpsUsed : BOOLEAN;
tmp : LONGINT;
BEGIN
cblkw := decSpec.cstyle[tile][comp].cblw;
cblkh := decSpec.cstyle[tile][comp].cblh;
maxpsUsed := decSpec.cstyle[tile][comp].maxps;
ndec := decSpec.cstyle[tile][comp].ndec;
ppx := decSpec.GetPPX(tile, comp, reslevel);
ppy := decSpec.GetPPY(tile, comp, reslevel);
incX := minIncStep[tile][comp][0];
incY := minIncStep[tile][comp][1];
IF reslevel = 0 THEN
IF cblkw > ppx THEN
cblkw := ppx;
END;
IF cblkh > ppy THEN
cblkh := ppy;
END;
precw := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppx);
prech := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppy);
nband := 1;
ELSE
IF cblkw > (ppx - 1) THEN
cblkw := ppx - 1;
END;
IF cblkh > (ppy - 1) THEN
cblkh := ppy - 1;
END;
precw := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppx - 1);
prech := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppy - 1);
nband := 3;
END;
subbInfo := cr.GetSubbandInfo(tile, comp, reslevel, J2KU.SUB_LL);
IF subbInfo.width > 0 THEN
tmp := SYSTEM.LSH(subbInfo.ulcx + subbInfo.width + SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppx) - 1, -ppx);
nprecx := tmp - SYSTEM.LSH(subbInfo.ulcx, -ppx);
ELSE
nprecx := 0;
END;
IF subbInfo.height > 0 THEN
tmp := SYSTEM.LSH(subbInfo.ulcy + subbInfo.height + SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), ppy) - 1, -ppy);
nprecy := tmp - SYSTEM.LSH(subbInfo.ulcy, -ppy);
ELSE
nprecy := 0;
END;
nprec := nprecx * nprecy;
precInfo.nprecx := nprecx;
precInfo.nprecy := nprecy;
NEW(precInfo.nblocks, nband, nprec);
incXR := incStep[tile][comp][reslevel][0];
incYR := incStep[tile][comp][reslevel][1];
maxSotX := maxSotEot[tile][comp][0][0];
maxSotY := maxSotEot[tile][comp][1][0];
maxEotX := maxSotEot[tile][comp][0][1];
maxEotY := maxSotEot[tile][comp][1][1];
sotX := sotEot[tile][comp][reslevel][0][0];
sotY := sotEot[tile][comp][reslevel][1][0];
cblkwCeil := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblkw) - 1;
cblkhCeil := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblkh) - 1;
curPrec := 0;
yr := maxSotY;
WHILE yr < maxEotY DO
xr := maxSotX;
WHILE xr < maxEotX DO
IF ((xr = maxSotX) OR (xr MOD incXR = 0))
& ((yr = maxSotY) OR (yr MOD incYR = 0))
THEN
IF curPrec < nprec THEN
FOR subband := 0 TO nband - 1 DO
subbInfo := cr.GetSubbandInfo(tile, comp, reslevel, J2KU.SubbandIndexToSubband(reslevel, subband));
IF (xr = maxSotX)
& (SYSTEM.LSH(sotX, reslevel - ndec) # maxSotX)
THEN
IF reslevel = 0 THEN
px := SYSTEM.LSH(sotX, reslevel - ndec) - subbInfo.ulcx;
ELSE
px := SYSTEM.LSH(sotX, reslevel - ndec - 1) - subbInfo.ulcx;
END;
ELSE
IF reslevel = 0 THEN
px := SYSTEM.LSH(xr, reslevel - ndec) - subbInfo.ulcx;
ELSE
px := SYSTEM.LSH(xr, reslevel - ndec - 1) - subbInfo.ulcx;
END;
END;
IF (yr = maxSotY)
& (SYSTEM.LSH(sotY, reslevel - ndec) # maxSotY)
THEN
IF reslevel = 0 THEN
py := SYSTEM.LSH(sotY, reslevel - ndec) - subbInfo.ulcy;
ELSE
py := SYSTEM.LSH(sotY, reslevel - ndec - 1) - subbInfo.ulcy;
END;
ELSE
IF reslevel = 0 THEN
py := SYSTEM.LSH(yr, reslevel - ndec) - subbInfo.ulcy;
ELSE
py := SYSTEM.LSH(yr, reslevel - ndec - 1) - subbInfo.ulcy;
END;
END;
IF (subbInfo.width <= 0) OR (subbInfo.height <= 0)
OR (px + precw <= 0) OR (py + prech <= 0)
OR (px >= subbInfo.width) OR (py >= subbInfo.height)
THEN
precInfo.nblocks[subband][curPrec][0] := 0;
precInfo.nblocks[subband][curPrec][1] := 0;
ELSE
IF px + precw > subbInfo.width THEN
width := subbInfo.width - px;
ELSE
width := precw;
END;
IF px < 0 THEN
width := width + px;
px := 0;
END;
precInfo.nblocks[subband][curPrec][0] := SYSTEM.LSH(px + subbInfo.ulcx + width + cblkwCeil, -cblkw)
- SYSTEM.LSH(px + subbInfo.ulcx, -cblkw);
IF py + prech > subbInfo.height THEN
height := subbInfo.height - py;
ELSE
height := prech;
END;
IF py < 0 THEN
height := height + py;
py := 0;
END;
precInfo.nblocks[subband][curPrec][1] := SYSTEM.LSH(py + subbInfo.ulcy + height + cblkhCeil, -cblkh)
- SYSTEM.LSH(py + subbInfo.ulcy , -cblkh);
END;
END;
INC(curPrec);
END;
END;
INC(xr, incX);
END;
INC(yr, incY);
END;
END CreatePrecinctInfo;
PROCEDURE InitSubbands (tile, comp, reslevel : LONGINT; VAR precInfo : PrecinctInfo);
VAR
nl : LONGINT;
nband, subband : LONGINT;
subbInfo : J2KU.SubbandInfo;
ppx, ppy, nprec, precx, nprecx, precy, nprecy, precIdx : LONGINT;
nblocks, ncblkx, ncblky, cblkIdx, cblkIdxX, cblkIdxY, cblkPrecIdx, i, j, cblkw, cblkh : LONGINT;
cblkInfoObj : J2KU.CblkInfo;
cblkStartX, cblkStartY : LONGINT;
nomCblkw, nomCblkh : LONGINT;
tmp1, tmp2 : LONGINT;
BEGIN
nl := decSpec.cics[tile].nl;
ppx := decSpec.GetPPX(tile, comp, reslevel);
ppy := decSpec.GetPPY(tile, comp, reslevel);
cblkw := decSpec.cstyle[tile][comp].cblw;
cblkh := decSpec.cstyle[tile][comp].cblh;
IF reslevel = 0 THEN
IF cblkw > ppx THEN
cblkw := ppx;
END;
IF cblkh > ppy THEN
cblkh := ppy;
END;
nband := 1;
ELSE
IF cblkw > (ppx - 1) THEN
cblkw := ppx - 1;
END;
IF cblkh > (ppy - 1) THEN
cblkh := ppy - 1;
END;
nband := 3;
END;
nomCblkw := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblkw);
nomCblkh := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblkh);
nprecx := precInfo.nprecx;
nprecy := precInfo.nprecy;
nprec := nprecx*nprecy;
NEW(zeroTrees[tile][comp][reslevel], nband);
NEW(inclTrees[tile][comp][reslevel], nband);
NEW(lblock[tile][comp][reslevel], nband);
NEW(cblkInfo[tile][comp][reslevel], nband);
FOR subband := 0 TO nband - 1 DO
subbInfo := cr.GetSubbandInfo(tile, comp, reslevel, J2KU.SubbandIndexToSubband(reslevel, subband));
NEW(zeroTrees[tile][comp][reslevel][subband], nprec);
NEW(inclTrees[tile][comp][reslevel][subband], nprec);
NEW(lblock[tile][comp][reslevel][subband], nprec);
NEW(cblkInfo[tile][comp][reslevel][subband], nprec);
cblkIdx := 0;
precIdx := 0;
cblkStartY := SYSTEM.LSH(SYSTEM.LSH(subbInfo.ulcy, -cblkh), cblkh);
cblkStartX := SYSTEM.LSH(SYSTEM.LSH(subbInfo.ulcx, -cblkw), cblkw);
FOR precy := 0 TO nprecy - 1 DO
tmp1 := cblkIdx;
FOR precx := 0 TO nprecx - 1 DO
ncblkx := precInfo.nblocks[subband][precIdx][0];
ncblky := precInfo.nblocks[subband][precIdx][1];
nblocks := ncblkx*ncblky;
NEW(zeroTrees[tile][comp][reslevel][subband][precIdx], ncblkx, ncblky, SELF);
NEW(inclTrees[tile][comp][reslevel][subband][precIdx], ncblkx, ncblky, SELF);
IF nblocks > 0 THEN
NEW(lblock[tile][comp][reslevel][subband][precIdx], nblocks);
NEW(cblkInfo[tile][comp][reslevel][subband][precIdx], nblocks);
Machine.Fill32(SYSTEM.ADR(lblock[tile][comp][reslevel][subband][precIdx][0]), nblocks*SYSTEM.SIZEOF(LONGINT), 3);
END;
cblkPrecIdx := 0;
tmp2 := cblkIdx;
FOR i := 0 TO ncblky - 1 DO
FOR j := 0 TO ncblkx - 1 DO
NEW(cblkInfoObj);
cblkInfoObj.subbinfo := subbInfo;
cblkInfoObj.index := cblkIdx;
NEW(cblkInfoObj.cpasseslyr, nl);
NEW(cblkInfoObj.datalenlyr, nl);
cblkIdxX := cblkIdx MOD subbInfo.nblocksx;
cblkIdxY := cblkIdx DIV subbInfo.nblocksx;
IF cblkIdxY = 0 THEN
cblkInfoObj.ulsy := subbInfo.ulsy;
ELSE
cblkInfoObj.ulsy := cblkStartY + cblkIdxY*nomCblkh - subbInfo.ulcy + subbInfo.ulsy;
END;
IF cblkIdxX = 0 THEN
cblkInfoObj.ulsx := subbInfo.ulsx;
ELSE
cblkInfoObj.ulsx := cblkStartX + cblkIdxX*nomCblkw - subbInfo.ulcx + subbInfo.ulsx;
END;
IF (cblkIdxY < subbInfo.nblocksy - 1) THEN
cblkInfoObj.height := cblkStartY + (cblkIdxY+1)*nomCblkh - subbInfo.ulcy + subbInfo.ulsy - cblkInfoObj.ulsy;
ELSE
cblkInfoObj.height := (subbInfo.ulsy + subbInfo.height) - cblkInfoObj.ulsy;
END;
IF (cblkIdxX < subbInfo.nblocksx - 1) THEN
cblkInfoObj.width := cblkStartX + (cblkIdxX+1)*nomCblkw - subbInfo.ulcx + subbInfo.ulsx - cblkInfoObj.ulsx;
ELSE
cblkInfoObj.width := (subbInfo.ulsx + subbInfo.width) - cblkInfoObj.ulsx;
END;
cblkInfo[tile][comp][reslevel][subband][precIdx][cblkPrecIdx] := cblkInfoObj;
INC(cblkIdx);
INC(cblkPrecIdx);
END;
cblkIdx := (cblkIdx - ncblkx) + subbInfo.nblocksx;
END;
cblkIdx := tmp2 + ncblkx;
INC(precIdx);
END;
cblkIdx := tmp1 + ncblky*subbInfo.nblocksx;
END;
END;
END InitSubbands;
PROCEDURE SetPPHeadersTile (pphNewFirst, pphNewLast : DataListElement; tile : LONGINT);
VAR
nt, i : LONGINT;
BEGIN
ASSERT(~pphMainUsed);
IF pphTileFirstLast = NIL THEN
nt := decSpec.imgInfo.nt;
NEW(pphTileFirstLast, nt, 2);
NEW(pphTilePos, nt);
NEW(pphTileUsed, nt);
FOR i := 0 TO nt - 1 DO
pphTileUsed[i] := FALSE;
END;
END;
IF pphTileFirstLast[tile][0] = NIL THEN
pphTileFirstLast[tile][0] := pphNewFirst;
pphTileFirstLast[tile][1] := pphNewLast;
pphTilePos[tile] := 0;
pphTileUsed[tile] := TRUE;
ELSE
pphTileFirstLast[tile][1].next := pphNewFirst;
pphTileFirstLast[tile][1] := pphNewLast;
END;
END SetPPHeadersTile;
PROCEDURE PPHTileUsed () : BOOLEAN;
BEGIN
RETURN ((pphTileUsed # NIL) & pphTileUsed[curTile]);
END PPHTileUsed;
PROCEDURE PPHMainAvailable () : BOOLEAN;
BEGIN
ASSERT(pphMainUsed);
RETURN (pph # NIL) & (pphPos < LEN(pph.data^));
END PPHMainAvailable;
PROCEDURE PPHTileAvailable () : BOOLEAN;
BEGIN
ASSERT(~pphMainUsed);
RETURN (pph # NIL) & ((pphPos < LEN(pph.data^)) OR (pph.next # NIL));
END PPHTileAvailable;
PROCEDURE DecodePacket (comp, reslevel, layer, precno : LONGINT; VAR cblk : ARRAY OF J2KU.CodedCblk; VAR cblkInfo : ARRAY OF J2KU.CblkInfo) : LONGINT;
VAR
blocksInPacket, i, j, bit, bitsUsed, subband, nbands, ncblx, ncbly, cblkx, cblky : LONGINT;
cblkPrecIdx, cpasses, nseg, passtype, dataLen, lastIdx : LONGINT;
inclTree, zeroTree : J2KU.TagTree;
emptyPkt, included : BOOLEAN;
cInfo : J2KU.CblkInfo;
BEGIN
IF precno
>= (precInfo[curTile][comp][reslevel].nprecx * precInfo[curTile][comp][reslevel].nprecy)
THEN
RETURN 0;
END;
IF sopUsed THEN
ReadSOP();
END;
curBytePos := 0;
IF reslevel = 0 THEN
nbands := 1;
ELSE
nbands := 3;
END;
blocksInPacket := 0;
IF NextBit() = 0 THEN
emptyPkt := TRUE;
ELSE
emptyPkt := FALSE;
END;
FOR subband := 0 TO nbands - 1 DO
inclTree := inclTrees[curTile][comp][reslevel][subband][precno];
zeroTree := zeroTrees[curTile][comp][reslevel][subband][precno];
ncblx := precInfo[curTile][comp][reslevel].nblocks[subband][precno][0];
ncbly := precInfo[curTile][comp][reslevel].nblocks[subband][precno][1];
cblkPrecIdx := 0;
FOR cblky := 0 TO ncbly - 1 DO
FOR cblkx := 0 TO ncblx - 1 DO
cInfo := SELF.cblkInfo[curTile][comp][reslevel][subband][precno][cblkPrecIdx];
included := FALSE;
IF ~emptyPkt THEN
IF ~inclTree.IsValid(cblkx, cblky) THEN
IF ~inclTree.Update(cblkx, cblky, layer) THEN
RETURN -1;
END;
IF inclTree.IsValid(cblkx, cblky) THEN
included := TRUE;
END;
ELSE
bit := NextBit();
IF bit = 1 THEN
included := TRUE;
END;
END;
END;
IF included THEN
IF ~zeroTree.IsValid(cblkx, cblky) THEN
IF ~zeroTree.Update(cblkx, cblky, MAX(LONGINT)) THEN
RETURN -1;
END;
cInfo.zerobp := zeroTree.CurrentVal(cblkx, cblky);
cInfo.curbp := J2KU.LONGINT_BITS - 2 - cInfo.zerobp;
cInfo.truncpt := 0;
END;
cpasses := ReadCodingPasses();
cblk[blocksInPacket].cpasses := cpasses;
INC(cInfo.truncpt, cpasses);
bit := NextBit();
WHILE bit = 1 DO
INC(lblock[curTile][comp][reslevel][subband][precno][cblkPrecIdx]);
bit := NextBit();
END;
IF decSpec.cstyle[curTile][comp].term THEN
nseg := cpasses;
ELSIF decSpec.cstyle[curTile][comp].selcb THEN
IF cInfo.truncpt <= ENTROPY_FIRST_BYPASS_IDX THEN
nseg := 1;
ELSE
nseg := 1;
FOR i := cInfo.truncpt - cpasses TO cInfo.truncpt - 2 DO
IF i >= ENTROPY_FIRST_BYPASS_IDX - 1 THEN
passtype := i MOD ENTROPY_NUM_PASSES;
IF (passtype = 0) OR (passtype = 2) THEN
INC(nseg);
END;
END;
END;
END;
ELSE
nseg := 1;
END;
cblk[blocksInPacket].nseg := nseg;
IF nseg = 1 THEN
bitsUsed := lblock[curTile][comp][reslevel][subband][precno][cblkPrecIdx] + J2KU.Log2Floor(cpasses);
cblk[blocksInPacket].dataLen := NextBits(bitsUsed);
ELSE
NEW(cblk[blocksInPacket].segLen, nseg);
dataLen := 0;
IF decSpec.cstyle[curTile][comp].term THEN
FOR i := 0 TO nseg - 1 DO
bitsUsed := lblock[curTile][comp][reslevel][subband][precno][cblkPrecIdx];
cblk[blocksInPacket].segLen[i] := NextBits(bitsUsed);
INC(dataLen, cblk[blocksInPacket].segLen[i]);
END;
ELSIF decSpec.cstyle[curTile][comp].selcb THEN
j := 0;
lastIdx := cInfo.truncpt - cpasses - 1;
FOR i := cInfo.truncpt - cpasses TO cInfo.truncpt - 2 DO
IF i >= ENTROPY_FIRST_BYPASS_IDX - 1 THEN
passtype := i MOD ENTROPY_NUM_PASSES;
IF passtype # 1 THEN
bitsUsed := lblock[curTile][comp][reslevel][subband][precno][cblkPrecIdx] + J2KU.Log2Floor(i - lastIdx);
cblk[blocksInPacket].segLen[j] := NextBits(bitsUsed);
INC(dataLen, cblk[blocksInPacket].segLen[j]);
INC(j);
lastIdx := i;
END;
END;
END;
bitsUsed := lblock[curTile][comp][reslevel][subband][precno][cblkPrecIdx] + J2KU.Log2Floor(i - lastIdx);
cblk[blocksInPacket].segLen[j] := NextBits(bitsUsed);
INC(dataLen, cblk[blocksInPacket].segLen[j]);
END;
cblk[blocksInPacket].dataLen := dataLen;
END;
ELSE
cblk[blocksInPacket].segLen := NIL;
cblk[blocksInPacket].dataLen := 0;
cblk[blocksInPacket].cpasses := 0;
END;
cblkInfo[blocksInPacket] := cInfo;
IF layer = 0 THEN
cInfo.cpasseslyr[layer] := cblk[blocksInPacket].cpasses;
cInfo.datalenlyr[layer] := cblk[blocksInPacket].dataLen;
ELSE
cInfo.cpasseslyr[layer] := cblk[blocksInPacket].cpasses + cInfo.cpasseslyr[layer - 1];
cInfo.datalenlyr[layer] := cblk[blocksInPacket].dataLen + cInfo.datalenlyr[layer - 1];
END;
INC(blocksInPacket);
INC(cblkPrecIdx);
END;
END;
END;
IF curByte = 0FFH THEN
curByte := NextByte();
END;
IF ephUsed THEN
ReadEPH();
END;
FOR i := 0 TO blocksInPacket - 1 DO
IF cblk[i].dataLen > 0 THEN
NEW(cblk[i].data, cblk[i].dataLen);
cr.ReadBytes(cblk[i].data^, cblk[i].dataLen);
cblk[i].dataOffset := 0;
END;
END;
RETURN blocksInPacket;
END DecodePacket;
PROCEDURE ReadCodingPasses() : LONGINT;
VAR
buf : LONGINT;
BEGIN
buf := NextBit();
IF buf = 0 THEN
RETURN 1;
END;
buf := NextBit();
IF buf = 0 THEN
RETURN 2;
END;
buf := NextBits(2);
IF buf < 00000003H THEN
RETURN 3 + buf;
END;
buf := NextBits(5);
IF buf < 0000001FH THEN
RETURN 6 + buf;
END;
buf := NextBits(7);
RETURN 37 + buf;
END ReadCodingPasses;
PROCEDURE GetNumPrecincts(comp, reslevel : LONGINT) : LONGINT;
BEGIN
RETURN precInfo[curTile][comp][reslevel].nprecx * precInfo[curTile][comp][reslevel].nprecy;
END GetNumPrecincts;
PROCEDURE GetMaxNumCodeblocksPkt() : LONGINT;
VAR
ncomp, nprec, ndec, maxCblks, curCblks : LONGINT;
i, r, k : LONGINT;
BEGIN
ncomp := decSpec.imgInfo.GetNumComponents();
maxCblks := 0;
FOR i := 0 TO ncomp - 1 DO
nprec := precInfo[curTile][i][0].nprecx * precInfo[curTile][i][0].nprecy;
FOR k := 0 TO nprec - 1 DO
curCblks := precInfo[curTile][i][0].nblocks[0][k][0] * precInfo[curTile][i][0].nblocks[0][k][1];
IF curCblks > maxCblks THEN
maxCblks := curCblks;
END;
END;
ndec := decSpec.GetNumDecLevels(curTile, i);
FOR r := 1 TO ndec DO
nprec := precInfo[curTile][i][r].nprecx * precInfo[curTile][i][r].nprecy;
FOR k := 0 TO nprec - 1 DO
curCblks := precInfo[curTile][i][r].nblocks[0][k][0] * precInfo[curTile][i][r].nblocks[0][k][1]
+ precInfo[curTile][i][r].nblocks[1][k][0] * precInfo[curTile][i][r].nblocks[1][k][1]
+ precInfo[curTile][i][r].nblocks[2][k][0] * precInfo[curTile][i][r].nblocks[2][k][1];
IF curCblks > maxCblks THEN
maxCblks := curCblks;
END;
END;
END;
END;
RETURN maxCblks;
END GetMaxNumCodeblocksPkt;
PROCEDURE GetCblkInfo (comp, reslevel, subband, cblkSubbIdx : LONGINT) : J2KU.CblkInfo;
VAR
lastIdx, cblkPrecIdx, cblkPrecIdxX, cblkPrecIdxY : LONGINT;
nprecx, precIdx, precMin, precMax, precX, precY, precFirstInRowIdx : LONGINT;
subbIdx, cblkSubbIdxX, cblkSubbIdxY, cblkInfoUpLeftIdx, cblkInfoLowRightIdx : LONGINT;
subbInfo : J2KU.SubbandInfo;
BEGIN
nprecx := precInfo[curTile][comp][reslevel].nprecx;
subbIdx := J2KU.SubbandToSubbandIndex(subband);
subbInfo := cr.GetSubbandInfo(curTile, comp, reslevel, subband);
cblkSubbIdxX := cblkSubbIdx MOD subbInfo.nblocksx;
cblkSubbIdxY := cblkSubbIdx DIV subbInfo.nblocksx;
precMin := 0;
precMax := nprecx - 1;
precX := ASH(precMax + precMin, -1);
LOOP
IF precMax <= precMin THEN EXIT END;
cblkInfoUpLeftIdx := cblkInfo[curTile][comp][reslevel][subbIdx][precX][0].index;
lastIdx := LEN(cblkInfo[curTile][comp][reslevel][subbIdx][precX]^) - 1;
cblkInfoLowRightIdx := cblkInfo[curTile][comp][reslevel][subbIdx][precX][lastIdx].index;
IF (cblkInfoUpLeftIdx MOD subbInfo.nblocksx) > cblkSubbIdxX THEN
precMax := precX - 1;
ELSIF (cblkInfoLowRightIdx MOD subbInfo.nblocksx) < cblkSubbIdxX THEN
precMin := precX + 1;
ELSE
EXIT;
END;
precX := ASH(precMax + precMin, -1);
END;
precMin := 0;
precMax := precInfo[curTile][comp][reslevel].nprecy - 1;
precY := ASH(precMax + precMin, -1);
precFirstInRowIdx := ASH(precMax + precMin, -1)*nprecx;
LOOP
IF precMax <= precMin THEN EXIT END;
cblkInfoUpLeftIdx := cblkInfo[curTile][comp][reslevel][subbIdx][precFirstInRowIdx][0].index;
lastIdx := LEN(cblkInfo[curTile][comp][reslevel][subbIdx][precFirstInRowIdx]^) - 1;
cblkInfoLowRightIdx := cblkInfo[curTile][comp][reslevel][subbIdx][precFirstInRowIdx][lastIdx].index;
IF (cblkInfoUpLeftIdx DIV subbInfo.nblocksx) > cblkSubbIdxY THEN
precMax := precY - 1;
ELSIF (cblkInfoLowRightIdx DIV subbInfo.nblocksx) < cblkSubbIdxY THEN
precMin := precY + 1;
ELSE
EXIT;
END;
precY := ASH(precMax + precMin, -1);
precFirstInRowIdx := ASH(precMax + precMin, -1)*nprecx;
END;
precIdx := precFirstInRowIdx + precX;
cblkInfoUpLeftIdx := cblkInfo[curTile][comp][reslevel][subbIdx][precIdx][0].index;
cblkPrecIdxX := cblkSubbIdxX - (cblkInfoUpLeftIdx MOD subbInfo.nblocksx);
cblkPrecIdxY := cblkSubbIdxY - (cblkInfoUpLeftIdx DIV subbInfo.nblocksx);
cblkPrecIdx := cblkPrecIdxY*precInfo[curTile][comp][reslevel].nblocks[subbIdx][precIdx][0] + cblkPrecIdxX;
RETURN cblkInfo[curTile][comp][reslevel][subbIdx][precIdx][cblkPrecIdx];
END GetCblkInfo;
PROCEDURE GetIncStep (comp, reslevel : LONGINT; VAR xStep, yStep : LONGINT);
BEGIN
xStep := incStep[curTile][comp][reslevel][0];
yStep := incStep[curTile][comp][reslevel][1];
END GetIncStep;
PROCEDURE GetMinIncStep (comp : LONGINT; VAR xStep, yStep : LONGINT);
BEGIN
xStep := minIncStep[curTile][comp][0];
yStep := minIncStep[curTile][comp][1];
END GetMinIncStep;
PROCEDURE GetSotEot (comp, reslevel : LONGINT; VAR sotX, eotX, sotY, eotY : LONGINT);
BEGIN
sotX := sotEot[curTile][comp][reslevel][0][0];
eotX := sotEot[curTile][comp][reslevel][0][1];
sotY := sotEot[curTile][comp][reslevel][1][0];
eotY := sotEot[curTile][comp][reslevel][1][1];
END GetSotEot;
PROCEDURE GetMaxSotEot (comp : LONGINT; VAR sotX, eotX, sotY, eotY : LONGINT);
BEGIN
sotX := maxSotEot[curTile][comp][0][0];
eotX := maxSotEot[curTile][comp][0][1];
sotY := maxSotEot[curTile][comp][1][0];
eotY := maxSotEot[curTile][comp][1][1];
END GetMaxSotEot;
PROCEDURE ReadSOP;
VAR
marker : LONGINT;
tmpBytes : ARRAY 6 OF CHAR;
BEGIN
marker := cr.Peek16();
IF marker = SOP THEN
cr.ReadBytes(tmpBytes, 6);
END;
END ReadSOP;
PROCEDURE ReadEPH;
VAR
marker : LONGINT;
tmpBytes : ARRAY 2 OF CHAR;
BEGIN
IF (pph # NIL) & ((LEN(pph.data^) - pphPos) >= 2) THEN
marker := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(LONG(ORD(pph.data[pphPos])), 8))
+ SYSTEM.VAL(SET, LONG(ORD(pph.data[pphPos + 1])))
);
IF marker = EPH THEN
INC(pphPos, 2);
END;
ELSE
marker := cr.Peek16();
IF marker = EPH THEN
cr.ReadBytes(tmpBytes, 2);
END;
END;
END ReadEPH;
PROCEDURE NextByte () : LONGINT;
VAR
byte8 : CHAR;
BEGIN
IF pph # NIL THEN
IF pphPos >= LEN(pph.data^) THEN
pph := pph.next;
IF pph = NIL THEN
KernelLog.String("ERROR (PacketDecoder.NextByte) : No more data available from packed packet headers");
KernelLog.Ln();
RETURN -1;
END;
pphPos := 0;
END;
INC(pphPos);
RETURN ORD(pph.data[pphPos - 1]);
ELSE
cr.ReadByte(byte8);
RETURN ORD(byte8);
END;
END NextByte;
PROCEDURE NextBit() : LONGINT;
BEGIN
IF curBytePos = 0 THEN
IF curByte = 0FFH THEN
curBytePos := 7;
ELSE
curBytePos := 8;
END;
curByte := NextByte();
END;
DEC(curBytePos);
RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.LSH(curByte, -curBytePos)) * {0} );
END NextBit;
PROCEDURE NextBits (n : LONGINT) : LONGINT;
VAR
result : LONGINT;
BEGIN
IF n <= curBytePos THEN
DEC(curBytePos, n);
RETURN SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(curByte, -curBytePos))
* SYSTEM.VAL(SET, SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), n) - 1)
);
ELSE
result := 0;
REPEAT
result := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(result, curBytePos))
+ (
SYSTEM.VAL(SET, curByte)
* SYSTEM.VAL(SET, SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), curBytePos) - 1)
)
);
DEC(n, curBytePos);
IF curByte = 0FFH THEN
curBytePos := 7;
ELSE
curBytePos := 8;
END;
curByte := NextByte();
UNTIL n <= curBytePos;
DEC(curBytePos, n);
result := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(result, n))
+ SYSTEM.VAL(SET, SYSTEM.LSH(curByte, -curBytePos))
);
RETURN result;
END;
END NextBits;
END PacketDecoder;
CodestreamReader* = OBJECT
VAR
s : Streams.Reader;
ntp : LONGINT;
ntilePartsRead : J2KU.LongIntArrayPtr;
ntilePartsAvailable : J2KU.LongIntArrayPtr;
curTile : LONGINT;
curPart : LONGINT;
partRem : LONGINT;
initError : BOOLEAN;
pktDec : PacketDecoder;
cblkBuf : POINTER TO ARRAY OF J2KU.CodedCblk;
cblkInfoBuf : POINTER TO ARRAY OF J2KU.CblkInfo;
cblkBufSize : LONGINT;
ncblkInBuf : LONGINT;
cblkBufPos : LONGINT;
endOfCS : BOOLEAN;
curMarker : LONGINT;
subbInfos : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF J2KU.SubbandInfo;
decSpec : DecoderSpecs;
ppmUsed : BOOLEAN;
buf8 : LONGINT;
buf8Valid : BOOLEAN;
progChanges : POINTER TO ARRAY OF ProgChangeArrayPtr;
progStates : POINTER TO ARRAY OF ProgState;
curLay, curComp, curRes : LONGINT;
curPrec : J2KU.LongInt3DArrayPtr;
lmin : J2KU.LongInt2DArrayPtr;
lmax, cmax, rmax, rmin, cmin : LONGINT;
curX, curY, incX, incY : LONGINT;
xmax, ymax, xmin, ymin : LONGINT;
progOrder : LONGINT;
maxStartLayer, maxEndLayer : LONGINT;
startLayer, endLayer : LONGINT;
maxStartDecLvl, maxEndDecLvl : LONGINT;
startDecLvl, endDecLvl : LONGINT;
printCSInfo : BOOLEAN;
printCOM : BOOLEAN;
PROCEDURE &InitNew* (crOpt : J2KU.CodestreamReaderOptions;
stream : Streams.Reader);
BEGIN
pktDec := NIL;
ReInit(crOpt, stream);
END InitNew;
PROCEDURE ReInit* (crOpt : J2KU.CodestreamReaderOptions;
stream : Streams.Reader);
VAR
ok : BOOLEAN;
nt, ncomp, comp, i, j : LONGINT;
markerStr : ARRAY 8 OF CHAR;
nppmLeft, nppmRead : LONGINT;
ppmFirst, ppmLast : DataListElement;
ncod, nqcd, npoc, ncrg : LONGINT;
ncoc, nqcc, nrgn : J2KU.LongIntArrayPtr;
changes : ProgChangeArrayPtr;
cstyle : CodingStyle;
cics : CICodingStyle;
quant : Quantization;
imgInfo : ImageInfo;
roiShift : LONGINT;
BEGIN
s := stream;
curMarker := s.Net16();
printCOM := crOpt.printComments;
IF curMarker # SOC THEN
KernelLog.String("ERROR (CodestreamReader.InitNew): Unexpected/Invalid marker found at beginning of codestream (");
MarkerToString(curMarker, markerStr);
KernelLog.String(markerStr);
KernelLog.String(")");
KernelLog.Ln();
initError := TRUE;
RETURN;
END;
curMarker := s.Net16();
IF curMarker # SIZ THEN
KernelLog.String("ERROR: Unexpected/Invalid marker found at beginning of main header (");
MarkerToString(curMarker, markerStr);
KernelLog.String(markerStr);
KernelLog.String(")");
KernelLog.Ln();
initError := TRUE;
RETURN;
END;
ok := ReadSIZSegment(imgInfo);
IF ok THEN
nt := imgInfo.nt;
ncomp := imgInfo.ncomp;
ncod := 0;
nqcd := 0;
npoc := 0;
ncrg := 0;
NEW(ncoc, ncomp);
NEW(nqcc, ncomp);
NEW(nrgn, ncomp);
Machine.Fill32(SYSTEM.ADR(ncoc[0]), imgInfo.ncomp*SYSTEM.SIZEOF(LONGINT), 0);
Machine.Fill32(SYSTEM.ADR(nqcc[0]), imgInfo.ncomp*SYSTEM.SIZEOF(LONGINT), 0);
Machine.Fill32(SYSTEM.ADR(nrgn[0]), imgInfo.ncomp*SYSTEM.SIZEOF(LONGINT), 0);
nppmLeft := 0;
nppmRead := 0;
ppmFirst := NIL;
ppmLast := NIL;
ppmUsed := FALSE;
progChanges := NIL;
NEW(decSpec);
decSpec.imgInfo := imgInfo;
NEW(decSpec.cstyle, nt, ncomp);
NEW(decSpec.cics, nt);
NEW(decSpec.quant, nt, ncomp);
NEW(decSpec.roiShift, nt, ncomp);
Machine.Fill32(SYSTEM.ADR(decSpec.roiShift[0][0]), nt*ncomp*SYSTEM.SIZEOF(LONGINT), -1);
curMarker := s.Net16();
END;
WHILE ok & (curMarker # SOT) DO
CASE curMarker OF
| COD :
ok := ReadCODSegment(cstyle, cics);
FOR i := 0 TO nt - 1 DO
decSpec.cics[i] := cics;
FOR j := 0 TO ncomp - 1 DO
IF ncoc[j] = 0 THEN
decSpec.cstyle[i][j] := cstyle;
END;
END;
END;
INC(ncod);
| COC :
ok := ReadCOCSegment(cstyle, comp);
IF ok THEN
FOR i := 0 TO nt - 1 DO
decSpec.cstyle[i][comp] := cstyle;
END;
INC(ncoc[comp]);
END;
| RGN :
ok := ReadRGNSegment(roiShift, comp);
IF ok THEN
FOR i := 0 TO nt - 1 DO
decSpec.roiShift[i][comp] := roiShift;
END;
INC(nrgn[comp]);
END;
| QCD :
ok := ReadQCDSegment(quant);
FOR i := 0 TO nt - 1 DO
FOR j := 0 TO ncomp - 1 DO
IF nqcc[j] = 0 THEN
decSpec.quant[i][j] := quant;
END;
END;
END;
INC(nqcd);
| QCC :
ok := ReadQCCSegment(quant, comp);
IF ok THEN
FOR i := 0 TO nt - 1 DO
decSpec.quant[i][comp] := quant;
END;
INC(nqcc[comp]);
END;
| POC :
ok := ReadPOCSegment(changes);
NEW(progChanges, nt);
FOR i := 0 TO nt - 1 DO
progChanges[i] := changes;
END;
INC(npoc);
| TLM :
ok := ReadTLMSegment();
| PLM :
ok := ReadPLMSegment();
| PPM :
ok := ReadPPMSegment(ppmFirst, ppmLast, nppmLeft, nppmRead);
ppmUsed := TRUE;
| CRG :
ok := ReadCRGSegment();
INC(ncrg);
| COM :
ok := ReadCOMSegment();
ELSE
KernelLog.String("ERROR: Unexpected/Invalid marker found in main header (");
MarkerToString(curMarker, markerStr);
KernelLog.String(markerStr);
KernelLog.String(")");
KernelLog.Ln();
ok := FALSE;
END;
curMarker := s.Net16();
END;
IF ok THEN
IF ncod # 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(ncod, 0);
KernelLog.String(" COD segments in main header (exactly 1 required)");
KernelLog.Ln();
ok := FALSE;
END;
IF nqcd # 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nqcd, 0);
KernelLog.String(" QCD segments in main header (exactly 1 required)");
KernelLog.Ln();
ok := FALSE;
END;
IF npoc > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(npoc, 0);
KernelLog.String(" POC segments in main header (at most 1 allowed)");
KernelLog.Ln();
ok := FALSE;
END;
IF ncrg > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(ncrg, 0);
KernelLog.String(" CRG segments in main header (at most 1 allowed)");
KernelLog.Ln();
ok := FALSE;
END;
FOR i := 0 TO ncomp - 1 DO
IF ncoc[i] > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(ncoc[i], 0);
KernelLog.String(" COC segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in main header (at most 1 per component allowed)");
KernelLog.Ln();
ok := FALSE;
END;
IF nqcc[i] > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nqcc[i], 0);
KernelLog.String(" QCC segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in main header (at most 1 per component allowed)");
KernelLog.Ln();
ok := FALSE;
END;
IF nrgn[i] > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nrgn[i], 0);
KernelLog.String(" RGN segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in main header (at most 1 per component allowed)");
KernelLog.Ln();
ok := FALSE;
END;
END;
END;
IF ok THEN
ntp := 0;
NEW(ntilePartsRead, nt);
NEW(ntilePartsAvailable, nt);
Machine.Fill32(SYSTEM.ADR(ntilePartsRead[0]), nt*SYSTEM.SIZEOF(LONGINT), 0);
Machine.Fill32(SYSTEM.ADR(ntilePartsAvailable[0]), nt*SYSTEM.SIZEOF(LONGINT), 0);
ncblkInBuf := 0;
cblkBufPos := 0;
cblkBufSize := 0;
partRem := 0;
endOfCS := FALSE;
buf8Valid := FALSE;
maxStartLayer := 0;
maxEndLayer := MAX(LONGINT);
maxStartDecLvl := MAX(LONGINT);
maxEndDecLvl := 0;
startLayer := 0;
endLayer := MAX(LONGINT);
startDecLvl := MAX(LONGINT);
endDecLvl := 0;
NEW(subbInfos, nt, ncomp);
NEW(progStates, nt);
IF pktDec = NIL THEN
NEW(pktDec, SELF, decSpec, ppmFirst);
ELSE
pktDec.ReInit(SELF, decSpec, ppmFirst);
END;
END;
initError := ~ok;
END ReInit;
PROCEDURE InitError* () : BOOLEAN;
BEGIN
RETURN initError;
END InitError;
PROCEDURE NextTilePart*() : BOOLEAN;
VAR
markerStr : ARRAY 8 OF CHAR;
ok : BOOLEAN;
bytesSkipped, ncomp, c, ndec: LONGINT;
BEGIN
IF endOfCS THEN
KernelLog.String("ERROR (CodestreamReader.NextTilePart) : Already at end of stream");
KernelLog.Ln();
RETURN FALSE;
ELSIF TilePartAvailable() THEN
bytesSkipped := JumpToTilePartEnd();
IF bytesSkipped <= 0 THEN
KernelLog.String("ERROR (CodestreamReader.NextTilePart): ");
KernelLog.String("Tried to jump to end of tile-part (because end of current tile-part has not been reached yet), but failed");
KernelLog.Ln();
RETURN FALSE;
END;
END;
IF ntp > 0 THEN
IF buf8Valid THEN
buf8Valid := FALSE;
curMarker := SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(buf8, 8))
+ SYSTEM.VAL(SET, LONG(ORD(s.Get())))
);
ELSE
curMarker := s.Net16();
END;
progStates[curTile].progOrder := progOrder;
progStates[curTile].curLay := curLay;
progStates[curTile].startLay := lmin;
progStates[curTile].endLay := lmax;
progStates[curTile].curRes := curRes;
progStates[curTile].endRes := rmax;
progStates[curTile].startRes := rmin;
progStates[curTile].curComp := curComp;
progStates[curTile].endComp := cmax;
progStates[curTile].startComp := cmin;
progStates[curTile].curPrec := curPrec;
progStates[curTile].curX := curX;
progStates[curTile].curY := curY;
END;
IF curMarker = SOT THEN
IF ReadSOTSegment() THEN
IF curPart = 0 THEN
CreateSubbandInfos();
pktDec.SetAndInitTile(curTile);
progStates[curTile].progNr := 0;
ncomp := decSpec.imgInfo.ncomp;
NEW(lmin, ncomp);
FOR c := 0 TO ncomp - 1 DO
ndec := decSpec.cstyle[curTile][c].ndec;
NEW(lmin[c], ndec + 1);
Machine.Fill32(SYSTEM.ADR(lmin[c][0]), (ndec+1)*SYSTEM.SIZEOF(LONGINT), 0);
END;
lmax := -1;
ProgressionChange();
curRes := rmin;
curComp := cmin;
curLay := 0;
curX := xmin;
curY := ymin;
ELSE
pktDec.SetTile(curTile);
progOrder := progStates[curTile].progOrder;
curLay := progStates[curTile].curLay;
lmin := progStates[curTile].startLay;
lmax := progStates[curTile].endLay;
curRes := progStates[curTile].curRes;
rmax := progStates[curTile].endRes;
rmin := progStates[curTile].startRes;
curComp := progStates[curTile].curComp;
cmax:= progStates[curTile].endComp;
cmin := progStates[curTile].startComp;
curPrec := progStates[curTile].curPrec;
curX := progStates[curTile].curX;
curY := progStates[curTile].curY;
pktDec.GetMinIncStep(curComp, incX, incY);
pktDec.GetMaxSotEot(curComp, xmin, xmax, ymin, ymax);
DEC(xmax);
DEC(ymax);
END;
IF InitTile() THEN
INC(ntp);
INC(ntilePartsRead[curTile]);
ok := TRUE;
END;
ELSE
ok := FALSE;
END;
ELSIF curMarker = EOC THEN
endOfCS := TRUE;
ok := FALSE;
ELSE
MarkerToString(curMarker, markerStr);
KernelLog.String("ERROR (CodestreamReader.NextTilePart) : Invalid marker found (");
KernelLog.String(markerStr);
KernelLog.String(")");
KernelLog.Ln();
ok := FALSE;
END;
RETURN ok;
END NextTilePart;
PROCEDURE InitTile () : BOOLEAN;
VAR
nblocksPkt : LONGINT;
BEGIN
nblocksPkt := pktDec.GetMaxNumCodeblocksPkt();
IF nblocksPkt > cblkBufSize THEN
NEW(cblkBuf, nblocksPkt);
NEW(cblkInfoBuf, nblocksPkt);
cblkBufSize := nblocksPkt;
END;
RETURN TRUE;
END InitTile;
PROCEDURE SetMaxLayerRange* (maxStartLayer, maxEndLayer : LONGINT);
BEGIN
SELF.maxStartLayer := maxStartLayer;
SELF.maxEndLayer := maxEndLayer;
END SetMaxLayerRange;
PROCEDURE SetLayerRange* (startLayer, endLayer : LONGINT);
BEGIN
SELF.startLayer := startLayer;
SELF.endLayer := endLayer;
END SetLayerRange;
PROCEDURE GetLayerRange* (VAR startLayer, endLayer : LONGINT);
BEGIN
startLayer := SELF.startLayer;
endLayer := SELF.endLayer;
END GetLayerRange;
PROCEDURE SetMaxDecLevelRange* (maxStartDecLvl, maxEndDecLvl : LONGINT);
BEGIN
SELF.maxStartDecLvl := maxStartDecLvl;
SELF.maxEndDecLvl := maxEndDecLvl;
END SetMaxDecLevelRange;
PROCEDURE SetDecLevelRange* (startDecLvl, endDecLvl : LONGINT);
BEGIN
SELF.startDecLvl := startDecLvl;
SELF.endDecLvl := endDecLvl;
END SetDecLevelRange;
PROCEDURE GetDecLevelRange* (VAR startDecLvl, endDecLvl : LONGINT);
BEGIN
startDecLvl := SELF.startDecLvl;
endDecLvl := SELF.endDecLvl;
END GetDecLevelRange;
PROCEDURE SetReBuildMode*;
BEGIN
HALT(99);
END SetReBuildMode;
PROCEDURE GetCodeBlocks* (VAR cblocks : ARRAY OF J2KU.CodedCblk; VAR cblockInfos: ARRAY OF J2KU.CblkInfo; ncblocks : LONGINT) : LONGINT;
VAR
i, startPos, cblkDecLvl : LONGINT;
ok : BOOLEAN;
BEGIN
i := 0;
WHILE i < ncblocks DO
IF ~TilePartAvailable() THEN
RETURN i;
END;
IF ncblkInBuf <= cblkBufPos THEN
startPos := s.Pos();
ncblkInBuf := pktDec.DecodePacket(curComp, curRes, curLay, curPrec[curComp][curRes][curLay], cblkBuf^, cblkInfoBuf^);
cblkDecLvl := decSpec.cstyle[curTile][curComp].ndec - curRes;
IF (cblkDecLvl < endDecLvl)
OR (cblkDecLvl > startDecLvl)
OR (curLay < startLayer)
OR (curLay > endLayer)
THEN
ncblkInBuf := 0;
END;
CASE progOrder OF
PROG_LRCP:
ok := AdvanceLayResComPos ();
| PROG_RLCP:
ok := AdvanceResLayComPos ();
| PROG_RPCL:
ok := AdvanceResPosComLay ();
| PROG_PCRL:
ok := AdvancePosComResLay ();
| PROG_CPRL:
ok := AdvanceComPosResLay ();
ELSE
ok := FALSE;
END;
cblkBufPos := 0;
partRem := partRem - (s.Pos() - startPos);
IF ~ok THEN
RETURN i;
END;
ELSE
IF cblkBuf[cblkBufPos].dataLen > 0 THEN
cblocks[i] := cblkBuf[cblkBufPos];
cblockInfos[i] := cblkInfoBuf[cblkBufPos];
IF startLayer > 0 THEN
cblockInfos[i].curbp := J2KU.LONGINT_BITS - 2 - cblockInfos[i].zerobp
- ((cblockInfos[i].truncpt - cblocks[i].cpasses + 2) DIV 3);
END;
INC(i);
END;
INC(cblkBufPos);
END;
END;
RETURN ncblocks;
END GetCodeBlocks;
PROCEDURE AdvanceLayResComPos () : BOOLEAN;
VAR
kmax, c, r : LONGINT;
BEGIN
kmax := pktDec.GetNumPrecincts(curComp, curRes) - 1;
IF curPrec[curComp][curRes][curLay] >= kmax THEN
REPEAT
IF curComp >= cmax THEN
IF curRes >= rmax THEN
IF curLay >= lmax THEN
ProgressionChange();
curLay := MAX(LONGINT);
FOR c := cmin TO cmax DO
FOR r := rmin TO rmax DO
IF (r < LEN(lmin[c]^)) & (lmin[c][r] < curLay) THEN
curLay := lmin[c][r];
END;
END;
END;
ELSE
INC(curLay);
END;
curRes := rmin;
ELSE
INC(curRes);
END;
curComp := cmin;
ELSE
INC(curComp);
END;
UNTIL (curRes <= decSpec.cstyle[curTile][curComp].ndec) & (curLay >= lmin[curComp][curRes]);
ELSE
INC(curPrec[curComp][curRes][curLay]);
END;
RETURN TRUE;
END AdvanceLayResComPos;
PROCEDURE AdvanceResLayComPos () : BOOLEAN;
VAR
kmax, c : LONGINT;
BEGIN
kmax := pktDec.GetNumPrecincts(curComp, curRes) - 1;
IF curPrec[curComp][curRes][curLay] >= kmax THEN
REPEAT
IF curComp >= cmax THEN
IF curLay >= lmax THEN
IF curRes >= rmax THEN
ProgressionChange();
curRes := rmin;
ELSE
INC(curRes);
END;
curLay := MAX(LONGINT);
FOR c := cmin TO cmax DO
IF (curRes < LEN(lmin[c]^)) & (lmin[c][curRes] < curLay) THEN
curLay := lmin[c][curRes];
END;
END;
ELSE
INC(curLay);
END;
curComp := cmin;
ELSE
INC(curComp);
END;
UNTIL (curRes <= decSpec.cstyle[curTile, curComp].ndec) & (curLay >= lmin[curComp][curRes]);
ELSE
INC(curPrec[curComp][curRes][curLay]);
END;
RETURN TRUE;
END AdvanceResLayComPos;
PROCEDURE AdvanceResPosComLay () : BOOLEAN;
VAR
foundNext : BOOLEAN;
incXR, incYR : LONGINT;
BEGIN
foundNext := FALSE;
INC(curPrec[curComp][curRes][curLay]);
IF curLay >= lmax THEN
REPEAT
IF curComp >= cmax THEN
IF curX >= xmax THEN
IF curY >= ymax THEN
IF curRes >= rmax THEN
ProgressionChange();
curRes := rmin;
ELSE
INC(curRes);
END;
curY := ymin;
ELSE
INC(curY, incY);
END;
curX := xmin;
ELSE
INC(curX, incX);
END;
curComp := cmin;
ELSE
INC(curComp);
END;
IF (curRes <= decSpec.GetNumDecLevels(curTile, curComp)) THEN
pktDec.GetIncStep(curComp, curRes, incXR, incYR);
IF (((curX = xmin) OR (curX MOD incXR = 0)) & (curX <= xmax))
& (((curY = ymin) OR (curY MOD incYR = 0)) & (curY <= ymax))
THEN
foundNext := TRUE;
END;
END;
UNTIL foundNext;
curLay := lmin[curComp][curRes];
ELSE
INC(curLay);
END;
RETURN TRUE;
END AdvanceResPosComLay;
PROCEDURE AdvancePosComResLay () : BOOLEAN;
VAR
foundNext : BOOLEAN;
incXR, incYR : LONGINT;
BEGIN
foundNext := FALSE;
INC(curPrec[curComp][curRes][curLay]);
IF curLay >= lmax THEN
REPEAT
IF curRes >= rmax THEN
IF curComp >= cmax THEN
IF curX >= xmax THEN
IF curY >= ymax THEN
ProgressionChange();
curY := ymin;
ELSE
INC(curY, incY);
END;
curX := xmin;
ELSE
INC(curX, incX);
END;
curComp := cmin;
ELSE
INC(curComp);
END;
curRes := rmin;
ELSE
INC(curRes);
END;
IF (curRes <= decSpec.GetNumDecLevels(curTile, curComp)) THEN
pktDec.GetIncStep(curComp, curRes, incXR, incYR);
IF (((curX = xmin) OR (curX MOD incXR = 0)) & (curX <= xmax))
& (((curY = ymin) OR (curY MOD incYR = 0)) & (curY <= ymax))
THEN
foundNext := TRUE;
END;
END;
UNTIL foundNext;
curLay := lmin[curComp][curRes];
ELSE
INC(curLay);
END;
RETURN TRUE;
END AdvancePosComResLay;
PROCEDURE AdvanceComPosResLay () : BOOLEAN;
VAR
foundNext : BOOLEAN;
incXR, incYR : LONGINT;
BEGIN
foundNext := FALSE;
INC(curPrec[curComp][curRes][curLay]);
IF curLay >= lmax THEN
REPEAT
IF curRes >= rmax THEN
IF curX >= xmax THEN
IF curY >= ymax THEN
IF curComp >= cmax THEN
ProgressionChange();
curComp := cmin;
ELSE
INC(curComp);
END;
curY := ymin;
ELSE
INC(curY, incY);
END;
curX := xmin;
ELSE
INC(curX, incX);
END;
curRes := rmin;
ELSE
INC(curRes);
END;
IF (curRes <= decSpec.GetNumDecLevels(curTile, curComp)) THEN
pktDec.GetIncStep(curComp, curRes, incXR, incYR);
IF (((curX = xmin) OR (curX MOD incXR = 0)) & (curX <= xmax))
& (((curY = ymin) OR (curY MOD incYR = 0)) & (curY <= ymax))
THEN
foundNext := TRUE;
END;
END;
UNTIL foundNext;
curLay := lmin[curComp][curRes];
ELSE
INC(curLay);
END;
RETURN TRUE;
END AdvanceComPosResLay;
PROCEDURE ProgressionChange;
VAR
nextProgIdx, c, r : LONGINT;
BEGIN
FOR c := cmin TO cmax DO
FOR r := rmin TO rmax DO
IF r < LEN(lmin[c]^) THEN
lmin[c][r] := lmax + 1;
END;
END;
END;
nextProgIdx := progStates[curTile].progNr;
IF (progChanges # NIL) & (progChanges[curTile] # NIL) & (nextProgIdx < LEN(progChanges[curTile]^)) THEN
IF nextProgIdx > 0 THEN
progOrder := progChanges[curTile][nextProgIdx - 1].progOrder;
ELSE
progOrder := decSpec.cics[curTile].po;
END;
rmax := progChanges[curTile][nextProgIdx].endRes - 1;
cmax := progChanges[curTile][nextProgIdx].endComp - 1;
lmax := progChanges[curTile][nextProgIdx].endLay - 1;
rmin := progChanges[curTile][nextProgIdx].startRes;
cmin := progChanges[curTile][nextProgIdx].startComp;
ELSE
IF (progChanges # NIL) & (progChanges[curTile] # NIL) & (nextProgIdx = LEN(progChanges[curTile]^)) THEN
progOrder := progChanges[curTile][nextProgIdx - 1].progOrder;
ELSE
progOrder := decSpec.cics[curTile].po;
END;
rmax := decSpec.GetMaxDecLevels(curTile);
cmax := decSpec.imgInfo.ncomp - 1;
lmax := decSpec.cics[curTile].nl - 1;
rmin := 0;
cmin := 0;
END;
pktDec.GetMinIncStep(cmin, incX, incY);
pktDec.GetMaxSotEot(cmin, xmin, xmax, ymin, ymax);
DEC(xmax);
DEC(ymax);
CreatePrecCounter();
INC(progStates[curTile].progNr);
END ProgressionChange;
PROCEDURE EndOfCodestream* () : BOOLEAN;
BEGIN
RETURN endOfCS;
END EndOfCodestream;
PROCEDURE JumpToTilePartEnd () : LONGINT;
VAR
bytesSkipped, startPos : LONGINT;
ok : BOOLEAN;
BEGIN
bytesSkipped := 0;
ok := TRUE;
WHILE TilePartAvailable() & ok DO
startPos := s.Pos();
ncblkInBuf := pktDec.DecodePacket(curComp, curRes, curLay, curPrec[curComp][curRes][curLay], cblkBuf^, cblkInfoBuf^);
CASE progOrder OF
PROG_LRCP:
ok := AdvanceLayResComPos ();
| PROG_RLCP:
ok := AdvanceResLayComPos ();
| PROG_RPCL:
ok := AdvanceResPosComLay ();
| PROG_PCRL:
ok := AdvancePosComResLay ();
| PROG_CPRL:
ok := AdvanceComPosResLay ();
ELSE
ok := FALSE;
END;
partRem := partRem - (s.Pos() - startPos);
INC(bytesSkipped, s.Pos() - startPos);
END;
RETURN bytesSkipped;
END JumpToTilePartEnd;
PROCEDURE GetDecoderSpecs* () : DecoderSpecs;
BEGIN
RETURN decSpec;
END GetDecoderSpecs;
PROCEDURE CreateSubbandInfos;
VAR
c, ndec, tx0, tx1, ty0, ty1, tcx0, tcx1, tcy0, tcy1, p, q, curIdx, reslevel, declevel, tmpW, tmpH : LONGINT;
ppx, ppy, cblw, cblh : LONGINT;
parentBand, llBand, hlBand, lhBand, hhBand : J2KU.SubbandInfo;
cstyle : CodingStyle;
imgInfo : ImageInfo;
BEGIN
imgInfo := decSpec.imgInfo;
p := curTile MOD imgInfo.nxt;
q := curTile DIV imgInfo.nxt;
tx0 := imgInfo.xtos + p*imgInfo.xt;
IF imgInfo.xos > tx0 THEN
tx0 := imgInfo.xos;
END;
ty0 := imgInfo.ytos + q*imgInfo.yt;
IF imgInfo.yos > ty0 THEN
ty0 := imgInfo.yos;
END;
tx1 := imgInfo.xtos + (p+1)*imgInfo.xt;
IF imgInfo.xsiz < tx1 THEN
tx1 := imgInfo.xsiz;
END;
ty1 := imgInfo.ytos + (q+1)*imgInfo.yt;
IF imgInfo.ysiz < ty1 THEN
ty1 := imgInfo.ysiz;
END;
FOR c := 0 TO imgInfo.ncomp - 1 DO
tcx0 := (tx0 + imgInfo.comps[c].subsx - 1) DIV imgInfo.comps[c].subsx;
tcy0 := (ty0 + imgInfo.comps[c].subsy - 1) DIV imgInfo.comps[c].subsy;
tcx1 := (tx1 + imgInfo.comps[c].subsx - 1) DIV imgInfo.comps[c].subsx;
tcy1 := (ty1 + imgInfo.comps[c].subsy - 1) DIV imgInfo.comps[c].subsy;
cstyle := decSpec.cstyle[curTile][c];
ndec := cstyle.ndec;
ppx := decSpec.GetPPX(curTile, c, ndec);
ppy := decSpec.GetPPY(curTile, c, ndec);
IF cstyle.cblw > ppx THEN
cblw := ppx;
ELSE
cblw := cstyle.cblw;
END;
IF cstyle.cblh > ppy THEN
cblh := ppy;
ELSE
cblh := cstyle.cblh;
END;
tmpW := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblw) - 1;
tmpH := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblh) - 1;
NEW(subbInfos[curTile][c], 4 * ndec + 1);
NEW(parentBand);
parentBand.type := J2KU.SUB_LL;
parentBand.index := 0;
parentBand.ulcx := tcx0;
parentBand.ulcy := tcy0;
parentBand.width := tcx1 - tcx0;
parentBand.height := tcy1 - tcy0;
IF parentBand.width = 0 THEN
parentBand.nblocksx := 0;
ELSE
parentBand.nblocksx := SYSTEM.LSH(tcx1 + tmpW, -cblw) - SYSTEM.LSH(tcx0, -cblw);
END;
IF parentBand.height = 0 THEN
parentBand.nblocksy := 0;
ELSE
parentBand.nblocksy := SYSTEM.LSH(tcy1 + tmpH, -cblh) - SYSTEM.LSH(tcy0, -cblh);
END;
parentBand.ulsx := 0;
parentBand.ulsy := 0;
parentBand.magbits := GetNumMagBits(curTile, c, 0, J2KU.SUB_LL);
parentBand.component := c;
parentBand.reslevel := ndec;
parentBand.declevel := 0;
subbInfos[curTile][c][0] := parentBand;
curIdx := 1;
declevel := 1;
FOR reslevel := ndec TO 1 BY -1 DO
IF cstyle.cblw > (ppx - 1) THEN
cblw := ppx - 1;
ELSE
cblw := cstyle.cblw;
END;
IF cstyle.cblh > (ppy - 1) THEN
cblh := ppy - 1;
ELSE
cblh := cstyle.cblh;
END;
tmpW := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblw) - 1;
tmpH := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblh) - 1;
NEW(hlBand);
hlBand.type := J2KU.SUB_HL;
hlBand.index := 0;
hlBand.ulcx := SYSTEM.LSH(parentBand.ulcx, -1);
hlBand.ulcy := SYSTEM.LSH(parentBand.ulcy + 1, -1);
hlBand.width := SYSTEM.LSH(parentBand.ulcx + parentBand.width, -1) - hlBand.ulcx;
hlBand.height := SYSTEM.LSH(parentBand.ulcy + parentBand.height + 1, -1) - hlBand.ulcy;
IF hlBand.width = 0 THEN
hlBand.nblocksx := 0;
ELSE
hlBand.nblocksx := SYSTEM.LSH(hlBand.ulcx+hlBand.width + tmpW, -cblw) - SYSTEM.LSH(hlBand.ulcx, -cblw);
END;
IF hlBand.height = 0 THEN
hlBand.nblocksy := 0;
ELSE
hlBand.nblocksy := SYSTEM.LSH(hlBand.ulcy+hlBand.height + tmpH, -cblh) - SYSTEM.LSH(hlBand.ulcy, -cblh);
END;
hlBand.magbits := GetNumMagBits(curTile, c, reslevel, J2KU.SUB_HL);
hlBand.component := c;
hlBand.reslevel := reslevel;
hlBand.declevel := declevel;
subbInfos[curTile][c][curIdx] := hlBand;
INC(curIdx);
NEW(lhBand);
lhBand.type := J2KU.SUB_LH;
lhBand.index := 1;
lhBand.ulcx := SYSTEM.LSH(parentBand.ulcx + 1, -1);
lhBand.ulcy := SYSTEM.LSH(parentBand.ulcy, -1);
lhBand.width := SYSTEM.LSH(parentBand.ulcx + parentBand.width + 1, -1) - lhBand.ulcx;
lhBand.height := SYSTEM.LSH(parentBand.ulcy + parentBand.height, -1) - lhBand.ulcy;
IF lhBand.width = 0 THEN
lhBand.nblocksx := 0;
ELSE
lhBand.nblocksx := SYSTEM.LSH(lhBand.ulcx+lhBand.width + tmpW, -cblw) - SYSTEM.LSH(lhBand.ulcx, -cblw);
END;
IF lhBand.height = 0 THEN
lhBand.nblocksy := 0;
ELSE
lhBand.nblocksy := SYSTEM.LSH(lhBand.ulcy+lhBand.height + tmpH, -cblh) - SYSTEM.LSH(lhBand.ulcy, -cblh);
END;
lhBand.magbits := GetNumMagBits(curTile, c, reslevel, J2KU.SUB_LH);
lhBand.component := c;
lhBand.reslevel := reslevel;
lhBand.declevel := declevel;
subbInfos[curTile][c][curIdx] := lhBand;
INC(curIdx);
NEW(hhBand);
hhBand.type := J2KU.SUB_HH;
hhBand.index := 2;
hhBand.ulcx := hlBand.ulcx;
hhBand.ulcy := lhBand.ulcy;
hhBand.width := hlBand.width;
hhBand.height := lhBand.height;
hhBand.nblocksx := hlBand.nblocksx;
hhBand.nblocksy := lhBand.nblocksy;
hhBand.magbits := GetNumMagBits(curTile, c, reslevel, J2KU.SUB_HH);
hhBand.component := c;
hhBand.reslevel := reslevel;
hhBand.declevel := declevel;
subbInfos[curTile][c][curIdx] := hhBand;
INC(curIdx);
ppx := decSpec.GetPPX(curTile, c, reslevel - 1);
ppy := decSpec.GetPPY(curTile, c, reslevel - 1);
IF cstyle.cblw > ppx THEN
cblw := ppx;
ELSE
cblw := cstyle.cblw;
END;
IF cstyle.cblh > ppy THEN
cblh := ppy;
ELSE
cblh := cstyle.cblh;
END;
tmpW := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblw) - 1;
tmpH := SYSTEM.LSH(SYSTEM.VAL(LONGINT, 1), cblh) - 1;
NEW(llBand);
llBand.type := J2KU.SUB_LL;
llBand.index := 0;
llBand.ulcx := lhBand.ulcx;
llBand.ulcy := hlBand.ulcy;
llBand.width := lhBand.width;
llBand.height := hlBand.height;
IF llBand.width = 0 THEN
llBand.nblocksx := 0;
ELSE
llBand.nblocksx := SYSTEM.LSH(llBand.ulcx+llBand.width + tmpW, -cblw) - SYSTEM.LSH(llBand.ulcx, -cblw);
END;
IF llBand.height = 0 THEN
llBand.nblocksy := 0;
ELSE
llBand.nblocksy := SYSTEM.LSH(llBand.ulcy+llBand.height + tmpH, -cblh) - SYSTEM.LSH(llBand.ulcy, -cblh);
END;
llBand.magbits := GetNumMagBits(curTile, c, 0, J2KU.SUB_LL);
llBand.component := c;
llBand.reslevel := reslevel - 1;
llBand.declevel := declevel;
subbInfos[curTile][c][curIdx] := llBand;
INC(curIdx);
llBand.ulsx := parentBand.ulsx;
llBand.ulsy := parentBand.ulsy;
hlBand.ulsx := parentBand.ulsx + llBand.width;
hlBand.ulsy := parentBand.ulsy;
lhBand.ulsx := parentBand.ulsx;
lhBand.ulsy := parentBand.ulsy + llBand.height;
hhBand.ulsx := hlBand.ulsx;
hhBand.ulsy := lhBand.ulsy;
parentBand := llBand;
INC(declevel);
END;
END;
END CreateSubbandInfos;
PROCEDURE GetNumMagBits (tile, comp, reslevel, subband : LONGINT) : LONGINT;
VAR
exp, idx : LONGINT;
quant : Quantization;
BEGIN
quant := decSpec.quant[tile][comp];
IF (quant.style = NOQUANT) OR (quant.style = QUANT_EXP) THEN
IF reslevel = 0 THEN
idx := 0;
ELSE
idx := 3 * (reslevel - 1) + 1 + J2KU.SubbandToSubbandIndex(subband);
END;
exp := quant.stepsiz[idx].exp;
ELSIF quant.style = QUANT_DER THEN
IF reslevel = 0 THEN
exp := quant.stepsiz[0].exp;
ELSE
exp := quant.stepsiz[0].exp - (reslevel - 1);
END;
END;
RETURN quant.nguardb + exp - 1;
END GetNumMagBits;
PROCEDURE CreatePrecCounter;
VAR
c, r, ndec, ncomp, nl : LONGINT;
cstyle : CodingStyle;
BEGIN
ncomp := decSpec.imgInfo.ncomp;
NEW(curPrec, ncomp);
nl := decSpec.cics[curTile].nl;
FOR c := 0 TO ncomp - 1 DO
cstyle := decSpec.cstyle[curTile][c];
ndec := cstyle.ndec;
NEW(curPrec[c], ndec + 1);
FOR r := 0 TO ndec DO
NEW(curPrec[c][r], nl);
END;
END;
END CreatePrecCounter;
PROCEDURE GetSubbandInfo* (tile, comp, reslevel, subband : LONGINT) : J2KU.SubbandInfo;
VAR
ndec : LONGINT;
subbOff : LONGINT;
BEGIN
ndec := decSpec.cstyle[tile][comp].ndec;
IF subband = J2KU.SUB_LL THEN
subbOff := 0;
ELSE
subbOff := 1;
END;
RETURN subbInfos[tile][comp][(ndec - reslevel)*4 + J2KU.SubbandToSubbandIndex(subband) + subbOff];
END GetSubbandInfo;
PROCEDURE Peek16 () : LONGINT;
BEGIN
IF ~buf8Valid THEN
buf8 := ORD(s.Get());
buf8Valid := TRUE;
END;
RETURN
SYSTEM.VAL(LONGINT,
SYSTEM.VAL(SET, SYSTEM.LSH(buf8, 8))
+ SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, s.Peek()))
);
END Peek16;
PROCEDURE ReadByte (VAR byte : CHAR);
BEGIN
IF buf8Valid THEN
byte := CHR(buf8);
buf8Valid := FALSE;
ELSE
s.Char(byte);
END;
END ReadByte;
PROCEDURE ReadBytes(VAR bytes : ARRAY OF CHAR; nbytes : LONGINT);
VAR
len, off : LONGINT;
BEGIN
IF buf8Valid THEN
bytes[0] := CHR(buf8);
buf8Valid := FALSE;
off := 1;
DEC(nbytes);
ELSE
off := 0;
END;
s.Bytes(bytes, off, nbytes, len);
END ReadBytes;
PROCEDURE CurrentTile* () : LONGINT;
BEGIN
RETURN curTile;
END CurrentTile;
PROCEDURE CurrentTilePart* () : LONGINT;
BEGIN
RETURN curPart;
END CurrentTilePart;
PROCEDURE TilePartAvailable* () : BOOLEAN;
BEGIN
IF ppmUsed THEN
RETURN (ncblkInBuf > cblkBufPos) OR (partRem > 0) OR pktDec.PPHMainAvailable();
ELSIF pktDec.PPHTileUsed() & (ntilePartsRead[curTile] >= ntilePartsAvailable[curTile]) THEN
RETURN (ncblkInBuf > cblkBufPos) OR (partRem > 0) OR pktDec.PPHTileAvailable();
ELSE
RETURN (ncblkInBuf > cblkBufPos) OR (partRem > 0);
END;
END TilePartAvailable;
PROCEDURE AllTilePartsRead* () : BOOLEAN;
VAR
progVol, ncomps, nlayers, c, r : LONGINT;
BEGIN
IF TilePartAvailable() THEN
RETURN FALSE;
ELSIF ntilePartsAvailable[curTile] # 0 THEN
RETURN ntilePartsRead[curTile] >= ntilePartsAvailable[curTile];
ELSE
progVol := 0;
ncomps := decSpec.imgInfo.ncomp;
nlayers := decSpec.cics[curTile].nl;
FOR c := 0 TO decSpec.imgInfo.ncomp - 1 DO
INC(progVol, nlayers*(decSpec.cstyle[curTile][c].ndec + 1));
END;
FOR c := 0 TO ncomps - 1 DO
FOR r := 0 TO decSpec.cstyle[curTile][c].ndec DO
DEC(progVol, lmin[c][r]);
END;
END;
RETURN progVol <= 0;
END;
END AllTilePartsRead;
PROCEDURE FreeNonRebuildResources*;
BEGIN
HALT(99);
END FreeNonRebuildResources;
PROCEDURE FreeResources*;
BEGIN
s := NIL;
ntilePartsRead := NIL;
ntilePartsAvailable := NIL;
pktDec := NIL;
cblkBuf := NIL;
cblkInfoBuf := NIL;
progChanges := NIL;
progStates := NIL;
curPrec := NIL;
END FreeResources;
PROCEDURE ReadSOTSegment() : BOOLEAN;
VAR
lsot, psot, sPos, ePos, comp, i : LONGINT;
ncod, nqcd, npoc, nmax : LONGINT;
ncoc, nqcc, nrgn : J2KU.LongIntArrayPtr;
tileIdx, partIdx, nparts, ncomp, nt : LONGINT;
ch : CHAR;
ok : BOOLEAN;
cstyle : CodingStyle;
cics : CICodingStyle;
quant : Quantization;
roiShift : LONGINT;
pptFirst, pptLast : DataListElement;
pptUsed : BOOLEAN;
changes : ProgChangeArrayPtr;
BEGIN
ok := TRUE;
ncod := 0;
nqcd := 0;
npoc := 0;
ncomp := decSpec.imgInfo.ncomp;
NEW(ncoc, ncomp);
NEW(nqcc, ncomp);
NEW(nrgn, ncomp);
Machine.Fill32(SYSTEM.ADR(ncoc[0]), ncomp*SYSTEM.SIZEOF(LONGINT), 0);
Machine.Fill32(SYSTEM.ADR(nqcc[0]), ncomp*SYSTEM.SIZEOF(LONGINT), 0);
Machine.Fill32(SYSTEM.ADR(nrgn[0]), ncomp*SYSTEM.SIZEOF(LONGINT), 0);
pptUsed := FALSE;
pptFirst := NIL;
pptLast := NIL;
sPos := s.Pos() - 2;
lsot := s.Net16();
tileIdx := s.Net16();
psot := s.Net32();
s.Char(ch);
partIdx := ORD(ch);
s.Char(ch);
nparts := ORD(ch);
IF (ntilePartsAvailable[tileIdx] = 0) & (nparts # 0) THEN
ntilePartsAvailable[tileIdx] := nparts;
END;
IF (s.Pos() - (sPos + 2)) # lsot THEN
KernelLog.String("WARNING: Segment length signalled in SOT segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
curMarker := s.Net16();
WHILE ok & (curMarker # SOD) DO
CASE curMarker OF
| COD :
ok := ReadCODSegment(cstyle, cics);
decSpec.cics[tileIdx] := cics;
FOR i := 0 TO ncomp - 1 DO
IF ncoc[i] = 0 THEN
decSpec.cstyle[tileIdx][i] := cstyle;
END;
END;
INC(ncod);
| COC :
ok := ReadCOCSegment(cstyle, comp);
IF ok THEN
decSpec.cstyle[tileIdx][comp] := cstyle;
INC(ncoc[comp]);
END;
| RGN :
ok := ReadRGNSegment(roiShift, comp);
IF ok THEN
decSpec.roiShift[tileIdx][comp] := roiShift;
INC(nrgn[comp]);
END;
| QCD :
ok := ReadQCDSegment(quant);
FOR i := 0 TO ncomp - 1 DO
IF nqcc[i] = 0 THEN
decSpec.quant[tileIdx][i] := quant;
END;
END;
INC(nqcd);
| QCC :
ok := ReadQCCSegment(quant, comp);
IF ok THEN
decSpec.quant[tileIdx][comp] := quant;
INC(nqcc[comp]);
END;
| POC :
ok := ReadPOCSegment(changes);
IF progChanges = NIL THEN
nt := decSpec.imgInfo.nt;
NEW(progChanges, nt);
END;
progChanges[tileIdx] := changes;
INC(npoc);
| PLT :
ok := ReadPLTSegment();
| PPT :
ok := ReadPPTSegment(pptFirst, pptLast);
pptUsed := TRUE;
| COM :
ok := ReadCOMSegment();
ELSE
KernelLog.String("Unexpected/Invalid marker found in tile-part header (0x");
KernelLog.Hex(curMarker, 0);
KernelLog.String(")");
KernelLog.Ln();
ok := FALSE;
END;
curMarker := s.Net16();
END;
IF partIdx = 0 THEN
nmax := 1;
ELSE
nmax := 0;
END;
IF ncod > nmax THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(ncod, 0);
KernelLog.String(" COD segments in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most ");
KernelLog.Int(nmax, 0);
KernelLog.String(" allowed)");
KernelLog.Ln();
ok := FALSE;
END;
IF nqcd > nmax THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nqcd, 0);
KernelLog.String(" QCD segments in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most ");
KernelLog.Int(nmax, 0);
KernelLog.String(" allowed)");
KernelLog.Ln();
ok := FALSE;
END;
IF npoc > 1 THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(npoc, 0);
KernelLog.String(" POC segments in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most 1 allowed)");
KernelLog.Ln();
ok := FALSE;
END;
FOR i := 0 TO ncomp - 1 DO
IF ncoc[i] > nmax THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(ncoc[i], 0);
KernelLog.String(" COC segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most ");
KernelLog.Int(nmax, 0);
KernelLog.String(" per component allowed )");
KernelLog.Ln();
ok := FALSE;
END;
IF nqcc[i] > nmax THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nqcc[i], 0);
KernelLog.String(" QCC segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most ");
KernelLog.Int(nmax, 0);
KernelLog.String(" per component allowed )");
KernelLog.Ln();
ok := FALSE;
END;
IF nrgn[i] > nmax THEN
KernelLog.String("ERROR: Found ");
KernelLog.Int(nrgn[i], 0);
KernelLog.String(" RGN segments for component ");
KernelLog.Int(i, 0);
KernelLog.String(" in header of tile-part ");
KernelLog.Int(partIdx, 0);
KernelLog.String(" of tile ");
KernelLog.Int(tileIdx, 0);
KernelLog.String(" (at most ");
KernelLog.Int(nmax, 0);
KernelLog.String(" per component allowed )");
KernelLog.Ln();
ok := FALSE;
END;
END;
IF pptUsed & ppmUsed THEN
KernelLog.String("ERROR: Both PPM and PPT marker segments used in codestream");
KernelLog.Ln();
ok := FALSE;
END;
IF ok THEN
ePos := s.Pos();
IF psot = 0 THEN
partRem := s.Available() - 2;
ELSE
partRem := psot - (ePos - sPos);
END;
SELF.curTile := tileIdx;
SELF.curPart := partIdx;
IF pptUsed THEN
pktDec.SetPPHeadersTile (pptFirst, pptLast, curTile);
END;
END;
RETURN ok;
END ReadSOTSegment;
PROCEDURE ReadSIZSegment(VAR imgInfo : ImageInfo) : BOOLEAN;
VAR
rsiz, lsiz, i, ssizInt, sPos, ePos : LONGINT;
ssiz, ch : CHAR;
BEGIN
sPos := s.Pos();
lsiz := s.Net16();
rsiz := s.Net16();
IF rsiz # 0000H THEN
KernelLog.String("ERROR: Decoder currently only has capabilities specified in JPEG 2000 - Part 1");
KernelLog.Ln();
RETURN FALSE;
END;
NEW(imgInfo);
imgInfo.xsiz := s.Net32();
imgInfo.ysiz := s.Net32();
imgInfo.xos := s.Net32();
imgInfo.yos := s.Net32();
imgInfo.xt := s.Net32();
imgInfo.yt := s.Net32();
imgInfo.xtos := s.Net32();
imgInfo.ytos := s.Net32();
imgInfo.ncomp := s.Net16();
imgInfo.nxt := (imgInfo.xsiz - imgInfo.xtos + imgInfo.xt - 1) DIV imgInfo.xt;
imgInfo.nyt := (imgInfo.ysiz - imgInfo.ytos + imgInfo.yt - 1) DIV imgInfo.yt;
imgInfo.nt := imgInfo.nyt*imgInfo.nxt;
IF imgInfo.GetImgWidth(0) > MAX_IMG_WIDTH THEN
KernelLog.String("ERROR: Image width too large");
KernelLog.Ln();
RETURN FALSE;
END;
IF imgInfo.GetImgHeight(0) > MAX_IMG_HEIGHT THEN
KernelLog.String("ERROR: Image height too large");
KernelLog.Ln();
RETURN FALSE;
END;
IF imgInfo.GetNumTiles() > MAX_TILES THEN
KernelLog.String("ERROR: Too many tiles");
KernelLog.Ln();
RETURN FALSE;
END;
IF imgInfo.GetNumComponents() > MAX_COMPONENTS THEN
KernelLog.String("ERROR: Too many image components");
KernelLog.Ln();
RETURN FALSE;
END;
NEW(imgInfo.comps, imgInfo.ncomp);
FOR i := 0 TO imgInfo.ncomp - 1 DO
NEW(imgInfo.comps[i]);
s.Char(ssiz);
ssizInt := ORD(ssiz);
IF (SYSTEM.VAL(SET, ssizInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 00000080H))) # {} THEN
imgInfo.comps[i].signed := TRUE;
ELSE
imgInfo.comps[i].signed := FALSE;
END;
imgInfo.comps[i].depth := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ssizInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000007FH))) + 1;
s.Char(ch);
imgInfo.comps[i].subsx := ORD(ch);
s.Char(ch);
imgInfo.comps[i].subsy := ORD(ch);
END;
ePos := s.Pos();
IF (ePos - sPos) # lsiz THEN
KernelLog.String("WARNING: Segment length signalled in SIZ segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadSIZSegment;
PROCEDURE ReadCODSegment (VAR cod : CodingStyle; VAR cics : CICodingStyle) : BOOLEAN;
VAR
lcod, nl, i, scodInt, cblsInt, precsizInt, sPos, ePos : LONGINT;
scod, prog, mct, ndec, cblw, cblh, cbls, trans, precsiz: CHAR;
tmpCod : CodingStyle;
tmpCics : CICodingStyle;
BEGIN
sPos := s.Pos();
lcod := s.Net16();
s.Char(scod);
s.Char(prog);
nl := s.Net16();
IF nl > MAX_LAYERS THEN
KernelLog.String("ERROR: Too many layers");
KernelLog.Ln();
RETURN FALSE;
END;
s.Char(mct);
s.Char(ndec);
s.Char(cblw);
s.Char(cblh);
s.Char(cbls);
s.Char(trans);
NEW(tmpCics);
NEW(tmpCod);
tmpCics.po := ORD(prog);
tmpCics.nl := nl;
IF tmpCics.po > 5 THEN
KernelLog.String("ERROR: Invalid progression order: 0x");
KernelLog.Hex(tmpCics.po, -1);
KernelLog.Ln();
RETURN FALSE;
END;
tmpCics.mct := ORD(mct);
IF tmpCics.mct > 1 THEN
KernelLog.String("ERROR: Invalid value for multiple component transformation: 0x");
KernelLog.Hex(tmpCics.mct, -1);
KernelLog.Ln();
RETURN FALSE;
END;
scodInt := ORD(scod);
tmpCod.maxps := ~ODD(scodInt);
tmpCics.sop := ODD(SYSTEM.LSH(scodInt, -1));
tmpCics.eph := ODD(SYSTEM.LSH(scodInt, -2));
tmpCod.ndec := ORD(ndec);
IF tmpCod.ndec > 32 THEN
KernelLog.String("ERROR: Invalid number of decomposition levels");
KernelLog.Ln();
RETURN FALSE;
END;
tmpCod.cblw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(cblw)) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH))) + 2;
tmpCod.cblh := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(cblh)) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH))) + 2;
IF ((tmpCod.cblw > 10) OR (tmpCod.cblh > 10)) OR (tmpCod.cblw + tmpCod.cblh > 12) THEN
KernelLog.String("ERROR: Invalid code-block width or height exponent: width exp. = ");
KernelLog.Int(tmpCod.cblw, 0);
KernelLog.String(", heigth exp. = ");
KernelLog.Int(tmpCod.cblh, 0);
KernelLog.Ln();
RETURN FALSE;
END;
cblsInt := ORD(cbls);
tmpCod.selcb := ODD(cblsInt);
tmpCod.rescp := ODD(SYSTEM.LSH(cblsInt, -1));
tmpCod.term := ODD(SYSTEM.LSH(cblsInt, -2));
tmpCod.vert := ODD(SYSTEM.LSH(cblsInt, -3));
tmpCod.pred := ODD(SYSTEM.LSH(cblsInt, -4));
tmpCod.segs := ODD(SYSTEM.LSH(cblsInt, -5));
tmpCod.trans := ORD(trans);
IF ~tmpCod.maxps THEN
NEW(tmpCod.precs, tmpCod.ndec + 1);
FOR i := 0 TO tmpCod.ndec DO
s.Char(precsiz);
precsizInt := ORD(precsiz);
tmpCod.precs[i].ppx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, precsizInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH)));
tmpCod.precs[i].ppy := SYSTEM.LSH(precsizInt, -4);
END;
END;
cics := tmpCics;
cod := tmpCod;
ePos := s.Pos();
IF (ePos - sPos) # lcod THEN
KernelLog.String("WARNING: Segment length signalled in COD segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadCODSegment;
PROCEDURE ReadCOCSegment(VAR coc : CodingStyle; VAR comp : LONGINT) : BOOLEAN;
VAR
lcoc, ccoc, i, scocInt, cblsInt, precsizInt, sPos, ePos, ncomp : LONGINT;
ccocByte, scoc, ndec, cblw, cblh, cbls, trans, precsiz: CHAR;
tmpCoc : CodingStyle;
BEGIN
ncomp := decSpec.imgInfo.ncomp;
sPos := s.Pos();
lcoc := s.Net16();
IF ncomp < 257 THEN
s.Char(ccocByte);
ccoc := ORD(ccocByte);
ELSE
ccoc := s.Net16();
END;
IF ccoc >= ncomp THEN
KernelLog.String("ERROR (CodeStreamReader.ReadCOCSegment) : Ccoc parameter out of valid range");
KernelLog.Ln();
RETURN FALSE;
END;
s.Char(scoc);
s.Char(ndec);
s.Char(cblw);
s.Char(cblh);
s.Char(cbls);
s.Char(trans);
NEW(tmpCoc);
scocInt := ORD(scoc);
IF scocInt = 0 THEN
tmpCoc.maxps := TRUE;
ELSIF scocInt = 1 THEN
tmpCoc.maxps := FALSE;
ELSE
KernelLog.String( "ERROR (CodestreamReader.ReadCOCSegment) : Invalid value for coding style parameter read (concerning precinct sizes)");
KernelLog.Ln();
RETURN FALSE;
END;
tmpCoc.ndec := ORD(ndec);
IF tmpCoc.ndec > 32 THEN
KernelLog.String("ERROR (CodestreamReader.ReadCOCSegment) : Invalid number of decomposition levels");
KernelLog.Ln();
RETURN FALSE;
END;
tmpCoc.cblw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(cblw)) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH))) + 2;
tmpCoc.cblh := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(cblh)) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH))) + 2;
IF ((tmpCoc.cblw > 10) OR (tmpCoc.cblh > 10)) OR (tmpCoc.cblw + tmpCoc.cblh > 12) THEN
KernelLog.String("ERROR (CodestreamReader.ReadCOCSegment) : Invalid code-block width or height exponent: width exp. = ");
KernelLog.Int(tmpCoc.cblw, 0);
KernelLog.String(", heigth exp. = ");
KernelLog.Int(tmpCoc.cblh, 0);
KernelLog.Ln();
RETURN FALSE;
END;
cblsInt := ORD(cbls);
tmpCoc.selcb := ODD(cblsInt);
tmpCoc.rescp := ODD(SYSTEM.LSH(cblsInt, -1));
tmpCoc.term := ODD(SYSTEM.LSH(cblsInt, -2));
tmpCoc.vert := ODD(SYSTEM.LSH(cblsInt, -3));
tmpCoc.pred := ODD(SYSTEM.LSH(cblsInt, -4));
tmpCoc.segs := ODD(SYSTEM.LSH(cblsInt, -5));
tmpCoc.trans := ORD(trans);
IF ~tmpCoc.maxps THEN
NEW(tmpCoc.precs, tmpCoc.ndec + 1);
FOR i := 0 TO tmpCoc.ndec DO
s.Char(precsiz);
precsizInt := ORD(precsiz);
tmpCoc.precs[i].ppx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, precsizInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000000FH)));
tmpCoc.precs[i].ppy := SYSTEM.LSH(precsizInt, -4);
END;
END;
comp := ccoc;
coc := tmpCoc;
ePos := s.Pos();
IF (ePos - sPos) # lcoc THEN
KernelLog.String("WARNING: Segment length signalled in COC segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadCOCSegment;
PROCEDURE ReadRGNSegment(VAR roiShift, comp : LONGINT) : BOOLEAN;
VAR
lrgn, crgn, sPos, ePos, ncomp : LONGINT;
crgnByte, srgn, sprgn : CHAR;
BEGIN
ncomp := decSpec.imgInfo.ncomp;
sPos := s.Pos();
lrgn := s.Net16();
IF ncomp < 257 THEN
s.Char(crgnByte);
crgn := ORD(crgnByte);
ELSE
crgn := s.Net16();
END;
IF crgn >= ncomp THEN
KernelLog.String("ERROR (CodeStreamReader.ReadRGNSegment) : Crgn parameter out of valid range");
KernelLog.Ln();
RETURN FALSE;
END;
s.Char(srgn);
IF ORD(srgn) # 0 THEN
KernelLog.String("ERROR (CodestreamReader.ReadRGNSegment): Invalid ROI style");
KernelLog.Ln();
RETURN FALSE;
END;
s.Char(sprgn);
roiShift := ORD(sprgn);
comp := crgn;
ePos := s.Pos();
IF (ePos - sPos) # lrgn THEN
KernelLog.String("WARNING: Segment length signalled in RGN segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadRGNSegment;
PROCEDURE ReadQCDSegment(VAR quant : Quantization) : BOOLEAN;
VAR
lqcd, ssize, i, sqcdInt, sPos, ePos : LONGINT;
sqcd, ch : CHAR;
tmp : Quantization;
BEGIN
sPos := s.Pos();
lqcd := s.Net16();
s.Char(sqcd);
sqcdInt := ORD(sqcd);
NEW(tmp);
tmp.style := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, sqcdInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000001FH)));
tmp.nguardb := SYSTEM.LSH(sqcdInt, -5);
CASE tmp.style OF
NOQUANT :
tmp.nstepsiz := lqcd-3;
NEW(tmp.stepsiz, tmp.nstepsiz);
FOR i := 0 TO tmp.nstepsiz - 1 DO
NEW(tmp.stepsiz[i]);
tmp.stepsiz[i].mant := 0;
s.Char(ch);
tmp.stepsiz[i].exp := SYSTEM.LSH(ORD(ch), -3);
END;
| QUANT_DER :
tmp.nstepsiz := 1;
NEW(tmp.stepsiz, 1);
NEW(tmp.stepsiz[0]);
ssize := s.Net16();
tmp.stepsiz[0].mant := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ssize) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 000007FFH)));
tmp.stepsiz[0].exp := SYSTEM.LSH(ssize, -11);
| QUANT_EXP :
tmp.nstepsiz := (lqcd-3) DIV 2;
NEW(tmp.stepsiz, tmp.nstepsiz);
FOR i := 0 TO tmp.nstepsiz - 1 DO
NEW(tmp.stepsiz[i]);
ssize := s.Net16();
tmp.stepsiz[i].mant := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ssize) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 000007FFH)));
tmp.stepsiz[i].exp := SYSTEM.LSH(ssize, -11);
END;
ELSE
KernelLog.String("ERROR: Invalid quantization style in QCD segment : 0x");
KernelLog.Hex(tmp.style, -1);
KernelLog.Ln();
RETURN FALSE;
END;
quant := tmp;
ePos := s.Pos();
IF (ePos - sPos) # lqcd THEN
KernelLog.String("WARNING: Segment length signalled in QCD segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadQCDSegment;
PROCEDURE ReadQCCSegment(VAR quant : Quantization; VAR comp : LONGINT) : BOOLEAN;
VAR
lqcc, ssize, i, sqccInt, cqcc, cqccLen, sPos, ePos, ncomp : LONGINT;
sqcc, cqccByte, ch : CHAR;
tmp : Quantization;
BEGIN
ncomp := decSpec.imgInfo.ncomp;
sPos := s.Pos();
lqcc := s.Net16();
IF decSpec.imgInfo.ncomp < 257 THEN
s.Char(cqccByte);
cqcc := ORD(cqccByte);
cqccLen := 1;
ELSE
cqcc := s.Net16();
cqccLen := 2;
END;
IF cqcc >= ncomp THEN
KernelLog.String("ERROR (CodeStreamReader.ReadQCCSegment) : Cqcc parameter out of valid range");
KernelLog.Ln();
RETURN FALSE;
END;
s.Char(sqcc);
sqccInt := ORD(sqcc);
NEW(tmp);
tmp.style := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, sqccInt) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 0000001FH)));
tmp.nguardb := SYSTEM.LSH(sqccInt, -5);
CASE tmp.style OF
NOQUANT :
tmp.nstepsiz := lqcc - (3 + cqccLen);
NEW(tmp.stepsiz, tmp.nstepsiz);
FOR i := 0 TO tmp.nstepsiz - 1 DO
NEW(tmp.stepsiz[i]);
tmp.stepsiz[i].mant := 0;
s.Char(ch);
tmp.stepsiz[i].exp := SYSTEM.LSH(ORD(ch), -3);
END;
| QUANT_DER :
tmp.nstepsiz := 1;
NEW(tmp.stepsiz, 1);
NEW(tmp.stepsiz[0]);
ssize := s.Net16();
tmp.stepsiz[0].mant := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ssize) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 000007FFH)));
tmp.stepsiz[0].exp := SYSTEM.LSH(ssize, -11);
| QUANT_EXP :
tmp.nstepsiz := (lqcc - (3 + cqccLen)) DIV 2;
NEW(tmp.stepsiz, tmp.nstepsiz);
FOR i := 0 TO tmp.nstepsiz - 1 DO
NEW(tmp.stepsiz[i]);
ssize := s.Net16();
tmp.stepsiz[i].mant := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ssize) * SYSTEM.VAL(SET, SYSTEM.VAL(LONGINT, 000007FFH)));
tmp.stepsiz[i].exp := SYSTEM.LSH(ssize, -11);
END;
ELSE
KernelLog.String("ERROR: Invalid quantization style in QCC segment : 0x");
KernelLog.Hex(tmp.style, -1);
KernelLog.Ln();
RETURN FALSE;
END;
comp := cqcc;
quant := tmp;
ePos := s.Pos();
IF (ePos - sPos) # lqcc THEN
KernelLog.String("WARNING: Segment length signalled in QCC segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadQCCSegment;
PROCEDURE ReadPOCSegment(VAR changes : ProgChangeArrayPtr) : BOOLEAN;
VAR
nchanges, lpoc, i, sPos, ePos : LONGINT;
rspoc, repoc, cspocByte, cepocByte, ppoc : CHAR;
twoBytes : BOOLEAN;
BEGIN
sPos := s.Pos();
lpoc := s.Net16();
IF decSpec.imgInfo.ncomp < 257 THEN
nchanges := (lpoc - 2) DIV 7;
twoBytes := FALSE;
ELSE
nchanges := (lpoc - 2) DIV 9;
twoBytes := TRUE;
END;
NEW(changes, nchanges);
FOR i := 0 TO nchanges - 1 DO
s.Char(rspoc);
changes[i].startRes := ORD(rspoc);
IF twoBytes THEN
changes[i].startComp := s.Net16();
ELSE
s.Char(cspocByte);
changes[i].startComp := ORD(cspocByte);
END;
changes[i].endLay := s.Net16();
s.Char(repoc);
changes[i].endRes := ORD(repoc);
IF twoBytes THEN
changes[i].endComp := s.Net16();
ELSE
s.Char(cepocByte);
changes[i].endComp := ORD(cepocByte);
END;
s.Char(ppoc);
changes[i].progOrder := ORD(ppoc);
END;
ePos := s.Pos();
IF (ePos - sPos) # lpoc THEN
KernelLog.String("WARNING: Segment length signalled in POC segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadPOCSegment;
PROCEDURE ReadTLMSegment() : BOOLEAN;
VAR
ltlm : LONGINT;
BEGIN
ltlm := s.Net16();
s.SkipBytes(ltlm - 2);
KernelLog.String("NOTICE: Found a TLM segment -> skipping it");
KernelLog.Ln();
RETURN TRUE;
END ReadTLMSegment;
PROCEDURE ReadPLMSegment() : BOOLEAN;
VAR
lplm : LONGINT;
BEGIN
lplm := s.Net16();
s.SkipBytes(lplm - 2);
KernelLog.String("NOTICE: Found a PLM segment -> skipping it");
KernelLog.Ln();
RETURN TRUE;
END ReadPLMSegment;
PROCEDURE ReadPLTSegment() : BOOLEAN;
VAR
lplt : LONGINT;
BEGIN
lplt := s.Net16();
s.SkipBytes(lplt - 2);
KernelLog.String("NOTICE: Found a PLT segment -> skipping it");
KernelLog.Ln();
RETURN TRUE;
END ReadPLTSegment;
PROCEDURE ReadPPMSegment(VAR first, last : DataListElement; VAR nppmLeft, nppmRead : LONGINT) : BOOLEAN;
VAR
lppm, len, actLen, sPos, ePos, bytesLeft : LONGINT;
dummy, curElem, newElem : DataListElement;
zppm : CHAR;
BEGIN
sPos := s.Pos();
lppm := s.Net16();
s.Char(zppm);
IF first = NIL THEN
NEW(dummy);
dummy.next := NIL;
curElem := dummy;
ELSE
curElem := last;
END;
bytesLeft := lppm - 3;
WHILE bytesLeft > 0 DO
IF nppmLeft <= 0 THEN
nppmLeft := s.Net32();
NEW(newElem);
NEW(newElem.data, nppmLeft);
newElem.next := NIL;
curElem.next := newElem;
curElem := newElem;
nppmRead := 0;
DEC(bytesLeft, 4);
END;
IF bytesLeft < nppmLeft THEN
len := bytesLeft;
ELSE
len := nppmLeft;
END;
s.Bytes(curElem.data^, nppmRead, len, actLen);
INC(nppmRead, actLen);
DEC(nppmLeft, actLen);
DEC(bytesLeft, actLen);
END;
IF first = NIL THEN
first := dummy.next;
END;
last := curElem;
ePos := s.Pos();
IF (ePos - sPos) # lppm THEN
KernelLog.String("WARNING: Segment length signalled in PPM segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadPPMSegment;
PROCEDURE ReadPPTSegment(VAR first, last : DataListElement) : BOOLEAN;
VAR
lppt, actLen, sPos, ePos, bytesLeft : LONGINT;
zppt : CHAR;
newElem : DataListElement;
BEGIN
sPos := s.Pos();
lppt := s.Net16();
s.Char(zppt);
IF first = NIL THEN
NEW(first);
last := first;
newElem := first;
ELSE
NEW(last.next);
last := last.next;
newElem := last;
END;
bytesLeft := lppt - 3;
NEW(newElem.data, bytesLeft);
newElem.next := NIL;
WHILE bytesLeft > 0 DO
s.Bytes(newElem.data^, 0, bytesLeft, actLen);
DEC(bytesLeft, actLen);
END;
ePos := s.Pos();
IF (ePos - sPos) # lppt THEN
KernelLog.String("WARNING: Segment length signalled in PPT segment was wrong. ");
KernelLog.String("Trying to read further anyway");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadPPTSegment;
PROCEDURE ReadCRGSegment() : BOOLEAN;
VAR
lcrg : LONGINT;
BEGIN
lcrg := s.Net16();
s.SkipBytes(lcrg - 2);
KernelLog.String("NOTICE: Found a CRG segment -> skipping it");
KernelLog.Ln();
RETURN TRUE;
END ReadCRGSegment;
PROCEDURE ReadCOMSegment () : BOOLEAN;
VAR
lcom, rcom, i : LONGINT;
com : J2KU.ByteArrayPtr;
BEGIN
lcom := s.Net16();
rcom := s.Net16();
NEW(com, lcom - 3);
FOR i := 0 TO lcom - 5 DO
s.Char(com[i]);
END;
com[LEN(com)-1] := 0X;
IF printCOM THEN
KernelLog.String("JPEG2000 codestream comment [");
KernelLog.Ln();
KernelLog.String(" ");
KernelLog.String(com^);
KernelLog.Ln();
KernelLog.String("]");
KernelLog.Ln();
END;
RETURN TRUE;
END ReadCOMSegment;
END CodestreamReader;
BufferedCodestreamReader* = OBJECT(CodestreamReader)
VAR
bufferedBlocks : POINTER TO ARRAY OF ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF POINTER TO ARRAY OF J2KU.CodedCblk;
reBuildMode : BOOLEAN;
curSubbIdx, curSubbCblk : LONGINT;
maxSubbIdx, maxSubbCblk : LONGINT;
getAllLayers : BOOLEAN;
PROCEDURE &InitNew* (crOpt : J2KU.CodestreamReaderOptions;
stream : Streams.Reader);
BEGIN
ReInit(crOpt, stream);
END InitNew;
PROCEDURE ReInit* (crOpt : J2KU.CodestreamReaderOptions;
stream : Streams.Reader);
BEGIN
ReInit^(crOpt, stream);
IF ~initError THEN
NEW(bufferedBlocks, decSpec.imgInfo.nt, decSpec.imgInfo.ncomp);
reBuildMode := FALSE;
END;
END ReInit;
PROCEDURE InitTile () : BOOLEAN;
VAR
c, r, nblocks, subband, nband, ndec : LONGINT;
cstyle : CodingStyle;
subbInfo : J2KU.SubbandInfo;
BEGIN
IF ~InitTile^() THEN
RETURN FALSE;
END;
IF curPart = 0 THEN
FOR c := 0 TO decSpec.imgInfo.ncomp - 1 DO
cstyle := decSpec.cstyle[curTile][c];
NEW(bufferedBlocks[curTile][c], cstyle.ndec + 1);
FOR r := 0 TO cstyle.ndec DO
IF r = 0 THEN
nband := 1;
ELSE
nband := 3;
END;
NEW(bufferedBlocks[curTile][c][r], nband);
FOR subband := 0 TO nband - 1 DO
subbInfo := GetSubbandInfo(curTile, c, r, J2KU.SubbandIndexToSubband(r, subband));
nblocks := subbInfo.nblocksx * subbInfo.nblocksy;
IF nblocks > 0 THEN
NEW(bufferedBlocks[curTile][c][r][subband], nblocks);
Machine.Fill32(SYSTEM.ADR(bufferedBlocks[curTile][c][r][subband][0]), nblocks*SYSTEM.SIZEOF(J2KU.CodedCblk), 0);
END;
END;
END;
END;
ELSIF reBuildMode THEN
curComp := 0;
cmax := decSpec.imgInfo.GetNumComponents() - 1;
ndec := decSpec.GetNumDecLevels(curTile, 0);
IF startDecLvl > ndec THEN
curRes := 0;
ELSE
curRes := ndec - startDecLvl;
END;
IF endDecLvl > ndec THEN
rmax := -1;
ELSE
rmax := ndec - endDecLvl;
END;
curSubbIdx := 0;
curSubbCblk := 0;
END;
IF (startLayer = 0) & (endLayer >= decSpec.cics[curTile].nl - 1) THEN
getAllLayers := TRUE;
ELSE
getAllLayers := FALSE;
END;
RETURN TRUE;
END InitTile;
PROCEDURE SetReBuildMode*;
BEGIN
reBuildMode := TRUE;
curTile := -1;
curPart := REBUILD_TILEPART;
END SetReBuildMode;
PROCEDURE AddBlock (VAR cblock : J2KU.CodedCblk; cblockInfo : J2KU.CblkInfo);
VAR
i, j : LONGINT;
tmpSegLen : J2KU.LongIntArrayPtr;
totSegLen, firstSegLen, lastSegLen : LONGINT;
dataEndPos : LONGINT;
nseg : LONGINT;
locComp, locRes, locSubb, locSubbCblk : LONGINT;
BEGIN
locComp := cblockInfo.subbinfo.component;
locRes := cblockInfo.subbinfo.reslevel;
locSubb := cblockInfo.subbinfo.index;
locSubbCblk := cblockInfo.index;
cblock.data := bufferedBlocks[curTile][locComp][locRes][locSubb][locSubbCblk].data;
nseg := bufferedBlocks[curTile][locComp][locRes][locSubb][locSubbCblk].nseg;
tmpSegLen := bufferedBlocks[curTile][locComp][locRes][locSubb][locSubbCblk].segLen;
IF startLayer = 0 THEN
cblock.dataOffset := 0;
cblock.dataLen := cblockInfo.datalenlyr[endLayer];
cblock.cpasses := cblockInfo.cpasseslyr[endLayer];
cblockInfo.curbp := J2KU.LONGINT_BITS - 2 - cblockInfo.zerobp;
ELSE
cblock.dataOffset := cblockInfo.datalenlyr[startLayer - 1];
cblock.dataLen := cblockInfo.datalenlyr[endLayer] - cblockInfo.datalenlyr[startLayer - 1];
cblock.cpasses := cblockInfo.cpasseslyr[endLayer] - cblockInfo.cpasseslyr[startLayer - 1];
cblockInfo.curbp := J2KU.LONGINT_BITS - 2 - cblockInfo.zerobp
- ((cblockInfo.cpasseslyr[startLayer - 1] + 2) DIV 3);
END;
IF tmpSegLen # NIL THEN
i := -1;
totSegLen := 0;
REPEAT
INC(i);
INC(totSegLen, tmpSegLen[i]);
UNTIL totSegLen > cblock.dataOffset;
firstSegLen := totSegLen - cblock.dataOffset;
j := i;
dataEndPos := cblock.dataOffset + cblock.dataLen;
WHILE (totSegLen <= dataEndPos) & (j < LEN(tmpSegLen^) - 1) DO
INC(j);
INC(totSegLen, tmpSegLen[j]);
END;
IF j > i THEN
cblock.nseg := j-i+1;
lastSegLen := tmpSegLen[j] - (totSegLen - dataEndPos);
NEW(cblock.segLen, cblock.nseg);
cblock.segLen[0] := firstSegLen;
cblock.segLen[cblock.nseg - 1] := lastSegLen;
IF cblock.nseg > 2 THEN
SYSTEM.MOVE(SYSTEM.ADR(tmpSegLen[i+1]), SYSTEM.ADR(cblock.segLen[1]), (cblock.nseg-2)*SYSTEM.SIZEOF(LONGINT));
END;
ELSE
cblock.nseg := 1;
cblock.segLen := NIL;
END;
ELSE
cblock.nseg := 1;
cblock.segLen := NIL;
END;
END AddBlock;
PROCEDURE UpdateBufferedBlock (VAR cblk : J2KU.CodedCblk; cblkInfo : J2KU.CblkInfo);
VAR
newDataLen, newSegs : LONGINT;
newSize, newSegSize : LONGINT;
tmpBlock : J2KU.CodedCblk;
tmpData : J2KU.ByteArrayPtr;
tmpSegLen : J2KU.LongIntArrayPtr;
layLeft: LONGINT;
comp, reslevel, subbIdx, cblkSubbIdx : LONGINT;
BEGIN
newDataLen := cblk.dataLen;
newSegs := cblk.nseg;
comp := cblkInfo.subbinfo.component;
reslevel := cblkInfo.subbinfo.reslevel;
subbIdx := cblkInfo.subbinfo.index;
cblkSubbIdx := cblkInfo.index;
IF (maxEndLayer < decSpec.cics[curTile].nl - 1) THEN
layLeft := (maxEndLayer - maxStartLayer) - curLay;
ELSE
layLeft := (decSpec.cics[curTile].nl-1 - maxStartLayer) - curLay;
END;
IF newDataLen > 0 THEN
tmpBlock := bufferedBlocks[curTile][comp][reslevel][subbIdx][cblkSubbIdx];
IF tmpBlock.dataLen = 0 THEN
newSize := newDataLen + SYSTEM.LSH(newDataLen * layLeft, -1);
NEW(tmpBlock.data, newSize);
ELSIF LEN(tmpBlock.data^) < (newDataLen + tmpBlock.dataLen + tmpBlock.dataOffset) THEN
tmpData := tmpBlock.data;
newSize := newDataLen + tmpBlock.dataLen + SYSTEM.LSH(newDataLen * layLeft, -1);
NEW(tmpBlock.data, newSize);
SYSTEM.MOVE(SYSTEM.ADR(tmpData[0]), SYSTEM.ADR(tmpBlock.data[0]), tmpBlock.dataLen);
END;
IF decSpec.cstyle[curTile][comp].selcb OR decSpec.cstyle[curTile][comp].term THEN
IF tmpBlock.segLen = NIL THEN
newSegSize := newSegs + SYSTEM.LSH(newSegs * layLeft, -1);
NEW(tmpBlock.segLen, newSegSize);
Machine.Fill32(SYSTEM.ADR(tmpBlock.segLen[0]), newSegSize*SYSTEM.SIZEOF(LONGINT), 0);
ELSIF LEN(tmpBlock.segLen^) < (newSegs + tmpBlock.nseg) THEN
tmpSegLen := tmpBlock.segLen;
newSegSize := newSegs + tmpBlock.nseg + SYSTEM.LSH(newSegs * layLeft, -1);
NEW(tmpBlock.segLen, newSegSize);
SYSTEM.MOVE(SYSTEM.ADR(tmpSegLen[0]), SYSTEM.ADR(tmpBlock.segLen[0]), LEN(tmpSegLen^) * SYSTEM.SIZEOF(LONGINT));
Machine.Fill32(SYSTEM.ADR(tmpBlock.segLen[LEN(tmpSegLen^)]), (newSegSize-LEN(tmpSegLen^))*SYSTEM.SIZEOF(LONGINT), 0);
END;
IF decSpec.cstyle[curTile][comp].term THEN
IF newSegs > 1 THEN
SYSTEM.MOVE(SYSTEM.ADR(cblk.segLen[0]), SYSTEM.ADR(tmpBlock.segLen[tmpBlock.nseg]), newSegs * SYSTEM.SIZEOF(LONGINT));
INC(tmpBlock.nseg, newSegs);
ELSE
tmpBlock.segLen[tmpBlock.nseg] := cblk.dataLen;
INC(tmpBlock.nseg);
END;
ELSE
IF newSegs > 1 THEN
tmpSegLen := tmpBlock.segLen;
INC(tmpSegLen[tmpBlock.nseg], cblk.segLen[0]);
SYSTEM.MOVE(SYSTEM.ADR(cblk.segLen[1]), SYSTEM.ADR(tmpSegLen[tmpBlock.nseg + 1]), (newSegs-1)*SYSTEM.SIZEOF(LONGINT));
IF (cblkInfo.truncpt MOD ENTROPY_NUM_PASSES) # 2 THEN
INC(tmpBlock.nseg, newSegs);
ELSE
INC(tmpBlock.nseg, newSegs - 1);
END;
ELSE
INC(tmpBlock.segLen[tmpBlock.nseg], cblk.dataLen);
IF (cblkInfo.truncpt >= ENTROPY_FIRST_BYPASS_IDX) &
((cblkInfo.truncpt MOD ENTROPY_NUM_PASSES) # 2) THEN
INC(tmpBlock.nseg);
END;
END;
END;
END;
SYSTEM.MOVE(SYSTEM.ADR(cblk.data[cblk.dataOffset]), SYSTEM.ADR(tmpBlock.data[tmpBlock.dataLen]), newDataLen);
INC(tmpBlock.dataLen, newDataLen);
INC(tmpBlock.cpasses, cblk.cpasses);
bufferedBlocks[curTile][comp][reslevel][subbIdx][cblkSubbIdx] := tmpBlock;
END;
END UpdateBufferedBlock;
PROCEDURE GetCodeBlocks* (VAR cblocks : ARRAY OF J2KU.CodedCblk; VAR cblockInfos : ARRAY OF J2KU.CblkInfo; ncblocks : LONGINT) : LONGINT;
VAR
i, j, startPos, tmpCblkInBuf, cblkDecLvl, subbIdx, cblkSubbIdx : LONGINT;
ok, deliver : BOOLEAN;
BEGIN
IF reBuildMode THEN
RETURN GetBufferedBlocks(cblocks, cblockInfos, ncblocks);
END;
i := 0;
WHILE i < ncblocks DO
IF ~TilePartAvailable^() THEN
RETURN i;
END;
IF ncblkInBuf <= cblkBufPos THEN
startPos := s.Pos();
ncblkInBuf := 0;
deliver := TRUE;
tmpCblkInBuf := pktDec.DecodePacket(curComp, curRes, curLay, curPrec[curComp][curRes][curLay], cblkBuf^, cblkInfoBuf^);
cblkDecLvl := decSpec.cstyle[curTile][curComp].ndec - curRes;
IF (cblkDecLvl < endDecLvl)
OR (cblkDecLvl > startDecLvl)
THEN
IF (cblkDecLvl < maxEndDecLvl)
OR (cblkDecLvl > maxStartDecLvl)
THEN
tmpCblkInBuf := 0;
END;
deliver := FALSE;
END;
IF (curLay < startLayer)
OR (curLay > endLayer)
THEN
IF (curLay < maxStartLayer)
OR (curLay > maxEndLayer)
THEN
tmpCblkInBuf := 0;
END;
deliver := FALSE;
END;
FOR j := 0 TO tmpCblkInBuf - 1 DO
UpdateBufferedBlock(cblkBuf[j], cblkInfoBuf[j]);
END;
IF deliver &
((curLay = endLayer) OR (curLay = decSpec.cics[curTile].nl - 1))
THEN
FOR j := 0 TO tmpCblkInBuf - 1 DO
IF getAllLayers THEN
subbIdx := cblkInfoBuf[j].subbinfo.index;
cblkSubbIdx := cblkInfoBuf[j].index;
cblkBuf[ncblkInBuf] := bufferedBlocks[curTile][curComp][curRes][subbIdx][cblkSubbIdx];
ELSE
AddBlock(cblkBuf[ncblkInBuf], cblkInfoBuf[j]);
END;
cblkInfoBuf[ncblkInBuf] := cblkInfoBuf[j];
INC(ncblkInBuf);
END;
END;
CASE progOrder OF
PROG_LRCP:
ok := AdvanceLayResComPos();
| PROG_RLCP:
ok := AdvanceResLayComPos();
| PROG_RPCL:
ok := AdvanceResPosComLay();
| PROG_PCRL:
ok := AdvancePosComResLay();
| PROG_CPRL:
ok := AdvanceComPosResLay();
ELSE
ok := FALSE;
END;
IF ~ok THEN
RETURN i;
END;
cblkBufPos := 0;
partRem := partRem - (s.Pos() - startPos);
ELSE
IF cblkBuf[cblkBufPos].dataLen > 0 THEN
cblocks[i] := cblkBuf[cblkBufPos];
cblockInfos[i] := cblkInfoBuf[cblkBufPos];
INC(i);
END;
INC(cblkBufPos);
END;
END;
RETURN ncblocks;
END GetCodeBlocks;
PROCEDURE GetBufferedBlocks (VAR cblocks : ARRAY OF J2KU.CodedCblk; VAR cblockInfos : ARRAY OF J2KU.CblkInfo; ncblocks : LONGINT) : LONGINT;
VAR
ncblocksRet: LONGINT;
ndec, cblkDecLvl : LONGINT;
curSubbType : LONGINT;
locCurComp, locCurRes, locCurSubbIdx, locCurSubbCblk : LONGINT;
BEGIN
ncblocksRet := 0;
locCurComp := curComp;
locCurRes := curRes;
locCurSubbIdx := curSubbIdx;
locCurSubbCblk := curSubbCblk;
WHILE locCurComp <= cmax DO
WHILE locCurRes <= rmax DO
IF locCurRes = 0 THEN
maxSubbIdx := 0;
ELSE
maxSubbIdx := 2;
END;
cblkDecLvl := decSpec.cstyle[curTile][locCurComp].ndec - locCurRes;
IF (cblkDecLvl <= startDecLvl) & (cblkDecLvl >= endDecLvl) THEN
WHILE locCurSubbIdx <= maxSubbIdx DO
curSubbType := J2KU.SubbandIndexToSubband(locCurRes, locCurSubbIdx);
maxSubbCblk := LEN(bufferedBlocks[curTile][locCurComp][locCurRes][locCurSubbIdx]^) - 1;
WHILE locCurSubbCblk <= maxSubbCblk DO
cblockInfos[ncblocksRet] := pktDec.GetCblkInfo( locCurComp,
locCurRes,
curSubbType,
locCurSubbCblk);
IF getAllLayers THEN
cblocks[ncblocksRet] := bufferedBlocks[curTile][locCurComp][locCurRes][locCurSubbIdx][locCurSubbCblk];
cblockInfos[ncblocksRet].curbp := J2KU.LONGINT_BITS - 2 - cblockInfos[ncblocksRet].zerobp;
ELSE
AddBlock(cblocks[ncblocksRet], cblockInfos[ncblocksRet]);
END;
IF cblocks[ncblocksRet].dataLen > 0 THEN
INC(ncblocksRet);
END;
INC(locCurSubbCblk);
IF ncblocksRet = ncblocks THEN
curComp := locCurComp;
curRes := locCurRes;
curSubbIdx := locCurSubbIdx;
curSubbCblk := locCurSubbCblk;
RETURN ncblocksRet;
END;
END;
INC(locCurSubbIdx);
locCurSubbCblk := 0;
END;
END;
INC(locCurRes);
locCurSubbIdx := 0;
END;
INC(locCurComp);
IF locCurComp <= cmax THEN
ndec := decSpec.GetNumDecLevels(curTile, locCurComp);
IF startDecLvl > ndec THEN
locCurRes := 0;
ELSE
locCurRes := ndec - startDecLvl;
END;
IF endDecLvl > ndec THEN
rmax := -1;
ELSE
rmax := ndec - endDecLvl;
END;
END;
END;
curComp := locCurComp;
curRes := locCurRes;
curSubbIdx := locCurSubbIdx;
curSubbCblk := locCurSubbCblk;
RETURN ncblocksRet;
END GetBufferedBlocks;
PROCEDURE TilePartAvailable* () : BOOLEAN;
BEGIN
IF reBuildMode THEN
RETURN (curComp < cmax)
OR (
(curComp = cmax)
& (
(curRes < rmax)
OR (curSubbIdx < maxSubbIdx)
OR (curSubbCblk <= maxSubbCblk)
)
);
ELSE
RETURN TilePartAvailable^();
END;
END TilePartAvailable;
PROCEDURE JumpToTilePartEnd () : LONGINT;
BEGIN
IF reBuildMode THEN
curComp := cmax + 1;
curRes := rmax;
curSubbIdx := maxSubbIdx;
curSubbCblk := maxSubbCblk + 1;
RETURN 0;
ELSE
RETURN JumpToTilePartEnd^();
END;
END JumpToTilePartEnd;
PROCEDURE NextTilePart*() : BOOLEAN;
VAR
imgInfo : ImageInfo;
ntiles : LONGINT;
ok : BOOLEAN;
BEGIN
IF reBuildMode THEN
imgInfo := decSpec.GetImageInfo();
ntiles := imgInfo.GetNumTiles();
REPEAT
INC(curTile);
UNTIL (curTile >= ntiles) OR (ntilePartsRead[curTile] > 0);
IF curTile < ntiles THEN
pktDec.SetTile(curTile);
ok := InitTile();
ELSE
curComp := cmax + 1;
curRes := rmax;
curSubbIdx := maxSubbIdx;
curSubbCblk := maxSubbCblk + 1;
reBuildMode := FALSE;
IF ~EndOfCodestream^() THEN
ok := NextTilePart^();
ELSE
ok := FALSE;
END;
END;
RETURN ok;
ELSE
RETURN NextTilePart^();
END;
END NextTilePart;
PROCEDURE EndOfCodestream* () : BOOLEAN;
VAR
imgInfo : ImageInfo;
BEGIN
IF reBuildMode THEN
imgInfo := decSpec.GetImageInfo();
RETURN imgInfo.GetNumTiles() <= curTile;
ELSE
RETURN EndOfCodestream^();
END;
END EndOfCodestream;
PROCEDURE FreeNonRebuildResources*;
BEGIN
s := NIL;
progChanges := NIL;
progStates := NIL;
curPrec := NIL;
END FreeNonRebuildResources;
PROCEDURE FreeResources*;
BEGIN
FreeResources^();
bufferedBlocks := NIL;
END FreeResources;
END BufferedCodestreamReader;
PROCEDURE MarkerToString (marker : LONGINT; VAR str : ARRAY OF CHAR);
VAR
i : LONGINT;
BEGIN
ASSERT (LEN(str) >= 7);
CASE marker OF
| SOC :
COPY("SOC", str);
| SOT :
COPY("SOT", str);
| SOD :
COPY("SOD", str);
| EOC :
COPY("EOC", str);
| SIZ :
COPY("SIZ", str);
| COD :
COPY("COC", str);
| COC :
COPY("COC", str);
| RGN :
COPY("RGN", str);
| QCD :
COPY("QCD", str);
| QCC :
COPY("QCC", str);
| POC :
COPY("POC", str);
| TLM :
COPY("TLM", str);
| PLM :
COPY("PLM", str);
| PLT :
COPY("PLT", str);
| PPM :
COPY("PPM", str);
| PPT :
COPY("PPT", str);
| SOP :
COPY("SOP", str);
| EPH :
COPY("EPH", str);
| CRG :
COPY("CRG", str);
| COM :
COPY("COM", str);
ELSE
str[0] := '0';
str[1] := 'x';
FOR i := 5 TO 2 BY -1 DO
str[i] := CHR(marker MOD 10H + 48);
IF str[i] > "9" THEN
str[i] := CHR(ORD(str[i]) - 48 + 65 - 10)
END;
marker := marker DIV 10H;
END;
str[6] := 0X;
END;
END MarkerToString;
END JPEG2000DecoderCS.