Esempio n. 1
0
		// Checks whether a bitmap contains entirely the specified RGB value.
		public static bool IsRgbEntirely(Color expectedRgb, Bitmap bitmap)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadOnly))
			{
				for (int y = 0; y < bitmap.Height; y++)
				{
					for (int x = 0; x < bitmap.Width; x++)
					{
						System.Drawing.Color color = bitmapData[x, y];

						if (color.A == 0)
							continue;

						if ((color.R != expectedRgb.R) ||
						    (color.G != expectedRgb.G) ||
						    (color.B != expectedRgb.B))
						{
							return false;
						}
					}
				}
			}

			return true;
		}
        public override void PixBltBGRb(PixelAccessor<BGRb> accessor, int x, int y)
        {
            MemoryStream ms = new MemoryStream();

            // 2. Run length encode the image to a memory stream
            NewTOAPIA.Imaging.TargaRunLengthCodec rlc = new NewTOAPIA.Imaging.TargaRunLengthCodec();
            rlc.Encode(accessor, ms);

            // 3. Get the bytes from the stream
            byte[] imageBytes = ms.GetBuffer();
            int dataLength = (int)imageBytes.Length;

            // 4. Allocate a buffer chunk to accomodate the bytes, plus some more
            BufferChunk chunk = new BufferChunk(dataLength + 128);

            // 5. Put the command, destination, and data size into the buffer first
            chunk += (int)UICommands.PixBltRLE;
            ChunkUtils.Pack(chunk, x, y);
            ChunkUtils.Pack(chunk, accessor.Width, accessor.Height);
            chunk += dataLength;

            // 6. Put the image bytes into the chunk
            chunk += imageBytes;


            // 6. Finally, send the packet
            SendCommand(chunk);
        }
Esempio n. 3
0
		// Checks whether an area of a bitmap contains entirely the specified alpha value.
		public static bool IsAlphaEntirely(byte expectedAlpha, Bitmap bitmap, System.Drawing.Rectangle? region = null)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadOnly, region))
			{
				for (int y = 0; y < bitmapData.Region.Height; y++)
				{
					for (int x = 0; x < bitmapData.Region.Width; x++)
					{
						byte alpha = bitmapData[x, y].A;

						if (alpha != expectedAlpha)
							return false;
					}
				}
			}

			return true;
		}
Esempio n. 4
0
		// Copies a rectangular area from one bitmap to another.
		public static void CopyRect(Bitmap source, System.Drawing.Rectangle sourceRegion, Bitmap output, System.Drawing.Rectangle outputRegion)
		{
			if (sourceRegion.Width != outputRegion.Width ||
			    sourceRegion.Height != outputRegion.Height)
			{
				throw new ArgumentException();
			}

			using (var sourceData = new PixelAccessor(source, ImageLockMode.ReadOnly, sourceRegion))
				using (var outputData = new PixelAccessor(output, ImageLockMode.WriteOnly, outputRegion))
			{
				for (int y = 0; y < sourceRegion.Height; y++)
				{
					for (int x = 0; x < sourceRegion.Width; x++)
					{
						outputData[x, y] = sourceData[x, y];
					}
				}
			}
		}
Esempio n. 5
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int kernelYHeight = this.KernelY.Length;
            int kernelYWidth  = this.KernelY[0].Length;
            int kernelXHeight = this.KernelX.Length;
            int kernelXWidth  = this.KernelX[0].Length;
            int radiusY       = kernelYHeight >> 1;
            int radiusX       = kernelXWidth >> 1;

            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;
            int maxY   = endY - 1;
            int maxX   = endX - 1;

            TColor[] target = new TColor[source.Width * source.Height];
            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock <TColor, TPacked>(source.Width, source.Height))
                {
                    Parallel.For(
                        startY,
                        endY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = startX; x < endX; x++)
                        {
                            float rX = 0;
                            float gX = 0;
                            float bX = 0;
                            float rY = 0;
                            float gY = 0;
                            float bY = 0;

                            // Apply each matrix multiplier to the color components for each pixel.
                            for (int fy = 0; fy < kernelYHeight; fy++)
                            {
                                int fyr     = fy - radiusY;
                                int offsetY = y + fyr;

                                offsetY = offsetY.Clamp(0, maxY);

                                for (int fx = 0; fx < kernelXWidth; fx++)
                                {
                                    int fxr     = fx - radiusX;
                                    int offsetX = x + fxr;

                                    offsetX = offsetX.Clamp(0, maxX);

                                    Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4();
                                    float r = currentColor.X;
                                    float g = currentColor.Y;
                                    float b = currentColor.Z;

                                    if (fy < kernelXHeight)
                                    {
                                        rX += this.KernelX[fy][fx] * r;
                                        gX += this.KernelX[fy][fx] * g;
                                        bX += this.KernelX[fy][fx] * b;
                                    }

                                    if (fx < kernelYWidth)
                                    {
                                        rY += this.KernelY[fy][fx] * r;
                                        gY += this.KernelY[fy][fx] * g;
                                        bY += this.KernelY[fy][fx] * b;
                                    }
                                }
                            }

                            float red   = (float)Math.Sqrt((rX * rX) + (rY * rY));
                            float green = (float)Math.Sqrt((gX * gX) + (gY * gY));
                            float blue  = (float)Math.Sqrt((bX * bX) + (bY * bY));

                            TColor packed = default(TColor);
                            packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));
                            targetPixels[x, y] = packed;
                        }
                    });
                }

            source.SetPixels(source.Width, source.Height, target);
        }
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            using (IPenApplicator <TColor, TPacked> applicator = this.pen.CreateApplicator(this.region))
            {
                var rect = RectangleF.Ceiling(applicator.RequiredRegion);

                int polyStartY = rect.Y - PaddingFactor;
                int polyEndY   = rect.Bottom + PaddingFactor;
                int startX     = rect.X - PaddingFactor;
                int endX       = rect.Right + PaddingFactor;

                int minX = Math.Max(sourceRectangle.Left, startX);
                int maxX = Math.Min(sourceRectangle.Right, endX);
                int minY = Math.Max(sourceRectangle.Top, polyStartY);
                int maxY = Math.Min(sourceRectangle.Bottom, polyEndY);

                // Align start/end positions.
                minX = Math.Max(0, minX);
                maxX = Math.Min(source.Width, maxX);
                minY = Math.Max(0, minY);
                maxY = Math.Min(source.Height, maxY);

                // Reset offset if necessary.
                if (minX > 0)
                {
                    startX = 0;
                }

                if (minY > 0)
                {
                    polyStartY = 0;
                }

                using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY      = y - polyStartY;
                        var currentPoint = default(Vector2);
                        for (int x = minX; x < maxX; x++)
                        {
                            int offsetX    = x - startX;
                            currentPoint.X = offsetX;
                            currentPoint.Y = offsetY;

                            var dist = Closest(currentPoint);

                            var color = applicator.GetColor(dist);

                            var opacity = this.Opacity(color.DistanceFromElement);

                            if (opacity > Epsilon)
                            {
                                int offsetColorX = x - minX;

                                Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
                                Vector4 sourceVector     = color.Color.ToVector4();

                                var finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
                                finalColor.W   = backgroundVector.W;

                                TColor packed = default(TColor);
                                packed.PackFromVector4(finalColor);
                                sourcePixels[offsetX, offsetY] = packed;
                            }
                        }
                    });
                }
            }
        }
Esempio n. 7
0
        void SendVideoFrame(PixelAccessor<BGRb> aFrame)
        {
            BufferChunk chunk = EncodeBGRb(aFrame, 0, 0);

            fChannel.Send(chunk);
        }
