public JpegMarker getNextMarker(bool allowskip)
        {
            if (!allowskip)
            {
                byte idL = input.ReadByte();
                if (idL != 0xff)
                {
                    throw new Exception("getNextMarker: (Noskip) Expected marker not found. Propably corrupt file.");
                }

                JpegMarker markL = (JpegMarker)input.ReadByte();

                if (JpegMarker.M_FILL == markL || JpegMarker.M_STUFF == markL)
                {
                    throw new Exception("getNextMarker: (Noskip) Expected marker, but found stuffed 00 or ff.");
                }

                return(markL);
            }
            input.skipToMarker();
            byte id = input.ReadByte();
            //TODO change
            //_ASSERTE(0xff == id);
            JpegMarker mark = (JpegMarker)input.ReadByte();

            return(mark);
        }
示例#2
0
        public SOFInfo GetSOF(uint offset, uint size)
        {
            // JPEG is big endian
            if (Common.GetHostEndianness() == Endianness.Big)
            {
                input = new ImageBinaryReader(input.BaseStream, offset);
            }
            else
            {
                input = new ImageBinaryReaderBigEndian(input.BaseStream, offset);
            }

            if (GetNextMarker(false) != JpegMarker.SOI)
            {
                throw new RawDecoderException("Image did not start with SOI. Probably not an LJPEG");
            }

            while (true)
            {
                JpegMarker m = GetNextMarker(true);
                if (m == JpegMarker.Sof3)
                {
                    SOFInfo sof = new SOFInfo();
                    ParseSOF(sof);
                    return(sof);
                }
                if (m == JpegMarker.EOI)
                {
                    throw new RawDecoderException("Could not locate Start of Frame.");
                }
            }
        }
示例#3
0
        public JpegMarker GetNextMarker(bool allowskip)
        {
            if (!allowskip)
            {
                byte idL = input.ReadByte();
                if (idL != 0xff)
                {
                    throw new RawDecoderException("Expected marker not found. Probably corrupt file.");
                }

                JpegMarker markL = (JpegMarker)input.ReadByte();

                if (JpegMarker.Fill == markL || JpegMarker.Stuff == markL)
                {
                    throw new RawDecoderException("Expected marker, but found stuffed 00 or ff.");
                }

                return(markL);
            }
            input.SkipToMarker();
            var id = input.ReadByte();

            Debug.Assert(0xff == id);
            JpegMarker mark = (JpegMarker)input.ReadByte();

            return(mark);
        }
示例#4
0
        /// <summary>
        /// Emit a SOF marker
        /// </summary>
        private void EmitSOF(JpegMarker code)
        {
            EmitMarker(code);

            Emit2Bytes((3 * m_cinfo.m_num_components) + 2 + 5 + 1); /* length */

            /* Make sure image isn't bigger than SOF field can handle */
            if (m_cinfo.jpeg_height > 65535 || m_cinfo.jpeg_width > 65535)
            {
                m_cinfo.ErrExit(JMessageCode.JERR_IMAGE_TOO_BIG, 65535);
            }

            EmitByte(m_cinfo.m_data_precision);
            Emit2Bytes(m_cinfo.jpeg_height);
            Emit2Bytes(m_cinfo.jpeg_width);

            EmitByte(m_cinfo.m_num_components);

            for (var ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                var componentInfo = m_cinfo.Component_info[ci];
                EmitByte(componentInfo.Component_id);
                EmitByte((componentInfo.H_samp_factor << 4) + componentInfo.V_samp_factor);
                EmitByte(componentInfo.Quant_tbl_no);
            }
        }
示例#5
0
 public JpegBitReader(ReadOnlySequence <byte> data)
 {
     _data         = data;
     _firstSpan    = default;
     _buffer       = 0;
     _bitsInBuffer = 0;
     _nextMarker   = 0;
 }
