示例#1
0
        private NetpbmImage <TPixelComponent> CorrectOrderBA <TPixelComponent>(NetpbmImage <TPixelComponent> image)
        {
            Contract.Requires(image.Header.Components.Count == 2);
            Contract.Requires(image.Header.Components.Contains(Component.Black));
            Contract.Requires(image.Header.Components.Contains(Component.Alpha));

            return(CorrectOrder(new[] { Component.Black, Component.Alpha }, image));
        }
示例#2
0
        private NetpbmImage <TPixelComponent> CorrectOrderRGB <TPixelComponent>(NetpbmImage <TPixelComponent> image)
        {
            Contract.Requires(image.Header.Components.Count == 3);
            Contract.Requires(image.Header.Components.Contains(Component.Red));
            Contract.Requires(image.Header.Components.Contains(Component.Green));
            Contract.Requires(image.Header.Components.Contains(Component.Blue));

            return(CorrectOrder(new[] { Component.Red, Component.Green, Component.Blue }, image));
        }
示例#3
0
        private NetpbmImage <TPixelComponent> CorrectOrderCMYK <TPixelComponent>(NetpbmImage <TPixelComponent> image)
        {
            Contract.Requires(image.Header.Components.Count == 4);
            Contract.Requires(image.Header.Components.Contains(Component.Cyan));
            Contract.Requires(image.Header.Components.Contains(Component.Magenta));
            Contract.Requires(image.Header.Components.Contains(Component.Yellow));
            Contract.Requires(image.Header.Components.Contains(Component.Black));

            return(CorrectOrder(new[] { Component.Cyan, Component.Magenta, Component.Yellow, Component.Black }, image));
        }
示例#4
0
        /// <summary>
        /// Encodes up to eight bitmap values into a byte. The values are stored from the most significant bit downward,
        /// i.e. the leftmost value is stored in the most significant bit.
        /// </summary>
        /// <returns>The bitmap pixels encoded into a byte.</returns>
        /// <param name="image">The image being encoded.</param>
        /// <param name="pixels">The bitmap pixels to encode into a byte.</param>
        /// <typeparam name="TPixelComponent">The type of the pixel component.</typeparam>
        private byte EncodeBitmapValuesIntoByte <TPixelComponent>(NetpbmImage <TPixelComponent> image, IList <TPixelComponent> pixels)
        {
            Contract.Assert(pixels.Count > 0 && pixels.Count < 9);

            byte theByte = 0;

            // earliest value = most significant bit
            for (int i = 0; i < 8; ++i)
            {
                if (!image.IsComponentValueZero(pixels[i]))
                {
                    theByte |= (byte)(1 << (7 - i));
                }
            }

            return(theByte);
        }
示例#5
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));
        }
示例#6
0
        private IEnumerable <TPixelComponent> InvertRowComponent <TPixelComponent>(IEnumerable <TPixelComponent> row,
                                                                                   NetpbmImage <TPixelComponent> image, HashSet <int> componentIndices, Component from, Component to)
        {
            var componentCount = image.Header.Components.Count;
            var oldRowPixels   = row.Batch(componentCount);

            foreach (var oldPixel in oldRowPixels)
            {
                var oldPixelArray = oldPixel.ToArray();
                for (int c = 0; c < componentCount; ++c)
                {
                    if (componentIndices.Contains(c))
                    {
                        yield return(image.InvertPixelValue(oldPixelArray[c]));
                    }
                    else
                    {
                        yield return(oldPixelArray[c]);
                    }
                }
            }
        }
示例#7
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));
        }