Esempio n. 8
0
        // Converts a bitmap to premultiplied alpha format.
        public static void PremultiplyAlphaClearType(Bitmap bitmap, bool srgb)
        {
            using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        DrawingColor color = bitmapData[x, y];

                        int a;
                        if (srgb)
                        {
                            var colorLinear = new Color4(new SiliconStudio.Core.Mathematics.Color(color.R, color.G, color.B)).ToLinear();
                            var alphaLinear = (colorLinear.R + colorLinear.G + colorLinear.B) / 3.0f;
                            a = MathUtil.Clamp((int)Math.Round(alphaLinear * 255), 0, 255);
                        }
                        else
                        {
                            a = (color.R + color.G + color.B) / 3;
                        }
                        int r = color.R;
                        int g = color.G;
                        int b = color.B;

                        bitmapData[x, y] = DrawingColor.FromArgb(a, r, g, b);
                    }
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Decodes the raw interlaced pixel data row by row
        /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodeInterlacedPixelData <TPixel>(Stream compressedStream, PixelAccessor <TPixel> pixels)
            where TPixel : struct, IPixel <TPixel>
        {
            while (true)
            {
                int numColumns = this.ComputeColumnsAdam7(this.pass);

                if (numColumns == 0)
                {
                    this.pass++;

                    // This pass contains no data; skip to next pass
                    continue;
                }

                int bytesPerInterlaceScanline = this.CalculateScanlineLength(numColumns) + 1;

                while (this.currentRow < this.header.Height)
                {
                    int bytesRead = compressedStream.Read(this.scanline, this.currentRowBytesRead, bytesPerInterlaceScanline - this.currentRowBytesRead);
                    this.currentRowBytesRead += bytesRead;
                    if (this.currentRowBytesRead < bytesPerInterlaceScanline)
                    {
                        return;
                    }

                    this.currentRowBytesRead = 0;

                    FilterType filterType = (FilterType)this.scanline[0];

                    switch (filterType)
                    {
                    case FilterType.None:

                        NoneFilter.Decode(this.scanline);

                        break;

                    case FilterType.Sub:

                        SubFilter.Decode(this.scanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Up:

                        UpFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline);

                        break;

                    case FilterType.Average:

                        AverageFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Paeth:

                        PaethFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                        break;

                    default:
                        throw new ImageFormatException("Unknown filter type.");
                    }

                    this.ProcessInterlacedDefilteredScanline(this.scanline, this.currentRow, pixels, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);

                    Swap(ref this.scanline, ref this.previousScanline);

                    this.currentRow += Adam7RowIncrement[this.pass];
                }

                this.pass++;
                if (this.pass < 7)
                {
                    this.currentRow = Adam7FirstRow[this.pass];
                }
                else
                {
                    break;
                }
            }
        }
Esempio n. 10
0
 public void SendVideoFrame(PixelAccessor<BGRb> aFrame)
 {
     BufferChunk chunk = EncodeBGRb(aFrame, 0, 0);
     Session.SendVideoFrame(chunk);
 }
Esempio n. 11
0
		// Copies a single pixel within a bitmap, preserving RGB but forcing alpha to zero.
		static void CopyBorderPixel(PixelAccessor bitmapData, int sourceX, int sourceY, int destX, int destY)
		{
			System.Drawing.Color color = bitmapData[sourceX, sourceY];

			bitmapData[destX, destY] = System.Drawing.Color.FromArgb(0, color);
		}
Esempio n. 12
0
 /// <inheritdoc />
 public BrushApplicator <TColor> CreateApplicator(PixelAccessor <TColor> sourcePixels, RectangleF region)
 {
     return(new SolidBrushApplicator(sourcePixels, this.color));
 }
Esempio n. 13
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                using (PenApplicator <TPixel> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds))
                {
                    Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion);

                    int polyStartY = rect.Y - PaddingFactor;
                    int polyEndY   = rect.Bottom + PaddingFactor;
                    int startX     = rect.X - PaddingFactor;
                    int endX       = rect.Right + PaddingFactor;

                    int minX = Math.Max(sourceRectangle.Left, startX);
                    int maxX = Math.Min(sourceRectangle.Right, endX);
                    int minY = Math.Max(sourceRectangle.Top, polyStartY);
                    int maxY = Math.Min(sourceRectangle.Bottom, polyEndY);

                    // Align start/end positions.
                    minX = Math.Max(0, minX);
                    maxX = Math.Min(source.Width, maxX);
                    minY = Math.Max(0, minY);
                    maxY = Math.Min(source.Height, maxY);

                    // Reset offset if necessary.
                    if (minX > 0)
                    {
                        startX = 0;
                    }

                    if (minY > 0)
                    {
                        polyStartY = 0;
                    }

                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - polyStartY;

                        for (int x = minX; x < maxX; x++)
                        {
                            // TODO add find intersections code to skip and scan large regions of this.
                            int offsetX    = x - startX;
                            PointInfo info = this.Path.GetPointInfo(offsetX, offsetY);

                            ColoredPointInfo <TPixel> color = applicator.GetColor(offsetX, offsetY, info);

                            float opacity = this.Opacity(color.DistanceFromElement);

                            if (opacity > Constants.Epsilon)
                            {
                                Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
                                Vector4 sourceVector     = color.Color.ToVector4();

                                Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);

                                TPixel packed = default(TPixel);
                                packed.PackFromVector4(finalColor);
                                sourcePixels[offsetX, offsetY] = packed;
                            }
                        }
                    });
                }
        }
Esempio n. 14
0
 /// <inheritdoc />
 public BrushApplicator <TColor> CreateApplicator(PixelAccessor <TColor> sourcePixels, RectangleF region)
 {
     return(new ImageBrushApplicator(this.image, region));
 }
