예제 #1
0
        public static void DrawContainer(string filename, Container container)
        {
            SxzPoint boundingBox = new SxzPoint();

            container.EnsureDimensions(boundingBox);
            DrawContainer(filename, container, boundingBox);
        }
예제 #2
0
파일: Print.cs 프로젝트: jubalh/Sxz
        public static string GetString(Container container)
        {
            StringBuilder result = new StringBuilder();
            List<byte> bytes = new List<byte>();
            byte[] containerBytes = container.GetData().ToArray();
            for (int i = 0; i < 3; i++)
            {
                PrintLine(result, containerBytes[i]);
            }

            foreach (Frame frame in container.Frames)
            {
                result.AppendLine(string.Empty);
                result.Append(GetString(frame));

                foreach (Chunk chunk in frame.Chunks)
                {
                    result.AppendLine(string.Empty);
                    byte[] output = chunk.GetData().ToArray();
                    foreach (byte b in output)
                    {
                        PrintLine(result, b);
                    }
                }
            }

            return result.ToString();
        }
예제 #3
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: SxzWriter <sxzfilepath>");
                return;
            }

            string filename = args[0];

            if (!File.Exists(filename))
            {
                Console.WriteLine("Failed to find file " + filename);
                return;
            }

            byte[] byteData = Helper.ReadBytesFromFile(filename);
            Console.WriteLine("Read in size is " + byteData.Length);

            Container container = new Container();
            container.SetData(byteData);

            Helper.DrawContainer(Helper.GetPrefix(filename) + ".png", container);
        }
예제 #4
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;
        }
예제 #5
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: SxzAppend <sxzfilepath1> <sxzfilepath2>");
                return;
            }

            string filename1 = args[0];

            if (!File.Exists(filename1))
            {
                Console.WriteLine("Failed to find file " + filename1);
                return;
            }

            byte[] byteData = Helper.ReadBytesFromFile(filename1);
            Console.WriteLine("Read in size for file1 is " + byteData.Length);

            Container container = new Container();
            container.SetData(byteData);

            SxzPoint dimensions = new SxzPoint();
            container.EnsureDimensions(dimensions);
            dimensions.X = (int)(dimensions.X / 2);
            dimensions.Y = (int)(dimensions.Y / 2);

            string filename2 = args[1];

            if (!File.Exists(filename2))
            {
                Console.WriteLine("Failed to find file " + filename2);
                return;
            }

            byteData = Helper.ReadBytesFromFile(filename2);
            Console.WriteLine("Read in size for file2 is " + byteData.Length);
            Container container2 = new Container();
            container2.SetData(byteData);
            SxzPoint dimensions2 = new SxzPoint();
            container2.EnsureDimensions(dimensions2);
            dimensions.X = dimensions.X - (int)(dimensions2.X / 2);
            dimensions.Y = dimensions.Y - (int)(dimensions2.Y / 2);

            foreach (Frame frame in container2.Frames)
            {
                foreach (Chunk chunk in frame.Chunks)
                {
                    if (chunk.Origin == null)
                    {
                        continue;
                    }

                    chunk.Origin.X = chunk.Origin.X + dimensions.X;
                    chunk.Origin.Y = chunk.Origin.Y + dimensions.Y;
                }
            }

            container.Frames.AddRange(container2.Frames);

            byte[] output = container.GetData();
            Console.WriteLine("Output byte total is " + output.Length);
            Helper.WriteBytesToFile("appendoutput.sxz", output);
            File.WriteAllText("appendoutput.sxz.txt", Print.GetString(container));

            Helper.DrawContainer("appendoutput.png", container);
        }
