Esempio n. 1
0
        public Container Parse(string filename, SxzColor backgroundColor, bool useMostCommonColor, bool parseBackground, BackgroundType backgroundType, double bitsPerPixel, double maximumDistance)
        {
            int width = 0;
            int height = 0;

            //now we can act on our pixel byte array to get pixels out
            //and also histogram because it is informative if nothing else
            LocationPool locationPool = null;

            Dictionary<SxzColor, int> histogram = new Dictionary<SxzColor, int>();

            TransparentRegion transparentRegion = new TransparentRegion();

            //Parse all the pixels into the locationpool, histogram and remove the fully transparent pixels into the transparentregion
            using (System.Drawing.Bitmap bitMap = new System.Drawing.Bitmap(filename))
            {
                width = bitMap.Width;
                height = bitMap.Height;
                locationPool = new LocationPool(width, height);
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        System.Drawing.Color pixel = bitMap.GetPixel(x, y);

                        Location location = new Location();
                        location.Color = new SxzColor(pixel.R, pixel.G, pixel.B);
                        location.Point.X = x;
                        location.Point.Y = y;

                        //Don't put transparent colors into the histogram
                        if (pixel.A == 0)
                        {
                            transparentRegion.Add(location);
                            locationPool.SetLocation(location, x, y);
                            locationPool.SetMarked(location);
                            continue;
                        }

                        if (histogram.ContainsKey(location.Color))
                        {
                            int count = histogram[location.Color];
                            histogram[location.Color] = count + 1;
                        }
                        else
                        {
                            histogram.Add(location.Color, 1);
                        }

                        locationPool.SetLocation(location, x, y);
                    }
                }
            }

            Console.WriteLine("Total pixel count " + (width * height));
            Console.WriteLine("Total transparent pixel count " + transparentRegion.Locations.Count);

            //Remove all the transparent locations
            //foreach (Location location in transparentRegion.Locations)
            //{
            //    locationPool.SetMarked(location);
            //}

            //set the neighbors after removing transparent pixels to save time since those aren't needed anymore
            locationPool.SetNeighbors();

            Console.WriteLine("Done removing transparent pixels");
            //Sort the colors by frequency
            List<KeyValuePair<SxzColor, int>> colorList = histogram.ToList();
            colorList.Sort((first, second) =>
            {
                return first.Value == second.Value ? (int)(SxzColor.GetColorDistance(second.Key, new SxzColor(0, 0, 0)) - SxzColor.GetColorDistance(first.Key, new SxzColor(0, 0, 0)))
                        : second.Value.CompareTo(first.Value);
            });

            //Find the most commonly used color
            SxzColor mostCommonColor = colorList[0].Key;
            if (useMostCommonColor)
            {
                backgroundColor = mostCommonColor;
            }

            //always start with a palette, register empty palette and fill as we go

            Console.WriteLine("Processing the most common color");

            DefaultPaletteChunk defaultPaletteChunk = new DefaultPaletteChunk();
            Palette defaultPalette = new Palette(defaultPaletteChunk);

            //Initialization overhead
            List<PaletteContainer> paletteContainers = new List<PaletteContainer>();

            PaletteContainer initialPaletteContainer = new PaletteContainer();
            initialPaletteContainer.Initial = true;
            initialPaletteContainer.Palette = defaultPalette;
            paletteContainers.Add(initialPaletteContainer);

            HashSet<Location> locations = locationPool.GetByColor(backgroundColor);
            if (parseBackground && locations.Count > 0)
            {

                if (backgroundType == BackgroundType.Background)
                {
                    Console.WriteLine("Creating background chunk");
                    BackgroundChunk backgroundChunk = new BackgroundChunk();
                    BackgroundChunkContainer backgroundChunkContainer = new BackgroundChunkContainer();

                    backgroundChunkContainer.Chunk = backgroundChunk;
                    backgroundChunkContainer.Color = backgroundColor;

                    //pull out all the pixels with the most common color and throw them into a backgroundchunk
                    if (!initialPaletteContainer.Contains(backgroundColor))
                    {
                        Console.WriteLine("Background chunk in it's own palette");
                        //not in default palette so create a new palette
                        Palette palette = new Palette();
                        palette.Add(backgroundColor);
                        PaletteContainer paletteContainer = new PaletteContainer();
                        paletteContainer.Palette = palette;
                        paletteContainers.Add(paletteContainer);
                        paletteContainer.Add(backgroundChunkContainer);
                        backgroundChunk.Palette = palette.GetPaletteChunk();
                    }
                    else
                    {
                        backgroundChunk.Palette = defaultPaletteChunk;
                        initialPaletteContainer.Add(backgroundChunkContainer);
                    }

                    //AddChunk(paletteContainers, backgroundContainer, mostCommonColor);
                    backgroundChunkContainer.Locations = locations;
                }
                else if (backgroundType == BackgroundType.Rectangle)
                {
                    MonoRectangleChunk rectangleChunk = new MonoRectangleChunk();
                    rectangleChunk.Origin = new SxzPoint(0, 0);
                    rectangleChunk.Width = width;
                    rectangleChunk.Height = height;
                    MonoRectangleChunkContainer rectangleContainer = new MonoRectangleChunkContainer();
                    rectangleContainer.Color = backgroundColor;
                    rectangleContainer.Chunk = rectangleChunk;

                    if (!initialPaletteContainer.Contains(backgroundColor))
                    {
                        Console.WriteLine("Background chunk in it's own palette");
                        //not in default palette so create a new palette
                        Palette palette = new Palette();
                        palette.Add(backgroundColor);
                        PaletteContainer paletteContainer = new PaletteContainer();
                        paletteContainer.Palette = palette;
                        paletteContainers.Add(paletteContainer);
                        paletteContainer.Add(rectangleContainer);
                        rectangleChunk.Palette = palette.GetPaletteChunk();
                    }
                    else
                    {
                        rectangleChunk.Palette = defaultPaletteChunk;
                        initialPaletteContainer.Add(rectangleContainer);
                    }

                    //AddChunk(paletteContainers, backgroundContainer, mostCommonColor);
                    rectangleContainer.Locations = locations;
                }

                //Remove the pixels with the background color from the location pool
                foreach (Location location in locations)
                {
                    locationPool.SetMarked(location);
                }
            }

            Console.WriteLine("Done processing the most common color");

            Console.WriteLine("Parsing monocolor regions");
            //Pull out all regions with the same color in mono regions that were not pulled by the most common color if any
            HashSet<Region> monoRegions = Process(locationPool, maximumDistance, RegionType.MonoRegion);
            Console.WriteLine("Have mono region count " + monoRegions.Count);
            foreach (Region region in monoRegions)
            {
                HashSet<ChunkContainer> potentialContainers = region.GetChunks(locationPool);
                PaletteContainer paletteContainer = GetPaletteContainer(paletteContainers, region.GetColors());

                foreach (ChunkContainer chunkContainer in potentialContainers)
                {
                    //filter out chunks that are not storage sufficient, putting the unused locations
                    //back into the location pool
                    //...
                    if (!chunkContainer.IsValid(bitsPerPixel))
                    {
                        PrintTossedChunk(chunkContainer);
                        foreach (Location location in chunkContainer.Locations)
                        {
                            locationPool.Unmark(location);
                        }

                        continue;
                    }

                    if (paletteContainer == null)
                    {
                        paletteContainer = new PaletteContainer();
                        paletteContainer.Palette = new Palette();
                        paletteContainers.Add(paletteContainer);
                    }

                    paletteContainer.Add(chunkContainer);
                    paletteContainer.AddColors(region.GetColors());
                }
            }

            Console.WriteLine("Done processing monocolor regions");

            Console.WriteLine("Parsing multicolor regions");
            HashSet<Region> colorRegions = Process(locationPool, maximumDistance, RegionType.MultiColorRegion);
            Console.WriteLine("Have multi color region count " + colorRegions.Count);
            foreach (Region region in colorRegions)
            {
                HashSet<ChunkContainer> potentialContainers = region.GetChunks(locationPool);
                PaletteContainer paletteContainer = GetPaletteContainer(paletteContainers, region.GetColors());
                if (paletteContainer == null)
                {
                    paletteContainer = new PaletteContainer();
                    paletteContainer.Palette = new Palette();
                    paletteContainers.Add(paletteContainer);
                }

                foreach (ChunkContainer chunkContainer in potentialContainers)
                {
                    paletteContainer.Add(chunkContainer);
                    paletteContainer.AddColors(region.GetColors());
                }
            }

            Console.WriteLine("Done processing multicolor regions");
            Console.WriteLine("Histogram count " + colorList.Count);
            Console.WriteLine("Majority color " + mostCommonColor + " with count " + colorList[0].Value);
            //alrighty, let's get some output going
            Container container = new Container();
            Frame frame = new Frame();
            container.Frames.Add(frame);

            foreach (PaletteContainer paletteContainer in paletteContainers)
            {
                PaletteChunk paletteChunk = paletteContainer.Palette.GetPaletteChunk();
                if (paletteChunk == null)
                {
                    paletteChunk = defaultPaletteChunk;
                }

                if (!paletteContainer.Initial)
                {
                    paletteChunk.Colors.Sort(new PaletteChunk.ColorSorter());
                    frame.Chunks.Add(paletteChunk);
                }

                foreach (ChunkContainer chunkContainer in paletteContainer.ChunkContainers)
                {
                    int count = chunkContainer.Chunk.GetData().Count;
                    PrintKeptChunk(chunkContainer);
                    chunkContainer.SetIndex(paletteChunk);
                    chunkContainer.Chunk.Palette = paletteChunk;

                    frame.Chunks.Add(chunkContainer.Chunk);
                }
            }

            return container;
        }
