示例#1
0
        private void CalculateDistance(ImageBuffer image)
        {
            var maxDist = (image.Height + image.Width) > 255 ? 255 : (image.Height + image.Width);
            var buffer  = image.GetBuffer();

            // O(n^2) solution to find the Manhattan distance to "on" pixels in a two dimension array
            // traverse from top left to bottom right
            for (int y = 0; y < image.Height; y++)
            {
                var yOffset = image.GetBufferOffsetY(y);
                for (int x = 0; x < image.Width; x++)
                {
                    if (buffer[yOffset + x] == 0)
                    {
                        // first pass and pixel was off, it remains a zero
                    }
                    else
                    {
                        // pixel was on
                        // It is at most the sum of the lengths of the array
                        // away from a pixel that is off
                        buffer[yOffset + x] = (byte)maxDist;
                        // or one more than the pixel to the north
                        if (x > 0)
                        {
                            var value = Math.Min(buffer[yOffset + x], buffer[yOffset + x - 1] + 1);
                            buffer[yOffset + x] = (byte)value;
                        }
                        // or one more than the pixel to the west
                        if (y > 0)
                        {
                            var value = Math.Min(buffer[yOffset + x], buffer[yOffset - image.Width + x] + 1);
                            buffer[yOffset + x] = (byte)value;
                        }
                    }
                }
            }
            // traverse from bottom right to top left
            for (int y = image.Height - 1; y >= 0; y--)
            {
                var yOffset = image.GetBufferOffsetY(y);
                for (int x = image.Width - 1; x >= 0; x--)
                {
                    // either what we had on the first pass
                    // or one more than the pixel to the south
                    if (x + 1 < image.Width)
                    {
                        var value = Math.Min(buffer[yOffset + x], buffer[yOffset + x + 1] + 1);
                        buffer[yOffset + x] = (byte)value;
                    }
                    // or one more than the pixel to the east
                    if (y + 1 < image.Height)
                    {
                        var value = Math.Min(buffer[yOffset + x], buffer[yOffset + image.Width + x] + 1);
                        buffer[yOffset + x] = (byte)value;
                    }
                }
            }
        }
示例#2
0
		public void CopyColorBufferToImage(ImageBuffer destImage, RectangleInt viewport)
		{
			if (destImage.BitDepth != 32)
			{
				throw new Exception("We can only render to 32 bit dest at the moment.");
			}

			Byte[] destBuffer = destImage.GetBuffer();

			viewport.Bottom = Math.Max(0, Math.Min(destImage.Height, viewport.Bottom));
			viewport.Top = Math.Max(0, Math.Min(destImage.Height, viewport.Top));

#if MULTI_THREAD
			System.Threading.Tasks.Parallel.For(viewport.Bottom, viewport.Height, y => //
#else
            for (int y = viewport.Bottom; y < viewport.Height; y++)
#endif
			{
				for (int x = viewport.Left; x < viewport.Right; x++)
				{
					int bufferOffset = destImage.GetBufferOffsetY(y);

					// we don't need to set this if we are anti-aliased
					int totalOffset = bufferOffset + x * 4;
					destBuffer[totalOffset++] = (byte)colorBuffer[x][y].Blue0To255;
					destBuffer[totalOffset++] = (byte)colorBuffer[x][y].Green0To255;
					destBuffer[totalOffset++] = (byte)colorBuffer[x][y].Red0To255;
					destBuffer[totalOffset] = (byte)colorBuffer[x][y].Alpha0To255;
				}
			}
示例#3
0
        public static ImageBuffer Multiply(this ImageBuffer sourceImage, RGBA_Bytes color)
        {
            var outputImage = new ImageBuffer(sourceImage);

            switch (outputImage.BitDepth)
            {
            case 32:
                int    height       = outputImage.Height;
                int    width        = outputImage.Width;
                byte[] imageABuffer = outputImage.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA = outputImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        imageABuffer[offsetA + 0] = (byte)((imageABuffer[offsetA + 0] * color.blue) / 255);
                        imageABuffer[offsetA + 1] = (byte)((imageABuffer[offsetA + 1] * color.green) / 255);
                        imageABuffer[offsetA + 2] = (byte)((imageABuffer[offsetA + 2] * color.red) / 255);
                        imageABuffer[offsetA + 3] = (byte)((imageABuffer[offsetA + 3] * color.alpha) / 255);
                        offsetA += 4;
                    }
                }

                break;

            default:
                throw new NotImplementedException();
            }

            return(outputImage);
        }
示例#4
0
        public MarchingSquaresByte(ImageBuffer imageToMarch, PositiveArea0to1 thresholdFunction, int debugColor)
        {
            thersholdPerPixel = new double[imageToMarch.Width * imageToMarch.Height];
            {
                byte[] buffer        = imageToMarch.GetBuffer();
                int    strideInBytes = imageToMarch.StrideInBytes();
                for (int y = 0; y < imageToMarch.Height; y++)
                {
                    int imageBufferOffset     = imageToMarch.GetBufferOffsetY(y);
                    int thresholdBufferOffset = y * imageToMarch.Width;

                    for (int x = 0; x < imageToMarch.Width; x++)
                    {
                        int imageBufferOffsetWithX = imageBufferOffset + x * 4;
                        thersholdPerPixel[thresholdBufferOffset + x] = thresholdFunction(GetRGBA(buffer, imageBufferOffsetWithX));
                    }
                }
            }

            this.thresholdFunction = thresholdFunction;
            this.imageToMarch      = imageToMarch;
            this.debugColor        = debugColor;

            CreateLineSegments();
        }
