Ejemplo n.º 1
0
        internal static bool Fetch(
            string path,
            out uint refScale,
            out Vector2I size,
            out TextureFormat format,
            out Vector2B wrapped,
            out Vector2I padding,
            out Vector2I blockPadding,
            out byte[] data
            )
        {
            refScale     = 0;
            size         = Vector2I.Zero;
            format       = TextureFormat.Color;
            wrapped      = Vector2B.False;
            padding      = Vector2I.Zero;
            blockPadding = Vector2I.Zero;
            data         = null;

            if (Config.FileCache.Enabled && File.Exists(path))
            {
                int retries = Config.FileCache.LockRetries;

                while (retries-- > 0)
                {
                    if (SavingMap.TryGetValue(path, out var state) && state != SaveState.Saved)
                    {
                        Thread.Sleep(Config.FileCache.LockSleepMS);
                        continue;
                    }
Ejemplo n.º 2
0
        public void TestEquals()
        {
            Vector2B a = new Vector2B(false, true);
            Vector2B b = new Vector2B(true, false);
            Vector2B c = new Vector2B(false, true);

            Assert.IsTrue(a.Equals(c));
            Assert.IsTrue(c.Equals(a));
            Assert.IsTrue(a == c);
            Assert.IsTrue(c == a);
            Assert.IsFalse(c != a);
            Assert.IsFalse(c != a);
            Assert.IsFalse(a.Equals(b));
            Assert.IsFalse(b.Equals(a));
            Assert.IsFalse(a == b);
            Assert.IsFalse(b == a);
            Assert.IsTrue(a != b);
            Assert.IsTrue(b != a);

            object objA = a;
            object objB = b;
            object objC = c;

            Assert.IsTrue(a.Equals(objA));
            Assert.IsTrue(a.Equals(objC));
            Assert.IsFalse(a.Equals(objB));

            Assert.IsTrue(objA.Equals(objC));
            Assert.IsFalse(objA.Equals(objB));

            Assert.IsFalse(a.Equals(null));
            Assert.IsFalse(a.Equals(5));
        }
Ejemplo n.º 3
0
    internal Config(
        Vector2B wrapped,
        bool hasAlpha                     = true,
        double luminanceWeight            = 1.0,
        uint equalColorTolerance          = 30,
        double dominantDirectionThreshold = 3.6,
        double steepDirectionThreshold    = 2.2,
        double centerDirectionBias        = 4.0,
        bool gammaCorrected               = true,
        bool useRedmean                   = false
        ) : base(
            wrapped: wrapped,
            hasAlpha: hasAlpha,
            gammaCorrected: gammaCorrected
            )
    {
        EqualColorTolerance        = equalColorTolerance << 8;
        DominantDirectionThreshold = dominantDirectionThreshold;
        SteepDirectionThreshold    = steepDirectionThreshold;
        CenterDirectionBias        = centerDirectionBias;
        UseRedmean = useRedmean;

        var adjustedLuminanceWeight = luminanceWeight / (luminanceWeight + 1.0);

        LuminanceWeight   = adjustedLuminanceWeight * 2.0;
        ChrominanceWeight = (1.0 - adjustedLuminanceWeight) * 2.0;
    }
Ejemplo n.º 4
0
        public void TestGetHashCode()
        {
            Vector2B a = new Vector2B(false, true);
            Vector2B b = new Vector2B(true, false);
            Vector2B c = new Vector2B(false, true);

            Assert.AreEqual(a.GetHashCode(), c.GetHashCode());
            Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode());
        }
Ejemplo n.º 5
0
 protected Config(
     Vector2B wrapped,
     bool hasAlpha,
     bool gammaCorrected
     )
 {
     Wrapped        = wrapped;
     HasAlpha       = hasAlpha;
     GammaCorrected = gammaCorrected;
 }
Ejemplo n.º 6
0
 internal Results(
     Vector2B wrapped,
     Vector2B wrappedX,
     Vector2B wrappedY,
     Vector2B edgeX,
     Vector2B edgeY
     )
 {
     Wrapped  = wrapped;
     WrappedX = wrappedX;
     WrappedY = wrappedY;
     EdgeX    = edgeX;
     EdgeY    = edgeY;
 }
Ejemplo n.º 7
0
        internal static bool Save(
            string path,
            int refScale,
            Vector2I size,
            TextureFormat format,
            Vector2B wrapped,
            Vector2I padding,
            Vector2I blockPadding,
            byte[] data
            )
        {
            if (Config.Cache.Enabled)
            {
                if (!SavingMap.TryAdd(path, SaveState.Saving))
                {
                    return(false);
                }

                ThreadPool.QueueUserWorkItem((object dataItem) => {
                    var data = (byte[])dataItem;
                    try {
                        using (var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))) {
                            new CacheHeader()
                            {
                                RefScale     = refScale,
                                Size         = size,
                                Format       = format,
                                Wrapped      = wrapped,
                                Padding      = padding,
                                BlockPadding = blockPadding,
                                DataLength   = (uint)data.Length,
                                DataHash     = data.HashXX()
                            }.Write(writer);

                            foreach (var v in data)
                            {
                                writer.Write(v);
                            }
                        }
                        SavingMap.TryUpdate(path, SaveState.Saved, SaveState.Saving);
                    }
                    catch {
                        try { File.Delete(path); } catch { }
                        SavingMap.TryRemove(path, out var _);
                    }
                }, data);
            }
            return(true);
        }