Esempio n. 2
0
        /// <summary>
        /// To return a RectangleChunk we will need the bounding box and a check for missing locations
        /// </summary>
        /// <returns></returns>
        public override HashSet<ChunkContainer> GetChunks(LocationPool locationPool)
        {
            HashSet<ChunkContainer> result = new HashSet<ChunkContainer>();

            if (IsRectangle())
            {
                MonoRectangleChunk rectangleChunk = new MonoRectangleChunk();
                rectangleChunk.Origin = BoundingBox.UpperLeft;
                rectangleChunk.Width = BoundingBox.Width();
                rectangleChunk.Height = BoundingBox.Height();
                MonoRectangleChunkContainer container = new MonoRectangleChunkContainer();
                container.Chunk = rectangleChunk;
                container.Locations = GetLocations(BoundingBox);
                //container.AdditionalSize = NewColorCount(locationPool.Palette);
                container.Color = Color;
                result.Add(container);
                return result;
            }

            //break up into many rectangles and return rest here
            HashSet<Location> locations = new HashSet<Location>(Locations);
            HashSet<BoundingBox> rectangles = GetAllRectangles(locations, BoundingBox);

            foreach (BoundingBox rectangle in rectangles)
            {
                MonoRectangleChunk rectangleChunk = new MonoRectangleChunk();
                rectangleChunk.Origin = rectangle.UpperLeft;
                rectangleChunk.Width = rectangle.Width();
                rectangleChunk.Height = rectangle.Height();
                MonoRectangleChunkContainer container = new MonoRectangleChunkContainer();
                container.Chunk = rectangleChunk;
                container.Color = Color;
                //container.AdditionalSize = NewColorCount(locationPool.Palette);
                container.Locations = GetLocations(rectangle);
                result.Add(container);
            }

            //now for the remaining locations, create monocolorchunks
            BoundingBox remaining = new BoundingBox();
            foreach (Location location in locations)
            {
                remaining.Add(location.Point);
            }

            MonoBitPlaneChunk monoColorChunk = new MonoBitPlaneChunk();
            monoColorChunk.Width = remaining.Width();
            monoColorChunk.Height = remaining.Height();
            monoColorChunk.Initialize();
            monoColorChunk.Origin = remaining.UpperLeft;

            foreach (Location location in locations)
            {
                monoColorChunk.SetColor(location.Point.X, location.Point.Y);
            }

            MonoBitPlaneChunkContainer monoContainer = new MonoBitPlaneChunkContainer();
            monoContainer.Chunk = monoColorChunk;
            monoContainer.Locations = GetLocations(remaining);
            monoContainer.Color = Color;
            result.Add(monoContainer);

            return result;
        }
