Esempio n. 1
0
//		/// <summary>
//		/// Tests the encoder with 1,000,000 random pixel values.
//		/// </summary>
//		[Test]
//		public void Test1000000Pixels()
//		{
//			ReportStart();
//			RandomFill( 1000000 );
//			ReportEnd();
//		}
        #endregion

        #region private RandomFill method
        /// <summary>
        /// Fills _ip with random values
        /// </summary>
        /// <param name="count">
        /// Number of values to add
        /// </param>
        private void RandomFill(int count)
        {
            Random r = new Random();

            for (int blockiness = 1; blockiness < 20; blockiness++)
            {
                _ip = new IndexedPixels();
                byte[] bytes = new byte[count];
                r.NextBytes(bytes);
                byte lastByte = 0;
                foreach (byte b in bytes)
                {
                    // Add a new value to the collection only if we throw a 1
                    int diceThrow = r.Next(1, blockiness);
                    if (diceThrow == 1)
                    {
                        _ip.Add(b);
                        lastByte = b;
                    }
                    else
                    {
                        // otherwise add the previous value again
                        // (this more accurately simulates colour distribution in
                        // an actual image)
                        _ip.Add(lastByte);
                    }
                }
                TestIt();
            }
        }
Esempio n. 2
0
        private void AnalyseSingleImage()
        {
            if (_distinctColours.Count > 256)
            {
                switch (_quantizerType)
                {
                case QuantizerType.NeuQuant:
                    AnalyseSingleImageWithNeuQuant();
                    break;

                case QuantizerType.Octree:
                    AnalyseSingleImageWithOctree();
                    break;
                }
            }
            else
            {
                // few enough colours to create a colour table directly without
                // quantization.
                CreateDirectColourTable();
            }

            // Work out the indices in the colour table of each of the pixels
            // in the supplied image.
            _indexedPixels = GetIndexedPixels(_imageColours);
        }
Esempio n. 3
0
        private void AnalyseManyImages()
        {
            // Work out the colour table for the pixels in each of the
            // supplied images
            GetColours(_imagesToStudy);
            if (_distinctColours.Count > 256)
            {
                CreateColourTableUsingNeuQuant(_colourQuality);

                // TODO: work out how to create a global colour table using Octree quantizer
            }
            else
            {
                CreateDirectColourTable();
            }

            string analysingFrameCounterText = "Analysing frame";

            AddCounter(analysingFrameCounterText, _imagesToStudy.Count);

            // Work out the indices in the colour table of each of the pixels
            // in each of the supplied images.
            _indexedPixelsCollection = new Collection <IndexedPixels>();
            for (int i = 0; i < _imagesToStudy.Count; i++)
            {
                MyProgressCounters[analysingFrameCounterText].Value = i + 1;
                IndexedPixels indexedPixels = GetIndexedPixels(_imagesColours[i]);
                _indexedPixelsCollection.Add(indexedPixels);
            }

            RemoveCounter(analysingFrameCounterText);
        }
Esempio n. 4
0
        public void DefaultConstructor()
        {
            ReportStart();
            byte[] bytes = new byte[] { 24, 39, 2 };

            // Test the constructor
            _ip = new IndexedPixels();

            // Test the Add method
            foreach (byte b in bytes)
            {
                _ip.Add(b);
            }

            Assert.AreEqual(bytes.Length, _ip.Count);

            // Test the get accessor of the indexer
            for (int i = 0; i < bytes.Length; i++)
            {
                Assert.AreEqual(bytes[i], _ip[i]);
            }

            // Test the set accessor of the indexer
            _ip[1] = 246;
            Assert.AreEqual(246, _ip[1]);
            ReportEnd();
        }
Esempio n. 5
0
        /// <summary>
        /// Encodes and writes pixel data to the supplied stream
        /// </summary>
        /// <param name="indexedPixels">
        /// Collection of indices of the pixel colours within the active colour
        /// table.
        /// </param>
        /// <param name="outputStream">
        /// The stream to write to.
        /// </param>
        private static void WritePixels(IndexedPixels indexedPixels,
                                        Stream outputStream)
        {
            LzwEncoder encoder = new LzwEncoder(indexedPixels);

            encoder.Encode(outputStream);
        }
Esempio n. 6
0
        public void BlockTerminatorTest()
        {
            ReportStart();
            byte[] bytes = new byte[]
            {
                0x08,                 // LZW minimum code size
                0x05,                 // block size = 5
                // 5 bytes of LZW encoded data follows
                0x00, 0x51, 0xFC, 0x1B, 0x28,
                0x06,                 // block size = 6
                // 6 bytes of LZW encoded data follows
                0x70, 0xA0, 0xC1, 0x83, 0x01, 0x01,
                0x00,                 // block terminator - end of table based image data
            };
            MemoryStream s = new MemoryStream();

            s.Write(bytes, 0, bytes.Length);
            s.Seek(0, SeekOrigin.Begin);

            int pixelCount = WikipediaExample.FrameSize.Width
                             * WikipediaExample.FrameSize.Height;

            _tbid = new TableBasedImageData(s, pixelCount);

            Assert.AreEqual(ErrorState.Ok, _tbid.ConsolidatedState);

            Assert.AreEqual(15, _tbid.Pixels.Count);
            Assert.AreEqual(ErrorState.Ok, _tbid.ConsolidatedState);
            Assert.AreEqual(8, _tbid.LzwMinimumCodeSize);
            Assert.AreEqual(9, _tbid.InitialCodeSize);
            Assert.AreEqual(Math.Pow(2, 8), _tbid.ClearCode);
            Assert.AreEqual(Math.Pow(2, 8) + 1, _tbid.EndOfInformation);

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add(40);               // first pixel is black - index 0 in colour table
            expectedIndices.Add(255);              // 2nd pixel is white - index 255 in colour table
            expectedIndices.Add(255);              // 3rd pixel
            expectedIndices.Add(255);              // 4th pixel
            expectedIndices.Add(40);               // 5th pixel
            expectedIndices.Add(255);              // 6th pixel
            expectedIndices.Add(255);              // 7th pixel
            expectedIndices.Add(255);              // 8th pixel
            expectedIndices.Add(255);              // 9th pixel
            expectedIndices.Add(255);              // 10th pixel
            expectedIndices.Add(255);              // 11th pixel
            expectedIndices.Add(255);              // 12th pixel
            expectedIndices.Add(255);              // 13th pixel
            expectedIndices.Add(255);              // 14th pixel
            expectedIndices.Add(255);              // 15th pixel

            for (int i = 0; i < 15; i++)
            {
                Assert.AreEqual(expectedIndices[i], _tbid.Pixels[i], "pixel " + i);
            }
            ReportEnd();
        }