Esempio n. 15
0
        /// <summary>
        /// Processes the interlaced de-filtered scanline filling the image pixel data
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="defilteredScanline">The de-filtered scanline</param>
        /// <param name="row">The current image row.</param>
        /// <param name="pixels">The image pixels</param>
        /// <param name="pixelOffset">The column start index. Always 0 for none interlaced images.</param>
        /// <param name="increment">The column increment. Always 1 for none interlaced images.</param>
        private void ProcessInterlacedDefilteredScanline <TColor>(byte[] defilteredScanline, int row, PixelAccessor <TColor> pixels, int pixelOffset = 0, int increment = 1)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            TColor color = default(TColor);

            switch (this.PngColorType)
            {
            case PngColorType.Grayscale:
                int    factor       = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
                byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
                for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++)
                {
                    byte intensity = (byte)(newScanline1[o] * factor);
                    color.PackFromBytes(intensity, intensity, intensity, 255);
                    pixels[x, row] = color;
                }

                break;

            case PngColorType.GrayscaleWithAlpha:

                for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel)
                {
                    byte intensity = defilteredScanline[o];
                    byte alpha     = defilteredScanline[o + this.bytesPerSample];

                    color.PackFromBytes(intensity, intensity, intensity, alpha);
                    pixels[x, row] = color;
                }

                break;

            case PngColorType.Palette:

                byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);

                if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
                {
                    // If the alpha palette is not null and has one or more entries, this means, that the image contains an alpha
                    // channel and we should try to read it.
                    for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++)
                    {
                        int index  = newScanline[o];
                        int offset = index * 3;

                        byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;

                        if (a > 0)
                        {
                            byte r = this.palette[offset];
                            byte g = this.palette[offset + 1];
                            byte b = this.palette[offset + 2];
                            color.PackFromBytes(r, g, b, a);
                        }
                        else
                        {
                            color.PackFromBytes(0, 0, 0, 0);
                        }

                        pixels[x, row] = color;
                    }
                }
                else
                {
                    for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++)
                    {
                        int index  = newScanline[o];
                        int offset = index * 3;

                        byte r = this.palette[offset];
                        byte g = this.palette[offset + 1];
                        byte b = this.palette[offset + 2];

                        color.PackFromBytes(r, g, b, 255);
                        pixels[x, row] = color;
                    }
                }

                break;

            case PngColorType.Rgb:

                for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel)
                {
                    byte r = defilteredScanline[o];
                    byte g = defilteredScanline[o + this.bytesPerSample];
                    byte b = defilteredScanline[o + (2 * this.bytesPerSample)];

                    color.PackFromBytes(r, g, b, 255);
                    pixels[x, row] = color;
                }

                break;

            case PngColorType.RgbWithAlpha:

                for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel)
                {
                    byte r = defilteredScanline[o];
                    byte g = defilteredScanline[o + this.bytesPerSample];
                    byte b = defilteredScanline[o + (2 * this.bytesPerSample)];
                    byte a = defilteredScanline[o + (3 * this.bytesPerSample)];

                    color.PackFromBytes(r, g, b, a);
                    pixels[x, row] = color;
                }

                break;
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Decodes the raw interlaced pixel data row by row
        /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodeInterlacedPixelData <TColor>(Stream compressedStream, PixelAccessor <TColor> pixels)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            byte[] previousScanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            byte[] scanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            try
            {
                for (int pass = 0; pass < 7; pass++)
                {
                    // Zero out the scanlines, because the bytes that are rented from the arraypool may not be zero.
                    Array.Clear(scanline, 0, this.bytesPerScanline);
                    Array.Clear(previousScanline, 0, this.bytesPerScanline);

                    int y          = Adam7FirstRow[pass];
                    int numColumns = this.ComputeColumnsAdam7(pass);

                    if (numColumns == 0)
                    {
                        // This pass contains no data; skip to next pass
                        continue;
                    }

                    int bytesPerInterlaceScanline = this.CalculateScanlineLength(numColumns) + 1;

                    while (y < this.header.Height)
                    {
                        compressedStream.Read(scanline, 0, bytesPerInterlaceScanline);

                        FilterType filterType = (FilterType)scanline[0];

                        switch (filterType)
                        {
                        case FilterType.None:

                            NoneFilter.Decode(scanline);

                            break;

                        case FilterType.Sub:

                            SubFilter.Decode(scanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

                        case FilterType.Up:

                            UpFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline);

                            break;

                        case FilterType.Average:

                            AverageFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

                        case FilterType.Paeth:

                            PaethFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

                        default:
                            throw new ImageFormatException("Unknown filter type.");
                        }

                        this.ProcessInterlacedDefilteredScanline(scanline, y, pixels, Adam7FirstColumn[pass], Adam7ColumnIncrement[pass]);

                        Swap(ref scanline, ref previousScanline);

                        y += Adam7RowIncrement[pass];
                    }
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(previousScanline);

                ArrayPool <byte> .Shared.Return(scanline);
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Decodes the raw pixel data row by row
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodePixelData <TColor>(Stream compressedStream, PixelAccessor <TColor> pixels)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            byte[] previousScanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            byte[] scanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            // Zero out the scanlines, because the bytes that are rented from the arraypool may not be zero.
            Array.Clear(scanline, 0, this.bytesPerScanline);
            Array.Clear(previousScanline, 0, this.bytesPerScanline);

            try
            {
                for (int y = 0; y < this.header.Height; y++)
                {
                    compressedStream.Read(scanline, 0, this.bytesPerScanline);

                    FilterType filterType = (FilterType)scanline[0];

                    switch (filterType)
                    {
                    case FilterType.None:

                        NoneFilter.Decode(scanline);

                        break;

                    case FilterType.Sub:

                        SubFilter.Decode(scanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Up:

                        UpFilter.Decode(scanline, previousScanline, this.bytesPerScanline);

                        break;

                    case FilterType.Average:

                        AverageFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Paeth:

                        PaethFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

                    default:
                        throw new ImageFormatException("Unknown filter type.");
                    }

                    this.ProcessDefilteredScanline(scanline, y, pixels);

                    Swap(ref scanline, ref previousScanline);
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(previousScanline);

                ArrayPool <byte> .Shared.Return(scanline);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Decodes the stream to the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="image">The image to decode to.</param>
        /// <param name="stream">The stream containing image data. </param>
        /// <exception cref="ImageFormatException">
        /// Thrown if the stream does not contain and end chunk.
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// Thrown if the image is larger than the maximum allowable size.
        /// </exception>
        public void Decode <TColor>(Image <TColor> image, Stream stream)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            Image <TColor> currentImage = image;

            this.currentStream = stream;
            this.currentStream.Skip(8);

            bool isEndChunkReached = false;

            using (MemoryStream dataStream = new MemoryStream())
            {
                PngChunk currentChunk;
                while ((currentChunk = this.ReadChunk()) != null)
                {
                    if (isEndChunkReached)
                    {
                        throw new ImageFormatException("Image does not end with end chunk.");
                    }

                    try
                    {
                        switch (currentChunk.Type)
                        {
                        case PngChunkTypes.Header:
                            this.ReadHeaderChunk(currentChunk.Data);
                            this.ValidateHeader();
                            break;

                        case PngChunkTypes.Physical:
                            this.ReadPhysicalChunk(currentImage, currentChunk.Data);
                            break;

                        case PngChunkTypes.Data:
                            dataStream.Write(currentChunk.Data, 0, currentChunk.Length);
                            break;

                        case PngChunkTypes.Palette:
                            byte[] pal = new byte[currentChunk.Length];
                            Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length);
                            this.palette           = pal;
                            image.MetaData.Quality = pal.Length / 3;
                            break;

                        case PngChunkTypes.PaletteAlpha:
                            byte[] alpha = new byte[currentChunk.Length];
                            Buffer.BlockCopy(currentChunk.Data, 0, alpha, 0, currentChunk.Length);
                            this.paletteAlpha = alpha;
                            break;

                        case PngChunkTypes.Text:
                            this.ReadTextChunk(currentImage, currentChunk.Data, currentChunk.Length);
                            break;

                        case PngChunkTypes.End:
                            isEndChunkReached = true;
                            break;
                        }
                    }
                    finally
                    {
                        // Data is rented in ReadChunkData()
                        ArrayPool <byte> .Shared.Return(currentChunk.Data);
                    }
                }

                if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight)
                {
                    throw new ArgumentOutOfRangeException($"The input png '{this.header.Width}x{this.header.Height}' is bigger than the max allowed size '{image.MaxWidth}x{image.MaxHeight}'");
                }

                image.InitPixels(this.header.Width, this.header.Height);

                using (PixelAccessor <TColor> pixels = image.Lock())
                {
                    this.ReadScanlines(dataStream, pixels);
                }
            }
        }
Esempio n. 19
0
		// Converts the alpha channel into a greyscale premultiplied texture.
		public static void ConvertAlphaToGrey(Bitmap bitmap)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
			{
				for (int y = 0; y < bitmap.Height; y++)
				{
					for (int x = 0; x < bitmap.Width; x++)
					{
						System.Drawing.Color color = bitmapData[x, y];
                        bitmapData[x, y] = System.Drawing.Color.FromArgb(color.A, color.A, color.A, color.A);
					}
				}
			}
		}
Esempio n. 20
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int startY = sourceRectangle.Y;
            int endY = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX = sourceRectangle.Right;
            int size = this.Value;
            int offset = this.Value / 2;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            // Get the range on the y-plane to choose from.
            IEnumerable<int> range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size);
            TColor[] target = new TColor[source.Width * source.Height];

            using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
            using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))
            {
                Parallel.ForEach(
                    range,
                    this.ParallelOptions,
                    y =>
                        {
                            int offsetY = y - startY;
                            int offsetPy = offset;

                            for (int x = minX; x < maxX; x += size)
                            {
                                int offsetX = x - startX;
                                int offsetPx = offset;

                                // Make sure that the offset is within the boundary of the image.
                                while (offsetY + offsetPy >= maxY)
                                {
                                    offsetPy--;
                                }

                                while (x + offsetPx >= maxX)
                                {
                                    offsetPx--;
                                }

                                // Get the pixel color in the centre of the soon to be pixelated area.
                                // ReSharper disable AccessToDisposedClosure
                                TColor pixel = sourcePixels[offsetX + offsetPx, offsetY + offsetPy];

                                // For each pixel in the pixelate size, set it to the centre color.
                                for (int l = offsetY; l < offsetY + size && l < maxY; l++)
                                {
                                    for (int k = offsetX; k < offsetX + size && k < maxX; k++)
                                    {
                                        targetPixels[k, l] = pixel;
                                    }
                                }
                            }
                        });

                source.SetPixels(source.Width, source.Height, target);
            }
        }
Esempio n. 21
0
        // Copies a single pixel within a bitmap, preserving RGB but forcing alpha to zero.
        static void CopyBorderPixel(PixelAccessor bitmapData, int sourceX, int sourceY, int destX, int destY)
        {
            DrawingColor color = bitmapData[sourceX, sourceY];

            bitmapData[destX, destY] = DrawingColor.FromArgb(0, color);
        }
