예제 #1
0
        public static Stream CreateBrokenImage(ProcessImageSettings s)
        {
            s.Fixup(s.Width > 0 ? s.Width : s.Height, s.Height > 0 ? s.Height : s.Width);
            if (s.Width <= 0)
            {
                s.Height = s.Width = 100;
            }

            using (var bmp = new Bitmap(s.Width, s.Height, PixelFormat.Format24bppRgb))
                using (var gfx = Graphics.FromImage(bmp))
                    using (var pen = new Pen(Brushes.White, 1.75f))
                        using (var ms = new MemoryStream(8192))
                        {
                            gfx.FillRectangle(Brushes.Gainsboro, Rectangle.FromLTRB(0, 0, s.Width, s.Height));
                            gfx.SmoothingMode      = SmoothingMode.AntiAlias;
                            gfx.PixelOffsetMode    = PixelOffsetMode.Half;
                            gfx.CompositingQuality = CompositingQuality.GammaCorrected;

                            float l = 0.5f, t = 0.5f, r = s.Width - 0.5f, b = s.Height - 0.5f;
                            gfx.DrawLines(pen, new PointF[] { new PointF(l, t), new PointF(r, b), new PointF(l, b), new PointF(r, t) });
                            gfx.DrawLines(pen, new PointF[] { new PointF(l, b), new PointF(l, t), new PointF(r, t), new PointF(r, b) });
                            bmp.Save(ms, ImageFormat.Png);

                            ms.Seek(0, SeekOrigin.Begin);
                            return(ms);
                        }
        }
예제 #2
0
        private static void createBrokenImage(Stream ostm, ProcessImageSettings s)
        {
            s = s.Clone();
            if (s.Width == 0 && s.Height == 0)
            {
                s.Height = s.Width = 100;
            }

            s.Fixup(s.Width > 0 ? s.Width : s.Height, s.Height > 0 ? s.Height : s.Width);

            using var bmp = new Bitmap(s.Width, s.Height, GdiPixelFormat.Format24bppRgb);
            using var gfx = Graphics.FromImage(bmp);
            using var pen = new Pen(Brushes.White, 1.75f);

            gfx.FillRectangle(Brushes.Gainsboro, new Rectangle(0, 0, s.Width, s.Height));
            gfx.SmoothingMode      = SmoothingMode.AntiAlias;
            gfx.PixelOffsetMode    = PixelOffsetMode.Half;
            gfx.CompositingQuality = CompositingQuality.GammaCorrected;

            float l = 0.5f, t = 0.5f, r = s.Width - 0.5f, b = s.Height - 0.5f;

            gfx.DrawLines(pen, new[] { new PointF(l, t), new PointF(r, b), new PointF(l, b), new PointF(r, t) });
            gfx.DrawLines(pen, new[] { new PointF(l, b), new PointF(l, t), new PointF(r, t), new PointF(r, b) });
            bmp.Save(ostm, ImageFormat.Png);
        }
        public static void ProcessImage(Stream istm, Stream ostm, ProcessImageSettings s)
        {
            if (istm == null)
            {
                throw new ArgumentNullException(nameof(istm));
            }
            if (ostm == null)
            {
                throw new ArgumentNullException(nameof(ostm));
            }
            if (!istm.CanSeek || !istm.CanRead)
            {
                throw new ArgumentException("Input Stream must allow Seek and Read", nameof(istm));
            }
            if (!ostm.CanSeek || !ostm.CanWrite)
            {
                throw new ArgumentException("Output Stream must allow Seek and Write", nameof(ostm));
            }
            if (istm.Length <= 0 || istm.Position >= istm.Length)
            {
                throw new ArgumentException("Input Stream is empty or positioned at its end", nameof(istm));
            }

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(istm, ctx))
                    processImage(dec, ctx, ostm);
        }
예제 #4
0
 /// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" />
 /// <param name="imgContainer">A custom <see cref="IImageContainer"/> to use as input.</param>
 public static ProcessingPipeline BuildPipeline(IImageContainer imgContainer, ProcessImageSettings settings)
 {
     if (imgContainer is null)
     {
         throw new ArgumentNullException(nameof(imgContainer));
     }
     if (settings is null)
         throw new ArgumentNullException(nameof(settings)); }
예제 #5
0
        public static void ProcessImage(byte[] imgBuffer, Stream ostm, ProcessImageSettings s)
        {
            Contract.Requires <ArgumentNullException>(imgBuffer != null, nameof(imgBuffer));
            Contract.Requires <ArgumentNullException>(ostm != null, nameof(ostm));
            Contract.Requires <ArgumentException>(ostm.CanSeek && ostm.CanWrite, "Output Stream must allow Seek and Write");

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(imgBuffer, ctx))
                    processImage(dec, ctx, ostm);
        }