示例#6
0
        protected virtual bool ProcessMarkerForIdentification(JpegMarker marker, ref JpegReader reader, bool loadQuantizationTables)
        {
            switch (marker)
            {
            case JpegMarker.StartOfImage:
                break;

            case JpegMarker.StartOfFrame0:
            case JpegMarker.StartOfFrame1:
            case JpegMarker.StartOfFrame2:
            case JpegMarker.StartOfFrame3:
            case JpegMarker.StartOfFrame9:
            case JpegMarker.StartOfFrame10:
            case JpegMarker.StartOfFrame5:
            case JpegMarker.StartOfFrame6:
            case JpegMarker.StartOfFrame7:
            case JpegMarker.StartOfFrame11:
            case JpegMarker.StartOfFrame13:
            case JpegMarker.StartOfFrame14:
            case JpegMarker.StartOfFrame15:
                StartOfFrame = marker;
                ProcessFrameHeader(ref reader, false, false);
                break;

            case JpegMarker.StartOfScan:
                ProcessScanHeader(ref reader, true);
                break;

            case JpegMarker.DefineRestartInterval:
                ProcessDefineRestartInterval(ref reader);
                break;

            case JpegMarker.DefineQuantizationTable:
                ProcessDefineQuantizationTable(ref reader, loadQuantizationTables);
                break;

            case JpegMarker.DefineRestart0:
            case JpegMarker.DefineRestart1:
            case JpegMarker.DefineRestart2:
            case JpegMarker.DefineRestart3:
            case JpegMarker.DefineRestart4:
            case JpegMarker.DefineRestart5:
            case JpegMarker.DefineRestart6:
            case JpegMarker.DefineRestart7:
                break;

            case JpegMarker.EndOfImage:
                return(false);

            default:
                ProcessOtherMarker(ref reader);
                break;
            }

            return(true);
        }
示例#7
0
 public JpegMarker TryReadMarker()
 {
     if (_bitsInBuffer == 0)
     {
         JpegMarker marker = _nextMarker;
         _nextMarker = 0;
         return(marker);
     }
     return(0);
 }
示例#8
0
        public void WriteMarker(JpegMarker marker)
        {
            if (_bitMode)
            {
                throw new InvalidOperationException("When bit mode is enabled, you are not allowed to write bytes to the stream.");
            }

            EnsureBuffer(2);

            Span <byte> buffer = _buffer;

            buffer[1]         = (byte)marker;
            buffer[0]         = 0xff;
            _buffer           = buffer.Slice(2);
            _bufferConsunmed += 2;
        }
示例#9
0
        public static Marker Load(Stream stream)
        {
            byte [] raw = new byte [2];
            ushort  length;

            if (stream.Length - stream.Position < 2)
            {
                return(null);
            }

            // FIXME there is a potential loop here.

            int read = Read(stream, raw, 0, 2);

            if (read < 2 || raw [0] != 0xff)
            {
                throw new System.Exception(System.String.Format("Invalid marker found {0}", raw [0]));
            }

            JpegMarker id = (JpegMarker)raw [1];

            switch (id)
            {
            case JpegMarker.Soi:
            case JpegMarker.Eoi:
            case JpegMarker.Rst0:
            case JpegMarker.Rst1:
            case JpegMarker.Rst2:
            case JpegMarker.Rst3:
            case JpegMarker.Rst4:
            case JpegMarker.Rst5:
            case JpegMarker.Rst6:
            case JpegMarker.Rst7:
            case JpegMarker.Tem:
            case (JpegMarker)0:
                return(new Marker(id, null));

            default:
                Read(stream, raw, 0, 2);
                length = FSpot.BitConverter.ToUInt16(raw, 0, false);

                byte [] data = new byte [length - 2];
                Read(stream, data, 0, data.Length);
                return(new Marker(id, data));
            }
        }
示例#10
0
 private int FillBuffer()
 {
     // Read until we have at least 32 bits in the buffer
     while (_bitsInBuffer < 32)
     {
         if (_nextMarker != 0)
         {
             return(_bitsInBuffer);
         }
         // Read next byte
         if (!TryReadNextByte(out byte byteRead))
         {
             break;
         }
         if (byteRead == 0xff)
         {
             // A marker may be encountered, lets peek it out to see what it is.
             if (!TryPeekNextByte(out byteRead))
             {
                 // The stream ended prematurely
                 break;
             }
             if (byteRead == 0xff)
             {
                 // It is the padding byte, continue reading
                 continue;
             }
             // It is not the padding byte, advance past it
             _ = TryReadNextByte(out _);
             if (byteRead != 0)
             {
                 // It is a marker
                 _nextMarker = (JpegMarker)byteRead;
                 break;
             }
             // It a stuffed byte
             byteRead = 0xff;
         }
         // Put the byte read in the buffer
         _buffer        = (_buffer << 8) | byteRead;
         _bitsInBuffer += 8;
     }
     return(_bitsInBuffer);
 }
        public void getSOF(SOFInfo sof, UInt32 offset, UInt32 size)
        {
            if (!input.isValid(offset, size))
            {
                throw new Exception("getSOF: Start offset plus size is longer than file. Truncated file.");
            }
            try
            {
                Endianness host_endian = Common.getHostEndianness();
                // JPEG is big endian
                if (host_endian == Endianness.big)
                {
                    input = new TIFFBinaryReader(input.BaseStream, offset, size);
                }
                else
                {
                    input = new TIFFBinaryReaderRE(input.BaseStream, offset, size);
                }

                if (getNextMarker(false) != JpegMarker.M_SOI)
                {
                    throw new Exception("getSOF: Image did not start with SOI. Probably not an LJPEG");
                }

                while (true)
                {
                    JpegMarker m = getNextMarker(true);
                    if (JpegMarker.M_SOF3 == m)
                    {
                        parseSOF(sof);
                        return;
                    }
                    if (JpegMarker.M_EOI == m)
                    {
                        throw new Exception("LJpegDecompressor: Could not locate Start of Frame.");
                    }
                }
            }
            catch (IOException)
            {
                throw new Exception("LJpegDecompressor: IO exception, read outside file. Corrupt File.");
            }
        }