Ejemplo n.º 8
0
    internal static Span <Color16> Enhance(
        ReadOnlySpan <Color16> data,
        Vector2I size,
        Vector2B wrapped,
        int?passes    = null,
        int?threshold = null,
        int?blockSize = null
        )
    {
        var context = new DeposterizeContext(
            size: size,
            wrapped: wrapped,
            passes: passes ?? Config.Resample.Deposterization.Passes,
            threshold: threshold ?? Config.Resample.Deposterization.Threshold,
            blockSize: blockSize ?? Config.Resample.Deposterization.BlockSize,
            useRedmean: Config.Resample.Deposterization.UseRedmean
            );

        return(context.Execute(data));
    }
Ejemplo n.º 9
0
 internal LegacyResults(
     Vector2B wrapped,
     Vector2B repeatX,
     Vector2B repeatY,
     Vector2B edgeX,
     Vector2B edgeY,
     Vector2B gradientAxial,
     Vector2B gradientDiagonal,
     int maxChannelShades
     )
 {
     Wrapped          = wrapped;
     RepeatX          = repeatX;
     RepeatY          = repeatY;
     EdgeX            = edgeX;
     EdgeY            = edgeY;
     GradientAxial    = gradientAxial;
     GradientDiagonal = gradientDiagonal;
     MaxChannelShades = maxChannelShades;
 }
Ejemplo n.º 10
0
    internal Config(
        Vector2B wrapped,
        bool hasAlpha            = true,
        double luminanceWeight   = 1.0,
        bool gammaCorrected      = true,
        uint equalColorTolerance = 30,
        bool useRedmean          = false
        ) : base(
            wrapped: wrapped,
            hasAlpha: hasAlpha,
            gammaCorrected: gammaCorrected
            )
    {
        EqualColorTolerance = equalColorTolerance << 8;
        UseRedmean          = useRedmean;

        var adjustedLuminanceWeight = luminanceWeight / (luminanceWeight + 1.0);

        LuminanceWeight   = adjustedLuminanceWeight * 2.0;
        ChrominanceWeight = (1.0 - adjustedLuminanceWeight) * 2.0;
    }
Ejemplo n.º 11
0
        internal DeposterizeContext(
            Vector2I size,
            Vector2B wrapped,
            int passes,
            int threshold,
            int blockSize,
            bool useRedmean = false
            )
        {
            Size       = size;
            Wrapped    = wrapped;
            Passes     = passes;
            Threshold  = threshold * 256;
            BlockSize  = blockSize;
            UseRedmean = useRedmean;

            YccConfiguration = new() {
                LuminanceWeight   = 1.0,
                ChrominanceWeight = 1.0
            };
        }
Ejemplo n.º 12
0
 internal Config(
     Vector2B wrapped,
     bool hasAlpha       = true,
     bool gammaCorrected = true,
     float edgeStrength  = 2.0f,
     float weight        = 1.0f,
     float edgeShape     = 0.0f,
     float textureShape  = 0.0f,
     float antiRinging   = 1.0f
     ) : base(
         wrapped: wrapped,
         hasAlpha: hasAlpha,
         gammaCorrected: gammaCorrected
         )
 {
     EdgeStrength = edgeStrength;
     Weight       = weight;
     EdgeShape    = edgeShape;
     TextureShape = textureShape;
     AntiRinging  = antiRinging;
 }