示例#5
0
        public void CopyNoramlBufferToImage(ImageBuffer destImage, RectangleInt viewport)
        {
            if (destImage.BitDepth != 32)
            {
                throw new Exception("We can only render to 32 bit dest at the moment.");
            }

            byte[] destBuffer = destImage.GetBuffer();

            viewport.Bottom = Math.Max(0, Math.Min(destImage.Height, viewport.Bottom));
            viewport.Top    = Math.Max(0, Math.Min(destImage.Height, viewport.Top));

            for (int y = viewport.Bottom; y < viewport.Height; y++)
            {
                for (int x = viewport.Left; x < viewport.Right; x++)
                {
                    int bufferOffset = destImage.GetBufferOffsetY(y);

                    // we don't need to set this if we are anti-aliased
                    int totalOffset = bufferOffset + x * 4;
                    destBuffer[totalOffset++] = (byte)((NormalBuffer[x][y].X + 1) * 128);
                    destBuffer[totalOffset++] = (byte)((NormalBuffer[x][y].Y + 1) * 128);
                    destBuffer[totalOffset++] = (byte)((NormalBuffer[x][y].Z + 1) * 128);
                    destBuffer[totalOffset]   = 255;
                }
            }

            destImage.MarkImageChanged();
        }
示例#6
0
        internal static void DoXBlur(ImageBuffer sourceDest)
        {
            if (sourceDest.BitDepth != 8)
            {
                throw new NotImplementedException("We only work with 8 bit at the moment.");
            }

            int height = sourceDest.Height;
            int width  = sourceDest.Width;

            byte[] buffer = sourceDest.GetBuffer();
            byte[] cache  = new byte[width];

            for (int y = 0; y < height; y++)
            {
                int offset = sourceDest.GetBufferOffsetY(y);
                for (int x = 0; x < width; x++)
                {
                    cache[x] = buffer[offset + x];
                }

                for (int x = 1; x < width - 1; x++)
                {
                    int newValue = (cache[x - 1] + cache[x] * 2 + cache[x + 1] + 2) / 4;                     // the + 2 is so that we will round correctly
                    buffer[offset + x] = (byte)newValue;
                }
            }
        }