Esempio n. 22
0
        public virtual void ReceiveChunk(BufferChunk aRecord)
        {
            // First read out the record type
            int recordType = aRecord.NextInt32();

            // Then deserialize the rest from there
            switch (recordType)
            {

                //case (int)UICommands.PixBlt:
                //    {
                //        // Get the X, Y
                //        int x = aRecord.NextInt32();
                //        int y = aRecord.NextInt32();

                //        // get the length of the image bytes buffer
                //        int dataSize = aRecord.NextInt32();

                //        byte[] imageBytes = (byte[])aRecord;

                //        // Create a memory stream from the imageBytes
                //        MemoryStream ms = new MemoryStream(imageBytes, false);

                //        // Create a pixelArray from the stream
                //        Bitmap bm = (Bitmap)Bitmap.FromStream(ms);

                //        PixelArray<BGRAb> pixMap = PixelBufferHelper.CreatePixelArrayFromBitmap(bm);
                        
                //        // And finally, call the PixBlt function
                //        PixBltBGRAb(pixMap, x, y);
                //    }
                //    break;

                case (int)UICommands.PixBltRLE:
                    {
                        // Get the X, Y
                        int x = aRecord.NextInt32();
                        int y = aRecord.NextInt32();
                        int width = aRecord.NextInt32();
                        int height = aRecord.NextInt32();

                        // get the length of the image bytes buffer
                        int dataSize = aRecord.NextInt32();

                        byte[] imageBytes = (byte[])aRecord;

                        // Create a memory stream from the imageBytes
                        MemoryStream ms = new MemoryStream(imageBytes, false);

                        // Create a pixelArray from the stream
                        if ((width != fPixMap.Width) || (height != fPixMap.Height))
                            fPixMap = new GDIDIBSection(width, height);

                        TargaRunLengthCodec rlc = new TargaRunLengthCodec();
                        PixelAccessor<BGRb> accessor = new PixelAccessor<BGRb>(fPixMap.Width, fPixMap.Height, fPixMap.Orientation, fPixMap.Pixels, fPixMap.BytesPerRow);
                        rlc.Decode(ms, accessor);

                        // And finally, call the local PixBlt function
                        PixBltPixelBuffer24(fPixMap, x, y);
                    }
                    break;

                case (int)UICommands.PixBltLuminance:
                    {
                        // Get the X, Y
                        int x = aRecord.NextInt32();
                        int y = aRecord.NextInt32();
                        int width = aRecord.NextInt32();
                        int height = aRecord.NextInt32();

                        // get the length of the image bytes buffer
                        int dataSize = aRecord.NextInt32();

                        byte[] imageBytes = (byte[])aRecord;

                        // Create a memory stream from the imageBytes
                        MemoryStream ms = new MemoryStream(imageBytes, false);

                        // Create a pixelArray from the stream
                        if ((width != fGrayImage.Width) || (height != fGrayImage.Height))
                            fGrayImage = new PixelArray<Lumb>(width, height);

                        TargaLuminanceRLE rlc = new TargaLuminanceRLE();
                        rlc.Decode(ms, fGrayImage);

                        // And finally, call the local PixBlt function
                        PixBltLumb(fGrayImage, x, y);
                    }
                    break;




                default:
                    //if (CommandReceived != null)
                    //    CommandReceived(aRecord);
                    break;
            }
        }
Esempio n. 23
0
 /// <inheritdoc />
 public BrushApplicator <TPixel> CreateApplicator(PixelAccessor <TPixel> sourcePixels, RectangleF region)
 {
     return(new PatternBrushApplicator(sourcePixels, this.pattern, this.patternVector));
 }
Esempio n. 24
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SolidBrushApplicator"/> class.
 /// </summary>
 /// <param name="color">The color.</param>
 /// <param name="sourcePixels">The sourcePixels.</param>
 public SolidBrushApplicator(PixelAccessor <TColor> sourcePixels, TColor color)
     : base(sourcePixels)
 {
     this.color       = color;
     this.colorVector = color.ToVector4();
 }
Esempio n. 25
0
        /// <summary>
        /// Initializes the image and various buffers needed for processing
        /// </summary>
        /// <typeparam name="TPixel">The type the pixels will be</typeparam>
        /// <param name="metadata">The metadata information for the image</param>
        /// <param name="image">The image that we will populate</param>
        /// <param name="pixels">The pixel accessor</param>
        private void InitializeImage <TPixel>(ImageMetaData metadata, out Image <TPixel> image, out PixelAccessor <TPixel> pixels)
            where TPixel : struct, IPixel <TPixel>
        {
            if (this.header.Width > Image <TPixel> .MaxWidth || this.header.Height > Image <TPixel> .MaxHeight)
            {
                throw new ArgumentOutOfRangeException($"The input png '{this.header.Width}x{this.header.Height}' is bigger than the max allowed size '{Image<TPixel>.MaxWidth}x{Image<TPixel>.MaxHeight}'");
            }

            image                 = new Image <TPixel>(this.configuration, this.header.Width, this.header.Height, metadata);
            pixels                = image.Lock();
            this.bytesPerPixel    = this.CalculateBytesPerPixel();
            this.bytesPerScanline = this.CalculateScanlineLength(this.header.Width) + 1;
            this.bytesPerSample   = 1;
            if (this.header.BitDepth >= 8)
            {
                this.bytesPerSample = this.header.BitDepth / 8;
            }

            this.previousScanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            this.scanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            // Zero out the scanlines, because the bytes that are rented from the arraypool may not be zero.
            Array.Clear(this.scanline, 0, this.bytesPerScanline);
            Array.Clear(this.previousScanline, 0, this.bytesPerScanline);
        }
