internal virtual void ReadSegment(Jbig2SegmentReader.Jbig2Segment s)
        {
            int ptr = (int)ra.GetPosition();

            if (s.dataLength == unchecked ((long)(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 = (int)ra.GetPosition();
                ra.Seek(ptr);
                int page_bitmap_width  = ra.ReadInt();
                int page_bitmap_height = ra.ReadInt();
                ra.Seek(last);
                Jbig2SegmentReader.Jbig2Page p = pages.Get(s.page);
                if (p == null)
                {
                    throw new iText.IO.IOException("Referring to widht or height of a page we haven't seen yet: {0}").SetMessageParams
                              (s.page);
                }
                p.pageBitmapWidth  = page_bitmap_width;
                p.pageBitmapHeight = page_bitmap_height;
            }
        }
        public virtual byte[] GetGlobal(bool for_embedding)
        {
            MemoryStream os = new MemoryStream();

            byte[] streamBytes = null;
            try {
                foreach (Object element in globals)
                {
                    Jbig2SegmentReader.Jbig2Segment s = (Jbig2SegmentReader.Jbig2Segment)element;
                    if (for_embedding && (s.type == END_OF_FILE || s.type == END_OF_PAGE))
                    {
                        continue;
                    }
                    os.Write(s.headerData);
                    os.Write(s.data);
                }
                if (os.Length > 0)
                {
                    streamBytes = os.ToArray();
                }
                os.Dispose();
            }
            catch (System.IO.IOException e) {
                ILog logger = LogManager.GetLogger(typeof(Jbig2SegmentReader));
                logger.Debug(e.Message);
            }
            return(streamBytes);
        }
 public virtual void Read()
 {
     if (this.read)
     {
         throw new InvalidOperationException("already.attempted.a.read.on.this.jbig2.file");
     }
     this.read = true;
     ReadFileHeader();
     // Annex D
     if (this.sequential)
     {
         // D.1
         do
         {
             Jbig2SegmentReader.Jbig2Segment tmp = ReadHeader();
             ReadSegment(tmp);
             segments.Put(tmp.segmentNumber, tmp);
         }while (this.ra.GetPosition() < this.ra.Length());
     }
     else
     {
         // D.2
         Jbig2SegmentReader.Jbig2Segment tmp;
         do
         {
             tmp = ReadHeader();
             segments.Put(tmp.segmentNumber, tmp);
         }while (tmp.type != END_OF_FILE);
         foreach (int integer in segments.Keys)
         {
             ReadSegment(segments.Get(integer));
         }
     }
 }
            /// <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.
            /// </summary>
            /// <remarks>
            /// 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.
            /// </remarks>
            /// <param name="for_embedding">True if the bytes represents embedded data, false otherwise</param>
            /// <returns>a byte array</returns>
            public virtual byte[] GetData(bool for_embedding)
            {
                MemoryStream os = new MemoryStream();

                foreach (int sn in segs.Keys)
                {
                    Jbig2SegmentReader.Jbig2Segment s = segs.Get(sn);
                    // pdf reference 1.4, section 3.3.6 Jbig2Decode Filter
                    // D.3 Embedded organisation
                    if (for_embedding && (s.type == END_OF_FILE || s.type == END_OF_PAGE))
                    {
                        continue;
                    }
                    if (for_embedding)
                    {
                        // change the page association to page 1
                        byte[] headerData_emb = CopyByteArray(s.headerData);
                        if (s.page_association_size)
                        {
                            headerData_emb[s.page_association_offset]     = 0x0;
                            headerData_emb[s.page_association_offset + 1] = 0x0;
                            headerData_emb[s.page_association_offset + 2] = 0x0;
                            headerData_emb[s.page_association_offset + 3] = 0x1;
                        }
                        else
                        {
                            headerData_emb[s.page_association_offset] = 0x1;
                        }
                        os.Write(headerData_emb);
                    }
                    else
                    {
                        os.Write(s.headerData);
                    }
                    os.Write(s.data);
                }
                os.Dispose();
                return(os.ToArray());
            }
        internal virtual Jbig2SegmentReader.Jbig2Segment ReadHeader()
        {
            int ptr = (int)ra.GetPosition();
            // 7.2.1
            int segment_number = ra.ReadInt();

            Jbig2SegmentReader.Jbig2Segment s = new Jbig2SegmentReader.Jbig2Segment(segment_number);
            // 7.2.3
            int  segment_header_flags = ra.Read();
            bool deferred_non_retain  = (segment_header_flags & 0x80) == 0x80;

            s.deferredNonRetain = deferred_non_retain;
            bool page_association_size = (segment_header_flags & 0x40) == 0x40;
            int  segment_type          = segment_header_flags & 0x3f;

            s.type = segment_type;
            //7.2.4
            int referred_to_byte0             = ra.Read();
            int count_of_referred_to_segments = (referred_to_byte0 & 0xE0) >> 5;

            int[]  referred_to_segment_numbers = null;
            bool[] segment_retention_flags     = null;
            if (count_of_referred_to_segments == 7)
            {
                // at least five bytes
                ra.Seek(ra.GetPosition() - 1);
                count_of_referred_to_segments = ra.ReadInt() & 0x1fffffff;
                segment_retention_flags       = new bool[count_of_referred_to_segments + 1];
                int i = 0;
                int referred_to_current_byte = 0;
                do
                {
                    int j = i % 8;
                    if (j == 0)
                    {
                        referred_to_current_byte = ra.Read();
                    }
                    segment_retention_flags[i] = (0x1 << j & referred_to_current_byte) >> j == 0x1;
                    i++;
                }while (i <= count_of_referred_to_segments);
            }
            else
            {
                if (count_of_referred_to_segments <= 4)
                {
                    // only one byte
                    segment_retention_flags = new bool[count_of_referred_to_segments + 1];
                    referred_to_byte0      &= 0x1f;
                    for (int i = 0; i <= count_of_referred_to_segments; i++)
                    {
                        segment_retention_flags[i] = (0x1 << i & referred_to_byte0) >> i == 0x1;
                    }
                }
                else
                {
                    if (count_of_referred_to_segments == 5 || count_of_referred_to_segments == 6)
                    {
                        throw new iText.IO.IOException("Count of referred-to segments has forbidden value in the header for segment {0} starting at {1}"
                                                       ).SetMessageParams(segment_number, ptr);
                    }
                }
            }
            s.segmentRetentionFlags     = segment_retention_flags;
            s.countOfReferredToSegments = count_of_referred_to_segments;
            // 7.2.5
            referred_to_segment_numbers = new int[count_of_referred_to_segments + 1];
            for (int i = 1; i <= count_of_referred_to_segments; i++)
            {
                if (segment_number <= 256)
                {
                    referred_to_segment_numbers[i] = ra.Read();
                }
                else
                {
                    if (segment_number <= 65536)
                    {
                        referred_to_segment_numbers[i] = ra.ReadUnsignedShort();
                    }
                    else
                    {
                        // TODO wtf ack
                        referred_to_segment_numbers[i] = (int)ra.ReadUnsignedInt();
                    }
                }
            }
            s.referredToSegmentNumbers = referred_to_segment_numbers;
            // 7.2.6
            int segment_page_association;
            int page_association_offset = (int)ra.GetPosition() - ptr;

            if (page_association_size)
            {
                segment_page_association = ra.ReadInt();
            }
            else
            {
                segment_page_association = ra.Read();
            }
            if (segment_page_association < 0)
            {
                throw new iText.IO.IOException("Page {0} is invalid for segment {1} starting at {2}").SetMessageParams(segment_page_association
                                                                                                                       , segment_number, ptr);
            }
            s.page = segment_page_association;
            // so we can change the page association at embedding time.
            s.page_association_size   = page_association_size;
            s.page_association_offset = page_association_offset;
            if (segment_page_association > 0 && !pages.ContainsKey(segment_page_association))
            {
                pages.Put(segment_page_association, new Jbig2SegmentReader.Jbig2Page(segment_page_association, this));
            }
            if (segment_page_association > 0)
            {
                pages.Get(segment_page_association).AddSegment(s);
            }
            else
            {
                globals.Add(s);
            }
            // 7.2.7
            long segment_data_length = ra.ReadUnsignedInt();

            // TODO the 0xffffffff value that might be here, and how to understand those afflicted segments
            s.dataLength = segment_data_length;
            int end_ptr = (int)ra.GetPosition();

            ra.Seek(ptr);
            byte[] header_data = new byte[end_ptr - ptr];
            ra.Read(header_data);
            s.headerData = header_data;
            return(s);
        }
 public virtual void AddSegment(Jbig2SegmentReader.Jbig2Segment s)
 {
     segs.Put(s.segmentNumber, s);
 }
 public virtual void AddSegment(Jbig2SegmentReader.Jbig2Segment s)
 {
     segs[s.segmentNumber] = s;
 }