コード例 #1
0
        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);*/
        }
コード例 #2
0
            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);
            }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        /// <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));
        }
コード例 #5
0
        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));
        }
コード例 #6
0
 public NetpbmImage32(NetpbmHeader <uint> header, IEnumerable <IEnumerable <uint> > pixelData)
     : base(header, pixelData)
 {
 }
コード例 #7
0
 public override NetpbmImage <BigInteger> NewImageOfSameType(NetpbmHeader <BigInteger> header,
                                                             IEnumerable <IEnumerable <BigInteger> > pixelData)
 {
     return(new NetpbmImageBigInteger(header, pixelData));
 }
コード例 #8
0
 public NetpbmImageBigInteger(NetpbmHeader <BigInteger> header, IEnumerable <IEnumerable <BigInteger> > pixelData)
     : base(header, pixelData)
 {
 }
コード例 #9
0
 /// <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())));
     }
 }
コード例 #10
0
 public NetpbmImage8(NetpbmHeader <byte> header, IEnumerable <IEnumerable <byte> > pixelData)
     : base(header, pixelData)
 {
 }
コード例 #11
0
 /// <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;
 }
コード例 #12
0
 /// <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);
コード例 #13
0
        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));
        }
コード例 #14
0
 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");
     }
 }
コード例 #15
0
 public override NetpbmImage <ushort> NewImageOfSameType(NetpbmHeader <ushort> header,
                                                         IEnumerable <IEnumerable <ushort> > pixelData)
 {
     return(new NetpbmImage16(header, pixelData));
 }
コード例 #16
0
 public NetpbmImage16(NetpbmHeader <ushort> header, IEnumerable <IEnumerable <ushort> > pixelData)
     : base(header, pixelData)
 {
 }
コード例 #17
0
        /// <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');
                }
            }
        }
コード例 #18
0
 public override NetpbmImage <byte> NewImageOfSameType(NetpbmHeader <byte> header,
                                                       IEnumerable <IEnumerable <byte> > pixelData)
 {
     return(new NetpbmImage8(header, pixelData));
 }
コード例 #19
0
 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));
     }
 }