/// <summary> /// Converts a string (usually from file) to an Image object /// </summary> /// <param name="imgData">the image data in string format</param> /// <returns>the deserialized Image</returns> public Image Parse(string imgData) { string formatRgx = '^' + formatSpec + '$'; string commentRgx = '^' + commentTag + ".+$"; string sizeRgx = @"^\d+ \d+$"; string rangeRgx = @"^\d+$"; string pixelRgx = @"^(:?\d+ ?)+$"; //each line in the "file" string[] lines = imgData.Split (new string[] { Environment.NewLine }, StringSplitOptions.None); //the minimum length of any pgm file is 4 lines if (lines.Length < 4) { throw new InvalidDataException ("Invalid number of lines " + lines.Length + " is not enough"); } //first line should be format specifier checkFormat(lines[0], true, 0, formatRgx); //second line should be either comment or size specifier checkOneFormat(lines[1], true, 1, commentRgx, sizeRgx); string[] metadata = lines.Skip(1) //skip format specifier .TakeWhile(line => checkFormat(line, false, -1, commentRgx)) //take only metadata lines, line numbering is irrelevant here .Select(comment => comment = comment.Substring(1)) //remove # .ToArray(); //line after comments should be size specifier checkFormat(lines[metadata.Length + 1], true, metadata.Length + 1, sizeRgx); int[] size = lines[metadata.Length + 1].Split(' ') .Select(num => int.Parse(num)) .ToArray(); //line after size specifier should be range checkFormat(lines[metadata.Length + 2], true, metadata.Length + 2, rangeRgx); int maxRange = int.Parse(lines[metadata.Length + 2]); //the rest of the string should be filled with pixels for (int i = metadata.Length + 3; i < lines.Length; i++) { checkFormat(lines[i], true, i, pixelRgx); } int[] pixelsData = lines.Skip(metadata.Length + 3) //skip metadata and stuff .Select(line => line.Split(' ').Select(num => int.Parse(num))) //parse each collection of collection .SelectMany(list => list.ToArray()).ToArray(); //flatten the array //verify maxRange of each pixel for (int i = 0; i < pixelsData.Length; i++) { if (pixelsData[i] > maxRange) { throw new InvalidDataException ("Pixel " + i + " expected at most : " + maxRange + Environment.NewLine + "Actual : " + pixelsData[i]); } } //checking amount of pixel corresponds to specified size if (pixelsData.Length != size[0] * size[1]) { throw new InvalidDataException("Expected size : " + size[0] * size[1] + ", Actual size : " + pixelsData.Length); } //filling the resulting Pixel rectangular array Pixel[,] pixels = new Pixel[size[0], size[1]]; for (int i = 0; i < pixelsData.Length; i++) { pixels[i % pixels.GetLength(0), i / pixels.GetLength(0)] = new Pixel(pixelsData[i]); } return(new Image(string.Join(Environment.NewLine, metadata), maxRange, pixels)); }
public Image Parse(string imageData) { // Getting information from string string[] lines = imageData.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.None); int currentLine = 1; string metadata = ""; while (currentLine < lines.Length) { if (lines[currentLine].StartsWith("#")) { metadata += lines[currentLine].Substring(2) + System.Environment.NewLine; } else { break; } currentLine++; } metadata = metadata.Trim(); string[] widthHeight = lines[currentLine].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string widthInString = widthHeight[0].Trim(); string heightInString = widthHeight[1].Trim(); currentLine++; string maxRangeInString = lines[currentLine].Trim(); currentLine++; List <string> numbersInStrings = new List <string>(); while (currentLine < lines.Length) { string[] numbersOnLine = lines[currentLine].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string number in numbersOnLine) { numbersInStrings.Add(number); } currentLine++; } // Validating the information and parsing it into the right type int width; int height; if (int.TryParse(widthInString, out width) == false) { throw new InvalidDataException(); } if (int.TryParse(heightInString, out height) == false) { throw new InvalidDataException(); } if (width <= 0 || height <= 0) { throw new InvalidDataException(); } int maxRange; if (int.TryParse(maxRangeInString, out maxRange) == false) { throw new InvalidDataException(); } if (maxRange <= 0) { throw new InvalidDataException(); } if (numbersInStrings.Count / 3.0 != height * width) { throw new InvalidDataException(); } int[] numbers = new int[numbersInStrings.Count]; for (int i = 0; i < numbersInStrings.Count; i++) { int number; if (int.TryParse(numbersInStrings[i], out number) == false) { throw new InvalidDataException(); } if (number > maxRange) { throw new InvalidDataException(); } numbers[i] = number; } // Creating image object int red = 0; int green = 0; int blue = 0; List <Pixel> pixels = new List <Pixel>(); for (int i = 0; i < numbers.Length; i++) { if (i % 3 == 0) { red = numbers[i]; } else if ((i - 1) % 3 == 0) { green = numbers[i]; } else if ((i - 2) % 3 == 0) { blue = numbers[i]; Pixel pixel = new Pixel(red, green, blue); pixels.Add(pixel); } } // Putting all the values from pixels list (1D) into the image 2D array Pixel[,] image = new Pixel[height, width]; for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { image[row, column] = pixels[row * width + column]; } } return(new Image(metadata, maxRange, image)); }