Ejemplo n.º 13
0
 static MyTileTexture()
 {
     Vector2B[] vectorbArray1 = new Vector2B[0x10];
     vectorbArray1[0]  = new Vector2B(0, 0);
     vectorbArray1[1]  = new Vector2B(1, 0);
     vectorbArray1[2]  = new Vector2B(2, 0);
     vectorbArray1[3]  = new Vector2B(3, 0);
     vectorbArray1[4]  = new Vector2B(0, 1);
     vectorbArray1[5]  = new Vector2B(1, 1);
     vectorbArray1[6]  = new Vector2B(2, 1);
     vectorbArray1[7]  = new Vector2B(3, 1);
     vectorbArray1[8]  = new Vector2B(0, 2);
     vectorbArray1[9]  = new Vector2B(1, 2);
     vectorbArray1[10] = new Vector2B(2, 2);
     vectorbArray1[11] = new Vector2B(3, 2);
     vectorbArray1[12] = new Vector2B(0, 3);
     vectorbArray1[13] = new Vector2B(1, 3);
     vectorbArray1[14] = new Vector2B(2, 3);
     vectorbArray1[15] = new Vector2B(3, 3);
     MyTileTexture <TPixel> .s_baseCellCoords = vectorbArray1;
     MyTileTexture <TPixel> .Default          = new MyTileTexture <TPixel>();
 }
Ejemplo n.º 14
0
        public Config(
            Vector2B wrapped,
            bool Gamma                        = true,
            bool HasAlpha                     = true,
            double luminanceWeight            = 1.0,
            double equalColorTolerance        = 30.0,
            double dominantDirectionThreshold = 3.6,
            double steepDirectionThreshold    = 2.2,
            double centerDirectionBias        = 4.0
            )
        {
            this.Wrapped                    = wrapped;
            this.Gamma                      = Gamma;
            this.HasAlpha                   = HasAlpha;
            this.LuminanceWeight            = luminanceWeight;
            this.EqualColorTolerance        = equalColorTolerance;
            this.DominantDirectionThreshold = dominantDirectionThreshold;
            this.SteepDirectionThreshold    = steepDirectionThreshold;
            this.CenterDirectionBias        = centerDirectionBias;

            this.EqualColorTolerancePow2 = Math.Pow(EqualColorTolerance, 2.0);
        }
Ejemplo n.º 15
0
 public void ToVector2I()
 {
     Vector2B a = new Vector2B(false, true);
     Vector2I sA = a.ToVector2I();
     Assert.AreEqual(0, sA.X);
     Assert.AreEqual(1, sA.Y);
 }
Ejemplo n.º 16
0
 public void TestToString()
 {
     CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;
     try
     {
         Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
         Vector2B a = new Vector2B(false, true);
         Assert.AreEqual("(False, True)", a.ToString());
     }
     finally
     {
         Thread.CurrentThread.CurrentCulture = originalCulture;
     }
 }
Ejemplo n.º 17
0
 public void Construct()
 {
     Vector2B v = new Vector2B(false, true);
     Assert.IsFalse(v.X);
     Assert.IsTrue(v.Y);
 }
Ejemplo n.º 18
0
 public void ToVector2F()
 {
     Vector2B a = new Vector2B(false, true);
     Vector2F sA = a.ToVector2F();
     Assert.AreEqual(0.0f, sA.X, 1e-7);
     Assert.AreEqual(1.0f, sA.Y, 1e-7);
 }
