Пример #1
0
        public void EncodeImage( Bitmap inp, Stream outs )
        {
            if ( inp  == null ||
               outs == null ) return;

              int width  = inp.Width;
              int height = inp.Height;
              if ( width < 1 || height < 1 ) return;

              // !!!{{ TODO: add the encoding code here

              DeflateStream ds = new BufferedDeflateStream( 16384, outs, CompressionMode.Compress, true );

              // file header: [ MAGIC, width, height ]
              ds.WriteByte( (byte)((MAGIC >> 24) & 0xff) );
              ds.WriteByte( (byte)((MAGIC >> 16) & 0xff) );
              ds.WriteByte( (byte)((MAGIC >>  8) & 0xff) );
              ds.WriteByte( (byte)( MAGIC        & 0xff) );

              ds.WriteByte( (byte)((width >> 8) & 0xff) );
              ds.WriteByte( (byte)( width       & 0xff) );

              ds.WriteByte( (byte)((height >> 8) & 0xff) );
              ds.WriteByte( (byte)( height       & 0xff) );

              for ( int y = 0; y < height; y++ )
            for ( int x = 0; x < width; x++ )
            {
              byte gr = (byte)(inp.GetPixel( x, y ).GetBrightness() * 255.0f);
              ds.WriteByte( gr );
            }

              ds.Close();

              // !!!}}
        }