示例#8
0
        /// <summary>
        /// Writes a row of image data into the stream in the given format.
        /// </summary>
        /// <param name="image">The image whose row is being encoded (for formatting purposes).</param>
        /// <param name="row">The row to write.</param>
        /// <param name="stream">The stream to write into.</param>
        /// <param name="type">The format according to which to write.</param>
        public void WriteImageRow <TPixelComponent>(NetpbmImage <TPixelComponent> image, IEnumerable <TPixelComponent> row, Stream stream, ImageType type)
        {
            using (var writer = new NetpbmBinaryWriter(stream, new UTF8Encoding(false, true), leaveOpen: true))
            {
                bool isPlain;
                switch (type)
                {
                case ImageType.PBM:
                case ImageType.PGM:
                case ImageType.PPM:
                case ImageType.PAM:
                case ImageType.BigPAM:
                    isPlain = false;
                    break;

                case ImageType.PlainPBM:
                case ImageType.PlainPGM:
                case ImageType.PlainPPM:
                    isPlain = true;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("type", type, "unknown image type");
                }

                if (isPlain)
                {
                    // output row as decimal numbers
                    // add a newline after the row to make things nicer

                    foreach (var value in row)
                    {
                        writer.WriteUnprefixed(value.ToString());
                        writer.Write(' ');
                    }
                    writer.Write('\n');
                }
                else if (type == ImageType.PBM)
                {
                    // special case: bit-packed format!
                    var values = new List <TPixelComponent>(8);
                    foreach (var value in row)
                    {
                        values.Add(value);

                        if (values.Count == 8)
                        {
                            byte theByte = EncodeBitmapValuesIntoByte(image, values);
                            writer.Write(theByte);
                            values.Clear();
                        }
                    }

                    if (values.Count != 0)
                    {
                        byte theByte = EncodeBitmapValuesIntoByte(image, values);
                        writer.Write(theByte);
                    }
                }
                else
                {
                    // just the big endian bytes
                    foreach (var value in row)
                    {
                        writer.Write(image.ComponentToBigEndianBytes(value).ToArray());
                    }
                }
            }
        }
示例#9
0
        /// <summary>
        /// Writes the image data into the stream in the given format.
        /// </summary>
        /// <param name="image">The image whose data to write.</param>
        /// <param name="stream">The stream into which to write the data.</param>
        /// <param name="type">The type of Netpbm image according to which to encode the data.</param>
        /// <typeparam name="TPixelComponent">The type of pixel component values.</typeparam>
        public void WriteImageData <TPixelComponent>(NetpbmImage <TPixelComponent> image, Stream stream, ImageType type)
        {
            // check if the format is supported
            var supportedTypes = SupportedTypesForImage(image);

            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))
            {
                bool isPlain;
                switch (type)
                {
                case ImageType.PBM:
                case ImageType.PGM:
                case ImageType.PPM:
                case ImageType.PAM:
                case ImageType.BigPAM:
                    isPlain = false;
                    break;

                case ImageType.PlainPBM:
                case ImageType.PlainPGM:
                case ImageType.PlainPPM:
                    isPlain = true;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("type", type, "unknown image type");
                }

                if (isPlain)
                {
                    // output in row-major order as decimal numbers
                    // add newlines after each row to make things nicer

                    foreach (var row in image.NativeRows)
                    {
                        foreach (var value in row)
                        {
                            writer.WriteUnprefixed(value.ToString());
                            writer.Write(' ');
                        }
                        writer.Write('\n');
                    }
                }
                else if (type == ImageType.PBM)
                {
                    // special case: bit-packed format!
                    var values = new List <TPixelComponent>(8);
                    foreach (var row in image.NativeRows)
                    {
                        foreach (var value in row)
                        {
                            values.Add(value);

                            if (values.Count == 8)
                            {
                                byte theByte = EncodeBitmapValuesIntoByte(image, values);
                                writer.Write(theByte);
                                values.Clear();
                            }
                        }

                        if (values.Count != 0)
                        {
                            byte theByte = EncodeBitmapValuesIntoByte(image, values);
                            writer.Write(theByte);
                        }
                    }
                }
                else
                {
                    // just the big endian bytes
                    foreach (var row in image.NativeRows)
                    {
                        foreach (var value in row)
                        {
                            writer.Write(image.ComponentToBigEndianBytes(value).ToArray());
                        }
                    }
                }
            }
        }