Ejemplo n.º 19
0
        internal static bool Fetch(
            string path,
            out int refScale,
            out Vector2I size,
            out TextureFormat format,
            out Vector2B wrapped,
            out Vector2I padding,
            out Vector2I blockPadding,
            out byte[] data
            )
        {
            refScale     = 0;
            size         = Vector2I.Zero;
            format       = TextureFormat.Color;
            wrapped      = Vector2B.False;
            padding      = Vector2I.Zero;
            blockPadding = Vector2I.Zero;
            data         = null;

            if (Config.Cache.Enabled && File.Exists(path))
            {
                int retries = Config.Cache.LockRetries;

                while (retries-- > 0)
                {
                    if (SavingMap.TryGetValue(path, out var state) && state != SaveState.Saved)
                    {
                        Thread.Sleep(Config.Cache.LockSleepMS);
                        continue;
                    }

                    // https://stackoverflow.com/questions/1304/how-to-check-for-file-lock
                    bool WasLocked(in IOException ex)
                    {
                        var errorCode = Marshal.GetHRForException(ex) & ((1 << 16) - 1);

                        return(errorCode == 32 || errorCode == 33);
                    }

                    try {
                        using (var reader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                            var header = CacheHeader.Read(reader);
                            header.Validate(path);

                            refScale     = header.RefScale;
                            size         = header.Size;
                            format       = header.Format.Value;
                            wrapped      = header.Wrapped;
                            padding      = header.Padding;
                            blockPadding = header.BlockPadding;
                            var dataLength = header.DataLength;
                            var dataHash   = header.DataHash;

                            var remainingSize = reader.BaseStream.Length - reader.BaseStream.Position;
                            if (remainingSize < header.DataLength)
                            {
                                throw new EndOfStreamException("Cache File is corrupted");
                            }

                            data = new byte[dataLength];

                            foreach (int i in 0..data.Length)
                            {
                                data[i] = reader.ReadByte();
                            }

                            if (data.HashXX() != dataHash)
                            {
                                throw new IOException("Cache File is corrupted");
                            }
                        }
                        return(true);
                    }
                    catch (Exception ex) {
                        switch (ex)
                        {
                        case FileNotFoundException _:
                        case EndOfStreamException _:
                        case IOException iox when !WasLocked(iox):
                        default:
                            ex.PrintWarning();
                            try { File.Delete(path); } catch { }
                            return(false);

                        case IOException iox when WasLocked(iox):
                            Debug.TraceLn($"File was locked when trying to load cache file '{path}': {ex.Message} [{retries} retries]");

                            Thread.Sleep(Config.Cache.LockSleepMS);
                            break;
                        }
                    }
                }
            }
            return(false);
        }
