public override void readSegment() { if (JBIG2StreamDecoder.debug) { Console.WriteLine("==== Read Segment Symbol Dictionary ===="); } /** read symbol dictionary flags */ readSymbolDictionaryFlags(); //List codeTables = new ArrayList(); int numberOfInputSymbols = 0; int noOfReferredToSegments = segmentHeader.getReferredToSegmentCount(); int[] referredToSegments = segmentHeader.getReferredToSegments(); long i = 0; for (i = 0; i < noOfReferredToSegments; i++) { Segment seg = decoder.findSegment(referredToSegments[i]); int type = seg.getSegmentHeader().getSegmentType(); if (type == Segment.SYMBOL_DICTIONARY) { numberOfInputSymbols += ((SymbolDictionarySegment)seg).noOfExportedSymbols; } else if (type == Segment.TABLES) { //codeTables.add(seg); } } int symbolCodeLength = 0; i = 1; while (i < numberOfInputSymbols + noOfNewSymbols) { symbolCodeLength++; i <<= 1; } JBIG2Bitmap[] bitmaps = new JBIG2Bitmap[numberOfInputSymbols + noOfNewSymbols]; long j, k = 0; SymbolDictionarySegment inputSymbolDictionary = null; for (i = 0; i < noOfReferredToSegments; i++) { Segment seg = decoder.findSegment(referredToSegments[i]); if (seg.getSegmentHeader().getSegmentType() == Segment.SYMBOL_DICTIONARY) { inputSymbolDictionary = (SymbolDictionarySegment)seg; for (j = 0; j < inputSymbolDictionary.noOfExportedSymbols; j++) { bitmaps[k++] = inputSymbolDictionary.bitmaps[j]; } } } long[,] huffmanDHTable = null; long[,] huffmanDWTable = null; long[,] huffmanBMSizeTable = null; long[,] huffmanAggInstTable = null; bool sdHuffman = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_HUFF) != 0; int sdHuffmanDifferenceHeight = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_HUFF_DH); int sdHuffmanDiferrenceWidth = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_HUFF_DW); int sdHuffBitmapSize = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_HUFF_BM_SIZE); int sdHuffAggregationInstances = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_HUFF_AGG_INST); i = 0; if (sdHuffman) { if (sdHuffmanDifferenceHeight == 0) { huffmanDHTable = HuffmanDecoder.huffmanTableD; } else if (sdHuffmanDifferenceHeight == 1) { huffmanDHTable = HuffmanDecoder.huffmanTableE; } else { //huffmanDHTable = ((JBIG2CodeTable) codeTables.get(i++)).getHuffTable(); } if (sdHuffmanDiferrenceWidth == 0) { huffmanDWTable = HuffmanDecoder.huffmanTableB; } else if (sdHuffmanDiferrenceWidth == 1) { huffmanDWTable = HuffmanDecoder.huffmanTableC; } else { //huffmanDWTable = ((JBIG2CodeTable) codeTables.get(i++)).getHuffTable(); } if (sdHuffBitmapSize == 0) { huffmanBMSizeTable = HuffmanDecoder.huffmanTableA; } else { //huffmanBMSizeTable = ((JBIG2CodeTable) codeTables.get(i++)).getHuffTable(); } if (sdHuffAggregationInstances == 0) { huffmanAggInstTable = HuffmanDecoder.huffmanTableA; } else { //huffmanAggInstTable = ((JBIG2CodeTable) codeTables.get(i++)).getHuffTable(); } } int contextUsed = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.BITMAP_CC_USED); int sdTemplate = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_TEMPLATE); if (!sdHuffman) { if (contextUsed != 0 && inputSymbolDictionary != null) { arithmeticDecoder.resetGenericStats(sdTemplate, inputSymbolDictionary.genericRegionStats); } else { arithmeticDecoder.resetGenericStats(sdTemplate, null); } arithmeticDecoder.resetIntStats(symbolCodeLength); arithmeticDecoder.start(); } int sdRefinementAggregate = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_REF_AGG); int sdRefinementTemplate = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.SD_R_TEMPLATE); if (sdRefinementAggregate != 0) { if (contextUsed != 0 && inputSymbolDictionary != null) { arithmeticDecoder.resetRefinementStats(sdRefinementTemplate, inputSymbolDictionary.refinementRegionStats); } else { arithmeticDecoder.resetRefinementStats(sdRefinementTemplate, null); } } long[] deltaWidths = new long[noOfNewSymbols]; long deltaHeight = 0; i = 0; while (i < noOfNewSymbols) { long instanceDeltaHeight = 0; if (sdHuffman) { instanceDeltaHeight = huffmanDecoder.decodeInt(huffmanDHTable).intResult(); } else { instanceDeltaHeight = arithmeticDecoder.decodeInt(arithmeticDecoder.iadhStats).intResult(); } if (instanceDeltaHeight < 0 && -instanceDeltaHeight >= deltaHeight) { if (JBIG2StreamDecoder.debug) { Console.WriteLine("Bad delta-height value in JBIG2 symbol dictionary"); } } deltaHeight += instanceDeltaHeight; long symbolWidth = 0; long totalWidth = 0; j = i; while (true) { long deltaWidth = 0; DecodeIntResult decodeIntResult; if (sdHuffman) { decodeIntResult = huffmanDecoder.decodeInt(huffmanDWTable); } else { decodeIntResult = arithmeticDecoder.decodeInt(arithmeticDecoder.iadwStats); } if (!decodeIntResult.booleanResult()) { break; } deltaWidth = decodeIntResult.intResult(); if (deltaWidth < 0 && -deltaWidth >= symbolWidth) { if (JBIG2StreamDecoder.debug) { Console.WriteLine("Bad delta-width value in JBIG2 symbol dictionary"); } } symbolWidth += deltaWidth; if (sdHuffman && sdRefinementAggregate == 0) { deltaWidths[i] = symbolWidth; totalWidth += symbolWidth; } else if (sdRefinementAggregate == 1) { long refAggNum = 0; if (sdHuffman) { refAggNum = huffmanDecoder.decodeInt(huffmanAggInstTable).intResult(); } else { refAggNum = arithmeticDecoder.decodeInt(arithmeticDecoder.iaaiStats).intResult(); } if (refAggNum == 1) { long symbolID = 0, referenceDX = 0, referenceDY = 0; if (sdHuffman) { symbolID = decoder.readBits(symbolCodeLength); referenceDX = huffmanDecoder.decodeInt(HuffmanDecoder.huffmanTableO).intResult(); referenceDY = huffmanDecoder.decodeInt(HuffmanDecoder.huffmanTableO).intResult(); decoder.consumeRemainingBits(); arithmeticDecoder.start(); } else { symbolID = (int)arithmeticDecoder.decodeIAID(symbolCodeLength, arithmeticDecoder.iaidStats); referenceDX = arithmeticDecoder.decodeInt(arithmeticDecoder.iardxStats).intResult(); referenceDY = arithmeticDecoder.decodeInt(arithmeticDecoder.iardyStats).intResult(); } JBIG2Bitmap referredToBitmap = bitmaps[symbolID]; JBIG2Bitmap bitmap = new JBIG2Bitmap(symbolWidth, deltaHeight, arithmeticDecoder, huffmanDecoder, mmrDecoder); bitmap.readGenericRefinementRegion(sdRefinementTemplate, false, referredToBitmap, referenceDX, referenceDY, symbolDictionaryRAdaptiveTemplateX, symbolDictionaryRAdaptiveTemplateY); bitmaps[numberOfInputSymbols + i] = bitmap; } else { JBIG2Bitmap bitmap = new JBIG2Bitmap(symbolWidth, deltaHeight, arithmeticDecoder, huffmanDecoder, mmrDecoder); bitmap.readTextRegion(sdHuffman, true, refAggNum, 0, numberOfInputSymbols + i, null, symbolCodeLength, bitmaps, 0, 0, false, 1, 0, HuffmanDecoder.huffmanTableF, HuffmanDecoder.huffmanTableH, HuffmanDecoder.huffmanTableK, HuffmanDecoder.huffmanTableO, HuffmanDecoder.huffmanTableO, HuffmanDecoder.huffmanTableO, HuffmanDecoder.huffmanTableO, HuffmanDecoder.huffmanTableA, sdRefinementTemplate, symbolDictionaryRAdaptiveTemplateX, symbolDictionaryRAdaptiveTemplateY, decoder); bitmaps[numberOfInputSymbols + i] = bitmap; } } else { JBIG2Bitmap bitmap = new JBIG2Bitmap(symbolWidth, deltaHeight, arithmeticDecoder, huffmanDecoder, mmrDecoder); bitmap.readBitmap(false, sdTemplate, false, false, null, symbolDictionaryAdaptiveTemplateX, symbolDictionaryAdaptiveTemplateY, 0); bitmaps[numberOfInputSymbols + i] = bitmap; } i++; } if (sdHuffman && sdRefinementAggregate == 0) { long bmSize = huffmanDecoder.decodeInt(huffmanBMSizeTable).intResult(); decoder.consumeRemainingBits(); JBIG2Bitmap collectiveBitmap = new JBIG2Bitmap(totalWidth, deltaHeight, arithmeticDecoder, huffmanDecoder, mmrDecoder); if (bmSize == 0) { long padding = totalWidth % 8; long bytesPerRow = (int)Math.Ceiling(totalWidth / 8d); //short[] bitmap = new short[totalWidth]; //decoder.readbyte(bitmap); long size = deltaHeight * ((totalWidth + 7) >> 3); short[] bitmap = new short[size]; decoder.readbyte(bitmap); short[][] logicalMap = new short[deltaHeight][]; int count = 0; for (int row = 0; row < deltaHeight; row++) { for (int col = 0; col < bytesPerRow; col++) { logicalMap[row][col] = bitmap[count]; count++; } } int collectiveBitmapRow = 0, collectiveBitmapCol = 0; for (int row = 0; row < deltaHeight; row++) { for (int col = 0; col < bytesPerRow; col++) { if (col == (bytesPerRow - 1)) // this is the last // byte in the row { short currentbyte = logicalMap[row][col]; for (int bitPointer = 7; bitPointer >= padding; bitPointer--) { short mask = (short)(1 << bitPointer); int bit = (currentbyte & mask) >> bitPointer; collectiveBitmap.setPixel(collectiveBitmapCol, collectiveBitmapRow, bit); collectiveBitmapCol++; } collectiveBitmapRow++; collectiveBitmapCol = 0; } else { short currentbyte = logicalMap[row][col]; for (int bitPointer = 7; bitPointer >= 0; bitPointer--) { short mask = (short)(1 << bitPointer); int bit = (currentbyte & mask) >> bitPointer; collectiveBitmap.setPixel(collectiveBitmapCol, collectiveBitmapRow, bit); collectiveBitmapCol++; } } } } } else { collectiveBitmap.readBitmap(true, 0, false, false, null, null, null, bmSize); } long x = 0; while (j < i) { bitmaps[numberOfInputSymbols + j] = collectiveBitmap.getSlice(x, 0, deltaWidths[j], deltaHeight); x += deltaWidths[j]; j++; } } } this.bitmaps = new JBIG2Bitmap[noOfExportedSymbols]; j = i = 0; bool export = false; while (i < numberOfInputSymbols + noOfNewSymbols) { long run = 0; if (sdHuffman) { run = huffmanDecoder.decodeInt(HuffmanDecoder.huffmanTableA).intResult(); } else { run = arithmeticDecoder.decodeInt(arithmeticDecoder.iaexStats).intResult(); } if (export) { for (int cnt = 0; cnt < run; cnt++) { this.bitmaps[j++] = bitmaps[i++]; } } else { i += run; } export = !export; } int contextRetained = symbolDictionaryFlags.getFlagValue(SymbolDictionaryFlags.BITMAP_CC_RETAINED); if (!sdHuffman && contextRetained == 1) { genericRegionStats = genericRegionStats.copy(); if (sdRefinementAggregate == 1) { refinementRegionStats = refinementRegionStats.copy(); } } /** consume any remaining bits */ decoder.consumeRemainingBits(); }
private void readSegments() { bool finished = false; while (!reader.isFinished() && !finished) { SegmentHeader segmentHeader = new SegmentHeader(); readSegmentHeader(segmentHeader); // read the Segment data Segment segment = null; int segmentType = segmentHeader.getSegmentType(); int[] referredToSegments = segmentHeader.getReferredToSegments(); int noOfReferredToSegments = segmentHeader.getReferredToSegmentCount(); switch (segmentType) { case Segment.SYMBOL_DICTIONARY: segment = new SymbolDictionarySegment(this); segment.setSegmentHeader(segmentHeader); break; case Segment.INTERMEDIATE_TEXT_REGION: segment = new TextRegionSegment(this, false); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_TEXT_REGION: segment = new TextRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_LOSSLESS_TEXT_REGION: segment = new TextRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.PATTERN_DICTIONARY: segment = new PatternDictionarySegment(this); segment.setSegmentHeader(segmentHeader); break; case Segment.INTERMEDIATE_HALFTONE_REGION: segment = new HalftoneRegionSegment(this, false); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_HALFTONE_REGION: segment = new HalftoneRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_LOSSLESS_HALFTONE_REGION: segment = new HalftoneRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.INTERMEDIATE_GENERIC_REGION: segment = new GenericRegionSegment(this, false); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_GENERIC_REGION: segment = new GenericRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_LOSSLESS_GENERIC_REGION: segment = new GenericRegionSegment(this, true); segment.setSegmentHeader(segmentHeader); break; case Segment.INTERMEDIATE_GENERIC_REFINEMENT_REGION: segment = new RefinementRegionSegment(this, false, referredToSegments, noOfReferredToSegments); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_GENERIC_REFINEMENT_REGION: segment = new RefinementRegionSegment(this, true, referredToSegments, noOfReferredToSegments); segment.setSegmentHeader(segmentHeader); break; case Segment.IMMEDIATE_LOSSLESS_GENERIC_REFINEMENT_REGION: segment = new RefinementRegionSegment(this, true, referredToSegments, noOfReferredToSegments); segment.setSegmentHeader(segmentHeader); break; case Segment.PAGE_INFORMATION: segment = new PageInformationSegment(this); segment.setSegmentHeader(segmentHeader); break; case Segment.END_OF_PAGE: continue; case Segment.END_OF_STRIPE: segment = new EndOfStripeSegment(this); segment.setSegmentHeader(segmentHeader); break; case Segment.END_OF_FILE: finished = true; continue; case Segment.PROFILES: break; case Segment.TABLES: break; case Segment.EXTENSION: segment = new ExtensionSegment(this); segment.setSegmentHeader(segmentHeader); break; default: break; } if (!randomAccessOrganisation) { segment.readSegment(); } segments.Add(segment); } if (randomAccessOrganisation) { foreach (Segment segment in segments) { segment.readSegment(); } } }