Пример #2
0
        public void EncodeImage(Bitmap inputImage, Stream outputStream)
        {
            if (inputImage == null ||
                 outputStream == null) return;

            int width = inputImage.Width;
            int height = inputImage.Height;

            if (width < 1 || height < 1) return;

            int backgroundColor = ComputeDominantColor(inputImage);

            Bitmap copyImage = new Bitmap(inputImage);

            DeflateStream ds = new BufferedDeflateStream(16384, outputStream, CompressionMode.Compress, true);

            try
            {
                // file header: [ MAGIC, width, height, dominant color ]
                ds.WriteByte((byte)((MAGIC >> 24) & 0xff));
                ds.WriteByte((byte)((MAGIC >> 16) & 0xff));
                ds.WriteByte((byte)((MAGIC >> 8) & 0xff));
                ds.WriteByte((byte)(MAGIC & 0xff));

                ds.WriteByte((byte)((width >> 8) & 0xff));
                ds.WriteByte((byte)(width & 0xff));

                ds.WriteByte((byte)((height >> 8) & 0xff));
                ds.WriteByte((byte)(height & 0xff));

                // dominant color
                ds.WriteByte((byte)(backgroundColor & 0x01));

                // debug counters:
                int totalPixels = width * height;
                if (InfoEnabled)
                {
                    Console.WriteLine("Total pixels: {0}, [{1}, {2}]", totalPixels, width, height);
                }

                int totalLinePixels = GetTotalLinePixels(inputImage, backgroundColor);
                if (InfoEnabled)
                {
                    Console.WriteLine("Total line pixels: {0} ({1} %)", totalLinePixels, 100.0 * totalLinePixels / totalPixels);
                }
                int firstLinePixels = 0;
                int neighborhoodLinePixels = 0;

                int totalStartPixelBits = 0;

                Point previousStartingPoint = new Point();

                int longestLine = 0;

                List<int> lineDirections = new List<int>();

                if (TraceEnabled)
                {
                    Console.WriteLine("Encoding.");
                }

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        int bwIntensity = BWImageHelper.GetBWPixel(copyImage, x, y);
                        if (IsBackground(backgroundColor, bwIntensity))
                        {
                            continue;
                        }

                        // now we have found the first unprocessed non-background pixel
                        if (TraceEnabled)
                        {
                            Console.WriteLine("First pixel: [{0}, {1}]", x, y);
                        }
                        BWImageHelper.SetBWPixel(copyImage, x, y, backgroundColor);
                        // write position of line's starting pixel
                        // X and Y as two-byte numbers
                        int diffX = x - previousStartingPoint.X;
                        int diffY = y - previousStartingPoint.Y;

                        firstLinePixels++;

                        int currentX = x;
                        int currentY = y;
                        previousStartingPoint.X = x;
                        previousStartingPoint.Y = y;
                        bool lineContinues = true;
                        int lineLength = 1;
                        while (lineContinues && (lineLength < 256))
                        //while (lineContinues)
                        {
                            lineContinues = false;
                            for (int directionIndex = 0; directionIndex < neighborhood.Directions.Count; directionIndex++)
                            {
                                Point direction = neighborhood.Directions[directionIndex];
                                int nextX = currentX + direction.X;
                                int nextY = currentY + direction.Y;
                                if (!BWImageHelper.IsInside(copyImage, nextX, nextY))
                                {
                                    continue;
                                }
                                int nextIntensity = BWImageHelper.GetBWPixel(copyImage, nextX, nextY);
                                if (!IsBackground(backgroundColor, nextIntensity))
                                {
                                    currentX = nextX;
                                    currentY = nextY;
                                    if (TraceEnabled)
                                    {
                                        Console.WriteLine("Neighbor pixel: [{0}, {1}]", nextX, nextY);
                                        Console.WriteLine("  Direction: {0} ({1})", direction, directionIndex);
                                    }
                                    lineDirections.Add(directionIndex);
                                    lineContinues = true;
                                    neighborhoodLinePixels++;
                                    lineLength++;
                                    BWImageHelper.SetBWPixel(copyImage, nextX, nextY, backgroundColor);
                                    break;
                                }
                            }
                        }

                        // store diffX and diffY as two signed 15-bit numbers in 4 bytes
                        // |1-bit X sign|15-bit abs(diffX)|1-bit Y sign|15-bit abs(diffY)|
                        // sign: 0 = positive or zero, 1 = negative
                        if (TraceEnabled)
                        {
                            Console.WriteLine("Diff: [{0}, {1}]", diffX, diffY);
                        }
                        // X sign
                        int buffer = (diffX < 0) ? 1 : 0;
                        // diff X
                        buffer <<= 15;
                        buffer |= Math.Abs(diffX) & 0x1fff;
                        // Y sign
                        buffer <<= 1;
                        buffer |= (diffY < 0) ? 1 : 0;
                        // diff Y
                        buffer <<= 15;
                        buffer |= Math.Abs(diffY) & 0x1fff;
                        ds.WriteByte((byte)((buffer >> 24) & 0xff));
                        ds.WriteByte((byte)((buffer >> 16) & 0xff));
                        ds.WriteByte((byte)((buffer >> 8) & 0xff));
                        ds.WriteByte((byte)(buffer & 0xff));

                        totalStartPixelBits += CountBits(buffer);

                        // write the number of following directions
                        ds.WriteByte((byte)((lineLength - 1) & 0xff));

                        // write the list of following directions
                        buffer = 0;
                        int bufferLength = 0;
                        foreach (int directionIndex in lineDirections)
                        {
                            buffer = (buffer << neighborhood.SignificantBits) + directionIndex;
                            bufferLength += neighborhood.SignificantBits;
                            int remainingBits = bufferLength - 8; // free space in the byte
                            if ((bufferLength >= 8) && (remainingBits < neighborhood.SignificantBits))
                            {
                                int writtenByte = (buffer >> remainingBits) & 0xff;
                                ds.WriteByte((byte)(writtenByte & 0xff));
                                buffer -= writtenByte << remainingBits;
                                bufferLength -= 8;
                            }
                        }
                        if (bufferLength > 0)
                        {
                            // shift the remaining bits completely to the left
                            // (so that the rest of the byte is filled with zeros only)
                            buffer <<= 8 - bufferLength;
                            ds.WriteByte((byte)(buffer & 0xff));
                            buffer = 0;
                            bufferLength = 0;
                        }

                        lineDirections.Clear();

                        longestLine = Math.Max(longestLine, lineLength);
                    }
                }

                if (InfoEnabled)
                {
                    Console.WriteLine("Total first pixels: {0} ({1} %) ({2} %)", firstLinePixels, 100.0 * firstLinePixels / totalPixels, 100.0 * firstLinePixels / totalLinePixels);
                    Console.WriteLine("Total neighborhood pixels: {0} ({1} %) ({2} %)", neighborhoodLinePixels, 100.0 * neighborhoodLinePixels / totalPixels, 100.0 * neighborhoodLinePixels / totalLinePixels);
                    Console.WriteLine("First + neighborhood: {0}", firstLinePixels + neighborhoodLinePixels);
                    Console.WriteLine("Total start pixel bits: {0}", totalStartPixelBits);
                    Console.WriteLine("Longest line: {0}", longestLine);
                    Console.WriteLine();
                }
            }
            finally
            {
                if (ds != null)
                {
                    ds.Close();
                }
            }
        }