示例#1
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="applicationExtension">
		/// The application extension to build the Netscape extension from.
		/// </param>
		public NetscapeExtension( ApplicationExtension applicationExtension )
			: base( applicationExtension.IdentificationBlock,
			        applicationExtension.ApplicationData )
		{
			#region guard against application extensions which are not Netscape extensions
			string message;
			if( applicationExtension.ApplicationIdentifier != "NETSCAPE" )
			{
				message = "The application identifier is not 'NETSCAPE' "
						+ "therefore this application extension is not a "
						+ "Netscape extension. Application identifier: "
						+ applicationExtension.ApplicationIdentifier;
				throw new ArgumentException( message, "applicationExtension" );
			}
			
			if( applicationExtension.ApplicationAuthenticationCode != "2.0" )
			{
				message = "The application authentication code is not '2.0' "
						+ "therefore this application extension is not a "
						+ "Netscape extension. Application authentication code: "
						+ applicationExtension.ApplicationAuthenticationCode;
				throw new ArgumentException( message, "applicationExtension" );
			}
			#endregion

			foreach( DataBlock block in ApplicationData )
			{
				if( block.ActualBlockSize == 0 )
				{
					// then we've found the block terminator
					break;
				}
				// The first byte in a Netscape application extension data
				// block should be 1. Ignore if anything else.
				if( block.ActualBlockSize > 2 && block[0] == 1 )
				{
					// The loop count is held in the second and third bytes
					// of the data block, least significant byte first.
					int byte1 = ( (int) block[1] ) & 0xff;
					int byte2 = ( (int) block[2] ) & 0xff;
					
					// String the two bytes together to make an integer,
					// with byte 2 coming first.
					_loopCount = (byte2 << 8) | byte1;
				}
			}
		}
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="applicationExtension">
        /// The application extension to build the Netscape extension from.
        /// </param>
        public NetscapeExtension(ApplicationExtension applicationExtension)
            : base(applicationExtension.IdentificationBlock,
                   applicationExtension.ApplicationData)
        {
            #region guard against application extensions which are not Netscape extensions
            string message;
            if (applicationExtension.ApplicationIdentifier != "NETSCAPE")
            {
                message = "The application identifier is not 'NETSCAPE' "
                          + "therefore this application extension is not a "
                          + "Netscape extension. Application identifier: "
                          + applicationExtension.ApplicationIdentifier;
                throw new ArgumentException(message, "applicationExtension");
            }

            if (applicationExtension.ApplicationAuthenticationCode != "2.0")
            {
                message = "The application authentication code is not '2.0' "
                          + "therefore this application extension is not a "
                          + "Netscape extension. Application authentication code: "
                          + applicationExtension.ApplicationAuthenticationCode;
                throw new ArgumentException(message, "applicationExtension");
            }
            #endregion

            foreach (DataBlock block in ApplicationData)
            {
                if (block.ActualBlockSize == 0)
                {
                    // then we've found the block terminator
                    break;
                }
                // The first byte in a Netscape application extension data
                // block should be 1. Ignore if anything else.
                if (block.ActualBlockSize > 2 && block[0] == 1)
                {
                    // The loop count is held in the second and third bytes
                    // of the data block, least significant byte first.
                    int byte1 = ((int)block[1]) & 0xff;
                    int byte2 = ((int)block[2]) & 0xff;

                    // String the two bytes together to make an integer,
                    // with byte 2 coming first.
                    _loopCount = (byte2 << 8) | byte1;
                }
            }
        }