Esempio n. 26
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;
            int radius = this.BrushSize >> 1;
            int levels = this.Levels;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            TColor[] target = new TColor[source.Width * source.Height];
            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock <TColor, TPacked>(source.Width, source.Height))
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = startX; x < endX; x++)
                        {
                            int maxIntensity = 0;
                            int maxIndex     = 0;

                            int[] intensityBin = new int[levels];
                            float[] redBin     = new float[levels];
                            float[] blueBin    = new float[levels];
                            float[] greenBin   = new float[levels];

                            for (int fy = 0; fy <= radius; fy++)
                            {
                                int fyr     = fy - radius;
                                int offsetY = y + fyr;

                                // Skip the current row
                                if (offsetY < minY)
                                {
                                    continue;
                                }

                                // Outwith the current bounds so break.
                                if (offsetY >= maxY)
                                {
                                    break;
                                }

                                for (int fx = 0; fx <= radius; fx++)
                                {
                                    int fxr     = fx - radius;
                                    int offsetX = x + fxr;

                                    // Skip the column
                                    if (offsetX < 0)
                                    {
                                        continue;
                                    }

                                    if (offsetX < maxX)
                                    {
                                        // ReSharper disable once AccessToDisposedClosure
                                        Vector4 color = sourcePixels[offsetX, offsetY].ToVector4();

                                        float sourceRed   = color.X;
                                        float sourceBlue  = color.Z;
                                        float sourceGreen = color.Y;

                                        int currentIntensity = (int)Math.Round((sourceBlue + sourceGreen + sourceRed) / 3.0 * (levels - 1));

                                        intensityBin[currentIntensity] += 1;
                                        blueBin[currentIntensity]      += sourceBlue;
                                        greenBin[currentIntensity]     += sourceGreen;
                                        redBin[currentIntensity]       += sourceRed;

                                        if (intensityBin[currentIntensity] > maxIntensity)
                                        {
                                            maxIntensity = intensityBin[currentIntensity];
                                            maxIndex     = currentIntensity;
                                        }
                                    }
                                }

                                float red   = Math.Abs(redBin[maxIndex] / maxIntensity);
                                float green = Math.Abs(greenBin[maxIndex] / maxIntensity);
                                float blue  = Math.Abs(blueBin[maxIndex] / maxIntensity);

                                TColor packed = default(TColor);
                                packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));
                                targetPixels[x, y] = packed;
                            }
                        }
                    });
                }

            source.SetPixels(source.Width, source.Height, target);
        }
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            int kernelYHeight = this.KernelY.Height;
            int kernelYWidth  = this.KernelY.Width;
            int kernelXHeight = this.KernelX.Height;
            int kernelXWidth  = this.KernelX.Width;
            int radiusY       = kernelYHeight >> 1;
            int radiusX       = kernelXWidth >> 1;

            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;
            int maxY   = endY - 1;
            int maxX   = endX - 1;

            using (var targetPixels = new PixelAccessor <TPixel>(source.Width, source.Height))
            {
                source.CopyTo(targetPixels);

                Parallel.For(
                    startY,
                    endY,
                    this.ParallelOptions,
                    y =>
                {
                    Span <TPixel> sourceRow = source.GetRowSpan(y);
                    Span <TPixel> targetRow = targetPixels.GetRowSpan(y);

                    for (int x = startX; x < endX; x++)
                    {
                        float rX = 0;
                        float gX = 0;
                        float bX = 0;
                        float rY = 0;
                        float gY = 0;
                        float bY = 0;

                        // Apply each matrix multiplier to the color components for each pixel.
                        for (int fy = 0; fy < kernelYHeight; fy++)
                        {
                            int fyr     = fy - radiusY;
                            int offsetY = y + fyr;

                            offsetY = offsetY.Clamp(0, maxY);
                            Span <TPixel> sourceOffsetRow = source.GetRowSpan(offsetY);

                            for (int fx = 0; fx < kernelXWidth; fx++)
                            {
                                int fxr     = fx - radiusX;
                                int offsetX = x + fxr;

                                offsetX          = offsetX.Clamp(0, maxX);
                                var currentColor = sourceOffsetRow[offsetX].ToVector4();

                                if (fy < kernelXHeight)
                                {
                                    Vector4 kx = this.KernelX[fy, fx] * currentColor;
                                    rX        += kx.X;
                                    gX        += kx.Y;
                                    bX        += kx.Z;
                                }

                                if (fx < kernelYWidth)
                                {
                                    Vector4 ky = this.KernelY[fy, fx] * currentColor;
                                    rY        += ky.X;
                                    gY        += ky.Y;
                                    bY        += ky.Z;
                                }
                            }
                        }

                        float red   = MathF.Sqrt((rX * rX) + (rY * rY));
                        float green = MathF.Sqrt((gX * gX) + (gY * gY));
                        float blue  = MathF.Sqrt((bX * bX) + (bY * bY));

                        ref TPixel pixel = ref targetRow[x];
                        pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
                    }
                });

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Esempio n. 28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PatternBrushApplicator" /> class.
 /// </summary>
 /// <param name="sourcePixels">The sourcePixels.</param>
 /// <param name="pattern">The pattern.</param>
 /// <param name="patternVector">The patternVector.</param>
 public PatternBrushApplicator(PixelAccessor <TPixel> sourcePixels, Fast2DArray <TPixel> pattern, Fast2DArray <Vector4> patternVector)
     : base(sourcePixels)
 {
     this.pattern       = pattern;
     this.patternVector = patternVector;
 }
Esempio n. 29
0
 /// <inheritdoc />
 public BrushApplicator <TPixel> CreateApplicator(PixelAccessor <TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
 {
     return(new PatternBrushApplicator(sourcePixels, this.pattern, this.patternVector, options));
 }
Esempio n. 30
0
        // Converts greyscale luminosity to alpha data.
        public static void ConvertGreyToAlpha(Bitmap bitmap, Rectangle region)
        {
            using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite, region))
            {
                for (int y = 0; y < region.Height; y++)
                {
                    for (int x = 0; x < region.Width; x++)
                    {
                        var color = bitmapData[x, y];

                        // Average the red, green and blue values to compute brightness.
                        var alpha = (color.R + color.G + color.B) / 3;

                        bitmapData[x, y] = DrawingColor.FromArgb(alpha, 255, 255, 255);
                    }
                }
            }
        }
Esempio n. 31
0
 /// <inheritdoc />
 public BrushApplicator <TColor> CreateApplicator(PixelAccessor <TColor> sourcePixels, RectangleF region)
 {
     return(new RecolorBrushApplicator(sourcePixels, this.SourceColor, this.TargetColor, this.Threshold));
 }
Esempio n. 32
0
        // Converts a bitmap to premultiplied alpha format.
        public static void PremultiplyAlpha(Bitmap bitmap, bool srgb)
        {
            using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        DrawingColor color = bitmapData[x, y];
                        int a = color.A;
                        int r;
                        int g;
                        int b;
                        if (srgb)
                        {
                            var colorLinear = new Color4(new SiliconStudio.Core.Mathematics.Color(color.R, color.G, color.B)).ToLinear();
                            colorLinear *= color.A / 255.0f;
                            var colorSRgb = (SiliconStudio.Core.Mathematics.Color)colorLinear.ToSRgb();
                            r = colorSRgb.R;
                            g = colorSRgb.G;
                            b = colorSRgb.B;
                        }
                        else
                        {
                            r = color.R * a / 255;
                            g = color.G * a / 255;
                            b = color.B * a / 255;
                        }

                        bitmapData[x, y] = DrawingColor.FromArgb(a, r, g, b);
                    }
                }
            }
        }
Esempio n. 33
0
 public void Dither <TColor>(PixelAccessor <TColor> pixels, TColor source, TColor transformed, int x, int y, int width, int height)
     where TColor : struct, IPixel <TColor>
 {
     this.Dither(pixels, source, transformed, x, y, width, height, true);
 }
Esempio n. 34
0
        BufferChunk EncodeBGRb(PixelAccessor<BGRb> accessor, int x, int y)
        {
            fImageStream.SetLength(0);

            // 2. Run length encode the image to a memory stream
            NewTOAPIA.Imaging.TargaRunLengthCodec rlc = new NewTOAPIA.Imaging.TargaRunLengthCodec();
            rlc.Encode(accessor, fImageStream);

            // 3. Get the bytes from the stream
            byte[] imageBytes = fImageStream.GetBuffer();
            int dataLength = (int)imageBytes.Length;

            // 4. Allocate a buffer chunk to accomodate the bytes, plus some more
            BufferChunk chunk = new BufferChunk(dataLength + 128);

            // 5. Put the command, destination, and data size into the buffer first
            chunk += (int)UICommands.PixBltRLE;
            chunk += (int)x;
            chunk += (int)y;
            chunk += (int)accessor.Width;
            chunk += (int)accessor.Height;
            chunk += dataLength;

            // 6. Put the image bytes into the chunk
            chunk += imageBytes;


            // 7. Finally, return the packet
            return chunk;
        }
Esempio n. 35
0
        /// <inheritdoc />
        protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration)
        {
            DenseMatrix <float>[] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast };

            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // we need a clean copy for each pass to start from
            using (ImageFrame <TPixel> cleanCopy = source.Clone())
            {
                new ConvolutionProcessor <TPixel>(kernels[0]).Apply(source, sourceRectangle, configuration);

                if (kernels.Length == 1)
                {
                    return;
                }

                int shiftY = startY;
                int shiftX = startX;

                // Reset offset if necessary.
                if (minX > 0)
                {
                    shiftX = 0;
                }

                if (minY > 0)
                {
                    shiftY = 0;
                }

                // Additional runs.
                // ReSharper disable once ForCanBeConvertedToForeach
                for (int i = 1; i < kernels.Length; i++)
                {
                    using (ImageFrame <TPixel> pass = cleanCopy.Clone())
                    {
                        new ConvolutionProcessor <TPixel>(kernels[i]).Apply(pass, sourceRectangle, configuration);

                        using (PixelAccessor <TPixel> passPixels = pass.Lock())
                            using (PixelAccessor <TPixel> targetPixels = source.Lock())
                            {
                                Parallel.For(
                                    minY,
                                    maxY,
                                    configuration.ParallelOptions,
                                    y =>
                                {
                                    int offsetY = y - shiftY;
                                    for (int x = minX; x < maxX; x++)
                                    {
                                        int offsetX = x - shiftX;

                                        // Grab the max components of the two pixels
                                        TPixel packed = default(TPixel);
                                        packed.PackFromVector4(Vector4.Max(passPixels[offsetX, offsetY].ToVector4(), targetPixels[offsetX, offsetY].ToVector4()));
                                        targetPixels[offsetX, offsetY] = packed;
                                    }
                                });
                            }
                    }
                }
            }
        }
