Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="JPEGFile"/> class.
        /// </summary>
        /// <param name="stream">A stream that contains image data.</param>
        /// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
        /// <param name="readTrailingData">Whether to read data beyond the EOI (end of image) marker.</param>
        protected internal JPEGFile(MemoryStream stream, Encoding encoding, bool readTrailingData = false)
        {
            Format       = ImageFileFormat.JPEG;
            Sections     = new List <JPEGSection>();
            TrailingData = new byte[0];
            Encoding     = encoding;

            stream.Seek(0, SeekOrigin.Begin);

            // Read the Start of Image (SOI) marker. SOI marker is represented
            // with two bytes: 0xFF, 0xD8.
            byte[] markerbytes = new byte[2];
            if (stream.Read(markerbytes, 0, 2) != 2 || markerbytes[0] != 0xFF || markerbytes[1] != 0xD8)
            {
                throw new NotValidJPEGFileException();
            }
            stream.Seek(0, SeekOrigin.Begin);

            // Search and read sections until we reach the end of file.
            while (stream.Position != stream.Length)
            {
                // Read the next section marker. Section markers are two bytes
                // with values 0xFF, 0x?? where ?? must not be 0x00 or 0xFF.
                if (stream.Read(markerbytes, 0, 2) != 2 || markerbytes[0] != 0xFF || markerbytes[1] == 0x00 || markerbytes[1] == 0xFF)
                {
                    throw new NotValidJPEGFileException();
                }

                JPEGMarker marker = (JPEGMarker)markerbytes[1];

                byte[] header = new byte[0];
                // SOI, EOI and RST markers do not contain any header
                if (marker != JPEGMarker.SOI && marker != JPEGMarker.EOI && !(marker >= JPEGMarker.RST0 && marker <= JPEGMarker.RST7))
                {
                    // Length of the header including the length bytes.
                    // This value is a 16-bit unsigned integer
                    // in big endian byte-order.
                    byte[] lengthbytes = new byte[2];
                    if (stream.Read(lengthbytes, 0, 2) != 2)
                    {
                        throw new NotValidJPEGFileException();
                    }
                    long length = (long)BitConverterEx.BigEndian.ToUInt16(lengthbytes, 0);

                    // Read section header.
                    header = Utility.GetStreamBytes(stream, length - 2);
                }

                // Start of Scan (SOS) sections and RST sections are immediately
                // followed by entropy coded data. For that, we need to read until
                // the next section marker once we reach a SOS or RST.
                byte[] entropydata = new byte[0];
                if (marker == JPEGMarker.SOS || (marker >= JPEGMarker.RST0 && marker <= JPEGMarker.RST7))
                {
                    long position = stream.Position;

                    // Search for the next section marker
                    while (true)
                    {
                        // Search for an 0xFF indicating start of a marker
                        int nextbyte = 0;
                        do
                        {
                            nextbyte = stream.ReadByte();
                            if (nextbyte == -1)
                            {
                                break;
                            }
                        } while ((byte)nextbyte != 0xFF);

                        // Skip filler bytes (0xFF)
                        do
                        {
                            nextbyte = stream.ReadByte();
                            if (nextbyte == -1)
                            {
                                break;
                            }
                        } while ((byte)nextbyte == 0xFF);

                        // We either reached the end of file before a new marker(this would indicate
                        // a corrupt image file) or we are at a section marker. In that case the
                        // next byte must not be 0x00.
                        if (nextbyte != 0)
                        {
                            // If we reached a section marker seek back to just before the marker.
                            if (nextbyte != -1)
                            {
                                stream.Seek(-2, SeekOrigin.Current);
                            }

                            // Calculate the length of the entropy coded data.
                            long edlength = stream.Position - position;
                            stream.Seek(position, SeekOrigin.Begin);

                            // Read entropy coded data
                            entropydata = Utility.GetStreamBytes(stream, edlength);

                            break;
                        }
                    }
                }

                // Store section.
                JPEGSection section = new JPEGSection(marker, header, entropydata);
                Sections.Add(section);

                // Some propriety formats store data past the EOI marker
                if (marker == JPEGMarker.EOI)
                {
                    if (readTrailingData)
                    {
                        long eoflength = stream.Length - stream.Position;
                        TrailingData = Utility.GetStreamBytes(stream, eoflength);
                    }
                    // stop reading once we are past the EOI marker
                    break;
                }
            }

            // Read metadata sections
            ReadJFIFAPP0();
            ReadJFXXAPP0();
            ReadExifAPP1();

            // Process the maker note
            makerNoteProcessed = false;
        }
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 public JPEGSection(JPEGMarker marker)
     : this(marker, new byte[0], new byte[0])
 {
     ;
 }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ExifFile"/> class.
        /// </summary>
        /// <param name="stream">A <see cref="Sytem.IO.Stream"/> that contains image data.</param>
        protected internal JPEGFile(Stream stream)
        {
            Format       = ImageFileFormat.JPEG;
            Sections     = new List <JPEGSection>();
            TrailingData = new byte[0];

            stream.Seek(0, SeekOrigin.Begin);

            // Read the Start of Image (SOI) marker. SOI marker is represented
            // with two bytes: 0xFF, 0xD8.
            byte[] markerbytes = new byte[2];
            if (stream.Read(markerbytes, 0, 2) != 2 || markerbytes[0] != 0xFF || markerbytes[1] != 0xD8)
            {
                throw new NotValidJPEGFileException();
            }
            stream.Seek(0, SeekOrigin.Begin);

            // Search and read sections until we reach the end of file.
            while (stream.Position != stream.Length)
            {
                // Read the next section marker. Section markers are two bytes
                // with values 0xFF, 0x?? where ?? must not be 0x00 or 0xFF.
                if (stream.Read(markerbytes, 0, 2) != 2 || markerbytes[0] != 0xFF || markerbytes[1] == 0x00 || markerbytes[1] == 0xFF)
                {
                    throw new NotValidJPEGFileException();
                }

                JPEGMarker marker = (JPEGMarker)markerbytes[1];

                byte[] header = new byte[0];
                // SOI, EOI and RST markers do not contain any header
                if (marker != JPEGMarker.SOI && marker != JPEGMarker.EOI && !(marker >= JPEGMarker.RST0 && marker <= JPEGMarker.RST7))
                {
                    // Length of the header including the length bytes.
                    // This value is a 16-bit unsigned integer
                    // in big endian byte-order.
                    byte[] lengthbytes = new byte[2];
                    if (stream.Read(lengthbytes, 0, 2) != 2)
                    {
                        throw new NotValidJPEGFileException();
                    }
                    long length = (long)BitConverterEx.BigEndian.ToUInt16(lengthbytes, 0);

                    // Read section header.
                    header = new byte[length - 2];
                    int bytestoread = header.Length;
                    while (bytestoread > 0)
                    {
                        int count     = Math.Min(bytestoread, 4 * 1024);
                        int bytesread = stream.Read(header, header.Length - bytestoread, count);
                        if (bytesread == 0)
                        {
                            throw new NotValidJPEGFileException();
                        }
                        bytestoread -= bytesread;
                    }
                }

                // Start of Scan (SOS) sections and RST sections are immediately
                // followed by entropy coded data. For that, we need to read until
                // the next section marker once we reach a SOS or RST.
                byte[] entropydata = new byte[0];
                if (marker == JPEGMarker.SOS || (marker >= JPEGMarker.RST0 && marker <= JPEGMarker.RST7))
                {
                    long position = stream.Position;

                    // Search for the next section marker
                    while (true)
                    {
                        // Search for an 0xFF indicating start of a marker
                        int nextbyte = 0;
                        do
                        {
                            nextbyte = stream.ReadByte();
                            if (nextbyte == -1)
                            {
                                throw new NotValidJPEGFileException();
                            }
                        } while ((byte)nextbyte != 0xFF);

                        // Skip filler bytes (0xFF)
                        do
                        {
                            nextbyte = stream.ReadByte();
                            if (nextbyte == -1)
                            {
                                throw new NotValidJPEGFileException();
                            }
                        } while ((byte)nextbyte == 0xFF);

                        // Looks like a section marker. The next byte must not be 0x00.
                        if ((byte)nextbyte != 0x00)
                        {
                            // We reached a section marker. Calculate the
                            // length of the entropy coded data.
                            stream.Seek(-2, SeekOrigin.Current);
                            long edlength = stream.Position - position;
                            stream.Seek(-edlength, SeekOrigin.Current);

                            // Read entropy coded data
                            entropydata = new byte[edlength];
                            int bytestoread = entropydata.Length;
                            while (bytestoread > 0)
                            {
                                int count     = Math.Min(bytestoread, 4 * 1024);
                                int bytesread = stream.Read(entropydata, entropydata.Length - bytestoread, count);
                                if (bytesread == 0)
                                {
                                    throw new NotValidJPEGFileException();
                                }
                                bytestoread -= bytesread;
                            }

                            break;
                        }
                    }
                }

                // Store section.
                JPEGSection section = new JPEGSection(marker, header, entropydata);
                Sections.Add(section);

                // Some propriety formats store data past the EOI marker
                if (marker == JPEGMarker.EOI)
                {
                    int bytestoread = (int)(stream.Length - stream.Position);
                    TrailingData = new byte[bytestoread];
                    while (bytestoread > 0)
                    {
                        int count     = (int)Math.Min(bytestoread, 4 * 1024);
                        int bytesread = stream.Read(TrailingData, TrailingData.Length - bytestoread, count);
                        if (bytesread == 0)
                        {
                            throw new NotValidJPEGFileException();
                        }
                        bytestoread -= bytesread;
                    }
                }
            }

            // Read metadata sections
            ReadJFIFAPP0();
            ReadJFXXAPP0();
            ReadExifAPP1();

            // Process the maker note
            makerNoteProcessed = false;
        }
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte and containing
 /// the given data.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 /// <param name="data">Section data.</param>
 /// <param name="entropydata">Entropy coded data.</param>
 public JPEGSection(JPEGMarker marker, byte[] data, byte[] entropydata)
 {
     Marker      = marker;
     Header      = data;
     EntropyData = entropydata;
 }
Esempio n. 5
0
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 public JPEGSection(JPEGMarker marker)
 {
     Marker = marker;
 }
Esempio n. 6
0
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 public JPEGSection(JPEGMarker marker)
 {
     Marker = marker;
 }
Esempio n. 7
0
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte and containing
 /// the given data.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 /// <param name="data">Section data.</param>
 /// <param name="entropydata">Entropy coded data.</param>
 public JPEGSection(JPEGMarker marker, byte[] data, byte[] entropydata)
 {
     Marker = marker;
     Header = data;
     EntropyData = entropydata;
 }
Esempio n. 8
0
 /// <summary>
 /// Constructs a JPEGSection represented by the marker byte.
 /// </summary>
 /// <param name="marker">The marker byte representing the section.</param>
 public JPEGSection(JPEGMarker marker)
     : this(marker, new byte[0], new byte[0])
 {
     ;
 }