public static void DrawContainer(string filename, Container container) { SxzPoint boundingBox = new SxzPoint(); container.EnsureDimensions(boundingBox); DrawContainer(filename, container, boundingBox); }
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(); }
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); }
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; }
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); }
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); }
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); } } }