Example #1
0
        /// <summary>
        /// Crops image to given size
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="endX"></param>
        /// <param name="endY"></param>
        public void Crop(int startX, int startY, int endX, int endY)
        {
            if (startX > endX || startY > endY || startX < 0 || startY < 0 ||
                endX > data.GetLength(0) || endY > data.GetLength(1))
            {
                throw new ArgumentException("Invalid input");
            }

            Pixel[,] temp = new Pixel[endX - startX, endY - startY];

            int xcount = startX;
            int ycount = startY;

            for (int i = 0; i < temp.GetLength(0); i++)
            {
                for (int j = 0; j < temp.GetLength(1); j++)
                {
                    temp[i, j] = data[xcount, ycount];
                    ycount++;
                }
                ycount = startY;
                xcount++;
            }
            data = temp;
        }
        /// <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));
        }