示例#12
0
        /*****************************************************************************/

        /*
         *--------------------------------------------------------------
         *
         * EmitSof --
         *
         *	Emit a SOF marker plus data.
         *
         * Results:
         *	None.
         *
         * Side effects:
         *	None.
         *
         *--------------------------------------------------------------
         */

        public void EmitSof(JpegMarker code)
        {
            EmitMarker(code);

            Emit2bytes((int)(3 * fSrcChannels + 2 + 5 + 1));   // length

            EmitByte((uint8)fSrcBitDepth);

            Emit2bytes((int)fSrcRows);
            Emit2bytes((int)fSrcCols);

            EmitByte((uint8)fSrcChannels);

            for (uint32 i = 0; i < fSrcChannels; i++)
            {
                EmitByte((uint8)i);

                EmitByte((uint8)((1 << 4) + 1)); // Not subsampled.

                EmitByte(0);                     // Tq shall be 0 for lossless.
            }
        }
示例#13
0
        public bool TryReadMarker(out JpegMarker marker)
        {
            Span <byte> buffer = stackalloc byte[2];

            while (TryPeekToBuffer(buffer))
            {
                byte b1 = buffer[0];
                byte b2 = buffer[1];

                if (b1 == (byte)JpegMarker.Padding)
                {
                    if (b2 == (byte)JpegMarker.Padding)
                    {
                        _data = _data.Slice(1);
                        continue;
                    }
                    else if (b2 == 0)
                    {
                        _data = _data.Slice(2);
                        continue;
                    }
                    _data  = _data.Slice(2);
                    marker = (JpegMarker)b2;
                    return(true);
                }

                SequencePosition?position = _data.PositionOf((byte)JpegMarker.Padding);
                if (!position.HasValue)
                {
                    _data  = default;
                    marker = default;
                    return(false);
                }

                _data = _data.Slice(position.GetValueOrDefault());
            }
            marker = default;
            return(false);
        }