示例#7
0
        public void BuildHistogramFromImage(ImageBuffer image, ImageToPathObject3D_2.AnalysisTypes analysisType)
        {
            // build the histogram cache
            var height = (int)(100 * GuiWidget.DeviceScale);

            _histogramRawCache = new ImageBuffer(256, height);
            var counts = new int[_histogramRawCache.Width];
            IThresholdFunction function = new MapOnMaxIntensity(0, 1);
            var bottom = 0;

            if (analysisType == ImageToPathObject3D_2.AnalysisTypes.Colors)
            {
                function = new QuickHue();
                bottom   = (int)(10 * GuiWidget.DeviceScale);
            }

            byte[] buffer = image.GetBuffer();
            for (int y = 0; y < image.Height; y++)
            {
                int imageBufferOffset = image.GetBufferOffsetY(y);

                for (int x = 0; x < image.Width; x++)
                {
                    int imageBufferOffsetWithX = imageBufferOffset + x * 4;
                    var color = GetRGBA(buffer, imageBufferOffsetWithX);
                    counts[(int)(function.Transform(color) * (_histogramRawCache.Width - 1))]++;
                }
            }

            double max = counts.Select((value, index) => new { value, index })
                         .OrderByDescending(vi => vi.value)
                         .First().value;
            var graphics = _histogramRawCache.NewGraphics2D();
            var theme    = ApplicationController.Instance.Theme;

            graphics.Clear(theme.SlightShade);

            var graphShape  = new VertexStorage();
            var graphHeight = height - bottom;

            graphShape.MoveTo(0, bottom);
            for (int i = 0; i < 256; i++)
            {
                graphShape.LineTo(i, bottom + Easing.Exponential.Out(counts[i] / max) * graphHeight);
                // graphShape.LineTo(i, bottom + Easing.Cubic.Out(counts[i] / max) * graphHeight);
                // graphShape.LineTo(i, bottom + Easing.Exponential.Out(counts[i] / max) * graphHeight);
                // graphShape.LineTo(i, bottom + counts[i] / max * graphHeight);
            }
            graphShape.LineTo(256, bottom);
            graphShape.LineTo(0, bottom);
            graphics.Render(graphShape, 0, 0, theme.TextColor);

            for (int i = 0; i < 256; i++)
            {
                var hue = ColorF.FromHSL(i / 255.0, 1, .49).ToColor();
                graphics.Line(i, 0, i, bottom, hue);
            }
        }
        public static ImageBuffer AnyAlphaToColor(this ImageBuffer sourceImage, Color color, Color transparency)
        {
            var outputImage = new ImageBuffer(sourceImage);

            switch (outputImage.BitDepth)
            {
            case 32:
            {
                int    height       = outputImage.Height;
                int    width        = outputImage.Width;
                byte[] imageABuffer = outputImage.GetBuffer();

                for (int y = 0; y < height; y++)
                {
                    int offsetA = outputImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        int alpha = imageABuffer[offsetA + 3];
                        if (alpha > 0)
                        {
                            // Set semi-transparent colors
                            imageABuffer[offsetA + 0] = color.blue;
                            imageABuffer[offsetA + 1] = color.green;
                            imageABuffer[offsetA + 2] = color.red;
                            //imageABuffer[offsetA + 3] = (byte) (alpha == 255 ? 255 : 255 - alpha);
                            imageABuffer[offsetA + 3] = (byte)alpha;
                        }
                        else
                        {
                            // Set transparent colors
                            imageABuffer[offsetA + 0] = transparency.blue;
                            imageABuffer[offsetA + 1] = transparency.green;
                            imageABuffer[offsetA + 2] = transparency.red;
                            imageABuffer[offsetA + 3] = transparency.alpha;
                        }

                        offsetA += 4;
                    }
                }

                //outputImage.SetRecieveBlender(new BlenderPreMultBGRA());
            }
            break;

            default:
                throw new NotImplementedException();
            }

            return(outputImage);
        }
        public static void DoAllWhite(ImageBuffer result, ImageBuffer imageA)
        {
            if (imageA.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (imageA.Width != result.Width || imageA.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (imageA.BitDepth)
            {
            case 32:
            {
                int    height       = imageA.Height;
                int    width        = imageA.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] imageABuffer = imageA.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA      = imageA.GetBufferOffsetY(y);
                    int offsetResult = result.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        int alpha = imageABuffer[offsetA + 3];
                        if (alpha > 0)
                        {
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)alpha; offsetA++;
                        }
                        else
                        {
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                        }
                    }
                }
                result.SetRecieveBlender(new BlenderPreMultBGRA());
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#10
0
        private void CopyColorXSpan(ImageBuffer destImage, RectangleInt viewport, int y, byte[] destBuffer)
        {
            for (int x = viewport.Left; x < viewport.Right; x++)
            {
                int bufferOffset = destImage.GetBufferOffsetY(y);

                // we don't need to set this if we are anti-aliased
                int totalOffset = bufferOffset + x * 4;
                destBuffer[totalOffset++] = (byte)ColorBuffer[x][y].Blue0To255;
                destBuffer[totalOffset++] = (byte)ColorBuffer[x][y].Green0To255;
                destBuffer[totalOffset++] = (byte)ColorBuffer[x][y].Red0To255;
                destBuffer[totalOffset]   = (byte)ColorBuffer[x][y].Alpha0To255;
            }
        }
示例#11
0
        public static void DoSubtract(ImageBuffer result, ImageBuffer imageToSubtractFrom, ImageBuffer imageToSubtract)
        {
            if (lookupSubtractAndClamp == null)
            {
                CreateLookup();
            }

            if (imageToSubtractFrom.BitDepth != imageToSubtract.BitDepth || imageToSubtract.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (imageToSubtractFrom.Width != imageToSubtract.Width || imageToSubtractFrom.Height != imageToSubtract.Height ||
                imageToSubtractFrom.Width != result.Width || imageToSubtractFrom.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (imageToSubtractFrom.BitDepth)
            {
            case 32:
            {
                int    height       = imageToSubtractFrom.Height;
                int    width        = imageToSubtractFrom.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] imageABuffer = imageToSubtractFrom.GetBuffer();
                byte[] imageBBuffer = imageToSubtract.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offset = imageToSubtractFrom.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255];         // add 255 to make sure not < 0
                        offset++;
                        resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255];
                        offset++;
                        resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255];
                        offset++;
                        resultBuffer[offset] = 255;
                        offset++;
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#12
0
        public static void DoSetGrayToColor(ImageBuffer result, ImageBuffer imageA, Color color)
        {
            if (imageA.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (imageA.Width != result.Width || imageA.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (imageA.BitDepth)
            {
            case 32:
            {
                int    height       = imageA.Height;
                int    width        = imageA.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] imageABuffer = imageA.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA      = imageA.GetBufferOffsetY(y);
                    int offsetResult = result.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        imageA.GetPixel(x, y).ToColorF().GetHSL(out double _, out double s, out double _);

                        if (s < .01)
                        {
                            resultBuffer[offsetResult++] = (byte)(color.blue); offsetA++;
                            resultBuffer[offsetResult++] = (byte)(color.green); offsetA++;
                            resultBuffer[offsetResult++] = (byte)(color.red); offsetA++;
                            resultBuffer[offsetResult++] = imageABuffer[offsetA++];
                        }
                        else
                        {
                            offsetResult += 4;
                            offsetA      += 4;
                        }
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#13
0
        public static void DoThreshold(ImageBuffer result, ImageBuffer sourceImage, int threshold, TestThreshold testFunction)
        {
            if (sourceImage.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (sourceImage.Width != result.Width || sourceImage.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (sourceImage.BitDepth)
            {
            case 32:
            {
                int    height       = sourceImage.Height;
                int    width        = sourceImage.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] sourceBuffer = sourceImage.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offset = sourceImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        if (testFunction(sourceBuffer, offset, threshold))
                        {
                            resultBuffer[offset + 0] = (byte)255;
                            resultBuffer[offset + 1] = (byte)255;
                            resultBuffer[offset + 2] = (byte)255;
                            resultBuffer[offset + 3] = (byte)255;
                        }
                        else
                        {
                            resultBuffer[offset + 0] = (byte)0;
                            resultBuffer[offset + 1] = (byte)0;
                            resultBuffer[offset + 2] = (byte)0;
                            resultBuffer[offset + 3] = (byte)0;
                        }
                        offset += 4;
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#14
0
        public static ImageBuffer ReplaceColor(this ImageBuffer sourceImage, Color existingColor, Color newColor, bool keepExistingAlpha = true)
        {
            var outputImage = new ImageBuffer(sourceImage);

            switch (outputImage.BitDepth)
            {
            case 32:
            {
                int    height       = outputImage.Height;
                int    width        = outputImage.Width;
                byte[] imageABuffer = outputImage.GetBuffer();

                for (int y = 0; y < height; y++)
                {
                    int offsetA = outputImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        if (imageABuffer[offsetA + 0] == existingColor.blue &&
                            imageABuffer[offsetA + 1] == existingColor.green &&
                            imageABuffer[offsetA + 2] == existingColor.red &&
                            imageABuffer[offsetA + 3] == existingColor.alpha)
                        {
                            // Set transparent colors
                            imageABuffer[offsetA + 0] = newColor.blue;
                            imageABuffer[offsetA + 1] = newColor.green;
                            imageABuffer[offsetA + 2] = newColor.red;

                            if (!keepExistingAlpha)
                            {
                                imageABuffer[offsetA + 3] = newColor.alpha;
                            }
                        }

                        offsetA += 4;
                    }
                }

                outputImage.SetRecieveBlender(new BlenderPreMultBGRA());
            }
            break;

            default:
                throw new NotImplementedException();
            }

            return(outputImage);
        }
示例#15
0
        public static ImageBuffer AllWhite(this ImageBuffer sourceImage)
        {
            var destImage = new ImageBuffer(sourceImage);

            switch (destImage.BitDepth)
            {
            case 32:
            {
                int    height       = destImage.Height;
                int    width        = destImage.Width;
                byte[] resultBuffer = sourceImage.GetBuffer();
                byte[] imageABuffer = destImage.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA      = destImage.GetBufferOffsetY(y);
                    int offsetResult = sourceImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        int alpha = imageABuffer[offsetA + 3];
                        if (alpha > 0)
                        {
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)255; offsetA++;
                            resultBuffer[offsetResult++] = (byte)alpha; offsetA++;
                        }
                        else
                        {
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                            resultBuffer[offsetResult++] = (byte)0; offsetA++;
                        }
                    }
                }

                destImage.SetRecieveBlender(new BlenderPreMultBGRA());
            }
            break;

            default:
                throw new NotImplementedException();
            }

            return(destImage);
        }
示例#16
0
        private void CopyDepthXSpan(ImageBuffer destImage, RectangleInt viewport, int y, byte[] destBuffer, double minZ, double divisor)
        {
            for (int x = viewport.Left; x < viewport.Right; x++)
            {
                int bufferOffset = destImage.GetBufferOffsetY(y);

                // we don't need to set this if we are anti-aliased
                int    totalOffset  = bufferOffset + x * 4;
                double depthXY      = DepthBuffer[x][y];
                double rangedDepth  = (depthXY - minZ) / divisor;
                double clampedDepth = Math.Max(0, Math.Min(255, rangedDepth * 255));
                byte   depthColor   = (byte)clampedDepth;
                destBuffer[totalOffset++] = depthColor;
                destBuffer[totalOffset++] = depthColor;
                destBuffer[totalOffset++] = depthColor;
                destBuffer[totalOffset]   = 255;
            }
        }
示例#17
0
        private bool ColorDetected(ImageBuffer sourceImage, out double hueDetected)
        {
            byte[] sourceBuffer = sourceImage.GetBuffer();
            var    min          = new Vector3(double.MaxValue, double.MaxValue, double.MaxValue);
            var    max          = new Vector3(double.MinValue, double.MinValue, double.MinValue);

            var hueCount    = new int[10];
            var colorPixels = 0;

            for (int y = 0; y < sourceImage.Height; y++)
            {
                int imageOffset = sourceImage.GetBufferOffsetY(y);
                for (int x = 0; x < sourceImage.Width; x++)
                {
                    int offset = imageOffset + x * 4;
                    var b      = sourceBuffer[offset + 0];
                    var g      = sourceBuffer[offset + 1];
                    var r      = sourceBuffer[offset + 2];

                    var color = new ColorF(r / 255.0, g / 255.0, b / 255.0);
                    color.GetHSL(out double hue, out double saturation, out double lightness);

                    min = Vector3.ComponentMin(min, new Vector3(hue, saturation, lightness));
                    max = Vector3.ComponentMax(max, new Vector3(hue, saturation, lightness));

                    if (saturation > .4 && lightness > .1 && lightness < .9)
                    {
                        hueCount[(int)(hue * 9)]++;
                        colorPixels++;
                    }
                }
            }


            if (colorPixels / (double)(sourceImage.Width * sourceImage.Height) > .1)
            {
                var indexAtMax = hueCount.ToList().IndexOf(hueCount.Max());
                hueDetected = indexAtMax / 10.0;
                return(true);
            }

            hueDetected = 0;
            return(false);
        }
示例#18
0
        private void RebuildColorToAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage, ImageBuffer displayImage)
        {
            if (sourceImage == null)
            {
                return;
            }

            // build the alpha image
            if (alphaImage == null)
            {
                alphaImage = new ImageBuffer(sourceImage.Width, sourceImage.Height);
            }
            else if (alphaImage.Width != sourceImage.Width ||
                     alphaImage.Height != sourceImage.Height)
            {
                alphaImage.Allocate(sourceImage.Width, sourceImage.Height, sourceImage.BitDepth, sourceImage.GetRecieveBlender());
            }

            byte[] sourceBuffer = sourceImage.GetBuffer();
            byte[] destBuffer   = alphaImage.GetBuffer();
            Parallel.For(0, sourceImage.Height, (y) =>
                         //for(int y = 0; y < sourceImage.Height; y++)
            {
                int imageOffset = sourceImage.GetBufferOffsetY(y);

                for (int x = 0; x < sourceImage.Width; x++)
                {
                    int imageBufferOffsetWithX = imageOffset + x * 4;
                    var b = sourceBuffer[imageBufferOffsetWithX + 0];
                    var g = sourceBuffer[imageBufferOffsetWithX + 1];
                    var r = sourceBuffer[imageBufferOffsetWithX + 2];
                    destBuffer[imageBufferOffsetWithX + 0] = b;
                    destBuffer[imageBufferOffsetWithX + 1] = g;
                    destBuffer[imageBufferOffsetWithX + 2] = r;
                    destBuffer[imageBufferOffsetWithX + 3] = GetAlphaFromHue(r, g, b, RangeStart, RangeEnd);
                }
                //}
            });

            alphaImage.MarkImageChanged();

            displayImage.CopyFrom(alphaImage);
        }
示例#19
0
        public static void DoInvertLightness(ImageBuffer result, ImageBuffer sourceImage)
        {
            if (sourceImage.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (sourceImage.Width != result.Width || sourceImage.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (sourceImage.BitDepth)
            {
            case 32:
            {
                int    height       = sourceImage.Height;
                int    width        = sourceImage.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] sourceBuffer = sourceImage.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offset = sourceImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        RGBA_Bytes color         = new RGBA_Bytes(resultBuffer[offset + 2], resultBuffer[offset + 1], resultBuffer[offset + 0], resultBuffer[offset + 3]);
                        RGBA_Bytes invertedColor = InvertColor(color);

                        resultBuffer[offset + 0] = invertedColor.blue;
                        resultBuffer[offset + 1] = invertedColor.green;
                        resultBuffer[offset + 2] = invertedColor.blue;
                        resultBuffer[offset + 3] = invertedColor.alpha;

                        offset += 4;
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#20
0
        public static void DoMultiply(ImageBuffer result, ImageBuffer imageA, ImageBuffer imageB)
        {
            if (imageA.BitDepth != imageB.BitDepth || imageB.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (imageA.Width != imageB.Width || imageA.Height != imageB.Height ||
                imageA.Width != result.Width || imageA.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (imageA.BitDepth)
            {
            case 32:
            {
                int    height       = imageA.Height;
                int    width        = imageA.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] imageABuffer = imageA.GetBuffer();
                byte[] imageBBuffer = imageB.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA      = imageA.GetBufferOffsetY(y);
                    int offsetB      = imageB.GetBufferOffsetY(y);
                    int offsetResult = result.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255);
                        resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255);
                        resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255);
                        resultBuffer[offsetResult++] = 255; offsetA++; offsetB++;
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#21
0
        public static void DoWhiteToColor(ImageBuffer result, ImageBuffer imageA, RGBA_Bytes color)
        {
            if (imageA.BitDepth != result.BitDepth)
            {
                throw new NotImplementedException("All the images have to be the same bit depth.");
            }
            if (imageA.Width != result.Width || imageA.Height != result.Height)
            {
                throw new Exception("All images must be the same size.");
            }

            switch (imageA.BitDepth)
            {
            case 32:
            {
                int    height       = imageA.Height;
                int    width        = imageA.Width;
                byte[] resultBuffer = result.GetBuffer();
                byte[] imageABuffer = imageA.GetBuffer();
                for (int y = 0; y < height; y++)
                {
                    int offsetA      = imageA.GetBufferOffsetY(y);
                    int offsetResult = result.GetBufferOffsetY(y);

                    byte amoutOfWhite = imageABuffer[offsetA];

                    for (int x = 0; x < width; x++)
                    {
                        resultBuffer[offsetResult++] = (byte)(color.blue * amoutOfWhite / 255); offsetA++;
                        resultBuffer[offsetResult++] = (byte)(color.green * amoutOfWhite / 255); offsetA++;
                        resultBuffer[offsetResult++] = (byte)(color.red * amoutOfWhite / 255); offsetA++;
                        resultBuffer[offsetResult++] = imageABuffer[offsetA++];
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#22
0
        public static ImageBuffer AjustAlpha(this ImageBuffer sourceImage, double factor)
        {
            var outputImage = new ImageBuffer(sourceImage);

            switch (outputImage.BitDepth)
            {
            case 32:
            {
                int    height       = outputImage.Height;
                int    width        = outputImage.Width;
                byte[] imageABuffer = outputImage.GetBuffer();

                for (int y = 0; y < height; y++)
                {
                    int offsetA = outputImage.GetBufferOffsetY(y);

                    for (int x = 0; x < width; x++)
                    {
                        var alpha = imageABuffer[offsetA + 3];
                        if (alpha > 0)
                        {
                            imageABuffer[offsetA + 3] = (byte)(alpha * factor);
                        }

                        offsetA += 4;
                    }
                }

                outputImage.SetRecieveBlender(new BlenderPreMultBGRA());
            }
            break;

            default:
                throw new NotImplementedException();
            }

            return(outputImage);
        }
示例#23
0
        private void Paint(ImageBuffer dest, ImageBuffer source, int level)
        {
            int height = source.Height;
            int width  = source.Width;
            int sourceStrideInBytes = source.StrideInBytes();
            int destStrideInBytes   = dest.StrideInBytes();

            byte[] sourceBuffer = source.GetBuffer();
            byte[] destBuffer   = dest.GetBuffer();

            for (int y = 1; y < height - 1; y++)
            {
                int offset = source.GetBufferOffsetY(y);
                for (int x = 1; x < width - 1; x++)
                {
                    if (destBuffer[offset] == 255 &&                  // the dest is white
                        sourceBuffer[offset] == 0)                            // the dest is cleared
                    {
                        destBuffer[offset] = (byte)level;
                    }
                    offset++;
                }
            }
        }
示例#24
0
        public MarchingSquaresByte(ImageBuffer sourceImage, Color edgeColor, Func <Color, double> thresholdFunction, int debugColor)
        {
            // expand the image so we have a border around it (in case it goes to the edge)
            var imageToMarch = new ImageBuffer(sourceImage.Width + 2, sourceImage.Height + 2);

            imageToMarch.SetRecieveBlender(new BlenderBGRAExactCopy());
            var graphics2D = imageToMarch.NewGraphics2D();

            graphics2D.Clear(edgeColor);
            graphics2D.Render(sourceImage, 1, 1);

            thersholdPerPixel = new double[imageToMarch.Width * imageToMarch.Height];
            {
                byte[] buffer        = imageToMarch.GetBuffer();
                int    strideInBytes = imageToMarch.StrideInBytes();
                for (int y = 0; y < imageToMarch.Height; y++)
                {
                    int imageBufferOffset     = imageToMarch.GetBufferOffsetY(y);
                    int thresholdBufferOffset = y * imageToMarch.Width;

                    for (int x = 0; x < imageToMarch.Width; x++)
                    {
                        int imageBufferOffsetWithX = imageBufferOffset + x * 4;
                        var color          = GetRGBA(buffer, imageBufferOffsetWithX);
                        var thresholdValue = thresholdFunction(color);
                        thersholdPerPixel[thresholdBufferOffset + x] = thresholdValue;
                    }
                }
            }

            this.ThresholdFunction = thresholdFunction;
            this.imageToMarch      = imageToMarch;
            this.debugColor        = debugColor;

            CreateLineSegments();
        }
示例#25
0
        private static void Copy8BitDataToImage(ImageBuffer destImage, Bitmap bitmap)
        {
            destImage.Allocate(bitmap.Width, bitmap.Height, bitmap.Width * 4, 32);
            if (destImage.GetRecieveBlender() == null)
            {
                destImage.SetRecieveBlender(new BlenderBGRA());
            }

            BitmapData bitmapData  = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
            int        sourceIndex = 0;
            int        destIndex   = 0;

            unsafe
            {
                byte[] destBuffer    = destImage.GetBuffer(out int offset);
                byte * pSourceBuffer = (byte *)bitmapData.Scan0;

                System.Drawing.Color[] colors = bitmap.Palette.Entries;

                for (int y = 0; y < destImage.Height; y++)
                {
                    sourceIndex = y * bitmapData.Stride;
                    destIndex   = destImage.GetBufferOffsetY(destImage.Height - 1 - y);
                    for (int x = 0; x < destImage.Width; x++)
                    {
                        System.Drawing.Color color = colors[pSourceBuffer[sourceIndex++]];
                        destBuffer[destIndex++] = color.B;
                        destBuffer[destIndex++] = color.G;
                        destBuffer[destIndex++] = color.R;
                        destBuffer[destIndex++] = color.A;
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
        }
示例#26
0
        private void RebuildIntensityToAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage, ImageBuffer displayImage)
        {
            if (sourceImage == null)
            {
                return;
            }

            // build the alpha image
            if (alphaImage.Width != sourceImage.Width ||
                alphaImage.Height != sourceImage.Height)
            {
                alphaImage.Allocate(sourceImage.Width, sourceImage.Height, sourceImage.BitDepth, sourceImage.GetRecieveBlender());
                displayImage.Allocate(sourceImage.Width, sourceImage.Height, sourceImage.BitDepth, sourceImage.GetRecieveBlender());
            }

            var startInt = (int)(RangeStart * 255);
            var endInt   = (int)(RangeEnd * 255);
            var rangeInt = (int)Math.Max(1, (RangeEnd - RangeStart) * 255);

            byte GetAlphaFromIntensity(byte r, byte g, byte b)
            {
                // return (color.Red0To1 * 0.2989) + (color.Green0To1 * 0.1140) + (color.Blue0To1 * 0.5870);
                var alpha = (r * 76 + g * 29 + b * 150) / 255;

                if (alpha < startInt)
                {
                    return(0);
                }
                else if (alpha > endInt)
                {
                    return(0);
                }
                else
                {
                    if (rangeInt > 64)
                    {
                        var s1 = 255 - Math.Min(255, ((alpha - startInt) * 255 / rangeInt));
                        return((byte)s1);
                    }

                    return(255);
                }
            }

            byte[] sourceBuffer = sourceImage.GetBuffer();
            byte[] destBuffer   = alphaImage.GetBuffer();
            Parallel.For(0, sourceImage.Height, (y) =>
            {
                int imageOffset = sourceImage.GetBufferOffsetY(y);

                for (int x = 0; x < sourceImage.Width; x++)
                {
                    int imageBufferOffsetWithX = imageOffset + x * 4;
                    var b = sourceBuffer[imageBufferOffsetWithX + 0];
                    var g = sourceBuffer[imageBufferOffsetWithX + 1];
                    var r = sourceBuffer[imageBufferOffsetWithX + 2];
                    var a = sourceBuffer[imageBufferOffsetWithX + 3];
                    destBuffer[imageBufferOffsetWithX + 0] = b;
                    destBuffer[imageBufferOffsetWithX + 1] = g;
                    destBuffer[imageBufferOffsetWithX + 2] = r;
                    destBuffer[imageBufferOffsetWithX + 3] = (byte)(GetAlphaFromIntensity(r, g, b) * a / 255);
                }
            });

            alphaImage.MarkImageChanged();

            byte[] displayBuffer = displayImage.GetBuffer();
            Parallel.For(0, sourceImage.Height, (y) =>
            {
                int imageOffset = displayImage.GetBufferOffsetY(y);

                for (int x = 0; x < displayImage.Width; x++)
                {
                    int imageBufferOffsetWithX = imageOffset + x * 4;
                    displayBuffer[imageBufferOffsetWithX + 0] = destBuffer[imageBufferOffsetWithX + 0];
                    displayBuffer[imageBufferOffsetWithX + 1] = destBuffer[imageBufferOffsetWithX + 1];
                    displayBuffer[imageBufferOffsetWithX + 2] = destBuffer[imageBufferOffsetWithX + 2];
                    if (destBuffer[imageBufferOffsetWithX + 3] > 1)
                    {
                        displayBuffer[imageBufferOffsetWithX + 3] = 255;
                    }
                    else
                    {
                        displayBuffer[imageBufferOffsetWithX + 3] = 0;
                    }
                }
            });

            displayImage.MarkImageChanged();
        }
        void FindSubPixelPositions(ImageBuffer imageBuffer)
        {
            // find the subpixel center
            int imageWidth  = imageBuffer.Width;
            int imageHeight = imageBuffer.Height;

            byte[] buffer = imageBuffer.GetBuffer();

            foreach (ValidResponseData validResponse in validResponsesBotomToTopList)
            {
                Vector2 position   = validResponse.position;
                int     centerXInt = (int)(position.x + .5);
                int     centerYInt = (int)(position.y + .5);

                int min = int.MaxValue;
                int max = int.MinValue;
                {
                    for (int y = centerYInt - 5; y <= centerYInt + 5; y++)
                    {
                        int byteOffset = imageBuffer.GetBufferOffsetY(y);
                        ValidResponseData[] totalResponseRow = allResponsesGrid.GetRow(y);
                        for (int x = centerXInt - 5; x <= centerXInt + 5; x++)
                        {
                            int intensity = buffer[byteOffset + x];
                            if (intensity < min)
                            {
                                min = intensity;
                            }
                            if (intensity > max)
                            {
                                max = intensity;
                            }
                        }
                    }
                }
                double center   = (max - min) / 2 + min;
                double maxRange = (max - min) / 4;

                {
                    double  weight = 0;
                    Vector2 accumulatedPosition = Vector2.Zero;
                    for (int y = centerYInt - 5; y <= centerYInt + 5; y++)
                    {
                        int byteOffset = imageBuffer.GetBufferOffsetY(y);
                        ValidResponseData[] totalResponseRow = allResponsesGrid.GetRow(y);
                        for (int x = centerXInt - 5; x <= centerXInt + 5; x++)
                        {
                            int    value = buffer[byteOffset + x];
                            double absDeltaFromCenter = Math.Abs(value - center);
                            double contribution       = 1 - (absDeltaFromCenter / maxRange);
                            contribution = Math.Max(0, Math.Min(1, contribution));
                            double distScalling = Math.Min(1, Math.Max(0, 1 - ((new Vector2(x, y) - position).Length - 3) / 2));
                            contribution        *= distScalling;
                            weight              += contribution;
                            accumulatedPosition += new Vector2(x, y) * contribution;

#if SHOW_SUB_PIXEL_LOGIC
                            if (i == 4)
                            {
                                buffer[byteOffset + x] = (byte)(contribution * 255);
                            }
#endif
                        }
                    }

                    validResponse.position = accumulatedPosition / weight;
                }
            }
        }
示例#28
0
        public static void DoErode3x3Binary(ImageBuffer source, ImageBuffer dest, int threshold)
        {
            if (source.Width != dest.Width ||
                source.Height != dest.Height ||
                source.StrideInBytes() != dest.StrideInBytes())
            {
                throw new NotImplementedException("Source and Dest have to be the same size");
            }

            switch (source.BitDepth)
            {
            case 8:
            {
                int    height        = source.Height;
                int    width         = source.Width;
                int    strideInBytes = source.StrideInBytes();
                byte[] sourceBuffer  = source.GetBuffer();
                byte[] destBuffer    = dest.GetBuffer();

                System.Threading.Tasks.Parallel.For(1, height, y =>
                                                    //for (int y = 1; y < height - 1; y++)
                    {
                        int rowOffset = source.GetBufferOffsetY(y);
                        for (int x = 1; x < width - 1; x++)
                        {
                            int bufferOffset = rowOffset + x;
                            // make sure it is set to 1 if we don't change it to 0
                            destBuffer[bufferOffset] = 255;

                            // do the upper left
                            int checkOffset = bufferOffset - strideInBytes - 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }
                            // do the upper center
                            checkOffset = bufferOffset - strideInBytes + 0;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the upper right
                            checkOffset = bufferOffset - strideInBytes + 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the center left
                            checkOffset = bufferOffset + strideInBytes - 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the center center
                            checkOffset = bufferOffset + strideInBytes + 0;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the lower right
                            checkOffset = bufferOffset + strideInBytes + 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the lower left
                            checkOffset = bufferOffset + strideInBytes - 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the lower center
                            checkOffset = bufferOffset + strideInBytes + 0;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }

                            // do the lower right
                            checkOffset = bufferOffset + strideInBytes + 1;
                            if (sourceBuffer[checkOffset] < threshold)
                            {
                                destBuffer[bufferOffset] = 0;
                                continue;
                            }
                        }
                    });
            }
            break;

            case 32:
            {
                int    height = source.Height;
                int    width  = source.Width;
                int    sourceStrideInBytes = source.StrideInBytes();
                int    destStrideInBytes   = dest.StrideInBytes();
                byte[] sourceBuffer        = source.GetBuffer();
                byte[] destBuffer          = dest.GetBuffer();

                for (int destY = 1; destY < height - 1; destY++)
                {
                    for (int destX = 1; destX < width - 1; destX++)
                    {
                        for (int sourceY = -1; sourceY <= 1; sourceY++)
                        {
                            for (int sourceX = -1; sourceX <= 1; sourceX++)
                            {
                                int sourceOffset = source.GetBufferOffsetXY(destX + sourceX, destY + sourceY);
                                if (sourceBuffer[sourceOffset] < threshold)
                                {
                                    int destOffset = dest.GetBufferOffsetXY(destX, destY);
                                    destBuffer[destOffset++] = 0;
                                    destBuffer[destOffset++] = 0;
                                    destBuffer[destOffset++] = 0;
                                    destBuffer[destOffset++] = 255;
                                }
                            }
                        }
                    }
                }
            }
            break;

            default:
                throw new NotImplementedException();
            }
        }
示例#29
0
        public void RayTraceScene(ImageBuffer destImage, RectangleInt viewport, Scene scene)
        {
            int maxsamples = (int)AntiAliasing;

            //graphics2D.FillRectangle(viewport, RGBA_Floats.Black);

            if (imageBufferAsDoubles == null || imageBufferAsDoubles.Length < viewport.Width || imageBufferAsDoubles[0].Length < viewport.Height)
            {
                imageBufferAsDoubles = new RGBA_Floats[viewport.Width][];
                for (int i = 0; i < viewport.Width; i++)
                {
                    imageBufferAsDoubles[i] = new RGBA_Floats[viewport.Height];
                }
            }

            if (destImage.BitDepth != 32)
            {
                throw new Exception("We can only render to 32 bit dest at the moment.");
            }

            Byte[] destBuffer = destImage.GetBuffer();

            viewport.Bottom = Math.Max(0, Math.Min(destImage.Height, viewport.Bottom));
            viewport.Top = Math.Max(0, Math.Min(destImage.Height, viewport.Top));

#if MULTI_THREAD
            System.Threading.Tasks.Parallel.For(viewport.Bottom, viewport.Height, y => //  
#else
            for (int y = viewport.Bottom; y < viewport.Height; y++)
#endif
            {
                for (int x = viewport.Left; x < viewport.Right; x++)
                {
                    if (traceWithRayBundles)
                    {
                        int width = Math.Min(8, viewport.Right - x);
                        int height = Math.Min(8, viewport.Top - y);
                        FrustumRayBundle rayBundle = new FrustumRayBundle(width * height);
                        IntersectInfo[] intersectionsForBundle = new IntersectInfo[width * height];
                        for (int rayY = 0; rayY < height; rayY++)
                        {
                            for (int rayX = 0; rayX < width; rayX++)
                            {
                                rayBundle.rayArray[rayX + rayY * width] = scene.camera.GetRay(x + rayX, y + rayY);
                                intersectionsForBundle[rayX + rayY * width] = new IntersectInfo();
                            }
                        }

                        rayBundle.CalculateFrustum(width, height,  scene.camera.Origin);
                        
                        FullyTraceRayBundle(rayBundle, intersectionsForBundle, scene);

                        for (int rayY = 0; rayY < height; rayY++)
                        {
                            int bufferOffset = destImage.GetBufferOffsetY(y + rayY);

                            for (int rayX = 0; rayX < width; rayX++)
                            {
                                imageBufferAsDoubles[x + rayX][y + rayY] = intersectionsForBundle[rayX + rayY * width].totalColor;

                                if (AntiAliasing == AntiAliasing.None)
                                {
                                    // we don't need to set this if we are anti-aliased
                                    int totalOffset = bufferOffset + (x + rayX) * 4;
                                    destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Blue0To255;
                                    destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Green0To255;
                                    destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Red0To255;
                                    destBuffer[totalOffset] = 255;
                                }
                            }
                        }
                        x += width - 1; // skip all the pixels we bundled
                        y += height - 1; // skip all the pixels we bundled
                    }
                    else
                    {
                        int bufferOffset = destImage.GetBufferOffsetY(y);

                        Ray ray = scene.camera.GetRay(x, y);

                        imageBufferAsDoubles[x][y] = FullyTraceRay(ray, scene);

                        // we don't need to set this if we are anti-aliased
                        int totalOffset = bufferOffset + x * 4;
                        destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Blue0To255;
                        destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Green0To255;
                        destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Red0To255;
                        destBuffer[totalOffset] = 255;
                    }
                }
            }