Esempio n. 3
0
        public override HashSet<ChunkContainer> GetChunks(LocationPool locationPool)
        {
            HashSet<ChunkContainer> result = new HashSet<ChunkContainer>();

            if (Locations.Count == 0)
            {
                return result;
            }

            if (Palette.Count() == 1)
            {
                if (IsRectangle())
                {
                    MonoRectangleChunk rectangleChunk = new MonoRectangleChunk();
                    rectangleChunk.Origin = BoundingBox.UpperLeft;
                    rectangleChunk.Width = BoundingBox.Width();
                    rectangleChunk.Height = BoundingBox.Height();
                    MonoRectangleChunkContainer container = new MonoRectangleChunkContainer();
                    container.Chunk = rectangleChunk;
                    container.Locations = GetLocations(BoundingBox);
                    container.Color = Palette.Colors.First();
                    result.Add(container);
                    return result;
                }

                //output a monochunk?
                MonoBitPlaneChunk monoColorChunk = new MonoBitPlaneChunk();
                monoColorChunk.Width = BoundingBox.Width();
                monoColorChunk.Height = BoundingBox.Height();
                monoColorChunk.Initialize();
                monoColorChunk.Origin = BoundingBox.UpperLeft;

                foreach (Location location in Locations)
                {
                    monoColorChunk.SetColor(location.Point.X, location.Point.Y);
                }

                MonoBitPlaneChunkContainer monoContainer = new MonoBitPlaneChunkContainer();
                monoContainer.Chunk = monoColorChunk;
                monoContainer.Locations = Locations;
                monoContainer.Color = Palette.Colors.First();
                result.Add(monoContainer);

                return result;

            }

            if (IsRectangle())
            {
                MultiColorRectangleChunkContainer container = new MultiColorRectangleChunkContainer();
                ColorRectangleChunk rectangleChunk = new ColorRectangleChunk();
                rectangleChunk.Origin = BoundingBox.UpperLeft;
                rectangleChunk.Width = BoundingBox.Width();
                rectangleChunk.Height = BoundingBox.Height();
                //rectangleChunk.Direction = Direction.Left;
                rectangleChunk.Initialize();
                container.Chunk = rectangleChunk;
                container.Locations = Locations;
                rectangleChunk.Palette = Palette.GetPaletteChunk();

                foreach (Location location in Locations)
                {
                    rectangleChunk.SetColor(location.Color, location.Point.X, location.Point.Y);
                }

                result.Add(container);
                return result;
            }

            //Don't break it into further rectangles right now... just output a bitplane
            MultiColorBitPlaneChunkContainer chunkContainer = new MultiColorBitPlaneChunkContainer();
            ColorBitPlaneChunk colorBitPlaneChunk = new ColorBitPlaneChunk();
            colorBitPlaneChunk.Origin = BoundingBox.UpperLeft;
            colorBitPlaneChunk.Height = BoundingBox.Height();
            colorBitPlaneChunk.Width = BoundingBox.Width();
            colorBitPlaneChunk.Palette = Palette.GetPaletteChunk();
            colorBitPlaneChunk.Initialize();
            chunkContainer.Chunk = colorBitPlaneChunk;
            chunkContainer.Locations = Locations;

            foreach (Location location in Locations)
            {
                //bitmask must use local coordinates
                colorBitPlaneChunk.SetColor(location.Color, location.Point.X, location.Point.Y);
            }

            result.Add(chunkContainer);

            return result;
        }