示例#10
0
 /// <summary>
 /// Returns the set of Netpbm image types into which the given image can be encoded.
 /// </summary>
 /// <returns>The Netpbm image types the given image can be encoded into.</returns>
 /// <param name="img">The image to be encoded.</param>
 /// <typeparam name="TPixelComponent">The pixel component type of the image.</typeparam>
 public ISet <ImageType> SupportedTypesForImage <TPixelComponent>(NetpbmImage <TPixelComponent> img)
 {
     return(SupportedTypesForHeader(img.Header));
 }
示例#11
0
 /// <summary>
 /// Writes the image into the stream in the given format.
 /// </summary>
 /// <param name="image">The image to write.</param>
 /// <param name="stream">The stream into which to write the image.</param>
 /// <param name="type">The type of Netpbm image into which to encode the image.</param>
 /// <typeparam name="TPixelComponent">The type of pixel component values.</typeparam>
 public void WriteImage <TPixelComponent>(NetpbmImage <TPixelComponent> image, Stream stream, ImageType type)
 {
     WriteImageHeader(image.Header, stream, type);
     WriteImageData(image, stream, type);
 }
示例#12
0
        /// <summary>
        /// Returns a new image which is the given image converted to a canonical form.
        /// </summary>
        /// <typeparam name="TPixelComponent">The pixel component type being used.</typeparam>
        /// <param name="image">The image whose canonical form to return.</param>
        /// <param name="grayscaleConversion">Whether to perform grayscale conversion and what kind.</param>
        /// <returns>The new image, in canonical form.</returns>
        public NetpbmImage <TPixelComponent> Canonicalize <TPixelComponent>(NetpbmImage <TPixelComponent> image,
                                                                            GrayscaleConversion grayscaleConversion = GrayscaleConversion.None)
        {
            var ret = image.NewImageOfSameType(image.Header, image.NativeRows);

            // perform grayscale conversion if necessary
            if (grayscaleConversion == GrayscaleConversion.BlackToWhite && image.Header.Components.Contains(Component.Black))
            {
                ret = InvertComponent(ret, Component.Black, Component.White);
            }
            else if (grayscaleConversion == GrayscaleConversion.WhiteToBlack && image.Header.Components.Contains(Component.White))
            {
                ret = InvertComponent(ret, Component.White, Component.Black);
            }

            // canonicalize order
            if (
                ret.Header.Components.Count == 3 &&
                ret.Header.Components.Contains(Component.Red) &&
                ret.Header.Components.Contains(Component.Green) &&
                ret.Header.Components.Contains(Component.Blue)
                )
            {
                ret = CorrectOrderRGB(ret);
            }
            else if (
                ret.Header.Components.Count == 4 &&
                ret.Header.Components.Contains(Component.Red) &&
                ret.Header.Components.Contains(Component.Green) &&
                ret.Header.Components.Contains(Component.Blue) &&
                ret.Header.Components.Contains(Component.Alpha)
                )
            {
                ret = CorrectOrderRGBA(ret);
            }
            else if (
                ret.Header.Components.Count == 2 &&
                ret.Header.Components.Contains(Component.White) &&
                ret.Header.Components.Contains(Component.Alpha)
                )
            {
                ret = CorrectOrderWA(ret);
            }
            else if (
                ret.Header.Components.Count == 2 &&
                ret.Header.Components.Contains(Component.Black) &&
                ret.Header.Components.Contains(Component.Alpha)
                )
            {
                ret = CorrectOrderBA(ret);
            }
            else if (
                ret.Header.Components.Count == 4 &&
                ret.Header.Components.Contains(Component.Cyan) &&
                ret.Header.Components.Contains(Component.Magenta) &&
                ret.Header.Components.Contains(Component.Yellow) &&
                ret.Header.Components.Contains(Component.Black)
                )
            {
                ret = CorrectOrderCMYK(ret);
            }
            else if (
                ret.Header.Components.Count == 5 &&
                ret.Header.Components.Contains(Component.Cyan) &&
                ret.Header.Components.Contains(Component.Magenta) &&
                ret.Header.Components.Contains(Component.Yellow) &&
                ret.Header.Components.Contains(Component.Black) &&
                ret.Header.Components.Contains(Component.Alpha)
                )
            {
                ret = CorrectOrderCMYKA(ret);
            }

            return(ret);
        }