Ejemplo n.º 20
0
    internal static unsafe LegacyResults AnalyzeLegacy(ReadOnlySpan <Color8> data, Bounds bounds, Vector2B wrapped, bool strict = true)
    {
        var boundsInverted = bounds.Invert;

        if (bounds.Width < 0 || bounds.Height < 0)
        {
            Debug.Error($"Inverted Sprite Bounds Value leaked to AnalyzeLegacy: {bounds}");

            boundsInverted.X = bounds.Width < 0;
            boundsInverted.Y = bounds.Height < 0;

            bounds.Width  = Math.Abs(bounds.Width);
            bounds.Height = Math.Abs(bounds.Height);
        }

        float edgeThreshold = Config.WrapDetection.EdgeThreshold;

        if (strict)
        {
            var ratio = (float)bounds.Extent.MaxOf / (float)bounds.Extent.MinOf;
            edgeThreshold = ratio >= 4.0f ? 2.0f : 0.8f;
        }

        var wrappedXY = wrapped;
        var repeatX   = Vector2B.False;
        var repeatY   = Vector2B.False;

        if (Config.WrapDetection.Enabled)
        {
            long numSamples = 0;
            if (!wrappedXY.All)
            {
                for (int y = 0; y < bounds.Height; ++y)
                {
                    int offset = (y + bounds.Top) * bounds.Width + bounds.Left;
                    for (int x = 0; x < bounds.Width; ++x)
                    {
                        int address = offset + x;
                        var sample  = data[address];
                        ++numSamples;
                    }
                }
            }

            byte alphaThreshold = Config.WrapDetection.AlphaThreshold;

            // Count the fragments that are not alphad out completely on the edges.
            // Both edges must meet the threshold.
            if (!wrappedXY.X)
            {
                var samples = stackalloc int[] { 0, 0 };
                for (int y = 0; y < bounds.Height; ++y)
                {
                    int offset  = (y + bounds.Top) * bounds.Width + bounds.Left;
                    var sample0 = data[offset];
                    var sample1 = data[offset + (bounds.Width - 1)];

                    if (sample0.A.Value >= alphaThreshold)
                    {
                        samples[0]++;
                    }
                    if (sample1.A.Value >= alphaThreshold)
                    {
                        samples[1]++;
                    }
                }
                int threshold      = (bounds.Height * edgeThreshold).NearestInt();
                var aboveThreshold = Vector2B.From(samples[0] >= threshold, samples[1] >= threshold);
                if (aboveThreshold.All)
                {
                    wrappedXY.X = true;
                }
                else
                {
                    repeatX = aboveThreshold;
                }
            }
            if (!wrappedXY.Y)
            {
                var samples = stackalloc int[] { 0, 0 };
                var offsets = stackalloc int[] { bounds.Top *bounds.Width, (bounds.Bottom - 1) * bounds.Width };
                int sampler = 0;
                for (int i = 0; i < 2; ++i)
                {
                    var yOffset = offsets[i];
                    for (int x = 0; x < bounds.Width; ++x)
                    {
                        int offset = yOffset + x + bounds.Left;
                        var sample = data[offset];
                        if (sample.A.Value >= alphaThreshold)
                        {
                            samples[sampler]++;
                        }
                    }
                    sampler++;
                }
                int threshold      = (bounds.Width * edgeThreshold).NearestInt();
                var aboveThreshold = Vector2B.From(samples[0] >= threshold, samples[1] >= threshold);
                if (aboveThreshold.All)
                {
                    wrappedXY.Y = true;
                }
                else
                {
                    repeatY = aboveThreshold;
                }
            }
        }

        if (wrappedXY.Any)
        {
            // Perform tests against both sides of an edge to see if they match up. If they do not, convert
            // a wrapped edge into a repeat edge
            if (wrappedXY.X)
            {
            }
            if (wrappedXY.Y)
            {
            }
        }

        // Gradient analysis
        var gradientAxial    = Vector2B.True;
        var gradientDiagonal = Vector2B.False;
        // Horizontal
        {
            for (int y = bounds.Top; gradientAxial.X && y < bounds.Bottom; ++y)
            {
                int offset    = (y * bounds.Width) + bounds.Left;
                var prevColor = data[offset];
                for (int x = 1; x < bounds.Width; ++x)
                {
                    var currColor = data[offset + x];

                    //if (Config.Resample.Analysis.UseRedmean)
                    var difference = prevColor.RedmeanDifference(currColor, linear: false, alpha: true);

                    if (difference >= Config.Resample.Analysis.MaxGradientColorDifference)
                    {
                        gradientAxial.X = false;
                        break;
                    }

                    prevColor = currColor;
                }
            }
        }
        // Vertical
        {
            int offset    = (bounds.Top * bounds.Width) + bounds.Left;
            var prevColor = data[offset];
            for (int y = 1; gradientAxial.Y && y < bounds.Height; ++y)
            {
                for (int x = 0; x < bounds.Width; ++x)
                {
                    var currColor = data[offset + (y * bounds.Width) + x];
                    //if (Config.Resample.Analysis.UseRedmean)
                    var difference = prevColor.RedmeanDifference(currColor, linear: false, alpha: true);

                    if (difference >= Config.Resample.Analysis.MaxGradientColorDifference)
                    {
                        gradientAxial.Y = false;
                        break;
                    }

                    prevColor = currColor;
                }
            }
        }
        // Diagonal
        // TODO : use Bresenham's Line Algorithm (https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm)

        Span <int> shadesR = stackalloc int[byte.MaxValue + 1];

        shadesR.Fill(0);
        Span <int> shadesG = stackalloc int[byte.MaxValue + 1];

        shadesG.Fill(0);
        Span <int> shadesB = stackalloc int[byte.MaxValue + 1];

        shadesB.Fill(0);
        Span <int> shadesA = stackalloc int[byte.MaxValue + 1];

        shadesA.Fill(0);
        foreach (var color in data)
        {
            ++shadesR[color.R.Value];
            ++shadesG[color.G.Value];
            ++shadesB[color.B.Value];
            ++shadesA[color.A.Value];
        }
Ejemplo n.º 21
0
 public void ToVector2H()
 {
     Vector2B a = new Vector2B(false, true);
     Vector2H sA = a.ToVector2H();
     Assert.AreEqual((Half)0.0, sA.X, 1e-7);
     Assert.AreEqual((Half)1.0, sA.Y, 1e-7);
 }