/// <summary> /// List-based constructor. /// </summary> /// <param name="rawImage">Is an F#-based list of lists, one list per row.</param> public PixelMap(FSharpList <FSharpList <Tuple <int, int, int> > > rawImage) { // format info for "P3" PPM images: this.pixelFormat = PixelFormat.Format24bppRgb; this.bytesPerPixel = 3; // get info for this image and store in header: PixelMapHeader hdr = new PixelMapHeader(); hdr.MagicNumber = "P3"; hdr.Depth = 255; // we are assuming "P3" PPM image files; hdr.Height = rawImage.Length; // height = # of rows of data; hdr.Width = rawImage.Head.Length; // width is # of PIXELS per row this.Header = hdr; // stride is # of color values per row, for P3 this is width * bytesPerPixel: this.stride = hdr.Width * this.bytesPerPixel; // allocate and initialize raw data for image: this.rawImageData = new byte[hdr.Height * this.stride]; int i = 0; // index into image data array: foreach (FSharpList <Tuple <int, int, int> > row in rawImage) { foreach (Tuple <int, int, int> T in row) { rawImageData[i++] = (byte)T.Item1; rawImageData[i++] = (byte)T.Item2; rawImageData[i++] = (byte)T.Item3; } } System.Diagnostics.Debug.Assert(i == this.rawImageData.Length); // create bitmap for display: if (this.stride % 4 == 0) { this.bitmap = CreateBitMap(); } else { this.bitmap = CreateBitmapOffSize(); } // finally, save this list! this.imageListData = rawImage; }
private void FromStream(Stream stream) { int index; this.header = new PixelMapHeader(); int headerItemCount = 0; BinaryReader binReader = new BinaryReader(stream); try { //1. Read the Header. while (headerItemCount < 4) { char nextChar = (char)binReader.PeekChar(); if (nextChar == '#') // comment { while (binReader.ReadChar() != '\n') ; // ignore the rest of the line. } else if (Char.IsWhiteSpace(nextChar)) // whitespace { binReader.ReadChar(); // ignore whitespace } else { switch (headerItemCount) { case 0: // next item is Magic Number // Read the first 2 characters and determine the type of pixelmap. char[] chars = binReader.ReadChars(2); this.header.MagicNumber = chars[0].ToString() + chars[1].ToString(); headerItemCount++; break; case 1: // next item is the width. this.header.Width = ReadValue(binReader); headerItemCount++; break; case 2: // next item is the height. this.header.Height = ReadValue(binReader); headerItemCount++; break; case 3: // next item is the depth. if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P4") { // no depth value for PBM type. headerItemCount++; } else { this.header.Depth = ReadValue(binReader); headerItemCount++; } break; default: throw new Exception("Error parsing the file header."); } } } // 2. Read the image data. // 2.1 Size the imageData array to hold the image bytes. switch (this.header.MagicNumber) { case "P1": // 1 byte per pixel this.pixelFormat = PixelFormat.Format8bppIndexed; this.bytesPerPixel = 1; break; case "P2": // 1 byte per pixel this.pixelFormat = PixelFormat.Format8bppIndexed; this.bytesPerPixel = 1; break; case "P3": // 3 bytes per pixel this.pixelFormat = PixelFormat.Format24bppRgb; this.bytesPerPixel = 3; break; case "P4": throw new Exception("Binary .pbm (Magic Number P4) is not supported at this time."); case "P5": // 1 byte per pixel this.pixelFormat = PixelFormat.Format8bppIndexed; this.bytesPerPixel = 1; break; case "P6": // 3 bytes per pixel this.pixelFormat = PixelFormat.Format24bppRgb; this.bytesPerPixel = 3; break; default: throw new Exception("Unknown Magic Number: " + this.header.MagicNumber); } this.imageData = new byte[this.header.Width * this.header.Height * this.bytesPerPixel]; this.stride = this.header.Width * this.bytesPerPixel; //while ((this.stride % 4) != 0) //{ // this.stride++; //} if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P2" | this.header.MagicNumber == "P3") // ASCII Encoding { int charsLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); char[] charData = binReader.ReadChars(charsLeft); // read all the data into an array in one go, for efficiency. string valueString = string.Empty; index = 0; for (int i = 0; i < charData.Length; i++) { if (Char.IsWhiteSpace(charData[i])) // value is ignored if empty, or converted to byte and added to array otherwise. { if (valueString != string.Empty) { this.imageData[index] = (byte)int.Parse(valueString); valueString = string.Empty; index++; } } else // add the character to the end of the valueString. { valueString += charData[i]; } } } else // binary encoding. { int bytesLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); this.imageData = binReader.ReadBytes(bytesLeft); } // 3. We need to change the byte order of this.imageData from BGR to RGB. ReorderBGRtoRGB(); // 4. Create the BitMap if (this.stride % 4 == 0) { this.bitmap = CreateBitMap(); } else { this.bitmap = CreateBitmapOffSize(); } // 5. Rotate the BitMap by 180 degrees so it is in the same orientation as the original image. this.bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); } // If the end of the stream is reached before reading all of the expected values raise an exception. catch (EndOfStreamException e) { Console.WriteLine(e.Message); throw new Exception("Error reading the stream! ", e); } catch (Exception ex) { Console.WriteLine(ex.Message); throw new Exception("Error reading the stream! ", ex); } finally { binReader.Close(); } }
private void FromStream(Stream stream) { int index; this.header = new PixelMapHeader(); int headerItemCount = 0; BinaryReader binReader = new BinaryReader(stream); try { while (headerItemCount < 4) { char nextChar = (char)binReader.PeekChar(); if (nextChar == '#') { while (binReader.ReadChar() != '\n') { ; } } else if (Char.IsWhiteSpace(nextChar)) { binReader.ReadChar(); } else { switch (headerItemCount) { case 0: // next item is Magic Number char[] chars = binReader.ReadChars(2); this.header.MagicNumber = chars[0].ToString() + chars[1].ToString(); headerItemCount++; break; case 1: // next item is the width. this.header.Width = ReadValue(binReader); headerItemCount++; break; case 2: // next item is the height. this.header.Height = ReadValue(binReader); headerItemCount++; break; case 3: // next item is the depth. if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P4") { headerItemCount++; } else { this.header.Depth = ReadValue(binReader); headerItemCount++; } break; default: throw new Exception("Error parsing the file header."); } } } switch (this.header.MagicNumber) { case "P1": // 1 byte per pixel this.BytesPerPixel = 1; break; case "P2": // 1 byte per pixel this.BytesPerPixel = 1; break; case "P3": // 3 bytes per pixel this.BytesPerPixel = 3; break; case "P4": throw new Exception("Binary .pbm (Magic Number P4) is not supported at this time."); case "P5": // 1 byte per pixel this.BytesPerPixel = 1; break; case "P6": // 3 bytes per pixel this.BytesPerPixel = 3; break; default: throw new Exception("Unknown Magic Number: " + this.header.MagicNumber); } this.ImageData = new byte[this.header.Width * this.header.Height * this.BytesPerPixel]; if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P2" | this.header.MagicNumber == "P3") // ASCII Encoding { int charsLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); char[] charData = binReader.ReadChars(charsLeft); string valueString = string.Empty; index = 0; for (int i = 0; i < charData.Length; i++) { if (Char.IsWhiteSpace(charData[i])) { if (valueString != string.Empty) { this.ImageData[index] = (byte)int.Parse(valueString); valueString = string.Empty; index++; } } else { valueString += charData[i]; } } } else { int bytesLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); this.ImageData = binReader.ReadBytes(bytesLeft); } } catch (EndOfStreamException e) { Console.WriteLine(e.Message); throw new Exception("Error reading the stream! ", e); } catch (Exception ex) { Console.WriteLine(ex.Message); throw new Exception("Error reading the stream! ", ex); } finally { binReader.Close(); } }
private void FromStream(Stream stream) { int index; this.header = new PixelMapHeader(); int headerItemCount = 0; BinaryReader binReader = new BinaryReader(stream); try { //1. Read the Header. while (headerItemCount < 4) { char nextChar = (char)binReader.PeekChar(); if (nextChar == '#') // comment { while (binReader.ReadChar() != '\n') ; // ignore the rest of the line. } else if (Char.IsWhiteSpace(nextChar)) // whitespace { binReader.ReadChar(); // ignore whitespace } else { switch (headerItemCount) { case 0: // next item is Magic Number // Read the first 2 characters and determine the type of pixelmap. char[] chars = binReader.ReadChars(2); this.header.MagicNumber = chars[0].ToString() + chars[1].ToString(); headerItemCount++; break; case 1: // next item is the width. this.header.Width = ReadValue(binReader); headerItemCount++; break; case 2: // next item is the height. this.header.Height = ReadValue(binReader); headerItemCount++; break; case 3: // next item is the depth. if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P4") { // no depth value for PBM type. headerItemCount++; } else { this.header.Depth = ReadValue(binReader); headerItemCount++; } break; default: throw new Exception("Error parsing the file header."); } } } // 2. Read the image data. // 2.1 Size the imageData array to hold the image bytes. switch (this.header.MagicNumber) { case "P3": // 3 bytes per pixel this.pixelFormat = PixelFormat.Format24bppRgb; this.bytesPerPixel = 3; break; default: throw new Exception("Unknown Magic Number: " + this.header.MagicNumber); } this.rawImageData = new byte[this.header.Width * this.header.Height * this.bytesPerPixel]; this.stride = this.header.Width * this.bytesPerPixel; System.Diagnostics.Debug.Assert(this.header.MagicNumber == "P3"); // ASCII Encoding { int charsLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); char[] charData = binReader.ReadChars(charsLeft); // read all the data into an array in one go, for efficiency. string valueString = string.Empty; index = 0; for (int i = 0; i < charData.Length; i++) { if (Char.IsWhiteSpace(charData[i])) // value is ignored if empty, or converted to byte and added to array otherwise. { if (valueString != string.Empty) { this.rawImageData[index] = (byte)int.Parse(valueString); valueString = string.Empty; index++; } } else // add the character to the end of the valueString. { valueString += charData[i]; } } } // 3. Create the BitMap if (this.stride % 4 == 0) { this.bitmap = CreateBitMap(); } else { this.bitmap = CreateBitmapOffSize(); } } // If the end of the stream is reached before reading all of the expected values raise an exception. catch (EndOfStreamException e) { Console.WriteLine(e.Message); throw new Exception("Error reading the stream! ", e); } catch (Exception ex) { Console.WriteLine(ex.Message); throw new Exception("Error reading the stream! ", ex); } finally { binReader.Close(); } }
/// <summary> /// List-based constructor. /// </summary> /// <param name="rawImage">Is an F#-based list of lists, one list per row.</param> public PixelMap(FSharpList<FSharpList<int>> rawImage) { // format info for "P3" PPM images: this.pixelFormat = PixelFormat.Format24bppRgb; this.bytesPerPixel = 3; // get info for this image and store in header: PixelMapHeader hdr = new PixelMapHeader(); hdr.MagicNumber = "P3"; hdr.Depth = 255; // we are assuming "P3" PPM image files; hdr.Height = rawImage.Length; // height = # of rows of data; hdr.Width = rawImage.Head.Length / this.bytesPerPixel; // width is # of PIXELS per row System.Diagnostics.Debug.Assert(rawImage.Head.Length % this.bytesPerPixel == 0); this.Header = hdr; // stride is # of color values per row, for P3 this is width * bytesPerPixel: this.stride = hdr.Width * this.bytesPerPixel; // allocate and initialize raw data for image: this.rawImageData = new byte[hdr.Height * this.stride]; int i = 0; // index into image data array: foreach (FSharpList<int> row in rawImage) foreach (int color in row) rawImageData[i++] = (byte)color; System.Diagnostics.Debug.Assert(i == this.rawImageData.Length); // create bitmap for display: if (this.stride % 4 == 0) { this.bitmap = CreateBitMap(); } else { this.bitmap = CreateBitmapOffSize(); } // finally, save this list! this.imageListData = rawImage; }