예제 #6
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgStream">A stream containing a supported input image container.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings)
        {
            checkInStream(imgStream);

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgStream, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #7
0
        /// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" />
        /// <param name="imgStream">A stream containing a supported input image container. The stream must allow Seek and Read.</param>
        public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings)
        {
            checkInStream(imgStream);

            var ctx = new PipelineContext(settings);

            ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #8
0
        public static void ProcessImage(Stream istm, Stream ostm, ProcessImageSettings s)
        {
            Contract.Requires <ArgumentNullException>(istm != null, nameof(istm));
            Contract.Requires <ArgumentNullException>(ostm != null, nameof(ostm));
            Contract.Requires <ArgumentException>(istm.CanSeek && istm.CanRead, "Input Stream must allow Seek and Read");
            Contract.Requires <ArgumentException>(ostm.CanSeek && ostm.CanWrite, "Output Stream must allow Seek and Write");
            Contract.Assume(istm.Position < istm.Length, "Input Stream Position is at the end.  Did you forget to Seek?");

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(istm, ctx))
                    processImage(dec, ctx, ostm);
        }
예제 #9
0
        public static ProcessingPipeline BuildPipeline(string imgPath, ProcessImageSettings settings)
        {
            if (imgPath == null)
            {
                throw new ArgumentNullException(nameof(imgPath));
            }

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgPath, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #10
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgSource">A custom pixel source to use as input.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(IPixelSource imgSource, ProcessImageSettings settings)
        {
            if (imgSource is null)
            {
                throw new ArgumentNullException(nameof(imgSource));
            }

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgSource, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #11
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgPath">The path to a file containing the input image.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(string imgPath, ProcessImageSettings settings)
        {
            if (imgPath is null)
            {
                throw new ArgumentNullException(nameof(imgPath));
            }

            var ctx = new PipelineContext(settings);

            ctx.ImageContainer = WicImageContainer.Create(imgPath, ctx.WicContext);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #12
0
        /// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" />
        /// <param name="imgStream">A stream containing a supported input image container. The stream must allow Seek and Read.</param>
        public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings)
        {
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            checkInStream(imgStream);

            var ctx = new PipelineContext(settings);

            ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #13
0
        /// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" />
        /// <param name="imgContainer">A custom <see cref="IImageContainer"/> to use as input.</param>
        public static ProcessingPipeline BuildPipeline(IImageContainer imgContainer, ProcessImageSettings settings)
        {
            if (imgContainer is null)
            {
                throw new ArgumentNullException(nameof(imgContainer));
            }

            var ctx = new PipelineContext(settings)
            {
                ImageContainer = imgContainer
            };

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #14
0
        /// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" />
        /// <param name="imgSource">A custom pixel source to use as input.</param>
        public static ProcessingPipeline BuildPipeline(IPixelSource imgSource, ProcessImageSettings settings)
        {
            if (imgSource is null)
            {
                throw new ArgumentNullException(nameof(imgSource));
            }

            var ctx = new PipelineContext(settings)
            {
                ImageContainer = new PixelSourceContainer(imgSource),
                Source         = imgSource.AsPixelSource()
            };

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
        public static void ProcessImage(byte[] imgBuffer, Stream ostm, ProcessImageSettings s)
        {
            if (imgBuffer == null)
            {
                throw new ArgumentNullException(nameof(imgBuffer));
            }
            if (ostm == null)
            {
                throw new ArgumentNullException(nameof(ostm));
            }
            if (!ostm.CanSeek || !ostm.CanWrite)
            {
                throw new ArgumentException("Output Stream must allow Seek and Write", nameof(ostm));
            }

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(imgBuffer, ctx))
                    processImage(dec, ctx, ostm);
        }
예제 #16
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgPath">The path to a file containing the input image.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(string imgPath, ProcessImageSettings settings)
        {
            if (imgPath is null)
            {
                throw new ArgumentNullException(nameof(imgPath));
            }
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            var ctx = new PipelineContext(settings);

            var fs = ctx.AddDispose(File.OpenRead(imgPath));

            ctx.AddDispose(new StreamBufferInjector(fs));
            ctx.ImageContainer = ctx.AddDispose(WicImageDecoder.Load(fs));

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #17
0
        internal static Image HybridScale(this Image img, ProcessImageSettings s, InterpolationMode mode)
        {
            if (s.HybridScaleRatio == 1 || (mode != InterpolationMode.HighQualityBicubic && mode != InterpolationMode.HighQualityBilinear))
            {
                return(img);
            }

            int intw = (int)Math.Ceiling((double)img.Width / s.HybridScaleRatio);
            int inth = (int)Math.Ceiling((double)img.Height / s.HybridScaleRatio);

            var bmp = new Bitmap(intw, inth);

            using (var gfx = Graphics.FromImage(bmp))
            {
                gfx.PixelOffsetMode = PixelOffsetMode.Half;
                gfx.CompositingMode = CompositingMode.SourceCopy;
                gfx.DrawImage(img, new Rectangle(0, 0, intw, inth), s.Crop.X, s.Crop.Y, s.Crop.Width, s.Crop.Height, GraphicsUnit.Pixel);
            }

            img.Dispose();
            s.Crop = new Rectangle(0, 0, intw, inth);

            return(bmp);
        }
예제 #18
0
 unsafe public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings)
 {
     fixed(byte *pbBuffer = imgBuffer)
     using (var ms = new UnmanagedMemoryStream(pbBuffer, imgBuffer.Length, imgBuffer.Length, FileAccess.Read))
         return(ProcessImage(ms, outStream, settings));
 }
예제 #19
0
 public static ProcessImageResult ProcessImage(string imgPath, Stream outStream, ProcessImageSettings settings)
 {
     using var fs = new FileStream(imgPath, FileMode.Open, FileAccess.Read, FileShare.Read);
     return(ProcessImage(fs, outStream, settings));
 }
예제 #20
0
        private static ProcessImageResult processImage(Stream istm, Stream ostm, ProcessImageSettings s)
        {
            using var img = Image.FromStream(istm, s.ColorProfileMode != ColorProfileMode.Ignore, false);

            if (s.FrameIndex > 0)
            {
                var fd = img.RawFormat.Guid == ImageFormat.Gif.Guid ? FrameDimension.Time : FrameDimension.Page;
                if (img.GetFrameCount(fd) > s.FrameIndex)
                {
                    img.SelectActiveFrame(fd, s.FrameIndex);
                }
                else
                {
                    throw new ArgumentOutOfRangeException(nameof(s), "Invalid Frame Index");
                }
            }

            if (s.OrientationMode == OrientationMode.Normalize)
            {
                img.ExifRotate();
            }

            s = s.Clone();
            s.Fixup(img.Width, img.Height);
            var usedSettings = s.Clone();

            bool alpha       = ((ImageFlags)img.Flags).HasFlag(ImageFlags.HasAlpha);
            var  pixelFormat = alpha && s.MatteColor.IsTransparent() ? GdiPixelFormat.Format32bppArgb : GdiPixelFormat.Format24bppRgb;
            var  mode        = s.Interpolation.WeightingFunction.Support <0.1 ? InterpolationMode.NearestNeighbor :
                                                                          s.Interpolation.WeightingFunction.Support <1.0 ? s.ScaleRatio> 1.0 ? InterpolationMode.Bilinear : InterpolationMode.NearestNeighbor :
                                                                          s.Interpolation.WeightingFunction.Support> 1.0 ? s.ScaleRatio > 1.0 || s.Interpolation.Blur > 1.0 ? InterpolationMode.HighQualityBicubic : InterpolationMode.Bicubic :
                               s.ScaleRatio > 1.0 ? InterpolationMode.HighQualityBilinear : InterpolationMode.Bilinear;

            using var src = img.HybridScale(s, mode);
            using var iat = new ImageAttributes();
            using var bmp = new Bitmap(s.Width, s.Height, pixelFormat);
            using var gfx = Graphics.FromImage(bmp);

            iat.SetWrapMode(WrapMode.TileFlipXY);
            gfx.PixelOffsetMode   = PixelOffsetMode.Half;
            gfx.CompositingMode   = CompositingMode.SourceCopy;
            gfx.InterpolationMode = mode;

            if ((alpha || s.InnerSize != s.OuterSize) && !s.MatteColor.IsEmpty)
            {
                gfx.Clear(s.MatteColor);
                gfx.CompositingMode    = CompositingMode.SourceOver;
                gfx.CompositingQuality = CompositingQuality.GammaCorrected;
            }

            gfx.DrawImage(src, s.InnerRect, s.Crop.X, s.Crop.Y, s.Crop.Width, s.Crop.Height, GraphicsUnit.Pixel, iat);

            switch (s.SaveFormat)
            {
            case FileFormat.Bmp:
                bmp.Save(ostm, ImageFormat.Bmp);
                break;

            case FileFormat.Tiff:
                using (var encoderParams = new EncoderParameters(1))
                    using (var param = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone))
                    {
                        encoderParams.Param[0] = param;
                        bmp.Save(ostm, tiffCodec, encoderParams);
                    }
                break;

            case FileFormat.Jpeg:
                using (var encoderParams = new EncoderParameters(1))
                    using (var param = new EncoderParameter(Encoder.Quality, s.JpegQuality))
                    {
                        encoderParams.Param[0] = param;
                        bmp.Save(ostm, jpegCodec, encoderParams);
                    }
                break;

            default:
                if (s.IndexedColor)
                {
                    bmp.Save(ostm, ImageFormat.Gif);
                }
                else
                {
                    bmp.Save(ostm, ImageFormat.Png);
                }
                break;
            }

            return(new ProcessImageResult(usedSettings, Enumerable.Empty <PixelSourceStats>()));
        }
예제 #21
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgBuffer">A buffer containing a supported input image container.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(ReadOnlySpan <byte> imgBuffer, ProcessImageSettings settings)
        {
            if (imgBuffer == default)
            {
                throw new ArgumentNullException(nameof(imgBuffer));
            }

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgBuffer, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
예제 #22
0
 public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings)
 {
     using (var ctx = new WicProcessingContext(settings))
         return(processImage(new WicDecoder(imgBuffer, ctx), ctx, outStream));
 }
예제 #23
0
 public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings)
 {
     using (var ctx = new WicProcessingContext(settings))
         return(processImage(new WicDecoder(imgStream, ctx), ctx, outStream));
 }
예제 #24
0
#pragma warning disable 1573 // not all params have docs

        /// <inheritdoc cref="ProcessImage(string, Stream, ProcessImageSettings)" />
        /// <param name="imgBuffer">A buffer containing a supported input image container.</param>
        public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings)
        {
            if (imgBuffer == default)
            {
                throw new ArgumentNullException(nameof(imgBuffer));
            }
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            checkOutStream(outStream);

            using var ctx      = new PipelineContext(settings);
            ctx.ImageContainer = WicImageContainer.Create(imgBuffer, ctx.WicContext);

            buildPipeline(ctx);
            return(WriteOutput(ctx, outStream));
        }
예제 #25
0
 public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings) => processImage(imgStream, outStream, settings);