Esempio n. 4
0
        public void SetData(byte[] data)
        {
            //skip label and size
            int index = 0;
            PaletteChunk paletteChunk = new DefaultPaletteChunk();
            while (index < data.Length)
            {
                string label = Encoding.ASCII.GetString(data, index, 2);

                //case statement would work better here
                if (label.Equals(ColorBitPlaneChunk.Label))
                {
                  int size = BitConverter.ToInt16(data, index + 2);
                  byte[] chunkData = new byte[size + 4];
                  Array.Copy(data, index, chunkData, 0, chunkData.Length);
                  ColorBitPlaneChunk colorChunk = new ColorBitPlaneChunk();
                  colorChunk.Palette = paletteChunk;
                  colorChunk.SetData(chunkData);
                  Chunks.Add(colorChunk);
                  index += size + 4;
                }
                else if (label.Equals(ColorRectangleChunk.Label))
                {
                    int size = BitConverter.ToInt16(data, index + 2);
                    byte[] chunkData = new byte[size + 4];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    ColorRectangleChunk colorRectangleChunk = new ColorRectangleChunk();
                    colorRectangleChunk.Palette = paletteChunk;
                    colorRectangleChunk.SetData(chunkData);
                    Chunks.Add(colorRectangleChunk);
                    index += size + 4;
                }
                else if (label.Equals(MonoBitPlaneChunk.Label))
                {
                    int size = BitConverter.ToInt16(data, index + 2);
                    byte[] chunkData = new byte[size + 4];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    MonoBitPlaneChunk monoChunk = new MonoBitPlaneChunk();
                    monoChunk.Palette = paletteChunk;
                    monoChunk.SetData(chunkData);
                    Chunks.Add(monoChunk);
                    index += size + 4;
                }
                else if (label.Equals(TransparentBitPlaneChunk.Label))
                {
                    int size = BitConverter.ToInt16(data, index + 2);
                    byte[] chunkData = new byte[size + 4];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    TransparentBitPlaneChunk transparentChunk = new TransparentBitPlaneChunk();
                    transparentChunk.SetData(chunkData);
                    Chunks.Add(transparentChunk);
                    index += size + 4;
                }
                else if (label.Equals(MonoRectangleChunk.Label))
                {
                    //must be background
                    MonoRectangleChunk chunk = new MonoRectangleChunk();
                    byte[] chunkData = new byte[11];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    chunk.Palette = paletteChunk;
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += chunkData.Length;
                }
                else if (label.Equals(TransparentRectangleChunk.Label))
                {
                    //must be background
                    TransparentRectangleChunk chunk = new TransparentRectangleChunk();
                    byte[] chunkData = new byte[10];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += chunkData.Length;
                }
                else if (label.Equals(PaletteChunk.Label))
                {
                    //must be background
                    PaletteChunk chunk = new PaletteChunk();
                    int count = (data[index + 2] + 1) * 3;
                    byte[] chunkData = new byte[count + 3];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += chunkData.Length;
                    paletteChunk = chunk;
                }
                else if (label.Equals(DefaultPaletteChunk.Label))
                {
                    //must be background
                    DefaultPaletteChunk chunk = new DefaultPaletteChunk();
                    int count = (data[index + 2] + 1) * 3;
                    byte[] chunkData = new byte[count + 3];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += chunkData.Length;
                    paletteChunk = chunk;
                }
                else if (label.Equals(GrayBitPlaneChunk.Label))
                {
                    int size = BitConverter.ToInt16(data, index + 2);
                    byte[] chunkData = new byte[size + 4];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    GrayBitPlaneChunk chunk = new GrayBitPlaneChunk();
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += size + 4;
                }
                else if (label.Equals(BlackWhiteBitPlaneChunk.Label))
                {
                    int size = BitConverter.ToInt16(data, index + 2);
                    byte[] chunkData = new byte[size + 4];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    BlackWhiteBitPlaneChunk chunk = new BlackWhiteBitPlaneChunk();
                    chunk.SetData(chunkData);
                    Chunks.Add(chunk);
                    index += size + 4;
                }
                else if (label.Equals(BackgroundChunk.Label))
                {
                    //Console.WriteLine("default to background with label " + label);
                    //must be background
                    BackgroundChunk background = new BackgroundChunk();
                    background.Palette = paletteChunk;
                    byte[] chunkData = new byte[3];
                    Array.Copy(data, index, chunkData, 0, chunkData.Length);
                    background.SetData(chunkData);
                    Chunks.Add(background);
                    index += chunkData.Length;
                }
                else
                {
                    Console.WriteLine("Invalid chunk label " + label);
                    Console.WriteLine("At " + index + " " + Chunks.Count);
                    if (Chunks.Last() != null)
                    {
                        Console.WriteLine("Last chunk was " + Chunks.Last().Origin.ToString());
                    }

                    return;
                }
            }
        }