/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source. /// Under the MIT License, details: License.txt. using System; using System.IO; namespace FluxJpeg.Core.IO { internal class JPEGMarkerFoundException : Exception { public JPEGMarkerFoundException(byte marker) { this.Marker = marker; } public byte Marker; } internal class JPEGBinaryReader : IO.BinaryReader { public int eob_run = 0; private byte marker; public JPEGBinaryReader(Stream input) : base(input) { } /// /// Seeks through the stream until a marker is found. /// public byte GetNextMarker() { try { while (true) { ReadJpegByte(); } } catch (JPEGMarkerFoundException ex) { return ex.Marker; } } byte _bitBuffer; protected int _bitsLeft = 0; public int BitOffset { get { return (8 - _bitsLeft) % 8; } set { if (_bitsLeft != 0) BaseStream.Seek(-1, SeekOrigin.Current); _bitsLeft = (8 - value) % 8; } } /// /// Places n bits from the stream, where the most-significant bits /// from the first byte read end up as the most-significant of the returned /// n bits. /// /// Number of bits to return /// Integer containing the bits desired -- shifted all the way right. public int ReadBits(int n) { int result = 0; #region Special case -- included for optimization purposes if (_bitsLeft >= n) { _bitsLeft-=n; result = _bitBuffer >> (8 - n); _bitBuffer = (byte)(_bitBuffer << n); return result; } #endregion while (n > 0) { if (_bitsLeft == 0) { _bitBuffer = ReadJpegByte(); _bitsLeft = 8; } int take = n <= _bitsLeft ? n : _bitsLeft; result = result | ((_bitBuffer >> 8 - take) << (n - take)); _bitBuffer = (byte)(_bitBuffer << take); _bitsLeft -= take; n -= take; } return result; } protected byte ReadJpegByte() { byte c = ReadByte(); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == JPEGMarker.XFF) { // Discard padded oxFFs while ((c = ReadByte()) == 0xff) ; // ff00 is the escaped form of 0xff if (c == 0) c = 0xff; else { // Otherwise we've found a new marker. marker = c; throw new JPEGMarkerFoundException(marker); } } return c; } } }