示例#14
0
        public static JpegScanDecoder?Create(JpegMarker sofMarker, JpegDecoder decoder, JpegFrameHeader header)
        {
            switch (sofMarker)
            {
            case JpegMarker.StartOfFrame0:
            case JpegMarker.StartOfFrame1:
                return(new JpegHuffmanBaselineScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame2:
                return(new JpegHuffmanProgressiveScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame3:
                return(new JpegHuffmanLosslessScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame9:
                return(new JpegArithmeticSequentialScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame10:
                return(new JpegArithmeticProgressiveScanDecoder(decoder, header));

            default:
                return(null);
            }
        }
        public void startDecoder(UInt32 offset, UInt32 size, UInt32 offsetX, UInt32 offsetY)
        {
            if (!input.isValid(offset, size))
            {
                throw new Exception("startDecoder: Start offset plus size is longer than file. Truncated file.");
            }
            if ((int)offsetX >= mRaw.dim.x)
            {
                throw new Exception("startDecoder: X offset outside of image");
            }
            if ((int)offsetY >= mRaw.dim.y)
            {
                throw new Exception("startDecoder: Y offset outside of image");
            }
            offX = offsetX;
            offY = offsetY;

            try
            {
                Endianness host_endian = Common.getHostEndianness();
                // JPEG is big endian
                if (host_endian == Endianness.big)
                {
                    input = new TIFFBinaryReader(input.BaseStream, offset, size);
                }
                else
                {
                    input = new TIFFBinaryReaderRE(input.BaseStream, offset, size);
                }

                if (getNextMarker(false) != JpegMarker.M_SOI)
                {
                    throw new Exception("startDecoder: Image did not start with SOI. Probably not an LJPEG");
                }
                //    _RPT0(0,"Found SOI marker\n");

                bool moreImage = true;
                while (moreImage)
                {
                    JpegMarker m = getNextMarker(true);

                    switch (m)
                    {
                    case JpegMarker.M_SOS:
                        //          _RPT0(0,"Found SOS marker\n");
                        parseSOS();
                        break;

                    case JpegMarker.M_EOI:
                        //          _RPT0(0,"Found EOI marker\n");
                        moreImage = false;
                        break;

                    case JpegMarker.M_DHT:
                        //          _RPT0(0,"Found DHT marker\n");
                        parseDHT();
                        break;

                    case JpegMarker.M_DQT:
                        throw new Exception("LJpegDecompressor: Not a valid RAW file.");

                    case JpegMarker.M_DRI:
                        //          _RPT0(0,"Found DRI marker\n");
                        break;

                    case JpegMarker.M_APP0:
                        //          _RPT0(0,"Found APP0 marker\n");
                        break;

                    case JpegMarker.M_SOF3:
                        //          _RPT0(0,"Found SOF 3 marker:\n");
                        parseSOF(frame);
                        break;

                    default:      // Just let it skip to next marker
                                  // _RPT1(0, "Found marker:0x%x. Skipping\n", m);
                        break;
                    }
                }
            }
            catch (IOException)
            {
                throw;
            }
        }
示例#16
0
 public Marker FindMarker(JpegMarker id, string name)
 {
     return(FindMarker(new Signature(id, name)));
 }
示例#17
0
 public Signature(JpegMarker marker, string name)
 {
     Id   = marker;
     Name = name;
 }
示例#18
0
 public Marker(JpegMarker type, byte [] data)
 {
     this.Type = type;
     this.Data = data;
 }
示例#19
0
	public Marker FindMarker (JpegMarker id, string name)
	{
		return FindMarker (new Signature (id, name));
	}
示例#20
0
        /*****************************************************************************/

        /*
         *--------------------------------------------------------------
         *
         * EmitMarker --
         *
         *	Emit a marker code into the output stream.
         *
         * Results:
         *	None.
         *
         * Side effects:
         *	None.
         *
         *--------------------------------------------------------------
         */

        public void EmitMarker(JpegMarker mark)
        {
            EmitByte(0xFF);
            EmitByte((uint8)mark);
        }
示例#21
0
        //////////////////////////////////////////////////////////////////////////
        // Basic output routines.
        //
        // Note that we do not support suspension while writing a marker.
        // Therefore, an application using suspension must ensure that there is
        // enough buffer space for the initial markers (typ. 600-700 bytes) before
        // calling jpeg_start_compress, and enough space to write the trailing EOI
        // (a few bytes) before calling jpeg_finish_compress.  Multipass compression
        // modes are not supported at all with suspension, so those two are the only
        // points where markers will be written.

        /// <summary>
        /// Emit a marker code
        /// </summary>
        private void EmitMarker(JpegMarker mark)
        {
            EmitByte(0xFF);
            EmitByte((int)mark);
        }
        public override void ProcessScan(ref JpegReader reader, JpegScanHeader scanHeader)
        {
            if (scanHeader.Components is null)
            {
                throw new InvalidOperationException();
            }
            if (Decoder.GetOutputWriter() is null)
            {
                throw new InvalidOperationException();
            }

            // Resolve each component
            Span <JpegHuffmanDecodingComponent> components = _components.AsSpan(0, InitDecodeComponents(_frameHeader, scanHeader, _components));

            foreach (JpegHuffmanDecodingComponent component in components)
            {
                if (component.DcTable is null)
                {
                    ThrowInvalidDataException($"Huffman table of component {component.ComponentIndex} is not defined.");
                }
            }

            JpegPartialScanlineAllocator allocator = _allocator;
            int mcusPerLine   = _mcusPerLine;
            int mcusPerColumn = _mcusPerColumn;

            // Prepare
            JpegBitReader bitReader         = new JpegBitReader(reader.RemainingBytes);
            int           restartInterval   = _restartInterval;
            int           mcusBeforeRestart = restartInterval;
            int           predictor         = scanHeader.StartOfSpectralSelection;
            int           initialPrediction = 1 << (_frameHeader.SamplePrecision - scanHeader.SuccessiveApproximationBitPositionLow - 1);

            for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++)
            {
                for (int colMcu = 0; colMcu < mcusPerLine; colMcu++)
                {
                    // Scan an interleaved mcu... process components in order
                    foreach (JpegHuffmanDecodingComponent component in components)
                    {
                        int index = component.ComponentIndex;
                        JpegHuffmanDecodingTable losslessTable = component.DcTable !;
                        int h       = component.HorizontalSamplingFactor;
                        int v       = component.VerticalSamplingFactor;
                        int offsetX = colMcu * h;
                        int offsetY = rowMcu * v;

                        for (int y = 0; y < v; y++)
                        {
                            Span <short> scanline = allocator.GetScanlineSpan(index, offsetY + y);

                            Span <short> lastScanline = (y == 0 && rowMcu == 0) ? default : allocator.GetScanlineSpan(index, offsetY + y - 1);

                                                        for (int x = 0; x < h; x++)
                                                        {
                                                            int diffValue = ReadSampleLossless(ref bitReader, losslessTable);

                                                            // The one-dimensional horizontal predictor (prediction sample Ra) is used
                                                            // for the first line of samples at the start of the scan and at the beginning of each restart interval
                                                            if (rowMcu == 0 || (restartInterval > 0 && mcusBeforeRestart == restartInterval))
                                                            {
                                                                // At the beginning of the first line and at the beginning of each restart interval the prediction value of 2^(P – 1) is used, where P is the input precision.
                                                                // If the point transformation parameter (see A.4) is non-zero, the prediction value at the beginning of the first lines and the beginning of each restart interval is 2^(P – Pt – 1), where Pt is the value of the point transformation parameter.
                                                                if (colMcu == 0 && x == 0)
                                                                {
                                                                    diffValue += initialPrediction;
                                                                }
                                                                else
                                                                {
                                                                    int ra = scanline[offsetX + x - 1];
                                                                    int rb = y == 0 ? initialPrediction : lastScanline[offsetX + x];
                                                                    int rc = y == 0 ? initialPrediction : lastScanline[offsetX + x - 1];
                                                                    diffValue += predictor switch
                                                                    {
                                                                        1 => ra,                    // Px = Ra
                                                                        2 => rb,                    // Px = Rb
                                                                        3 => rc,                    // Px = Rc
                                                                        4 => ra + rb - rc,          // Px = Ra + Rb – Rc
                                                                        5 => ra + ((rb - rc) >> 1), // Px = Ra + (Rb – Rc)/2
                                                                        6 => rb + ((ra - rc) >> 1), // Px = Rb + (Ra – Rc)/2
                                                                        7 => (ra + rb) >> 1,        // Px = (Ra + Rb)/2
                                                                        _ => 0,                     // No prediction (See Annex J)
                                                                    };
                                                                }
                                                            }
                                                            // The sample from the line above(prediction sample Rb) is used at the start of each line, except for the first line
                                                            else if (colMcu == 0)
                                                            {
                                                                diffValue += lastScanline[offsetX + x];
                                                            }
                                                            else
                                                            {
                                                                diffValue += predictor switch
                                                                {
                                                                    1 => scanline[offsetX + x - 1],                                                                      // Px = Ra
                                                                    2 => lastScanline[offsetX + x],                                                                      // Px = Rb
                                                                    3 => lastScanline[offsetX + x - 1],                                                                  // Px = Rc
                                                                    4 => scanline[offsetX + x - 1] + lastScanline[offsetX + x] - lastScanline[offsetX + x - 1],          // Px = Ra + Rb – Rc
                                                                    5 => scanline[offsetX + x - 1] + ((lastScanline[offsetX + x] - lastScanline[offsetX + x - 1]) >> 1), // Px = Ra + (Rb – Rc)/2
                                                                    6 => lastScanline[offsetX + x] + ((scanline[offsetX + x - 1] - lastScanline[offsetX + x - 1]) >> 1), // Px = Rb + (Ra – Rc)/2
                                                                    7 => (scanline[offsetX + x - 1] + lastScanline[offsetX + x]) >> 1,                                   // Px = (Ra + Rb)/2
                                                                    _ => 0,                                                                                              // No prediction (See Annex J)
                                                                };
                                                            }
                                                            scanline[offsetX + x] = (short)diffValue;
                                                        }
                        }
                    }

                    // Handle restart
                    if (restartInterval > 0 && (--mcusBeforeRestart) == 0)
                    {
                        bitReader.AdvanceAlignByte();

                        JpegMarker marker = bitReader.TryReadMarker();
                        if (marker == JpegMarker.EndOfImage)
                        {
                            int bytesConsumedEoi = reader.RemainingByteCount - bitReader.RemainingBits / 8;
                            reader.TryAdvance(bytesConsumedEoi - 2);
                            return;
                        }
                        if (!marker.IsRestartMarker())
                        {
                            throw new InvalidOperationException("Expect restart marker.");
                        }

                        mcusBeforeRestart = restartInterval;
                    }
                }

                // Flush allocator
                if (rowMcu == mcusPerColumn - 1)
                {
                    foreach (JpegHuffmanDecodingComponent component in components)
                    {
                        allocator.FlushLastMcu(component.ComponentIndex, (rowMcu + 1) * component.VerticalSamplingFactor);
                    }
                }
                else
                {
                    foreach (JpegHuffmanDecodingComponent component in components)
                    {
                        allocator.FlushMcu(component.ComponentIndex, (rowMcu + 1) * component.VerticalSamplingFactor);
                    }
                }
            }

            bitReader.AdvanceAlignByte();
            int bytesConsumed = reader.RemainingByteCount - bitReader.RemainingBits / 8;

            if (bitReader.TryPeekMarker() != 0)
            {
                if (!bitReader.TryPeekMarker().IsRestartMarker())
                {
                    bytesConsumed -= 2;
                }
            }
            reader.TryAdvance(bytesConsumed);
        }
示例#23
0
            /// <summary>
            /// Get next marker in jpeg file (starts with 0xff)
            /// </summary>
            /// <param name="stream"></param>
            /// <param name="last_marker"></param>
            /// <param name="comment_correction"></param>
            /// <param name="ff_read"></param>
            /// <returns></returns>
            private static JpegMarker GetNextMarker(Stream stream, JpegMarker last_marker, int comment_correction, int ff_read)
            {
                int a = 0;
                JpegMarker marker;

                /* get marker byte, swallowing possible padding                               */
                if (last_marker == JpegMarker.M_COM && comment_correction != 0)
                {
                    /* some software does not count the length bytes of COM section           */
                    /* one company doing so is very much envolved in JPEG... so we accept too */
                    /* by the way: some of those companies changed their code now...          */
                    comment_correction = 2;
                }
                else
                {
                    last_marker = 0;
                    comment_correction = 0;
                }

                if (ff_read != 0)
                {
                    a = 1; /* already read 0xff in filetype detection */
                }
                do
                {
                    marker = (JpegMarker)stream.ReadByte();
                    if (marker == JpegMarker.M_EOI)
                    {
                        return JpegMarker.M_EOI;/* we hit EOF */
                    }
                    if (last_marker == JpegMarker.M_COM && comment_correction > 0)
                    {
                        if (marker != (JpegMarker)0xFF)
                        {
                            marker = (JpegMarker)0xFF;
                            comment_correction--;
                        }
                        else
                        {
                            last_marker = JpegMarker.M_PSEUDO; /* stop skipping non 0xff for M_COM */
                        }
                    }
                    a++;
                } while (marker == (JpegMarker)0xff);
                if (a < 2)
                {
                    return JpegMarker.M_EOI; /* at least one 0xff is needed before marker code */
                }
                if (last_marker == JpegMarker.M_COM && comment_correction != 0)
                {
                    return JpegMarker.M_EOI; /* ah illegal: char after COM section not 0xFF */
                }

                return marker;
            }
示例#24
0
        public void StartDecoder(uint offset, uint size)
        {
            if (!input.IsValid(offset, size))
            {
                throw new RawDecoderException("Start offset plus size is longer than file. Truncated file.");
            }
            if ((int)offX >= raw.fullSize.dim.width)
            {
                throw new RawDecoderException("X offset outside of image");
            }
            if ((int)offY >= raw.fullSize.dim.height)
            {
                throw new RawDecoderException("Y offset outside of image");
            }

            // JPEG is big endian
            if (Common.GetHostEndianness() == Endianness.Big)
            {
                input = new ImageBinaryReader(input.BaseStream, offset);
            }
            else
            {
                input = new ImageBinaryReaderBigEndian(input.BaseStream, offset);
            }

            if (GetNextMarker(false) != JpegMarker.SOI)
            {
                throw new RawDecoderException("Image did not start with SOI. Probably not an LJPEG");
            }

            bool moreImage = true;

            while (moreImage)
            {
                JpegMarker m = GetNextMarker(true);
                switch (m)
                {
                case JpegMarker.DQT:
                    throw new RawDecoderException("Not a valid RAW file.");

                case JpegMarker.DHT:
                    //          _RPT0(0,"Found DHT marker\n");
                    ParseDHT();
                    break;

                case JpegMarker.SOS:
                    //          _RPT0(0,"Found SOS marker\n");
                    ParseSOS();
                    break;

                case JpegMarker.Sof3:
                    //          _RPT0(0,"Found SOF 3 marker:\n");
                    ParseSOF(frame);
                    break;

                case JpegMarker.EOI:
                    //          _RPT0(0,"Found EOI marker\n");
                    moreImage = false;
                    break;

                case JpegMarker.DRI:  //          _RPT0(0,"Found DRI marker\n");
                case JpegMarker.App0: //          _RPT0(0,"Found APP0 marker\n");
                default:              // _RPT1(0, "Found marker:0x%x. Skipping\n", m);
                                      // Just let it skip to next marker
                    break;
                }
            }
        }
示例#25
0
 public static bool IsRestartMarker(this JpegMarker marker)
 {
     return(JpegMarker.DefineRestart0 <= marker && marker <= JpegMarker.DefineRestart7);
 }
示例#26
0
		public Marker (JpegMarker type, byte [] data)
		{
			this.Type = type;
			this.Data = data;
		}
示例#27
0
        private void CopyScanBaseline(ref JpegReader reader, ref JpegWriter writer, JpegScanHeader scanHeader)
        {
            JpegFrameHeader frameHeader = _frameHeader.GetValueOrDefault();

            if (scanHeader.Components is null)
            {
                throw new InvalidOperationException();
            }

            // Compute maximum sampling factor
            byte maxHorizontalSampling = 1;
            byte maxVerticalSampling   = 1;

            foreach (JpegFrameComponentSpecificationParameters currentFrameComponent in frameHeader.Components !)
            {
                maxHorizontalSampling = Math.Max(maxHorizontalSampling, currentFrameComponent.HorizontalSamplingFactor);
                maxVerticalSampling   = Math.Max(maxVerticalSampling, currentFrameComponent.VerticalSamplingFactor);
            }

            // Resolve each component
            JpegTranscodeComponent[] components = new JpegTranscodeComponent[scanHeader.NumberOfComponents];

            for (int i = 0; i < scanHeader.NumberOfComponents; i++)
            {
                JpegScanComponentSpecificationParameters scanComponenet = scanHeader.Components[i];
                int componentIndex = 0;
                JpegFrameComponentSpecificationParameters?frameComponent = null;

                for (int j = 0; j < frameHeader.NumberOfComponents; j++)
                {
                    JpegFrameComponentSpecificationParameters currentFrameComponent = frameHeader.Components[j];
                    if (scanComponenet.ScanComponentSelector == currentFrameComponent.Identifier)
                    {
                        componentIndex = j;
                        frameComponent = currentFrameComponent;
                    }
                }
                if (frameComponent is null)
                {
                    throw new InvalidDataException();
                }
                components[i] = new JpegTranscodeComponent
                {
                    ComponentIndex           = componentIndex,
                    HorizontalSamplingFactor = frameComponent.GetValueOrDefault().HorizontalSamplingFactor,
                    VerticalSamplingFactor   = frameComponent.GetValueOrDefault().VerticalSamplingFactor,
                    DcTable         = GetHuffmanTable(true, scanComponenet.DcEntropyCodingTableSelector),
                    AcTable         = GetHuffmanTable(false, scanComponenet.AcEntropyCodingTableSelector),
                    DcEncodingTable = _encodingTables.GetTable(true, scanComponenet.DcEntropyCodingTableSelector),
                    AcEncodingTable = _encodingTables.GetTable(false, scanComponenet.AcEntropyCodingTableSelector)
                };
            }

            // Prepare
            int           mcusPerLine       = (frameHeader.SamplesPerLine + 8 * maxHorizontalSampling - 1) / (8 * maxHorizontalSampling);
            int           mcusPerColumn     = (frameHeader.NumberOfLines + 8 * maxVerticalSampling - 1) / (8 * maxVerticalSampling);
            JpegBitReader bitReader         = new JpegBitReader(reader.RemainingBytes);
            int           mcusBeforeRestart = _restartInterval;

            bool eoiReached = false;

            writer.EnterBitMode();
            for (int rowMcu = 0; rowMcu < mcusPerColumn && !eoiReached; rowMcu++)
            {
                for (int colMcu = 0; colMcu < mcusPerLine && !eoiReached; colMcu++)
                {
                    foreach (JpegTranscodeComponent component in components)
                    {
                        int h = component.HorizontalSamplingFactor;
                        int v = component.VerticalSamplingFactor;

                        for (int y = 0; y < v; y++)
                        {
                            for (int x = 0; x < h; x++)
                            {
                                CopyBlockBaseline(ref bitReader, ref writer, component);
                            }
                        }
                    }

                    if (_restartInterval > 0 && (--mcusBeforeRestart) == 0)
                    {
                        bitReader.AdvanceAlignByte();

                        JpegMarker marker = bitReader.TryReadMarker();
                        if (marker == JpegMarker.EndOfImage)
                        {
                            eoiReached = true;
                            break;
                        }
                        if (!marker.IsRestartMarker())
                        {
                            throw new InvalidOperationException("Expect restart marker.");
                        }

                        mcusBeforeRestart = _restartInterval;

                        writer.ExitBitMode();
                        writer.WriteMarker(marker);
                        writer.EnterBitMode();
                    }
                }
            }

            bitReader.AdvanceAlignByte();
            writer.ExitBitMode();

            int bytesConsumed = reader.RemainingByteCount - bitReader.RemainingBits / 8;

            if (eoiReached)
            {
                bytesConsumed -= 2;
            }
            else if (bitReader.TryPeekMarker() != 0)
            {
                if (!bitReader.TryPeekMarker().IsRestartMarker())
                {
                    bytesConsumed -= 2;
                }
            }
            reader.TryAdvance(bytesConsumed);
        }
示例#28
0
        public override void ProcessScan(ref JpegReader reader, JpegScanHeader scanHeader)
        {
            JpegFrameHeader       frameHeader  = _frameHeader;
            JpegBlockOutputWriter?outputWriter = Decoder.GetOutputWriter();

            if (frameHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (scanHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (outputWriter is null)
            {
                ThrowInvalidDataException();
            }

            // Resolve each component
            Span <JpegArithmeticDecodingComponent> components = _components.AsSpan(0, InitDecodeComponents(frameHeader, scanHeader, _components));

            foreach (JpegArithmeticDecodingComponent component in _components)
            {
                component.DcPredictor = 0;
                component.DcContext   = 0;
                component.DcStatistics?.Reset();
                component.AcStatistics?.Reset();
            }

            Reset();

            // Prepare
            int           maxHorizontalSampling = _maxHorizontalSampling;
            int           maxVerticalSampling   = _maxVerticalSampling;
            int           mcusBeforeRestart     = _restartInterval;
            int           mcusPerLine           = _mcusPerLine;
            int           mcusPerColumn         = _mcusPerColumn;
            int           levelShift            = _levelShift;
            JpegBitReader bitReader             = new JpegBitReader(reader.RemainingBytes);

            // DCT Block
            JpegBlock8x8F blockFBuffer  = default;
            JpegBlock8x8F outputFBuffer = default;
            JpegBlock8x8F tempFBuffer   = default;

            JpegBlock8x8 outputBuffer;

            for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++)
            {
                int offsetY = rowMcu * maxVerticalSampling;
                for (int colMcu = 0; colMcu < mcusPerLine; colMcu++)
                {
                    int offsetX = colMcu * maxHorizontalSampling;

                    // Scan an interleaved mcu... process components in order
                    foreach (JpegArithmeticDecodingComponent component in components)
                    {
                        int index = component.ComponentIndex;
                        int h     = component.HorizontalSamplingFactor;
                        int v     = component.VerticalSamplingFactor;
                        int hs    = component.HorizontalSubsamplingFactor;
                        int vs    = component.VerticalSubsamplingFactor;

                        for (int y = 0; y < v; y++)
                        {
                            int blockOffsetY = (offsetY + y) * 8;
                            for (int x = 0; x < h; x++)
                            {
                                // Read MCU
                                outputBuffer = default;
                                ReadBlock(ref bitReader, component, ref outputBuffer);

                                // Dequantization
                                DequantizeBlockAndUnZigZag(component.QuantizationTable, ref outputBuffer, ref blockFBuffer);

                                // IDCT
                                FastFloatingPointDCT.TransformIDCT(ref blockFBuffer, ref outputFBuffer, ref tempFBuffer);

                                // Level shift
                                ShiftDataLevel(ref outputFBuffer, ref outputBuffer, levelShift);

                                // CopyToOutput
                                WriteBlock(outputWriter, ref Unsafe.As <JpegBlock8x8, short>(ref outputBuffer), index, (offsetX + x) * 8, blockOffsetY, hs, vs);
                            }
                        }
                    }

                    // Handle restart
                    if (_restartInterval > 0 && (--mcusBeforeRestart) == 0)
                    {
                        bitReader.AdvanceAlignByte();

                        JpegMarker marker = bitReader.TryReadMarker();
                        if (marker == JpegMarker.EndOfImage)
                        {
                            int bytesConsumedEoi = reader.RemainingByteCount - bitReader.RemainingBits / 8;
                            reader.TryAdvance(bytesConsumedEoi - 2);
                            return;
                        }
                        if (!marker.IsRestartMarker())
                        {
                            throw new InvalidOperationException("Expect restart marker.");
                        }

                        mcusBeforeRestart = _restartInterval;

                        foreach (JpegArithmeticDecodingComponent component in components)
                        {
                            component.DcPredictor = 0;
                            component.DcContext   = 0;
                            component.DcStatistics?.Reset();
                            component.AcStatistics?.Reset();
                        }

                        Reset();
                    }
                }
            }

            bitReader.AdvanceAlignByte();
            int bytesConsumed = reader.RemainingByteCount - bitReader.RemainingBits / 8;

            if (bitReader.TryPeekMarker() != 0)
            {
                if (!bitReader.TryPeekMarker().IsRestartMarker())
                {
                    bytesConsumed -= 2;
                }
            }
            reader.TryAdvance(bytesConsumed);
        }
示例#29
0
		public Signature (JpegMarker marker, string name)
		{
			Id = marker;
			Name = name;
		}