Esempio n. 36
0
        /// <inheritdoc/>
        protected override void OnApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration)
        {
            if (this.BrushSize <= 0 || this.BrushSize > source.Height || this.BrushSize > source.Width)
            {
                throw new ArgumentOutOfRangeException(nameof(this.BrushSize));
            }

            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;
            int maxY   = endY - 1;
            int maxX   = endX - 1;

            int radius = this.BrushSize >> 1;
            int levels = this.Levels;

            using (var targetPixels = new PixelAccessor <TPixel>(source.Width, source.Height))
            {
                source.CopyTo(targetPixels);

                Parallel.For(
                    startY,
                    maxY,
                    configuration.ParallelOptions,
                    y =>
                {
                    Span <TPixel> sourceRow = source.GetPixelRowSpan(y);
                    Span <TPixel> targetRow = targetPixels.GetRowSpan(y);

                    for (int x = startX; x < endX; x++)
                    {
                        int maxIntensity = 0;
                        int maxIndex     = 0;

                        int[] intensityBin = new int[levels];
                        float[] redBin     = new float[levels];
                        float[] blueBin    = new float[levels];
                        float[] greenBin   = new float[levels];

                        for (int fy = 0; fy <= radius; fy++)
                        {
                            int fyr     = fy - radius;
                            int offsetY = y + fyr;

                            offsetY = offsetY.Clamp(0, maxY);

                            Span <TPixel> sourceOffsetRow = source.GetPixelRowSpan(offsetY);

                            for (int fx = 0; fx <= radius; fx++)
                            {
                                int fxr     = fx - radius;
                                int offsetX = x + fxr;
                                offsetX     = offsetX.Clamp(0, maxX);

                                var vector = sourceOffsetRow[offsetX].ToVector4();

                                float sourceRed   = vector.X;
                                float sourceBlue  = vector.Z;
                                float sourceGreen = vector.Y;

                                int currentIntensity = (int)Math.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1));

                                intensityBin[currentIntensity] += 1;
                                blueBin[currentIntensity]      += sourceBlue;
                                greenBin[currentIntensity]     += sourceGreen;
                                redBin[currentIntensity]       += sourceRed;

                                if (intensityBin[currentIntensity] > maxIntensity)
                                {
                                    maxIntensity = intensityBin[currentIntensity];
                                    maxIndex     = currentIntensity;
                                }
                            }

                            float red   = Math.Abs(redBin[maxIndex] / maxIntensity);
                            float green = Math.Abs(greenBin[maxIndex] / maxIntensity);
                            float blue  = Math.Abs(blueBin[maxIndex] / maxIntensity);

                            ref TPixel pixel = ref targetRow[x];
                            pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
                        }
                    }
                });

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Esempio n. 37
0
        /// <summary>
        /// Encode writes the image to the jpeg baseline format with the given options.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="image">The image to write from.</param>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="quality">The quality.</param>
        /// <param name="sample">The subsampling mode.</param>
        public void Encode <TColor, TPacked>(Image <TColor, TPacked> image, Stream stream, int quality, JpegSubsample sample)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            this.outputStream = stream;
            this.subsample    = sample;

            for (int i = 0; i < QuantizationTableCount; i++)
            {
                this.quant[i] = new byte[Block.BlockSize];
            }

            if (quality < 1)
            {
                quality = 1;
            }

            if (quality > 100)
            {
                quality = 100;
            }

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - (quality * 2);
            }

            // Initialize the quantization tables.
            for (int i = 0; i < QuantizationTableCount; i++)
            {
                for (int j = 0; j < Block.BlockSize; j++)
                {
                    int x = this.unscaledQuant[i, j];
                    x = ((x * scale) + 50) / 100;
                    if (x < 1)
                    {
                        x = 1;
                    }

                    if (x > 255)
                    {
                        x = 255;
                    }

                    this.quant[i][j] = (byte)x;
                }
            }

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            this.WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution);

            this.WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDefineQuantizationTables();

            // Write the image dimensions.
            this.WriteStartOfFrame(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDefineHuffmanTables(componentCount);

            // Write the image data.
            using (PixelAccessor <TColor, TPacked> pixels = image.Lock())
            {
                this.WriteStartOfScan(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.EOI;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 38
0
        // Converts a bitmap to premultiplied alpha format.

        public static void PremultiplyAlphaClearType(Bitmap bitmap)
        {
            using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        Color color = bitmapData[x, y];

                        int a = (color.R + color.G + color.B) / 3;
                        int r = color.R;
                        int g = color.G;
                        int b = color.B;

                        bitmapData[x, y] = Color.FromArgb(a, r, g, b);
                    }
                }
            }
        }
Esempio n. 39
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            Region    region = this.Region;
            Rectangle rect   = region.Bounds;

            // Align start/end positions.
            int minX = Math.Max(0, rect.Left);
            int maxX = Math.Min(source.Width, rect.Right);
            int minY = Math.Max(0, rect.Top);
            int maxY = Math.Min(source.Height, rect.Bottom);

            if (minX >= maxX)
            {
                return; // no effect inside image;
            }

            if (minY >= maxY)
            {
                return; // no effect inside image;
            }

            ArrayPool <float> arrayPool = ArrayPool <float> .Shared;

            int   maxIntersections = region.MaxIntersections;
            float subpixelCount    = 4;

            if (this.Options.Antialias)
            {
                subpixelCount = this.Options.AntialiasSubpixelDepth;
                if (subpixelCount < 4)
                {
                    subpixelCount = 4;
                }
            }

            using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                using (BrushApplicator <TPixel> applicator = this.Brush.CreateApplicator(sourcePixels, rect, this.Options))
                {
                    float[] buffer        = arrayPool.Rent(maxIntersections);
                    int     scanlineWidth = maxX - minX;
                    using (Buffer <float> scanline = new Buffer <float>(scanlineWidth))
                    {
                        try
                        {
                            bool scanlineDirty = true;
                            for (int y = minY; y < maxY; y++)
                            {
                                if (scanlineDirty)
                                {
                                    // clear the buffer
                                    for (int x = 0; x < scanlineWidth; x++)
                                    {
                                        scanline[x] = 0;
                                    }

                                    scanlineDirty = false;
                                }

                                float subpixelFraction      = 1f / subpixelCount;
                                float subpixelFractionPoint = subpixelFraction / subpixelCount;
                                for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction)
                                {
                                    int pointsFound = region.Scan(subPixel, buffer, maxIntersections, 0);
                                    if (pointsFound == 0)
                                    {
                                        // nothing on this line skip
                                        continue;
                                    }

                                    QuickSort(buffer, pointsFound);

                                    for (int point = 0; point < pointsFound; point += 2)
                                    {
                                        // points will be paired up
                                        float scanStart = buffer[point] - minX;
                                        float scanEnd   = buffer[point + 1] - minX;
                                        int   startX    = (int)MathF.Floor(scanStart);
                                        int   endX      = (int)MathF.Floor(scanEnd);

                                        if (startX >= 0 && startX < scanline.Length)
                                        {
                                            for (float x = scanStart; x < startX + 1; x += subpixelFraction)
                                            {
                                                scanline[startX] += subpixelFractionPoint;
                                                scanlineDirty     = true;
                                            }
                                        }

                                        if (endX >= 0 && endX < scanline.Length)
                                        {
                                            for (float x = endX; x < scanEnd; x += subpixelFraction)
                                            {
                                                scanline[endX] += subpixelFractionPoint;
                                                scanlineDirty   = true;
                                            }
                                        }

                                        int nextX = startX + 1;
                                        endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge
                                        if (nextX >= 0)
                                        {
                                            for (int x = nextX; x < endX; x++)
                                            {
                                                scanline[x]  += subpixelFraction;
                                                scanlineDirty = true;
                                            }
                                        }
                                    }
                                }

                                if (scanlineDirty)
                                {
                                    if (!this.Options.Antialias)
                                    {
                                        for (int x = 0; x < scanlineWidth; x++)
                                        {
                                            if (scanline[x] > 0.5)
                                            {
                                                scanline[x] = 1;
                                            }
                                            else
                                            {
                                                scanline[x] = 0;
                                            }
                                        }
                                    }

                                    applicator.Apply(scanline, minX, y);
                                }
                            }
                        }
                        finally
                        {
                            arrayPool.Return(buffer);
                        }
                    }
                }
        }