示例#3
0
        /// <summary>
        /// Main file parser. Reads GIF content blocks.
        /// </summary>
        /// <param name="inputStream">
        /// Input stream from which the GIF data is to be read.
        /// </param>
        private void ReadContents( Stream inputStream )
        {
            // read GIF file content blocks
            bool done = false;
            GraphicControlExtension lastGce = null;
            string message; // for error conditions
            while( !done && ConsolidatedState == ErrorState.Ok )
            {
                int code = Read( inputStream );
                MyProgressCounters[_readStreamCounterText].Value
                    = (int) inputStream.Position;
                WriteCodeToDebugXml( code );

                switch( code )
                {

                    case CodeImageSeparator:
                        WriteDebugXmlComment( "0x2C - image separator" );
                        AddFrame( inputStream, lastGce );
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int) inputStream.Position;
                        break;

                    case CodeExtensionIntroducer:
                        WriteDebugXmlComment( "0x21 - extension introducer" );
                        code = Read( inputStream );
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int) inputStream.Position;
                        WriteCodeToDebugXml( code );
                        switch( code )
                        {
                            case CodePlaintextLabel:
                                // FEATURE: handle plain text extension
                                WriteDebugXmlComment( "0x01 - plain text extension" );
                                SkipBlocks( inputStream );
                                MyProgressCounters[_readStreamCounterText].Value
                                    = (int) inputStream.Position;
                                break;

                            case CodeGraphicControlLabel:
                                WriteDebugXmlComment( "0xF9 - graphic control label" );
                                lastGce = new GraphicControlExtension( inputStream,
                                                                       XmlDebugging );
                                MyProgressCounters[_readStreamCounterText].Value
                                    = (int) inputStream.Position;
                                WriteDebugXmlNode( lastGce.DebugXmlReader );
                                break;

                            case CodeCommentLabel:
                                // FEATURE: handle comment extension
                                WriteDebugXmlComment( "0xFE - comment extension" );
                                SkipBlocks( inputStream );
                                MyProgressCounters[_readStreamCounterText].Value
                                    = (int) inputStream.Position;
                                break;

                            case CodeApplicationExtensionLabel:
                                WriteDebugXmlComment( "0xFF - application extension label" );
                                ApplicationExtension ext
                                    = new ApplicationExtension( inputStream,
                                                                XmlDebugging );
                                MyProgressCounters[_readStreamCounterText].Value
                                    = (int) inputStream.Position;
                                WriteDebugXmlNode( ext.DebugXmlReader );
                                if( ext.ApplicationIdentifier == "NETSCAPE"
                                    && ext.ApplicationAuthenticationCode == "2.0" )
                                {
                                    _netscapeExtension = new NetscapeExtension( ext );
                                }
                                else
                                {
                                    // TESTME: ReadContents - non-Netscape application extension
                                    _applicationExtensions.Add( ext );
                                }
                                break;

                            default : // uninteresting extension
                                // TESTME: ReadContents - uninteresting extension
                                WriteDebugXmlComment( "Ignoring this extension" );
                                SkipBlocks( inputStream );
                                MyProgressCounters[_readStreamCounterText].Value
                                    = (int) inputStream.Position;
                                break;
                        }
                        break;

                    case CodeTrailer:
                        // We've reached an explicit end-of-data marker, so stop
                        // processing the stream.
                        WriteDebugXmlComment( "0x3B - end of data" );
                        done = true;
                        break;

                    case 0x00 : // bad byte, but keep going and see what happens
                        WriteDebugXmlComment( "0x00 - unexpected code" );
                        message
                            = "Unexpected block terminator encountered at "
                            + "position " + inputStream.Position
                            + " after reading " + _frames.Count + " frames.";
                        SetStatus( ErrorState.UnexpectedBlockTerminator,
                                   message );
                        break;

                    case -1: // reached the end of the input stream
                        WriteDebugXmlComment( "-1 - end of input stream" );
                        message
                            = "Reached the end of the input stream without "
                            + "encountering trailer 0x3b";
                        SetStatus( ErrorState.EndOfInputStream, message );
                        break;

                    default :
                        WriteDebugXmlComment( "Not a recognised code" );
                        message
                            = "Bad data block introducer: 0x"
                            + code.ToString( "X", CultureInfo.InvariantCulture ).PadLeft( 2, '0' )
                            + " (" + code + ") at position " + inputStream.Position
                            + " ("
                            + inputStream.Position.ToString( "X",
                                                           CultureInfo.InvariantCulture )
                            + " hex) after reading "
                            + _frames.Count + " frames.";
                        SetStatus( ErrorState.BadDataBlockIntroducer, message );
                        break;
                }
            }
        }
        public void ConstructorTest()
        {
            byte[] idData = new byte[]
            {
                (byte) 'N',
                (byte) 'E',
                (byte) 'T',
                (byte) 'S',
                (byte) 'C',
                (byte) 'A',
                (byte) 'P',
                (byte) 'E',
                (byte) '2',
                (byte) '.',
                (byte) '0',
            };
            DataBlock idBlock = new DataBlock( 11, idData );

            Collection<DataBlock> appData = new Collection<DataBlock>();

            // First byte in the data block is always 1 for a netscape extension
            // Second and third bytes are the loop count, lsb first
            byte[] loopCount = new byte[] { 1, 4, 0 };
            appData.Add( new DataBlock( 3, loopCount ) );

            // Add the block terminator
            appData.Add( new DataBlock( 0, new byte[0] ) );

            ApplicationExtension appExt
                = new ApplicationExtension( idBlock, appData );
            _ne = new NetscapeExtension( appExt );

            Assert.AreEqual( 4, _ne.LoopCount );
            Assert.AreEqual( "NETSCAPE", _ne.ApplicationIdentifier );
            Assert.AreEqual( "2.0", _ne.ApplicationAuthenticationCode );
            Assert.AreEqual( ErrorState.Ok, _ne.ConsolidatedState );
        }
        public void ConstructorTestNotNetscape()
        {
            byte[] idData = new byte[]
            {
                (byte) 'B',
                (byte) 'I',
                (byte) 'G',
                (byte) 'P',
                (byte) 'A',
                (byte) 'N',
                (byte) 'T',
                (byte) 'S',
                (byte) '2',
                (byte) '.',
                (byte) '0',
            };
            DataBlock idBlock = new DataBlock( 11, idData );

            ApplicationExtension appExt
                = new ApplicationExtension( idBlock, new Collection<DataBlock>() );
            try
            {
                _ne = new NetscapeExtension( appExt );
            }
            catch( ArgumentException ex )
            {
                string message
                    = "The application identifier is not 'NETSCAPE' "
                    + "therefore this application extension is not a "
                    + "Netscape extension. Application identifier: BIGPANTS";
                StringAssert.Contains( message, ex.Message );
                Assert.AreEqual( "applicationExtension", ex.ParamName );
                throw;
            }
        }
        public void ConstructorTestNot2Point0()
        {
            byte[] idData = new byte[]
            {
                (byte) 'N',
                (byte) 'E',
                (byte) 'T',
                (byte) 'S',
                (byte) 'C',
                (byte) 'A',
                (byte) 'P',
                (byte) 'E',
                (byte) '3',
                (byte) '.',
                (byte) '0',
            };
            DataBlock idBlock = new DataBlock( 11, idData );

            ApplicationExtension appExt
                = new ApplicationExtension( idBlock, new Collection<DataBlock>() );
            try
            {
                _ne = new NetscapeExtension( appExt );
            }
            catch( ArgumentException ex )
            {
                string message
                    = "The application authentication code is not '2.0' "
                    + "therefore this application extension is not a "
                    + "Netscape extension. Application authentication code: 3.0";
                StringAssert.Contains( message, ex.Message );
                Assert.AreEqual( "applicationExtension", ex.ParamName );
                throw;
            }
        }
 private static void CheckNetscapeExtension( Stream s, int loopCount )
 {
     // check netscape extension
     ApplicationExtension ae = new ApplicationExtension( s );
     Assert.AreEqual( ErrorState.Ok, ae.ConsolidatedState );
     NetscapeExtension ne = new NetscapeExtension( ae );
     Assert.AreEqual( ErrorState.Ok, ne.ConsolidatedState );
     Assert.AreEqual( loopCount, ne.LoopCount );
 }
        public void WikipediaExampleTest()
        {
            ReportStart();
            _e = new AnimatedGifEncoder();
            GifFrame frame = new GifFrame( WikipediaExample.ExpectedBitmap );
            frame.Delay = WikipediaExample.DelayTime;
            _e.AddFrame( frame );

            // TODO: some way of creating/testing a UseLocal version of WikipediaExample
            string fileName = "WikipediaExampleUseGlobal.gif";
            _e.WriteToFile( fileName );
            Stream s = File.OpenRead( fileName );

            int code;

            // check GIF header
            GifHeader gh = new GifHeader( s );
            Assert.AreEqual( ErrorState.Ok, gh.ConsolidatedState );

            // check logical screen descriptor
            LogicalScreenDescriptor lsd = new LogicalScreenDescriptor( s );
            Assert.AreEqual( ErrorState.Ok, lsd.ConsolidatedState );
            WikipediaExample.CheckLogicalScreenDescriptor( lsd );

            // read global colour table
            ColourTable gct
                = new ColourTable( s, WikipediaExample.GlobalColourTableSize );
            Assert.AreEqual( ErrorState.Ok, gct.ConsolidatedState );
            // cannot compare global colour table as different encoders will
            // produce difference colour tables.
            //			WikipediaExample.CheckGlobalColourTable( gct );

            // check for extension introducer
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeExtensionIntroducer, code );

            // check for app extension label
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeApplicationExtensionLabel, code );

            // check netscape extension
            ApplicationExtension ae = new ApplicationExtension( s );
            Assert.AreEqual( ErrorState.Ok, ae.ConsolidatedState );
            NetscapeExtension ne = new NetscapeExtension( ae );
            Assert.AreEqual( ErrorState.Ok, ne.ConsolidatedState );
            Assert.AreEqual( 0, ne.LoopCount );

            // check for extension introducer
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeExtensionIntroducer, code );

            // check for gce label
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeGraphicControlLabel, code );

            // check graphic control extension
            GraphicControlExtension gce = new GraphicControlExtension( s );
            Assert.AreEqual( ErrorState.Ok, gce.ConsolidatedState );
            WikipediaExample.CheckGraphicControlExtension( gce );

            // check for image separator
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeImageSeparator, code );

            // check for image descriptor
            ImageDescriptor id = new ImageDescriptor( s );
            Assert.AreEqual( ErrorState.Ok, id.ConsolidatedState );
            WikipediaExample.CheckImageDescriptor( id );

            // read, decode and check image data
            // Cannot compare encoded LZW data directly as different encoders
            // will create different colour tables, so even if the bitmaps are
            // identical, the colour indices will be different
            int pixelCount = WikipediaExample.FrameSize.Width
                            * WikipediaExample.FrameSize.Height;
            TableBasedImageData tbid = new TableBasedImageData( s, pixelCount );
            for( int y = 0; y < WikipediaExample.LogicalScreenSize.Height; y++ )
            {
                for( int x = 0; x < WikipediaExample.LogicalScreenSize.Width; x++ )
                {
                    int i = (y * WikipediaExample.LogicalScreenSize.Width) + x;
                    Assert.AreEqual( WikipediaExample.ExpectedBitmap.GetPixel( x, y ),
                                     gct[tbid.Pixels[i]],
                                     "X: " + x + ", Y: " + y );
                }
            }

            // Check for block terminator after image data
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( 0x00, code );

            // check for GIF trailer
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( GifComponent.CodeTrailer, code );

            // check we're at the end of the stream
            code = ExampleComponent.CallRead( s );
            Assert.AreEqual( -1, code );
            s.Close();

            _d = new GifDecoder( fileName );
            _d.Decode();
            Assert.AreEqual( ErrorState.Ok, _d.ConsolidatedState );
            BitmapAssert.AreEqual( WikipediaExample.ExpectedBitmap,
                                  (Bitmap) _d.Frames[0].TheImage,
                                   "" );
            ReportEnd();
        }