Esempio n. 7
0
        private void DataBlockTooShort(bool xmlDebugging)
        {
            byte[] bytes = new byte[]
            {
                0x08,                                                       // LZW minimum code size
                0x0b,                                                       // block size = 11
                // 11 bytes of LZW encoded data follows (actually there's only 10 for this test)
                0x00, 0x51, 0xFC, 0x1B, 0x28, 0x70, 0xA0, 0xC1, 0x83, 0x01, //0x01,
//				0x00 // block terminator
            };
            MemoryStream s = new MemoryStream();

            s.Write(bytes, 0, bytes.Length);
            s.Seek(0, SeekOrigin.Begin);

            int pixelCount = WikipediaExample.FrameSize.Width
                             * WikipediaExample.FrameSize.Height;

            _tbid = new TableBasedImageData(s, pixelCount, xmlDebugging);

            Assert.AreEqual(15, _tbid.Pixels.Count);
            Assert.AreEqual(ErrorState.DataBlockTooShort | ErrorState.TooFewPixelsInImageData, _tbid.ConsolidatedState);
            Assert.AreEqual(8, _tbid.LzwMinimumCodeSize);
            Assert.AreEqual(9, _tbid.InitialCodeSize);
            Assert.AreEqual(Math.Pow(2, 8), _tbid.ClearCode);
            Assert.AreEqual(Math.Pow(2, 8) + 1, _tbid.EndOfInformation);

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add(0);               // first pixel
            expectedIndices.Add(0);               // 2nd pixel
            expectedIndices.Add(0);               // 3rd pixel
            expectedIndices.Add(0);               // 4th pixel
            expectedIndices.Add(0);               // 5th pixel
            expectedIndices.Add(0);               // 6th pixel
            expectedIndices.Add(0);               // 7th pixel
            expectedIndices.Add(0);               // 8th pixel
            expectedIndices.Add(0);               // 9th pixel
            expectedIndices.Add(0);               // 10th pixel
            expectedIndices.Add(0);               // 11th pixel
            expectedIndices.Add(0);               // 12th pixel
            expectedIndices.Add(0);               // 13th pixel
            expectedIndices.Add(0);               // 14th pixel
            expectedIndices.Add(0);               // 15th pixel

            for (int i = 0; i < 15; i++)
            {
                Assert.AreEqual(expectedIndices[i], _tbid.Pixels[i], "pixel " + i);
            }

            if (xmlDebugging)
            {
                Assert.AreEqual(ExpectedDebugXml, _tbid.DebugXml);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="pixels">
        /// Indices in the active colour table of the colours of the pixel
        /// making up the image.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The supplied pixel collection is null.
        /// </exception>
        public LzwEncoder(IndexedPixels pixels)
        {
            if (pixels == null)
            {
                throw new ArgumentNullException("pixels");
            }

            _pixels = pixels;
            //			_initCodeSize = Math.Max(2, colourDepth);
            _initCodeSize = 8; // only seems to work reliably when 8, even if this is sometimes larger than needed
        }
Esempio n. 9
0
        private void CodeNotInDictionary(bool xmlDebugging)
        {
            byte[] bytes = WikipediaExample.ImageDataBytes;
            bytes[4] = 0xFF;             // put an unexpected code into the stream
            MemoryStream s = new MemoryStream();

            s.Write(bytes, 0, bytes.Length);
            s.Seek(0, SeekOrigin.Begin);

            int pixelCount = WikipediaExample.FrameSize.Width
                             * WikipediaExample.FrameSize.Height;

            _tbid = new TableBasedImageData(s, pixelCount, xmlDebugging);

            Assert.IsTrue(_tbid.TestState(ErrorState.CodeNotInDictionary));
            Assert.AreEqual(15, _tbid.Pixels.Count);
            Assert.AreEqual(8, _tbid.LzwMinimumCodeSize);
            Assert.AreEqual(9, _tbid.InitialCodeSize);
            Assert.AreEqual(Math.Pow(2, 8), _tbid.ClearCode);
            Assert.AreEqual(Math.Pow(2, 8) + 1, _tbid.EndOfInformation);

            IndexedPixels expectedIndices = new IndexedPixels();

            // Check all the pixels have been zero-filled
            expectedIndices.Add(0);               // first pixel
            expectedIndices.Add(0);               // 2nd pixel
            expectedIndices.Add(0);               // 3rd pixel
            expectedIndices.Add(0);               // 4th pixel
            expectedIndices.Add(0);               // 5th pixel
            expectedIndices.Add(0);               // 6th pixel
            expectedIndices.Add(0);               // 7th pixel
            expectedIndices.Add(0);               // 8th pixel
            expectedIndices.Add(0);               // 9th pixel
            expectedIndices.Add(0);               // 10th pixel
            expectedIndices.Add(0);               // 11th pixel
            expectedIndices.Add(0);               // 12th pixel
            expectedIndices.Add(0);               // 13th pixel
            expectedIndices.Add(0);               // 14th pixel
            expectedIndices.Add(0);               // 15th pixel

            for (int i = 0; i < 15; i++)
            {
                Assert.AreEqual(expectedIndices[i], _tbid.Pixels[i], "pixel " + i);
            }

            if (xmlDebugging)
            {
                Assert.AreEqual(ExpectedDebugXml, _tbid.DebugXml);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Gets the indices of the colours of each of the supplied pixels
        /// within the colour table.
        /// </summary>
        /// <param name="pixelColours">
        /// A collection of the colours for which to get the indices in the
        /// colour table.
        /// </param>
        /// <returns>
        /// A collection of the indices of the colours of each of the supplied
        /// pixels within the colour table.
        /// </returns>
        private IndexedPixels GetIndexedPixels(Color[] pixelColours)
        {
            IndexedPixels indexedPixels = new IndexedPixels();
            // Take a copy of the distinct colours to make the IndexOf method
            // available
            string copyDistinctColoursCounterText = "Copying distinct colours";

            AddCounter(copyDistinctColoursCounterText, _distinctColours.Count);
            Collection <Color> distinctColours = new Collection <Color>();

            foreach (Color c in _distinctColours.Keys)
            {
                MyProgressCounters[copyDistinctColoursCounterText].Value++;
                distinctColours.Add(c);
            }
            RemoveCounter(copyDistinctColoursCounterText);

            int    indexInColourTable;
            int    red;
            int    green;
            int    blue;
            int    numberOfPixels = pixelColours.Length;
            string indexingPixelsCounterText
                = "Mapping colours to indices in colour table";

            AddCounter(indexingPixelsCounterText, numberOfPixels);

            for (int i = 0; i < numberOfPixels; i++)
            {
                MyProgressCounters[indexingPixelsCounterText].Value = i;
                red   = pixelColours[i].R;
                green = pixelColours[i].G;
                blue  = pixelColours[i].B;

                // Get the index in the colour table of the colour of this pixel
                if (_distinctColours.Count > 256)
                {
                    indexInColourTable = _nq.Map(red, green, blue);
                }
                else
                {
                    indexInColourTable = distinctColours.IndexOf(pixelColours[i]);
                }
                indexedPixels.Add((byte)indexInColourTable);
            }
            RemoveCounter(indexingPixelsCounterText);
            return(indexedPixels);
        }
Esempio n. 11
0
 public void IndexOutOfRangeSet()
 {
     ReportStart();
     _ip = new IndexedPixels();
     try
     {
         _ip[0] = 6;
     }
     catch (ArgumentOutOfRangeException ex)
     {
         string message = "Collection size: 0. Supplied index: 0.";
         StringAssert.Contains(message, ex.Message);
         ReportEnd();
         throw;
     }
 }
Esempio n. 12
0
 public void CapacityConstructorAdd()
 {
     ReportStart();
     _ip = new IndexedPixels(3);
     try
     {
         _ip.Add(1);
     }
     catch (NotSupportedException ex)
     {
         string message
             = "You cannot add pixels to this instance because it was "
               + "instantiated with a fixed size.";
         StringAssert.Contains(message, ex.Message);
         ReportEnd();
         throw;
     }
 }
Esempio n. 13
0
        private void MissingPixels(bool xmlDebugging)
        {
            byte[]       bytes = WikipediaExample.ImageDataBytes;
            MemoryStream s     = new MemoryStream();

            s.Write(bytes, 0, bytes.Length);
            s.Seek(0, SeekOrigin.Begin);

            // The stream contains 15 pixels, this image size implies 18 pixels
            _tbid = new TableBasedImageData(s, 18, xmlDebugging);

            Assert.AreEqual(18, _tbid.Pixels.Count);
            Assert.AreEqual(ErrorState.TooFewPixelsInImageData, _tbid.ConsolidatedState);
            Assert.AreEqual(8, _tbid.LzwMinimumCodeSize);
            Assert.AreEqual(9, _tbid.InitialCodeSize);
            Assert.AreEqual(Math.Pow(2, 8), _tbid.ClearCode);
            Assert.AreEqual(Math.Pow(2, 8) + 1, _tbid.EndOfInformation);

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add(0);               // first pixel is black - index 0 in colour table
            expectedIndices.Add(1);               // 2nd pixel is white - index 1 in colour table
            expectedIndices.Add(1);               // 3rd pixel
            expectedIndices.Add(1);               // 4th pixel
            expectedIndices.Add(0);               // 5th pixel
            expectedIndices.Add(1);               // 6th pixel
            expectedIndices.Add(1);               // 7th pixel
            expectedIndices.Add(1);               // 8th pixel
            expectedIndices.Add(1);               // 9th pixel
            expectedIndices.Add(1);               // 10th pixel
            expectedIndices.Add(1);               // 11th pixel
            expectedIndices.Add(1);               // 12th pixel
            expectedIndices.Add(1);               // 13th pixel
            expectedIndices.Add(1);               // 14th pixel
            expectedIndices.Add(1);               // 15th pixel
            expectedIndices.Add(0);               // 16th pixel
            expectedIndices.Add(0);               // 17th pixel
            expectedIndices.Add(0);               // 18th pixel

            for (int i = 0; i < 18; i++)
            {
                Assert.AreEqual(expectedIndices[i], _tbid.Pixels[i], "pixel " + i);
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Converts the supplied image to a collection of pixel indices using
        /// the supplied colour table.
        /// Only used when the QuantizerType is set to UseSuppliedPalette
        /// </summary>
        /// <param name="act">The active colour table</param>
        /// <param name="image">The image</param>
        /// <returns></returns>
        private IndexedPixels MakeIndexedPixels(ColourTable act, Image image)
        {
            //AddCounter( counterText, pixelCount );
            Bitmap        bitmap = (Bitmap)image;
            IndexedPixels ip     = new IndexedPixels();

            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    Color c     = bitmap.GetPixel(x, y);
                    int   index = FindClosest(c, act);
                    ip.Add((byte)index);
                    //MyProgressCounters[counterText].Value = ip.Count;
                }
            }
            //RemoveCounter( counterText );
            return(ip);
        }
Esempio n. 15
0
        public void CapacityConstructor()
        {
            ReportStart();
            byte[] bytes = new byte[] { 24, 39, 2 };

            // Test the constructor
            _ip = new IndexedPixels(bytes.Length);

            // Test the set accessor of the indexer
            for (int i = 0; i < bytes.Length; i++)
            {
                _ip[i] = bytes[i];
            }

            Assert.AreEqual(bytes.Length, _ip.Count);

            // Test the get accessor of the indexer
            for (int i = 0; i < bytes.Length; i++)
            {
                Assert.AreEqual(bytes[i], _ip[i]);
            }
            ReportEnd();
        }
        private void DataBlockTooShort( bool xmlDebugging )
        {
            byte[] bytes = new byte[]
            {
                0x08, // LZW minimum code size
                0x0b, // block size = 11
                // 11 bytes of LZW encoded data follows (actually there's only 10 for this test)
                0x00, 0x51, 0xFC, 0x1B, 0x28, 0x70, 0xA0, 0xC1, 0x83, 0x01, //0x01,
            //				0x00 // block terminator
            };
            MemoryStream s = new MemoryStream();
            s.Write( bytes, 0, bytes.Length );
            s.Seek( 0, SeekOrigin.Begin );

            int pixelCount = WikipediaExample.FrameSize.Width
                            * WikipediaExample.FrameSize.Height;
            _tbid = new TableBasedImageData( s, pixelCount, xmlDebugging );

            Assert.AreEqual( 15, _tbid.Pixels.Count );
            Assert.AreEqual( ErrorState.DataBlockTooShort | ErrorState.TooFewPixelsInImageData, _tbid.ConsolidatedState );
            Assert.AreEqual( 8, _tbid.LzwMinimumCodeSize );
            Assert.AreEqual( 9, _tbid.InitialCodeSize );
            Assert.AreEqual( Math.Pow( 2, 8 ), _tbid.ClearCode );
            Assert.AreEqual( Math.Pow( 2, 8 ) + 1, _tbid.EndOfInformation );

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add( 0 ); // first pixel
            expectedIndices.Add( 0 ); // 2nd pixel
            expectedIndices.Add( 0 ); // 3rd pixel
            expectedIndices.Add( 0 ); // 4th pixel
            expectedIndices.Add( 0 ); // 5th pixel
            expectedIndices.Add( 0 ); // 6th pixel
            expectedIndices.Add( 0 ); // 7th pixel
            expectedIndices.Add( 0 ); // 8th pixel
            expectedIndices.Add( 0 ); // 9th pixel
            expectedIndices.Add( 0 ); // 10th pixel
            expectedIndices.Add( 0 ); // 11th pixel
            expectedIndices.Add( 0 ); // 12th pixel
            expectedIndices.Add( 0 ); // 13th pixel
            expectedIndices.Add( 0 ); // 14th pixel
            expectedIndices.Add( 0 ); // 15th pixel

            for( int i = 0; i < 15; i++ )
            {
                Assert.AreEqual( expectedIndices[i], _tbid.Pixels[i], "pixel " + i );
            }

            if( xmlDebugging )
            {
                Assert.AreEqual( ExpectedDebugXml, _tbid.DebugXml );
            }
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="inputStream">
        /// The stream from which the image data is to be read, starting with
        /// the LZW minimum code size, and ending with a block terminator.
        /// </param>
        /// <param name="pixelCount">
        /// Number of pixels in the image.
        /// </param>
        /// <param name="xmlDebugging">Whether or not to create debug XML</param>
        /// <remarks>
        /// The input stream is read, first into the LZW minimum code size, then
        /// into data blocks. Bytes are extracted from the data blocks into a
        /// datum until the datum contains enough bits to form a code; this code
        /// is then extracted from the datum and decoded into a pixel index.
        /// Once all data has been read, or a block terminator,
        /// end-of-information code or error condition is encountered, any
        /// remaining pixel indices not already populated default to zero.
        /// </remarks>
        public TableBasedImageData(Stream inputStream,
                                   int pixelCount,
                                   bool xmlDebugging)
            : base(xmlDebugging)
        {
            #region guard against silly image sizes
            if (pixelCount < 1)
            {
                string message
                    = "The pixel count must be greater than zero. "
                      + "Supplied value was " + pixelCount;
                throw new ArgumentOutOfRangeException("pixelCount", message);
            }
            #endregion

            #region declare / initialise local variables
            _pixels     = new IndexedPixels(pixelCount);
            _dataBlocks = new Collection <DataBlock>();
            int nextAvailableCode;             // the next code to be added to the dictionary
            int currentCodeSize;
            int in_code;
            int previousCode;
            int code;
            int datum = 0;                 // temporary storage for codes read from the input stream
            int meaningfulBitsInDatum = 0; // number of bits of useful information held in the datum variable
            int firstCode             = 0; // first code read from the stream since last clear code
            int indexInDataBlock      = 0;
            int pixelIndex            = 0;

            // number of bytes still to be extracted from the current data block
            int bytesToExtract = 0;

            short[]      prefix     = new short[_maxStackSize];
            byte[]       suffix     = new byte[_maxStackSize];
            Stack <byte> pixelStack = new Stack <byte>();
            #endregion

            //  Initialize GIF data stream decoder.
            _lzwMinimumCodeSize = Read(inputStream);               // number of bits initially used for LZW codes in image data
            WriteDebugXmlElement("LzwMinimumCodeSize", _lzwMinimumCodeSize);
            nextAvailableCode = ClearCode + 2;
            previousCode      = _nullCode;
            currentCodeSize   = InitialCodeSize;

            #region guard against LZW code size being too large
            if (ClearCode >= _maxStackSize)
            {
                string message
                    = "LZW minimum code size: " + _lzwMinimumCodeSize
                      + ". Clear code: " + ClearCode
                      + ". Max stack size: " + _maxStackSize;
                SetStatus(ErrorState.LzwMinimumCodeSizeTooLarge, message);
                WriteDebugXmlFinish();
                return;
            }
            #endregion

            // TODO: what are prefix and suffix and why are we initialising them like this?
            for (code = 0; code < ClearCode; code++)
            {
                prefix[code] = 0;
                suffix[code] = (byte)code;
            }

            WriteDebugXmlStartElement("DataBlocks");

            #region decode LZW image data

            // Initialise block to an empty data block. This will be overwritten
            // first time through the loop with a data block read from the input
            // stream.
            DataBlock block = new DataBlock(0, new byte[0]);

            for (pixelIndex = 0; pixelIndex < pixelCount;)
            {
                if (pixelStack.Count == 0)
                {
                    // There are no pixels in the stack at the moment, so...
                    #region get some pixels and put them on the stack
                    if (meaningfulBitsInDatum < currentCodeSize)
                    {
                        // Then we don't have enough bits in the datum to make
                        // a code; we need to get some more from the current
                        // data block, or we may need to read another data
                        // block from the input stream
                        #region get another byte from the current data block
                        if (bytesToExtract == 0)
                        {
                            // Then we've extracted all the bytes from the
                            // current data block, so...

                            #region read the next data block from the stream
                            block          = ReadDataBlock(inputStream);
                            bytesToExtract = block.ActualBlockSize;

                            // Point to the first byte in the new data block
                            indexInDataBlock = 0;

                            if (block.TestState(ErrorState.DataBlockTooShort))
                            {
                                // then we've reached the end of the stream
                                // prematurely
                                break;
                            }

                            if (bytesToExtract == 0)
                            {
                                // then it's a block terminator, end of the
                                // image data (this is a data block other than
                                // the first one)
                                break;
                            }
                            #endregion
                        }
                        // Append the contents of the current byte in the data
                        // block to the beginning of the datum
                        int newDatum = block[indexInDataBlock] << meaningfulBitsInDatum;
                        datum += newDatum;

                        // so we've now got 8 more bits of information in the
                        // datum.
                        meaningfulBitsInDatum += 8;

                        // Point to the next byte in the data block
                        indexInDataBlock++;

                        // We've one less byte still to read from the data block
                        // now.
                        bytesToExtract--;

                        // and carry on reading through the data block
                        continue;
                        #endregion
                    }

                    #region get the next code from the datum
                    // Get the least significant bits from the read datum, up
                    // to the maximum allowed by the current code size.
                    code = datum & GetMaximumPossibleCode(currentCodeSize);

                    // Drop the bits we've just extracted from the datum.
                    datum >>= currentCodeSize;

                    // Reduce the count of meaningful bits held in the datum
                    meaningfulBitsInDatum -= currentCodeSize;
                    #endregion

                    #region interpret the code

                    #region end of information?
                    if (code == EndOfInformation)
                    {
                        // We've reached an explicit marker for the end of the
                        // image data.
                        break;
                    }
                    #endregion

                    #region code not in dictionary?
                    if (code > nextAvailableCode)
                    {
                        // We expect the code to be either one which is already
                        // in the dictionary, or the next available one to be
                        // added. If it's neither of these then abandon
                        // processing of the image data.
                        string message
                            = "Next available code: " + nextAvailableCode
                              + ". Last code read from input stream: " + code;
                        SetStatus(ErrorState.CodeNotInDictionary, message);
                        break;
                    }
                    #endregion

                    #region clear code?
                    if (code == ClearCode)
                    {
                        // We can get a clear code at any point in the image
                        // data, this is an instruction to reset the decoder
                        // and empty the dictionary of codes.
                        currentCodeSize   = InitialCodeSize;
                        nextAvailableCode = ClearCode + 2;
                        previousCode      = _nullCode;

                        // Carry on reading from the input stream.
                        continue;
                    }
                    #endregion

                    #region first code since last clear code?
                    if (previousCode == _nullCode)
                    {
                        // This is the first code read since the start of the
                        // image data or the most recent clear code.
                        // There's no previously read code in memory yet, so
                        // get the pixel index for the current code and add it
                        // to the stack.
                        pixelStack.Push(suffix[code]);
                        previousCode = code;
                        firstCode    = code;

                        // and carry on to the next pixel
                        continue;
                    }
                    #endregion

                    in_code = code;
                    if (code == nextAvailableCode)
                    {
                        pixelStack.Push((byte)firstCode);
                        code = previousCode;
                    }

                    while (code > ClearCode)
                    {
                        pixelStack.Push(suffix[code]);
                        code = prefix[code];
                    }

                    #endregion

                    firstCode = ((int)suffix[code]) & 0xff;

                    #region add a new string to the string table
                    if (nextAvailableCode >= _maxStackSize)
                    {
                        // TESTME: constructor - next available code >- _maxStackSize
                        break;
                    }
                    pixelStack.Push((byte)firstCode);
                    prefix[nextAvailableCode] = (short)previousCode;
                    suffix[nextAvailableCode] = (byte)firstCode;
                    nextAvailableCode++;
                    #endregion

                    #region do we need to increase the code size?
                    if ((nextAvailableCode & GetMaximumPossibleCode(currentCodeSize)) == 0)
                    {
                        // We've reached the largest code possible for this size
                        if (nextAvailableCode < _maxStackSize)
                        {
                            // so increase the code size by 1
                            currentCodeSize++;
                        }
                    }
                    #endregion

                    previousCode = in_code;
                    #endregion
                }

                // Pop all the pixels currently on the stack off, and add them
                // to the return value.
                _pixels[pixelIndex] = pixelStack.Pop();
                pixelIndex++;
            }

            #endregion

            #region check input stream contains enough data to fill the image
            if (pixelIndex < pixelCount)
            {
                string message
                    = "Expected pixel count: " + pixelCount
                      + ". Actual pixel count: " + pixelIndex;
                SetStatus(ErrorState.TooFewPixelsInImageData, message);
            }
            #endregion

            if (XmlDebugging)
            {
                WriteDebugXmlEndElement();
                byte[] bytes = new byte[_pixels.Count];
                _pixels.CopyTo(bytes, 0);
                WriteDebugXmlByteValues("IndexedPixels", bytes);
                WriteDebugXmlFinish();
            }
        }
Esempio n. 18
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="inputStream">
		/// The stream from which the image data is to be read, starting with
		/// the LZW minimum code size, and ending with a block terminator.
		/// </param>
		/// <param name="pixelCount">
		/// Number of pixels in the image.
		/// </param>
		/// <param name="xmlDebugging">Whether or not to create debug XML</param>
		/// <remarks>
		/// The input stream is read, first into the LZW minimum code size, then
		/// into data blocks. Bytes are extracted from the data blocks into a
		/// datum until the datum contains enough bits to form a code; this code
		/// is then extracted from the datum and decoded into a pixel index.
		/// Once all data has been read, or a block terminator, 
		/// end-of-information code or error condition is encountered, any
		/// remaining pixel indices not already populated default to zero.
		/// </remarks>
		public TableBasedImageData( Stream inputStream, 
		                            int pixelCount, 
		                            bool xmlDebugging )
			: base( xmlDebugging )
		{
			#region guard against silly image sizes
			if( pixelCount < 1 )
			{
				string message
					= "The pixel count must be greater than zero. "
					+ "Supplied value was " + pixelCount;
				throw new ArgumentOutOfRangeException( "pixelCount", message );
			}
			#endregion
			
			#region declare / initialise local variables
			_pixels = new IndexedPixels( pixelCount );
			_dataBlocks = new Collection<DataBlock>();
			int nextAvailableCode; // the next code to be added to the dictionary
			int	currentCodeSize;
			int	in_code;
			int	previousCode;
			int	code;
			int	datum = 0; // temporary storage for codes read from the input stream
			int	meaningfulBitsInDatum = 0; // number of bits of useful information held in the datum variable
			int	firstCode = 0; // first code read from the stream since last clear code
			int	indexInDataBlock = 0;
			int	pixelIndex = 0;
			
			// number of bytes still to be extracted from the current data block
			int bytesToExtract = 0; 

			short[] prefix = new short[_maxStackSize];
			byte[] suffix = new byte[_maxStackSize];
			Stack<byte> pixelStack = new Stack<byte>();
			#endregion

			//  Initialize GIF data stream decoder.
			_lzwMinimumCodeSize = Read( inputStream ); // number of bits initially used for LZW codes in image data
			WriteDebugXmlElement( "LzwMinimumCodeSize", _lzwMinimumCodeSize );
			nextAvailableCode = ClearCode + 2;
			previousCode = _nullCode;
			currentCodeSize = InitialCodeSize;
			
			#region guard against LZW code size being too large
			if( ClearCode >= _maxStackSize )
			{
				string message
					= "LZW minimum code size: " + _lzwMinimumCodeSize
					+ ". Clear code: " + ClearCode
					+ ". Max stack size: " + _maxStackSize;
				SetStatus( ErrorState.LzwMinimumCodeSizeTooLarge, message );
				WriteDebugXmlFinish();
				return;
			}
			#endregion
			
			// TODO: what are prefix and suffix and why are we initialising them like this?
			for( code = 0; code < ClearCode; code++ )
			{
				prefix[code] = 0;
				suffix[code] = (byte) code;
			}
			
			WriteDebugXmlStartElement( "DataBlocks" );

			#region decode LZW image data

			// Initialise block to an empty data block. This will be overwritten
			// first time through the loop with a data block read from the input
			// stream.
			DataBlock block = new DataBlock( 0, new byte[0] );
			
			for( pixelIndex = 0; pixelIndex < pixelCount; ) 
			{
				if( pixelStack.Count == 0 )
				{
					// There are no pixels in the stack at the moment, so...
					#region get some pixels and put them on the stack
					if( meaningfulBitsInDatum < currentCodeSize )
					{
						// Then we don't have enough bits in the datum to make
						// a code; we need to get some more from the current
						// data block, or we may need to read another data
						// block from the input stream
						#region get another byte from the current data block
						if( bytesToExtract == 0 )
						{
							// Then we've extracted all the bytes from the 
							// current data block, so...
							
							#region	read the next data block from the stream
							block = ReadDataBlock( inputStream );
							bytesToExtract = block.ActualBlockSize;
							
							// Point to the first byte in the new data block
							indexInDataBlock = 0;

							if( block.TestState( ErrorState.DataBlockTooShort ) )
							{
								// then we've reached the end of the stream
								// prematurely
								break;
							}
							
							if( bytesToExtract == 0 )
							{
								// then it's a block terminator, end of the
								// image data (this is a data block other than
								// the first one)
								break;
							}
							#endregion
						}
						// Append the contents of the current byte in the data 
						// block to the beginning of the datum
						int newDatum = block[indexInDataBlock] << meaningfulBitsInDatum;
						datum += newDatum;

						// so we've now got 8 more bits of information in the
						// datum.
						meaningfulBitsInDatum += 8;
						
						// Point to the next byte in the data block
						indexInDataBlock++;
						
						// We've one less byte still to read from the data block
						// now.
						bytesToExtract--;
						
						// and carry on reading through the data block
						continue;
						#endregion
					}

					#region get the next code from the datum
					// Get the least significant bits from the read datum, up
					// to the maximum allowed by the current code size.
					code = datum & GetMaximumPossibleCode( currentCodeSize );
					
					// Drop the bits we've just extracted from the datum.
					datum >>= currentCodeSize;
					
					// Reduce the count of meaningful bits held in the datum
					meaningfulBitsInDatum -= currentCodeSize;
					#endregion

					#region interpret the code

					#region end of information?
					if( code == EndOfInformation )
					{
						// We've reached an explicit marker for the end of the
						// image data.
						break;
					}
					#endregion

					#region code not in dictionary?
					if( code > nextAvailableCode )
					{
						// We expect the code to be either one which is already
						// in the dictionary, or the next available one to be
						// added. If it's neither of these then abandon 
						// processing of the image data.
						string message
							= "Next available code: " + nextAvailableCode
							+ ". Last code read from input stream: " + code;
						SetStatus( ErrorState.CodeNotInDictionary, message );
						break;
					}
					#endregion

					#region clear code?
					if( code == ClearCode )
					{
						// We can get a clear code at any point in the image
						// data, this is an instruction to reset the decoder
						// and empty the dictionary of codes.
						currentCodeSize = InitialCodeSize;
						nextAvailableCode = ClearCode + 2;
						previousCode = _nullCode;

						// Carry on reading from the input stream.
						continue;
					}
					#endregion
					
					#region first code since last clear code?
					if( previousCode == _nullCode )
					{
						// This is the first code read since the start of the
						// image data or the most recent clear code.
						// There's no previously read code in memory yet, so
						// get the pixel index for the current code and add it
						// to the stack.
						pixelStack.Push( suffix[code] );
						previousCode = code;
						firstCode = code;
						
						// and carry on to the next pixel
						continue;
					}
					#endregion

					in_code = code;
					if( code == nextAvailableCode )
					{
						pixelStack.Push( (byte) firstCode );
						code = previousCode;
					}
					
					while( code > ClearCode )
					{
						pixelStack.Push( suffix[code] );
						code = prefix[code];
					}

					#endregion

					firstCode = ((int) suffix[code]) & 0xff;

					#region add a new string to the string table
					if( nextAvailableCode >= _maxStackSize )
					{
						// TESTME: constructor - next available code >- _maxStackSize
						break;
					}
					pixelStack.Push( (byte) firstCode );
					prefix[nextAvailableCode] = (short) previousCode;
					suffix[nextAvailableCode] = (byte) firstCode;
					nextAvailableCode++;
					#endregion
					
					#region do we need to increase the code size?
					if( ( nextAvailableCode & GetMaximumPossibleCode( currentCodeSize ) ) == 0 )
					{
						// We've reached the largest code possible for this size
						if( nextAvailableCode < _maxStackSize )
						{
							// so increase the code size by 1
							currentCodeSize++;
						}
					}
					#endregion

					previousCode = in_code;
					#endregion
				}

				// Pop all the pixels currently on the stack off, and add them
				// to the return value.
				_pixels[pixelIndex] = pixelStack.Pop();
				pixelIndex++;
			}

			#endregion

			#region check input stream contains enough data to fill the image
			if( pixelIndex < pixelCount )
			{
				string message
					= "Expected pixel count: " + pixelCount
					+ ". Actual pixel count: " + pixelIndex;
				SetStatus( ErrorState.TooFewPixelsInImageData, message );
			}
			#endregion
			
			if( XmlDebugging )
			{
				WriteDebugXmlEndElement();
				byte[] bytes = new byte[_pixels.Count];
				_pixels.CopyTo( bytes, 0 );
				WriteDebugXmlByteValues( "IndexedPixels", bytes );
				WriteDebugXmlFinish();
			}
		}
 public void Setup()
 {
     _ip = new IndexedPixels();
 }
Esempio n. 20
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="pixels">
		/// Indices in the active colour table of the colours of the pixel 
		/// making up the image.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// The supplied pixel collection is null.
		/// </exception>
		public LzwEncoder( IndexedPixels pixels )
		{
			if( pixels == null )
			{
				throw new ArgumentNullException( "pixels" );
			}
			
			_pixels = pixels;
//			_initCodeSize = Math.Max(2, colourDepth);
			_initCodeSize = 8; // only seems to work reliably when 8, even if this is sometimes larger than needed
		}
        public void BlockTerminatorTest()
        {
            ReportStart();
            byte[] bytes = new byte[]
            {
                0x08, // LZW minimum code size
                0x05, // block size = 5
                // 5 bytes of LZW encoded data follows
                0x00, 0x51, 0xFC, 0x1B, 0x28,
                0x06, // block size = 6
                // 6 bytes of LZW encoded data follows
                0x70, 0xA0, 0xC1, 0x83, 0x01, 0x01,
                0x00, // block terminator - end of table based image data
            };
            MemoryStream s = new MemoryStream();
            s.Write( bytes, 0, bytes.Length );
            s.Seek( 0, SeekOrigin.Begin );

            int pixelCount = WikipediaExample.FrameSize.Width
                            * WikipediaExample.FrameSize.Height;
            _tbid = new TableBasedImageData( s, pixelCount );

            Assert.AreEqual( ErrorState.Ok, _tbid.ConsolidatedState );

            Assert.AreEqual( 15, _tbid.Pixels.Count );
            Assert.AreEqual( ErrorState.Ok, _tbid.ConsolidatedState );
            Assert.AreEqual( 8, _tbid.LzwMinimumCodeSize );
            Assert.AreEqual( 9, _tbid.InitialCodeSize );
            Assert.AreEqual( Math.Pow( 2, 8 ), _tbid.ClearCode );
            Assert.AreEqual( Math.Pow( 2, 8 ) + 1, _tbid.EndOfInformation );

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add( 40 ); // first pixel is black - index 0 in colour table
            expectedIndices.Add( 255 ); // 2nd pixel is white - index 255 in colour table
            expectedIndices.Add( 255 ); // 3rd pixel
            expectedIndices.Add( 255 ); // 4th pixel
            expectedIndices.Add( 40 ); // 5th pixel
            expectedIndices.Add( 255 ); // 6th pixel
            expectedIndices.Add( 255 ); // 7th pixel
            expectedIndices.Add( 255 ); // 8th pixel
            expectedIndices.Add( 255 ); // 9th pixel
            expectedIndices.Add( 255 ); // 10th pixel
            expectedIndices.Add( 255 ); // 11th pixel
            expectedIndices.Add( 255 ); // 12th pixel
            expectedIndices.Add( 255 ); // 13th pixel
            expectedIndices.Add( 255 ); // 14th pixel
            expectedIndices.Add( 255 ); // 15th pixel

            for( int i = 0; i < 15; i++ )
            {
                Assert.AreEqual( expectedIndices[i], _tbid.Pixels[i], "pixel " + i );
            }
            ReportEnd();
        }
        private void MissingPixels( bool xmlDebugging )
        {
            byte[] bytes = WikipediaExample.ImageDataBytes;
            MemoryStream s = new MemoryStream();
            s.Write( bytes, 0, bytes.Length );
            s.Seek( 0, SeekOrigin.Begin );

            // The stream contains 15 pixels, this image size implies 18 pixels
            _tbid = new TableBasedImageData( s, 18, xmlDebugging );

            Assert.AreEqual( 18, _tbid.Pixels.Count );
            Assert.AreEqual( ErrorState.TooFewPixelsInImageData, _tbid.ConsolidatedState );
            Assert.AreEqual( 8, _tbid.LzwMinimumCodeSize );
            Assert.AreEqual( 9, _tbid.InitialCodeSize );
            Assert.AreEqual( Math.Pow( 2, 8 ), _tbid.ClearCode );
            Assert.AreEqual( Math.Pow( 2, 8 ) + 1, _tbid.EndOfInformation );

            IndexedPixels expectedIndices = new IndexedPixels();

            expectedIndices.Add( 0 ); // first pixel is black - index 0 in colour table
            expectedIndices.Add( 1 ); // 2nd pixel is white - index 1 in colour table
            expectedIndices.Add( 1 ); // 3rd pixel
            expectedIndices.Add( 1 ); // 4th pixel
            expectedIndices.Add( 0 ); // 5th pixel
            expectedIndices.Add( 1 ); // 6th pixel
            expectedIndices.Add( 1 ); // 7th pixel
            expectedIndices.Add( 1 ); // 8th pixel
            expectedIndices.Add( 1 ); // 9th pixel
            expectedIndices.Add( 1 ); // 10th pixel
            expectedIndices.Add( 1 ); // 11th pixel
            expectedIndices.Add( 1 ); // 12th pixel
            expectedIndices.Add( 1 ); // 13th pixel
            expectedIndices.Add( 1 ); // 14th pixel
            expectedIndices.Add( 1 ); // 15th pixel
            expectedIndices.Add( 0 ); // 16th pixel
            expectedIndices.Add( 0 ); // 17th pixel
            expectedIndices.Add( 0 ); // 18th pixel

            for( int i = 0; i < 18; i++ )
            {
                Assert.AreEqual( expectedIndices[i], _tbid.Pixels[i], "pixel " + i );
            }
        }
        private void CodeNotInDictionary( bool xmlDebugging )
        {
            byte[] bytes = WikipediaExample.ImageDataBytes;
            bytes[4] = 0xFF; // put an unexpected code into the stream
            MemoryStream s = new MemoryStream();
            s.Write( bytes, 0, bytes.Length );
            s.Seek( 0, SeekOrigin.Begin );

            int pixelCount = WikipediaExample.FrameSize.Width
                            * WikipediaExample.FrameSize.Height;
            _tbid = new TableBasedImageData( s, pixelCount, xmlDebugging );

            Assert.IsTrue( _tbid.TestState( ErrorState.CodeNotInDictionary ) );
            Assert.AreEqual( 15, _tbid.Pixels.Count );
            Assert.AreEqual( 8, _tbid.LzwMinimumCodeSize );
            Assert.AreEqual( 9, _tbid.InitialCodeSize );
            Assert.AreEqual( Math.Pow( 2, 8 ), _tbid.ClearCode );
            Assert.AreEqual( Math.Pow( 2, 8 ) + 1, _tbid.EndOfInformation );

            IndexedPixels expectedIndices = new IndexedPixels();

            // Check all the pixels have been zero-filled
            expectedIndices.Add( 0 ); // first pixel
            expectedIndices.Add( 0 ); // 2nd pixel
            expectedIndices.Add( 0 ); // 3rd pixel
            expectedIndices.Add( 0 ); // 4th pixel
            expectedIndices.Add( 0 ); // 5th pixel
            expectedIndices.Add( 0 ); // 6th pixel
            expectedIndices.Add( 0 ); // 7th pixel
            expectedIndices.Add( 0 ); // 8th pixel
            expectedIndices.Add( 0 ); // 9th pixel
            expectedIndices.Add( 0 ); // 10th pixel
            expectedIndices.Add( 0 ); // 11th pixel
            expectedIndices.Add( 0 ); // 12th pixel
            expectedIndices.Add( 0 ); // 13th pixel
            expectedIndices.Add( 0 ); // 14th pixel
            expectedIndices.Add( 0 ); // 15th pixel

            for( int i = 0; i < 15; i++ )
            {
                Assert.AreEqual( expectedIndices[i], _tbid.Pixels[i], "pixel " + i );
            }

            if( xmlDebugging )
            {
                Assert.AreEqual( ExpectedDebugXml, _tbid.DebugXml );
            }
        }
Esempio n. 24
0
		/// <summary>
		/// Encodes and writes pixel data to the supplied stream
		/// </summary>
		/// <param name="indexedPixels">
		/// Collection of indices of the pixel colours within the active colour 
		/// table.
		/// </param>
		/// <param name="outputStream">
		/// The stream to write to.
		/// </param>
		private static void WritePixels( IndexedPixels indexedPixels,
		                                 Stream outputStream )
		{
			LzwEncoder encoder = new LzwEncoder( indexedPixels );
			encoder.Encode( outputStream );
		}
 /// <summary>
 /// Fills _ip with random values
 /// </summary>
 /// <param name="count">
 /// Number of values to add
 /// </param>
 private void RandomFill( int count )
 {
     Random r = new Random();
     for( int blockiness = 1; blockiness < 20; blockiness++ )
     {
         _ip = new IndexedPixels();
         byte[] bytes = new byte[count];
         r.NextBytes( bytes );
         byte lastByte = 0;
         foreach( byte b in bytes )
         {
             // Add a new value to the collection only if we throw a 1
             int diceThrow = r.Next( 1, blockiness );
             if( diceThrow == 1 )
             {
                 _ip.Add( b );
                 lastByte = b;
             }
             else
             {
                 // otherwise add the previous value again
                 // (this more accurately simulates colour distribution in
                 // an actual image)
                 _ip.Add( lastByte );
             }
         }
         TestIt();
     }
 }
Esempio n. 26
0
 public void Setup()
 {
     _ip = new IndexedPixels();
 }
Esempio n. 27
0
		private void AnalyseSingleImage()
		{
			if( _distinctColours.Count > 256 )
			{
				switch( _quantizerType )
				{
					case QuantizerType.NeuQuant:
						AnalyseSingleImageWithNeuQuant();
						break;
						
					case QuantizerType.Octree:
						AnalyseSingleImageWithOctree();
						break;
				}
			}
			else
			{
				// few enough colours to create a colour table directly without
				// quantization.
				CreateDirectColourTable();
			}

			// Work out the indices in the colour table of each of the pixels
			// in the supplied image.
			_indexedPixels = GetIndexedPixels( _imageColours );
		}
Esempio n. 28
0
		/// <summary>
		/// Gets the indices of the colours of each of the supplied pixels 
		/// within the colour table.
		/// </summary>
		/// <param name="pixelColours">
		/// A collection of the colours for which to get the indices in the 
		/// colour table.
		/// </param>
		/// <returns>
		/// A collection of the indices of the colours of each of the supplied 
		/// pixels within the colour table.
		/// </returns>
		private IndexedPixels GetIndexedPixels( Color[] pixelColours )
		{
			IndexedPixels indexedPixels = new IndexedPixels();
			// Take a copy of the distinct colours to make the IndexOf method
			// available
			string copyDistinctColoursCounterText = "Copying distinct colours";
			AddCounter( copyDistinctColoursCounterText, _distinctColours.Count );
			Collection<Color> distinctColours = new Collection<Color>();
			foreach( Color c in _distinctColours.Keys )
			{
				MyProgressCounters[copyDistinctColoursCounterText].Value++;
				distinctColours.Add( c );
			}
			RemoveCounter( copyDistinctColoursCounterText );

			int indexInColourTable;
			int red;
			int green;
			int blue;
			int numberOfPixels = pixelColours.Length;
			string indexingPixelsCounterText 
				= "Mapping colours to indices in colour table";
			AddCounter( indexingPixelsCounterText, numberOfPixels );
			
			for( int i = 0; i < numberOfPixels; i++ )
			{
				MyProgressCounters[indexingPixelsCounterText].Value = i;
				red = pixelColours[i].R;
				green = pixelColours[i].G;
				blue = pixelColours[i].B;
				
				// Get the index in the colour table of the colour of this pixel
				if( _distinctColours.Count > 256 )
				{
					indexInColourTable = _nq.Map( red, green, blue );
				}
				else
				{
					indexInColourTable = distinctColours.IndexOf( pixelColours[i] );
				}
				indexedPixels.Add( (byte) indexInColourTable );
			}
			RemoveCounter( indexingPixelsCounterText );
			return indexedPixels;
		}
Esempio n. 29
0
		/// <summary>
		/// Converts the supplied image to a collection of pixel indices using
		/// the supplied colour table.
		/// Only used when the QuantizerType is set to UseSuppliedPalette
		/// </summary>
		/// <param name="act">The active colour table</param>
		/// <param name="image">The image</param>
		/// <returns></returns>
		private IndexedPixels MakeIndexedPixels( ColourTable act, Image image )
		{
			int pixelCount = image.Height * image.Width;
			string counterText = "Getting indices in colour table";
			AddCounter( counterText, pixelCount );
			Bitmap bitmap = (Bitmap) image;
			IndexedPixels ip = new IndexedPixels();
			for( int y = 0; y < image.Height; y++ )
			{
				for( int x = 0; x < image.Width; x++ )
				{
					Color c = bitmap.GetPixel( x, y );
					int index = FindClosest( c, act );
					ip.Add( (byte) index );
					MyProgressCounters[counterText].Value = ip.Count;
				}
			}
			RemoveCounter( counterText );
			return ip;
		}