Esempio n. 40
0
		// Converts a bitmap to premultiplied alpha format.
		public static void PremultiplyAlpha(Bitmap bitmap)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
			{
				for (int y = 0; y < bitmap.Height; y++)
				{
					for (int x = 0; x < bitmap.Width; x++)
					{
						System.Drawing.Color color = bitmapData[x, y];

						int a = color.A;
						int r = color.R * a / 255;
						int g = color.G * a / 255;
						int b = color.B * a / 255;

						bitmapData[x, y] = System.Drawing.Color.FromArgb(a, r, g, b);
					}
				}
			}
		}
        /// <inheritdoc />
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            float[][][] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast };

            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // First run.
            ImageBase <TColor, TPacked> target = new Image <TColor, TPacked>(source.Width, source.Height);

            target.ClonePixels(source.Width, source.Height, source.Pixels);
            new ConvolutionProcessor <TColor, TPacked>(kernels[0]).Apply(target, sourceRectangle);

            if (kernels.Length == 1)
            {
                return;
            }

            int shiftY = startY;
            int shiftX = startX;

            // Reset offset if necessary.
            if (minX > 0)
            {
                shiftX = 0;
            }

            if (minY > 0)
            {
                shiftY = 0;
            }

            // Additional runs.
            // ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 1; i < kernels.Length; i++)
            {
                // Create a clone for each pass and copy the offset pixels across.
                ImageBase <TColor, TPacked> pass = new Image <TColor, TPacked>(source.Width, source.Height);
                pass.ClonePixels(source.Width, source.Height, source.Pixels);

                new ConvolutionProcessor <TColor, TPacked>(kernels[i]).Apply(pass, sourceRectangle);

                using (PixelAccessor <TColor, TPacked> passPixels = pass.Lock())
                    using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock())
                    {
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            int offsetY = y - shiftY;
                            for (int x = minX; x < maxX; x++)
                            {
                                int offsetX = x - shiftX;

                                // Grab the max components of the two pixels
                                TColor packed = default(TColor);
                                packed.PackFromVector4(Vector4.Max(passPixels[offsetX, offsetY].ToVector4(), targetPixels[offsetX, offsetY].ToVector4()));
                                targetPixels[offsetX, offsetY] = packed;
                            }
                        });
                    }
            }

            source.SetPixels(source.Width, source.Height, target.Pixels);
        }
Esempio n. 42
0
		// To avoid filtering artifacts when scaling or rotating fonts that do not use premultiplied alpha,
		// make sure the one pixel border around each glyph contains the same RGB values as the edge of the
		// glyph itself, but with zero alpha. This processing is an elaborate no-op when using premultiplied
		// alpha, because the premultiply conversion will change the RGB of all such zero alpha pixels to black.
		public static void PadBorderPixels(Bitmap bitmap, System.Drawing.Rectangle region)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
			{
				// Pad the top and bottom.
				for (int x = region.Left; x < region.Right; x++)
				{
					CopyBorderPixel(bitmapData, x, region.Top, x, region.Top - 1);
					CopyBorderPixel(bitmapData, x, region.Bottom - 1, x, region.Bottom);
				}

				// Pad the left and right.
				for (int y = region.Top; y < region.Bottom; y++)
				{
					CopyBorderPixel(bitmapData, region.Left, y, region.Left - 1, y);
					CopyBorderPixel(bitmapData, region.Right - 1, y, region.Right, y);
				}

				// Pad the four corners.
				CopyBorderPixel(bitmapData, region.Left, region.Top, region.Left - 1, region.Top - 1);
				CopyBorderPixel(bitmapData, region.Right - 1, region.Top, region.Right, region.Top - 1);
				CopyBorderPixel(bitmapData, region.Left, region.Bottom - 1, region.Left - 1, region.Bottom);
				CopyBorderPixel(bitmapData, region.Right - 1, region.Bottom - 1, region.Right, region.Bottom);
			}
		}
Esempio n. 43
0
        /// <summary>
        /// Encode writes the image to the jpeg baseline format with the given options.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="image">The image to write from.</param>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="quality">The quality.</param>
        /// <param name="sample">The subsampling mode.</param>
        public void Encode <TColor>(Image <TColor> image, Stream stream, int quality, JpegSubsample sample)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            this.outputStream = stream;
            this.subsample    = sample;

            if (quality < 1)
            {
                quality = 1;
            }

            if (quality > 100)
            {
                quality = 100;
            }

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - (quality * 2);
            }

            // Initialize the quantization tables.
            InitQuantizationTable(0, scale, ref this.luminanceQuantTable);
            InitQuantizationTable(1, scale, ref this.chrominanceQuantTable);

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);

            this.WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDefineQuantizationTables();

            // Write the image dimensions.
            this.WriteStartOfFrame(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDefineHuffmanTables(componentCount);

            // Write the image data.
            using (PixelAccessor <TColor> pixels = image.Lock())
            {
                this.WriteStartOfScan(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.EOI;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 44
0
        /// <summary>
        /// Encodes the image with subsampling. The Cb and Cr components are each subsampled
        /// at a factor of 2 both horizontally and vertically.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
        private void Encode420 <TColor>(PixelAccessor <TColor> pixels)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            // TODO: Need a JpegScanEncoder<TColor> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
            Block8x8F b = default(Block8x8F);

            BlockQuad  cb    = default(BlockQuad);
            BlockQuad  cr    = default(BlockQuad);
            Block8x8F *cbPtr = (Block8x8F *)cb.Data;
            Block8x8F *crPtr = (Block8x8F *)cr.Data;

            Block8x8F temp1 = default(Block8x8F);
            Block8x8F temp2 = default(Block8x8F);

            Block8x8F onStackLuminanceQuantTable   = this.luminanceQuantTable;
            Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable;

            UnzigData unzig = UnzigData.Create();

            // ReSharper disable once InconsistentNaming
            int prevDCY = 0, prevDCCb = 0, prevDCCr = 0;

            using (PixelArea <TColor> rgbBytes = new PixelArea <TColor>(8, 8, ComponentOrder.Xyz))
            {
                for (int y = 0; y < pixels.Height; y += 16)
                {
                    for (int x = 0; x < pixels.Width; x += 16)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            int xOff = (i & 1) * 8;
                            int yOff = (i & 2) * 4;

                            ToYCbCr(pixels, x + xOff, y + yOff, &b, cbPtr + i, crPtr + i, rgbBytes);

                            prevDCY = this.WriteBlock(
                                QuantIndex.Luminance,
                                prevDCY,
                                &b,
                                &temp1,
                                &temp2,
                                &onStackLuminanceQuantTable,
                                unzig.Data);
                        }

                        Block8x8F.Scale16X16To8X8(&b, cbPtr);
                        prevDCCb = this.WriteBlock(
                            QuantIndex.Chrominance,
                            prevDCCb,
                            &b,
                            &temp1,
                            &temp2,
                            &onStackChrominanceQuantTable,
                            unzig.Data);

                        Block8x8F.Scale16X16To8X8(&b, crPtr);
                        prevDCCr = this.WriteBlock(
                            QuantIndex.Chrominance,
                            prevDCCr,
                            &b,
                            &temp1,
                            &temp2,
                            &onStackChrominanceQuantTable,
                            unzig.Data);
                    }
                }
            }
        }
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            // Jump out, we'll deal with that later.
            if (source.Width == this.Width && source.Height == this.Height && sourceRectangle == this.ResizeRectangle)
            {
                return;
            }

            int width   = this.Width;
            int height  = this.Height;
            int sourceX = sourceRectangle.X;
            int sourceY = sourceRectangle.Y;
            int startY  = this.ResizeRectangle.Y;
            int endY    = this.ResizeRectangle.Bottom;
            int startX  = this.ResizeRectangle.X;
            int endX    = this.ResizeRectangle.Right;

            int minX = Math.Max(0, startX);
            int maxX = Math.Min(width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(height, endY);

            if (this.Sampler is NearestNeighborResampler)
            {
                // Scaling factors
                float widthFactor  = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
                float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;

                using (PixelAccessor <TColor> targetPixels = new PixelAccessor <TColor>(width, height))
                {
                    using (PixelAccessor <TColor> sourcePixels = source.Lock())
                    {
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Y coordinates of source points
                            int originY = (int)(((y - startY) * heightFactor) + sourceY);

                            for (int x = minX; x < maxX; x++)
                            {
                                // X coordinates of source points
                                targetPixels[x, y] = sourcePixels[(int)(((x - startX) * widthFactor) + sourceX), originY];
                            }
                        });
                    }

                    // Break out now.
                    source.SwapPixelsBuffers(targetPixels);
                    return;
                }
            }

            // Interpolate the image using the calculated weights.
            // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
            // First process the columns. Since we are not using multiple threads startY and endY
            // are the upper and lower bounds of the source rectangle.
            using (PixelAccessor <TColor> targetPixels = new PixelAccessor <TColor>(width, height))
            {
                using (PixelAccessor <TColor> sourcePixels = source.Lock())
                    using (PixelAccessor <TColor> firstPassPixels = new PixelAccessor <TColor>(width, source.Height))
                    {
                        Parallel.For(
                            0,
                            sourceRectangle.Bottom,
                            this.ParallelOptions,
                            y =>
                        {
                            for (int x = minX; x < maxX; x++)
                            {
                                // Ensure offsets are normalised for cropping and padding.
                                Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;

                                // Destination color components
                                Vector4 destination = Vector4.Zero;

                                for (int i = 0; i < horizontalValues.Length; i++)
                                {
                                    Weight xw    = horizontalValues[i];
                                    destination += sourcePixels[xw.Index + sourceX, y].ToVector4().Expand() * xw.Value;
                                }

                                TColor d = default(TColor);
                                d.PackFromVector4(destination.Compress());
                                firstPassPixels[x, y] = d;
                            }
                        });

                        // Now process the rows.
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Ensure offsets are normalised for cropping and padding.
                            Weight[] verticalValues = this.VerticalWeights[y - startY].Values;

                            for (int x = 0; x < width; x++)
                            {
                                // Destination color components
                                Vector4 destination = Vector4.Zero;

                                for (int i = 0; i < verticalValues.Length; i++)
                                {
                                    Weight yw    = verticalValues[i];
                                    destination += firstPassPixels[x, yw.Index + sourceY].ToVector4().Expand() * yw.Value;
                                }

                                TColor d = default(TColor);
                                d.PackFromVector4(destination.Compress());
                                targetPixels[x, y] = d;
                            }
                        });
                    }

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Esempio n. 46
0
		// Converts greyscale luminosity to alpha data.
		public static void ConvertGreyToAlpha(Bitmap bitmap)
		{
			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
			{
				for (int y = 0; y < bitmap.Height; y++)
				{
					for (int x = 0; x < bitmap.Width; x++)
					{
						System.Drawing.Color color = bitmapData[x, y];

						// Average the red, green and blue values to compute brightness.
						int alpha = (color.R + color.G + color.B) / 3;

						bitmapData[x, y] = System.Drawing.Color.FromArgb(alpha, 255, 255, 255);
					}
				}
			}
		}