예제 #26
0
        /// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary>
        /// <param name="imgStream">A stream containing a supported input image container.</param>
        /// <param name="outStream">The stream to which the output image will be written.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns>
        public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings)
        {
            checkInStream(imgStream);
            checkOutStream(outStream);

            using (var ctx = new WicProcessingContext(settings))
            {
                var dec = new WicDecoder(imgStream, ctx);
                buildPipeline(ctx);
                return(executePipeline(ctx, outStream));
            }
        }
예제 #27
0
        /// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary>
        /// <param name="imgBuffer">A buffer containing a supported input image container.</param>
        /// <param name="outStream">The stream to which the output image will be written.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns>
        public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings)
        {
            if (imgBuffer == default)
            {
                throw new ArgumentNullException(nameof(imgBuffer));
            }
            checkOutStream(outStream);

            using (var ctx = new WicProcessingContext(settings))
            {
                var dec = new WicDecoder(imgBuffer, ctx);
                buildPipeline(ctx);
                return(executePipeline(ctx, outStream));
            }
        }
예제 #28
0
        /// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary>
        /// <param name="imgPath">The path to a file containing the input image.</param>
        /// <param name="outStream">The stream to which the output image will be written.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns>
        public static ProcessImageResult ProcessImage(string imgPath, Stream outStream, ProcessImageSettings settings)
        {
            if (imgPath is null)
            {
                throw new ArgumentNullException(nameof(imgPath));
            }
            checkOutStream(outStream);

            using (var ctx = new WicProcessingContext(settings))
            {
                var dec = new WicDecoder(imgPath, ctx);
                buildPipeline(ctx);
                return(executePipeline(ctx, outStream));
            }
        }
예제 #29
0
 public static void CreateBrokenImage(Stream outStream, ProcessImageSettings settings) => createBrokenImage(outStream, settings);
예제 #30
0
        /// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary>
        /// <param name="imgPath">The path to a file containing the input image.</param>
        /// <param name="outStream">The stream to which the output image will be written. The stream must allow Seek and Write.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns>
        public static ProcessImageResult ProcessImage(string imgPath, Stream outStream, ProcessImageSettings settings)
        {
            if (imgPath is null)
            {
                throw new ArgumentNullException(nameof(imgPath));
            }
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            checkOutStream(outStream);

            using var ctx      = new PipelineContext(settings);
            ctx.ImageContainer = WicImageContainer.Create(imgPath, ctx.WicContext);

            buildPipeline(ctx);
            return(WriteOutput(ctx, outStream));
        }