예제 #1
0
        private Color GetTolerance(Point point, Color expected)
        {
            // pixelCenter is factored into this point

            int x = (int)Math.Floor(point.X - Const.pixelCenterX);
            int y = (int)Math.Floor(point.Y - Const.pixelCenterY);

            Color missingPixelTolerance = ColorOperations.ColorFromArgb(0, 0, 0, 0);
            Color lookupTolerance       = ColorOperations.ColorFromArgb(0, 0, 0, 0);

            for (int j = y; j < y + 2; j++)
            {
                for (int i = x; i < x + 2; i++)
                {
                    Color?current = SafeGetPixel(i, j);
                    if (current.HasValue)
                    {
                        // Keep the max of the diff tolerance and the existing tolerance
                        Color diff = ColorOperations.AbsoluteDifference(current.Value, expected);
                        lookupTolerance = ColorOperations.Max(lookupTolerance, diff);
                        lookupTolerance = ColorOperations.Max(lookupTolerance, toleranceBuffer[i, j]);
                    }
                    else
                    {
                        // increase tolerance by 25% since this pixel's value is unknown
                        missingPixelTolerance = ColorOperations.Add(missingPixelTolerance, ColorOperations.ColorFromArgb(.25, .25, .25, .25));
                    }
                }
            }
            return(ColorOperations.Add(lookupTolerance, missingPixelTolerance));
        }
예제 #2
0
        /// <summary/>
        virtual public Color FilteredErrorLookup(Point uvLow, Point uvHigh, Color computedColor)
        {
            // Mipmapping uses a recursive texture pyramid where each level is 1/4 of the previous one.
            // This makes it necessary to maintain a 1:1 width:height sample ratio for
            // error tolerance estimation since that is the area that the mipmapped sample was computed from.
            double uvWidth  = uvHigh.X - uvLow.X;
            double uvHeight = uvHigh.Y - uvLow.Y;

            // Force 1:1 aspect ratio on the larger side
            if (uvWidth > uvHeight)
            {
                double vFix = (uvWidth - uvHeight) / 2.0;
                uvLow.Y  -= vFix;
                uvHigh.Y += vFix;
            }
            else
            {
                double uFix = (uvHeight - uvWidth) / 2.0;
                uvLow.X  -= uFix;
                uvHigh.X += uFix;
            }

            // Define where we want to have texel centers
            double texelCenterX = 0.5;
            double texelCenterY = 0.5;
            // -/+ texelCenters so that we always at least compare against the raw indices of bilinear filtering
            int xLo = (int)Math.Floor(uvLow.X * width - (1 - texelCenterX));
            int xHi = (int)Math.Ceiling(uvHigh.X * width + texelCenterX);
            int yLo = (int)Math.Floor(uvLow.Y * height - (1 - texelCenterY));
            int yHi = (int)Math.Ceiling(uvHigh.Y * height + texelCenterY);

            Color tolerance = Color.FromArgb(0x00, 0x00, 0x00, 0x00);

            for (int y = yLo; y <= yHi; y++)
            {
                for (int x = xLo; x <= xHi; x++)
                {
                    Color current = GetColor(x, y);
                    Color diff    = ColorOperations.AbsoluteDifference(current, computedColor);
                    tolerance = ColorOperations.Max(tolerance, diff);
                }
            }

            return(tolerance);
        }
예제 #3
0
        public override Color FilteredErrorLookup(Point uvLow, Point uvHigh, Color computedColor)
        {
            int lowerIndex = 0;
            int upperIndex = 0;

            Color computedError;

            // look for appropriate levels
            while (upperIndex < levels.Count && mipmapFactor > levels[upperIndex].PixelSize)
            {
                upperIndex++;
            }
            upperIndex = Math.Min(upperIndex, levels.Count - 1);
            lowerIndex = Math.Max(upperIndex - 1, 0);

            // Now perform error lookup on the mipmap levels
            if (lowerIndex == upperIndex)
            {
                // no need to blend, clear case of too near (pure bilinear mag)
                // or too far (1 pixel last level)
                computedError = levels[lowerIndex].FilteredErrorLookup(uvLow, uvHigh, computedColor);
            }
            else
            {
                // Find the colors of the adjacent levels
                Color lowerLevel = levels[lowerIndex].FilteredErrorLookup(uvLow, uvHigh, computedColor);
                Color upperLevel = levels[upperIndex].FilteredErrorLookup(uvLow, uvHigh, computedColor);

                // Find a suitable blend factor
                double lowerPixelSize = levels[lowerIndex].PixelSize;
                double upperPixelSize = levels[upperIndex].PixelSize;
                // upper pixel is 2x larger than lower pixel
                double blendFactor = (mipmapFactor / lowerPixelSize) - 1;

                // return the mix
                computedError = ColorOperations.Blend(upperLevel, lowerLevel, blendFactor);
            }

            // Compare against bilinear error
            Color baseError = base.FilteredErrorLookup(uvLow, uvHigh, computedColor);

            computedError = ColorOperations.Max(computedError, baseError);

            return(computedError);
        }
예제 #4
0
        private void ApplyDropShadow(DropShadowBitmapEffect effect, Rect effectInput)
        {
            RenderBuffer clone = Clone();

            clone.boundsOverride = effectInput;
            double depth       = MathEx.ConvertToAbsolutePixels(effect.ShadowDepth);
            double angle       = MathEx.ToRadians(effect.Direction);
            Vector pixelOffset = new Vector(depth * Math.Cos(angle), depth * Math.Sin(-angle));
            Color  effectColor = effect.Color;

            effectColor = ColorOperations.ScaleAlpha(effectColor, effect.Opacity);
            double blurRadius = 1.0 + (effect.Softness * 9.0);

            int xEnd = (int)effectInput.Right;
            int yEnd = (int)effectInput.Bottom;

            for (int y = (int)effectInput.Y; y < yEnd; y++)
            {
                for (int x = (int)effectInput.X; x < xEnd; x++)
                {
                    Point point = new Point(x + Const.pixelCenterX, y + Const.pixelCenterY) - pixelOffset;
                    Color?color = clone.GetPixelSample(point, blurRadius);

                    if (color.HasValue)
                    {
                        double opacity = ColorOperations.ByteToDouble(color.Value.A);
                        Color  shadow  = ColorOperations.ScaleAlpha(effectColor, opacity);
                        shadow            = ColorOperations.PreMultiplyColor(shadow);
                        frameBuffer[x, y] = ColorOperations.PreMultipliedAlphaBlend(clone.frameBuffer[x, y], shadow);

                        if (frameBuffer[x, y] != clone.frameBuffer[x, y])
                        {
                            // Transfer the tolerance (silhouette, etc) over too
                            Color tolerance = clone.GetToleranceSample(point, blurRadius);
                            toleranceBuffer[x, y] = ColorOperations.Max(tolerance, clone.toleranceBuffer[x, y]);
                        }
                    }
                }
            }
        }