void readSegment(Jbig2Segment s) { int ptr = _ra.FilePointer; if (s.DataLength == 0xffffffffL) { // TODO figure this bit out, 7.2.7 return; } byte[] data = new byte[(int)s.DataLength]; _ra.Read(data); s.Data = data; if (s.Type == PAGE_INFORMATION) { int last = _ra.FilePointer; _ra.Seek(ptr); int pageBitmapWidth = _ra.ReadInt(); int pageBitmapHeight = _ra.ReadInt(); _ra.Seek(last); Jbig2Page p = (Jbig2Page)_pages[s.Page]; if (p == null) { throw new InvalidOperationException("referring to widht/height of page we havent seen yet? " + s.Page); } p.PageBitmapWidth = pageBitmapWidth; p.PageBitmapHeight = pageBitmapHeight; } }
public void Read() { if (_read) { throw new InvalidOperationException("already attempted a Read() on this Jbig2 File"); } _read = true; readFileHeader(); // Annex D if (_sequential) { // D.1 do { Jbig2Segment tmp = readHeader(); readSegment(tmp); _segments[tmp.SegmentNumber] = tmp; } while (_ra.FilePointer < _ra.Length); } else { // D.2 Jbig2Segment tmp; do { tmp = readHeader(); _segments[tmp.SegmentNumber] = tmp; } while (tmp.Type != END_OF_FILE); foreach (int ss in _segments.Keys) { readSegment((Jbig2Segment)_segments[ss]); } } }
/// <summary> /// return as a single byte array the header-data for each segment in segment number /// order, EMBEDDED organization, but i am putting the needed segments in SEQUENTIAL organization. /// if for_embedding, skip the segment types that are known to be not for acrobat. /// @throws IOException /// </summary> /// <param name="forEmbedding"></param> /// <returns>a byte array</returns> public byte[] GetData(bool forEmbedding) { MemoryStream os = new MemoryStream(); foreach (int sn in _segs.Keys) { Jbig2Segment s = (Jbig2Segment)_segs[sn]; // pdf reference 1.4, section 3.3.6 JBIG2Decode Filter // D.3 Embedded organisation if (forEmbedding && (s.Type == END_OF_FILE || s.Type == END_OF_PAGE)) { continue; } if (forEmbedding) { // change the page association to page 1 byte[] headerDataEmb = CopyByteArray(s.HeaderData); if (s.PageAssociationSize) { headerDataEmb[s.PageAssociationOffset] = 0x0; headerDataEmb[s.PageAssociationOffset + 1] = 0x0; headerDataEmb[s.PageAssociationOffset + 2] = 0x0; headerDataEmb[s.PageAssociationOffset + 3] = 0x1; } else { headerDataEmb[s.PageAssociationOffset] = 0x1; } os.Write(headerDataEmb, 0, headerDataEmb.Length); } else { os.Write(s.HeaderData, 0, s.HeaderData.Length); } os.Write(s.Data, 0, s.Data.Length); } return(os.ToArray()); }
public int CompareTo(Jbig2Segment s) { return(SegmentNumber - s.SegmentNumber); }
public void AddSegment(Jbig2Segment s) { _segs[s.SegmentNumber] = s; }
Jbig2Segment readHeader() { int ptr = _ra.FilePointer; // 7.2.1 int segmentNumber = _ra.ReadInt(); Jbig2Segment s = new Jbig2Segment(segmentNumber); // 7.2.3 int segmentHeaderFlags = _ra.Read(); bool deferredNonRetain = ((segmentHeaderFlags & 0x80) == 0x80); s.DeferredNonRetain = deferredNonRetain; bool pageAssociationSize = ((segmentHeaderFlags & 0x40) == 0x40); int segmentType = (segmentHeaderFlags & 0x3f); s.Type = segmentType; //7.2.4 int referredToByte0 = _ra.Read(); int countOfReferredToSegments = (referredToByte0 & 0xE0) >> 5; int[] referredToSegmentNumbers; bool[] segmentRetentionFlags = null; if (countOfReferredToSegments == 7) { // at least five bytes _ra.Seek(_ra.FilePointer - 1); countOfReferredToSegments = (_ra.ReadInt() & 0x1fffffff); segmentRetentionFlags = new bool[countOfReferredToSegments + 1]; int i = 0; int referredToCurrentByte = 0; do { int j = i % 8; if (j == 0) { referredToCurrentByte = _ra.Read(); } segmentRetentionFlags[i] = ((((0x1 << j) & referredToCurrentByte) >> j) == 0x1); i++; } while (i <= countOfReferredToSegments); } else if (countOfReferredToSegments <= 4) { // only one byte segmentRetentionFlags = new bool[countOfReferredToSegments + 1]; referredToByte0 &= 0x1f; for (int i = 0; i <= countOfReferredToSegments; i++) { segmentRetentionFlags[i] = ((((0x1 << i) & referredToByte0) >> i) == 0x1); } } else if (countOfReferredToSegments == 5 || countOfReferredToSegments == 6) { throw new InvalidOperationException("count of referred-to segments had bad value in header for segment " + segmentNumber + " starting at " + ptr); } s.SegmentRetentionFlags = segmentRetentionFlags; s.CountOfReferredToSegments = countOfReferredToSegments; // 7.2.5 referredToSegmentNumbers = new int[countOfReferredToSegments + 1]; for (int i = 1; i <= countOfReferredToSegments; i++) { if (segmentNumber <= 256) { referredToSegmentNumbers[i] = _ra.Read(); } else if (segmentNumber <= 65536) { referredToSegmentNumbers[i] = _ra.ReadUnsignedShort(); } else { referredToSegmentNumbers[i] = (int)_ra.ReadUnsignedInt(); // TODO wtf ack } } s.ReferredToSegmentNumbers = referredToSegmentNumbers; // 7.2.6 int segmentPageAssociation; int pageAssociationOffset = _ra.FilePointer - ptr; if (pageAssociationSize) { segmentPageAssociation = _ra.ReadInt(); } else { segmentPageAssociation = _ra.Read(); } if (segmentPageAssociation < 0) { throw new InvalidOperationException("page " + segmentPageAssociation + " invalid for segment " + segmentNumber + " starting at " + ptr); } s.Page = segmentPageAssociation; // so we can change the page association at embedding time. s.PageAssociationSize = pageAssociationSize; s.PageAssociationOffset = pageAssociationOffset; if (segmentPageAssociation > 0 && !_pages.ContainsKey(segmentPageAssociation)) { _pages[segmentPageAssociation] = new Jbig2Page(segmentPageAssociation, this); } if (segmentPageAssociation > 0) { ((Jbig2Page)_pages[segmentPageAssociation]).AddSegment(s); } else { _globals[s] = null; } // 7.2.7 long segmentDataLength = _ra.ReadUnsignedInt(); // TODO the 0xffffffff value that might be here, and how to understand those afflicted segments s.DataLength = segmentDataLength; int endPtr = _ra.FilePointer; _ra.Seek(ptr); byte[] headerData = new byte[endPtr - ptr]; _ra.Read(headerData); s.HeaderData = headerData; return(s); }
public int CompareTo(Jbig2Segment s) => SegmentNumber - s.SegmentNumber;