private IEnumerable <IEnumerable <TPixelFormat> > ReadPBMData <TPixelFormat>(Stream stream, NetpbmHeader <TPixelFormat> header, IImageFactory <TPixelFormat> imageFactory) { // read the bits! if (header.ImageType == ImageType.PBM) { for (int r = 0; r < header.Height; ++r) { yield return(ReadBinaryPBMRow(stream, header.Width, imageFactory)); } } else if (header.ImageType == ImageType.PlainPBM) { for (int r = 0; r < header.Height; ++r) { yield return(ReadPlainRow(stream, header.Width, r == header.Height - 1, imageFactory)); } } else { throw new ArgumentOutOfRangeException("header.ImageType", header.ImageType, "image type unsupported by this method"); } /*return imageFactory.MakeImage(width, height, imageFactory.BitmapOnPixelComponentValue, * new[] {Component.Black}, rows);*/ }
public NetpbmImage <byte> MakeImage(NetpbmHeader <byte> header, IEnumerable <IEnumerable <byte> > pixelData) { Exception exception; try { return(new NetpbmImage8(header, pixelData)); } catch (ArgumentOutOfRangeException exc) { exception = exc; } catch (OverflowException exc) { exception = exc; } throw new InvalidDataException("invalid image format", exception); }
/// <summary> /// Returns the set of Netpbm image types into which the image with the given header can be encoded. /// </summary> /// <returns>The Netpbm image types an image with the given header can be encoded into.</returns> /// <param name="header">The header of the image to be encoded.</param> /// <typeparam name="TPixelComponent">The pixel component type of the image.</typeparam> public ISet <ImageType> SupportedTypesForHeader <TPixelComponent>(NetpbmHeader <TPixelComponent> header) { // big PAM is always supported var types = new HashSet <ImageType> { ImageType.BigPAM }; if (header.BytesPerPixelComponent > 2) { // all other formats limit pixel values to two bytes per component return(types); } // PAM supports any component types types.Add(ImageType.PAM); // PPM requires RGB if ( header.Components.Count == 3 && header.Components[0] == Component.Red && header.Components[1] == Component.Green && header.Components[2] == Component.Blue ) { types.Add(ImageType.PPM); types.Add(ImageType.PlainPPM); } // PGM requires grayscale (black-to-white) if ( header.Components.Count == 1 && header.Components[0] == Component.White ) { types.Add(ImageType.PGM); types.Add(ImageType.PlainPGM); } return(types); }
/// <summary> /// Returns a new image which is the given image with the components of the given type inverted and changed to /// another type. /// </summary> /// <typeparam name="TPixelComponent">The pixel component type being used.</typeparam> /// <param name="image">The image whose component to invert.</param> /// <param name="from">The component whose values to invert.</param> /// <param name="to">The new component type of the component being inverted.</param> /// <returns>A copy of <paramref name="image"/> where all components of type <paramref name="from"/> are /// inverted and changed to type <paramref name="to"/>.</returns> private NetpbmImage <TPixelComponent> InvertComponent <TPixelComponent>(NetpbmImage <TPixelComponent> image, Component from, Component to) { Contract.Requires(image.Header.Components.Contains(from)); var componentIndices = new HashSet <int>(Enumerable.Range(0, image.Header.Components.Count).Where(i => image.Header.Components[i] == from)); var newRows = image.NativeRows.Select(oldRow => InvertRowComponent(oldRow, image, componentIndices, from, to)); var newComponents = image.Header.Components.Select(c => c == from ? to : c); var header = new NetpbmHeader <TPixelComponent>( image.Header.ImageType, image.Header.Width, image.Header.Height, image.Header.BytesPerPixelComponent, newComponents, image.Header.HighestComponentValue ); return(image.NewImageOfSameType(header, newRows)); }
private NetpbmImage <TPixelComponent> CorrectOrder <TPixelComponent>(IList <Component> requestedOrder, NetpbmImage <TPixelComponent> image) { Contract.Requires(requestedOrder.Count == image.Header.Components.Count); Contract.Requires(ListsContainTheSameElements(requestedOrder, image.Header.Components)); if (requestedOrder.SequenceEqual(image.Header.Components)) { // short-circuit return(image.NewImageOfSameType(image.Header, image.NativeRows)); } var newToOldOrder = new int[requestedOrder.Count]; var currentOrder = new List <int>(image.Header.Components.Select(c => (int)c)); for (int i = 0; i < requestedOrder.Count; ++i) { var index = currentOrder.IndexOf((int)requestedOrder[i]); Debug.Assert(index != -1); newToOldOrder[i] = index; currentOrder[index] = -1; } Debug.Assert(currentOrder.All(o => o == -1)); var newRows = image.NativeRows.Select(originalRow => TransposeComponentOrder(originalRow, image.Header.Width, newToOldOrder)); var newHeader = new NetpbmHeader <TPixelComponent>( image.Header.ImageType, image.Header.Width, image.Header.Height, image.Header.BytesPerPixelComponent, requestedOrder, image.Header.HighestComponentValue ); return(image.NewImageOfSameType(newHeader, newRows)); }
public NetpbmImage32(NetpbmHeader <uint> header, IEnumerable <IEnumerable <uint> > pixelData) : base(header, pixelData) { }
public override NetpbmImage <BigInteger> NewImageOfSameType(NetpbmHeader <BigInteger> header, IEnumerable <IEnumerable <BigInteger> > pixelData) { return(new NetpbmImageBigInteger(header, pixelData)); }
public NetpbmImageBigInteger(NetpbmHeader <BigInteger> header, IEnumerable <IEnumerable <BigInteger> > pixelData) : base(header, pixelData) { }
/// <summary> /// Returns the PAM tuple name and necessary component permutation for images with the given header. /// </summary> /// <param name="header">The header.</param> /// <typeparam name="TPixelComponent">The pixel component type.</typeparam> protected virtual string GetPamTupleType <TPixelComponent>(NetpbmHeader <TPixelComponent> header) { if ( header.Components.Count == 1 && header.Components[0] == Component.White ) { return("GRAYSCALE"); } else if ( header.Components.Count == 2 && header.Components[0] == Component.White && header.Components[1] == Component.Alpha ) { return("GRAYSCALE_ALPHA"); } else if ( header.Components.Count == 3 && header.Components[0] == Component.Red && header.Components[1] == Component.Green && header.Components[2] == Component.Blue ) { return("RGB"); } else if ( header.Components.Count == 4 && header.Components[0] == Component.Red && header.Components[1] == Component.Green && header.Components[2] == Component.Blue && header.Components[3] == Component.Alpha ) { return("RGB_ALPHA"); } else if ( header.Components.Count == 4 && header.Components[0] == Component.Cyan && header.Components[1] == Component.Magenta && header.Components[2] == Component.Yellow && header.Components[3] == Component.Black ) { // "CMYK" is an extension (compatible with GhostScript) return("CMYK"); } else if ( header.Components.Count == 5 && header.Components[0] == Component.Cyan && header.Components[1] == Component.Magenta && header.Components[2] == Component.Yellow && header.Components[3] == Component.Black && header.Components[4] == Component.Alpha ) { // "CMYK_ALPHA" is an extension return("CMYK_ALPHA"); } else { // extension: assemble a custom tuple type return(string.Join("_", header.Components.Select(c => c.ToString().ToUpperInvariant()))); } }
public NetpbmImage8(NetpbmHeader <byte> header, IEnumerable <IEnumerable <byte> > pixelData) : base(header, pixelData) { }
/// <summary> /// Initializes a new Netpbm image. /// </summary> /// <param name="header">The header of the image, containing all necessary information.</param> /// <param name="pixelData">The actual pixel data of the image. Drill down rows to pixels, with the pixels /// represented as a contiguous sequence of component values for each pixel (in pixel-major order, e.g. /// <c>RGBRGBRGB</c>. The data passed to this constructor must not be modified after the constructor /// completes, unless <see cref="LoadData"/> is called.</param> protected NetpbmImage(NetpbmHeader <TPixelComponent> header, IEnumerable <IEnumerable <TPixelComponent> > pixelData) { Header = header; Rows = pixelData; _loaded = false; }
/// <summary> /// Creates and returns a new image of the same type as this image. /// </summary> /// <param name="header">The header of the new image.</param> /// <param name="pixelData">The actual pixel data of the image. Drill down rows to pixels, with the pixels /// represented as a contiguous sequence of component values for each pixel (in pixel-major order, e.g. /// <c>RGBRGBRGB</c>.</param> /// <returns>The new image.</returns> public abstract NetpbmImage <TPixelComponent> NewImageOfSameType(NetpbmHeader <TPixelComponent> header, IEnumerable <IEnumerable <TPixelComponent> > pixelData);
public NetpbmImage <TPixelFormat> ReadImageData <TPixelFormat>(Stream stream, NetpbmHeader <TPixelFormat> header, IImageFactory <TPixelFormat> imageFactory) { IEnumerable <IEnumerable <TPixelFormat> > data; switch (header.ImageType) { case ImageType.PlainPBM: case ImageType.PBM: data = ReadPBMData(stream, header, imageFactory); break; case ImageType.PlainPGM: case ImageType.PGM: case ImageType.PlainPPM: case ImageType.PPM: data = ReadPGMOrPPMData(stream, header, imageFactory); break; case ImageType.PAM: case ImageType.BigPAM: data = ReadPAMData(stream, header, imageFactory); break; default: throw new ArgumentOutOfRangeException("header.ImageType", header.ImageType, "unknown image type"); } return(imageFactory.MakeImage(header, data)); }
private IEnumerable <IEnumerable <TPixelFormat> > ReadPGMOrPPMData <TPixelFormat>(Stream stream, NetpbmHeader <TPixelFormat> header, IImageFactory <TPixelFormat> imageFactory) { // read the bits! if (header.ImageType == ImageType.PGM || header.ImageType == ImageType.PPM) { for (int r = 0; r < header.Height; ++r) { yield return(imageFactory.ReadRow(stream, header.Width, header.Components.Count, header.HighestComponentValue)); } } else if (header.ImageType == ImageType.PlainPGM || header.ImageType == ImageType.PlainPPM) { for (int r = 0; r < header.Height; ++r) { yield return(ReadPlainRow(stream, header.Width * header.Components.Count, r == header.Height - 1, imageFactory)); } } else { throw new ArgumentOutOfRangeException("header.ImageType", header.ImageType, "image type unsupported by this method"); } }
public override NetpbmImage <ushort> NewImageOfSameType(NetpbmHeader <ushort> header, IEnumerable <IEnumerable <ushort> > pixelData) { return(new NetpbmImage16(header, pixelData)); }
public NetpbmImage16(NetpbmHeader <ushort> header, IEnumerable <IEnumerable <ushort> > pixelData) : base(header, pixelData) { }
/// <summary> /// Writes the image header into the stream in the given format. /// </summary> /// <param name="header">The image header to write.</param> /// <param name="stream">The stream into which to write the header.</param> /// <param name="type">The type of Netpbm image according to which to encode the header.</param> /// <typeparam name="TPixelComponent">The type of pixel component values.</typeparam> public void WriteImageHeader <TPixelComponent>(NetpbmHeader <TPixelComponent> header, Stream stream, ImageType type) { // check if the format is supported var supportedTypes = SupportedTypesForHeader(header); if (!supportedTypes.Contains(type)) { throw new ArgumentOutOfRangeException("type", type, "the image cannot be encoded into this type"); } using (var writer = new NetpbmBinaryWriter(stream, new UTF8Encoding(false, true), leaveOpen: true)) { int magicNumber = (int)type; switch (type) { case ImageType.PBM: case ImageType.PGM: case ImageType.PPM: case ImageType.PAM: case ImageType.PlainPBM: case ImageType.PlainPGM: case ImageType.PlainPPM: break; case ImageType.BigPAM: magicNumber = (int)ImageType.PAM; break; default: throw new ArgumentOutOfRangeException("type", type, "unknown image type"); } // output the magic writer.WriteUnprefixed("P{0}\n", magicNumber); if (type == ImageType.PAM || type == ImageType.BigPAM) { // output width line writer.WriteUnprefixed("WIDTH {0}\n", header.Width); // output height line writer.WriteUnprefixed("HEIGHT {0}\n", header.Height); // output number of components writer.WriteUnprefixed("DEPTH {0}\n", header.Components.Count); // maximum value writer.WriteUnprefixed("MAXVAL {0}\n", header.HighestComponentValue); // find the components we are working with writer.WriteUnprefixed("TUPLTYPE {0}\n", GetPamTupleType(header)); writer.WriteUnprefixed("ENDHDR\n"); } else { // output width and height writer.WriteUnprefixed("{0} {1}\n", header.Width, header.Height); // unless PBM (where the max value is always 1) if (type != ImageType.PBM && type != ImageType.PlainPBM) { // output the max value writer.WriteUnprefixed("{0}\n", header.HighestComponentValue); } // the header's final newline writer.Write('\n'); } } }
public override NetpbmImage <byte> NewImageOfSameType(NetpbmHeader <byte> header, IEnumerable <IEnumerable <byte> > pixelData) { return(new NetpbmImage8(header, pixelData)); }
private IEnumerable <IEnumerable <TPixelFormat> > ReadPAMData <TPixelFormat>(Stream stream, NetpbmHeader <TPixelFormat> header, IImageFactory <TPixelFormat> imageFactory) { // read the data! for (int r = 0; r < header.Height; ++r) { yield return(imageFactory.ReadRow(stream, header.Width, header.Components.Count, header.HighestComponentValue)); } }