Esempio n. 47
0
        /// <summary>
        /// Reads the frames colors, mapping indices to colors.
        /// </summary>
        /// <param name="indices">The indexed pixels.</param>
        /// <param name="colorTable">The color table containing the available colors.</param>
        /// <param name="colorTableLength">The color table length.</param>
        /// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
        private unsafe void ReadFrameColors(byte[] indices, byte[] colorTable, int colorTableLength, GifImageDescriptor descriptor)
        {
            int imageWidth  = this.logicalScreenDescriptor.Width;
            int imageHeight = this.logicalScreenDescriptor.Height;

            ImageFrame <TColor> previousFrame = null;

            ImageFrame <TColor> currentFrame = null;

            ImageBase <TColor> image;

            if (this.previousFrame == null)
            {
                this.decodedImage.MetaData.Quality = colorTableLength / 3;

                // This initializes the image to become fully transparent because the alpha channel is zero.
                this.decodedImage.InitPixels(imageWidth, imageHeight);

                this.SetFrameDelay(this.decodedImage.MetaData);

                image = this.decodedImage;
            }
            else
            {
                if (this.graphicsControlExtension != null &&
                    this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    previousFrame = this.previousFrame;
                }

                currentFrame = this.previousFrame.Clone();

                this.SetFrameDelay(currentFrame.MetaData);

                image = currentFrame;

                this.RestoreToBackground(image);

                this.decodedImage.Frames.Add(currentFrame);
            }

            int i                  = 0;
            int interlacePass      = 0; // The interlace pass
            int interlaceIncrement = 8; // The interlacing line increment
            int interlaceY         = 0; // The current interlaced line

            using (PixelAccessor <TColor> pixelAccessor = image.Lock())
            {
                for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                {
                    // Check if this image is interlaced.
                    int writeY; // the target y offset to write to
                    if (descriptor.InterlaceFlag)
                    {
                        // If so then we read lines at predetermined offsets.
                        // When an entire image height worth of offset lines has been read we consider this a pass.
                        // With each pass the number of offset lines changes and the starting line changes.
                        if (interlaceY >= descriptor.Height)
                        {
                            interlacePass++;
                            switch (interlacePass)
                            {
                            case 1:
                                interlaceY = 4;
                                break;

                            case 2:
                                interlaceY         = 2;
                                interlaceIncrement = 4;
                                break;

                            case 3:
                                interlaceY         = 1;
                                interlaceIncrement = 2;
                                break;
                            }
                        }

                        writeY = interlaceY + descriptor.Top;

                        interlaceY += interlaceIncrement;
                    }
                    else
                    {
                        writeY = y;
                    }

                    for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                    {
                        int index = indices[i];

                        if (this.graphicsControlExtension == null ||
                            this.graphicsControlExtension.TransparencyFlag == false ||
                            this.graphicsControlExtension.TransparencyIndex != index)
                        {
                            int indexOffset = index * 3;

                            TColor pixel = default(TColor);
                            pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
                            pixelAccessor[x, writeY] = pixel;
                        }

                        i++;
                    }
                }
            }

            if (previousFrame != null)
            {
                this.previousFrame = previousFrame;
                return;
            }

            this.previousFrame = currentFrame == null?this.decodedImage.ToFrame() : currentFrame;

            if (this.graphicsControlExtension != null &&
                this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
            {
                this.restoreArea = new Rectangle(descriptor.Left, descriptor.Top, descriptor.Width, descriptor.Height);
            }
        }
Esempio n. 48
0
 public virtual void PixBltBGRb(PixelAccessor<BGRb> pixBuff, int x, int y)
 {
     if (null != PixBltBGRbHandler)
         PixBltBGRbHandler(pixBuff, x, y);
 }
Esempio n. 49
0
		// Drawing against a transparent black background blends
		// the 'alpha' pixels against black, leaving a black outline.
		// Interpolate between black and white
		// based on it's intensity to covert this 'outline' to
		// it's grayscale equivalent.
		public static void ConvertToGrey( Bitmap bitmap)
		{
			var transBlack = Color.Transparent;

			using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
			{
				for (int y = 0; y < bitmap.Height; y++)
				{
					for (int x = 0; x < bitmap.Width; x++)
					{
						System.Drawing.Color color = bitmapData[x, y];

						if (color.ColorsEqual(transBlack))
						    continue;

					    var alpha = color.A / (255.0f);
						var col = Color.Lerp(Color.Transparent, Color.White, alpha);
						color = System.Drawing.Color.FromArgb(color.A, col.R, col.G, col.B);
						bitmapData [x, y] = color;
					}
				}
			}
		}