예제 #6
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: SxzReader <options> <imagefilepath>");
                return;
            }

            SxzColor backgroundColor = null;
            bool parseBackground = true;
            int backgroundType = 0;
            bool mostCommonColor = false;
            //Maximum number of bytes per pixel allowed for filtering fat chunks
            //Ideally this would be about 1 byte/pixel as is with indexed png images approximately (pre-compressed)
            double bitsPerPixel = 2;
            double colorDistance = 32;

            for (int argIndex = 0; argIndex < args.Length - 1; argIndex++)
            {
                if (args[argIndex].Equals("-bg"))
                {
                    argIndex++;
                    string colorInput = args[argIndex];
                    if (colorInput.Equals("none"))
                    {
                        parseBackground = false;

                    }
                    else if (colorInput.Equals("mostcommon"))
                    {
                        //removes most common color
                        mostCommonColor = true;
                    }
                    else
                    {
                        backgroundColor = SxzColor.Hex(colorInput);
                    }
                }
                else if (args[argIndex].Equals("-backgroundtype"))
                {
                    argIndex++;
                    if (!int.TryParse(args[argIndex], out backgroundType))
                    {
                        Console.WriteLine("Invalid background type " + args[argIndex]);
                        return;
                    }
                }
                else if (args[argIndex].Equals("-bpp"))
                {
                    argIndex++;
                    if (!double.TryParse(args[argIndex], out bitsPerPixel))
                    {
                        Console.WriteLine("Invalid Bits Per Pixel argument " + args[argIndex]);
                        return;
                    }
                }
                else if (args[argIndex].Equals("-distance"))
                {
                    argIndex++;
                    if (!double.TryParse(args[argIndex], out colorDistance))
                    {
                        Console.WriteLine("Invalid Color Distance argument " + args[argIndex]);
                        return;
                    }
                }
            }

            string filename = args[args.Length - 1];

            if (!File.Exists(filename))
            {
                Console.WriteLine("Failed to find file " + filename);
                return;
            }

            ParseImage parseImage = new ParseImage();
            Container container = parseImage.Parse(filename, backgroundColor, mostCommonColor, parseBackground, (BackgroundType)backgroundType, bitsPerPixel, colorDistance);

            File.WriteAllText(Helper.GetPrefix(filename) + ".sxz.txt", Print.GetString(container));
            byte[] output = container.GetData();
            Console.WriteLine("Output byte total is " + output.Length);
            Helper.WriteBytesToFile(Helper.GetPrefix(filename) + ".sxz", output);
            Helper.WriteBytesToZipFile(Helper.GetPrefix(filename) + ".sxz.gz", output);

            byte[] byteData = Helper.ReadBytesFromFile(Helper.GetPrefix(filename) + ".sxz");

            Container otherContainer = new Container();
            otherContainer.SetData(byteData);

            Helper.DrawContainer(Helper.GetPrefix(filename) + ".2.png", otherContainer);
        }
예제 #7
0
        public static void DrawContainer(string filename, Container container, SxzPoint boundingBox)
        {
            bool[,] drawable = new bool[boundingBox.X, boundingBox.Y];
            Color transparent = Color.Transparent;

            using (Bitmap drawableSurface = new Bitmap(boundingBox.X, boundingBox.Y, PixelFormat.Format32bppArgb))
            {
                drawableSurface.MakeTransparent(transparent);
                using (Graphics graphics = Graphics.FromImage(drawableSurface))
                {
                    graphics.Clear(transparent);
                    //debug color of green for now
                    SolidBrush brush = new SolidBrush(Color.Green);
                    //graphics.FillRectangle(brush, 0, 0, boundingBox.X, boundingBox.Y);
                    foreach (Frame frame in container.Frames)
                    {
                        foreach (Chunk chunk in frame.Chunks)
                        {
                            if (chunk.IsPalette())
                            {
                                continue;
                            }

                            if (chunk.IsBackground())
                            {
                                brush.Color = GetColor(chunk.GetColor(0, 0));
                                graphics.FillRectangle(brush, 0, 0, boundingBox.X, boundingBox.Y);
                                continue;
                            }

                            SxzPoint dimensions = chunk.GetDimensions();
                            SxzPoint origin = chunk.Origin;
                            for (int y = origin.Y; y < origin.Y + dimensions.Y; y++)
                            {
                                for (int x = origin.X; x < origin.X + dimensions.X; x++)
                                {
                                    SxzColor sxzColor = chunk.GetColor(x, y);

                                    if (sxzColor == null)
                                    {
                                        //For chunks with bitplanes, this means don't drawn on this pixel even though it is within
                                        //the region of the chunk
                                        continue;
                                    }

                                    if (chunk.IsTransparent())
                                    {
                                        drawableSurface.SetPixel(x, y, transparent);
                                        continue;
                                    }

                                    Color color = GetColor(sxzColor);
                                    if (color == null)
                                    {
                                        continue;
                                    }

                                    drawable[x, y] = true;
                                    brush.Color = color;
                                    graphics.FillRectangle(brush, x, y, 1, 1);
                                }
                            }
                        }
                    }

                    Image outputImage = (Image)drawableSurface;
                    outputImage.Save(filename, ImageFormat.Png);
                }
            }
        }