Ejemplo n.º 1
0
            // This is currently still very brute-forcey. Can be improved in the future
            public static bool RepackEtc1CompressedBlock(List <RGB> colors, out Block block)
            {
                foreach (var flip in new[] { false, true })
                {
                    var allpixels0 = colors.Where((c, j) => (j / (flip ? 2 : 8)) % 2 == 0).ToArray();
                    var pixels0    = allpixels0.Distinct().ToArray();
                    if (pixels0.Count() > 4)
                    {
                        continue;
                    }

                    var allpixels1 = colors.Where((c, j) => (j / (flip ? 2 : 8)) % 2 == 1).ToArray();
                    var pixels1    = allpixels1.Distinct().ToArray();
                    if (pixels1.Count() > 4)
                    {
                        continue;
                    }

                    foreach (var diff in new[] { false, true })
                    {
                        if (!diff)
                        {
                            var tables0 = Enumerable.Range(0, 8).Where(i => pixels0.All(c => lookup16[i][c.R] && lookup16[i][c.G] && lookup16[i][c.B])).ToList();
                            if (!tables0.Any())
                            {
                                continue;
                            }
                            var tables1 = Enumerable.Range(0, 8).Where(i => pixels1.All(c => lookup16[i][c.R] && lookup16[i][c.G] && lookup16[i][c.B])).ToList();
                            if (!tables1.Any())
                            {
                                continue;
                            }

                            var      opt0  = new Optimizer(allpixels0, 16, 1);
                            Solution soln0 = null;
                            foreach (var ti in tables0)
                            {
                                var rs = Enumerable.Range(0, 16).Where(a => pixels0.All(c => lookup16big[ti][a].Contains(c.R))).ToArray();
                                var gs = Enumerable.Range(0, 16).Where(a => pixels0.All(c => lookup16big[ti][a].Contains(c.G))).ToArray();
                                var bs = Enumerable.Range(0, 16).Where(a => pixels0.All(c => lookup16big[ti][a].Contains(c.B))).ToArray();
                                soln0 = opt0.FindExactMatches(from r in rs from g in gs from b in bs select new RGB(r, g, b), modifiers[ti]).FirstOrDefault();
                                if (soln0 != null)
                                {
                                    break;
                                }
                            }
                            if (soln0 == null)
                            {
                                continue;
                            }

                            var      opt1  = new Optimizer(allpixels1, 16, 1);
                            Solution soln1 = null;
                            foreach (var ti in tables1)
                            {
                                var rs = Enumerable.Range(0, 16).Where(a => pixels1.All(c => lookup16big[ti][a].Contains(c.R))).ToArray();
                                var gs = Enumerable.Range(0, 16).Where(a => pixels1.All(c => lookup16big[ti][a].Contains(c.G))).ToArray();
                                var bs = Enumerable.Range(0, 16).Where(a => pixels1.All(c => lookup16big[ti][a].Contains(c.B))).ToArray();
                                soln1 = opt1.FindExactMatches(from r in rs from g in gs from b in bs select new RGB(r, g, b), modifiers[ti]).FirstOrDefault();
                                if (soln1 != null)
                                {
                                    block = new SolutionSet(flip, diff, soln0, soln1).ToBlock();
                                    return(true);
                                }
                            }
                        }
                        else
                        {
                            var tables0 = Enumerable.Range(0, 8).Where(i => pixels0.All(c => lookup32[i][c.R] && lookup32[i][c.G] && lookup32[i][c.B])).ToList();
                            if (!tables0.Any())
                            {
                                continue;
                            }
                            var tables1 = Enumerable.Range(0, 8).Where(i => pixels1.All(c => lookup32[i][c.R] && lookup32[i][c.G] && lookup32[i][c.B])).ToList();
                            if (!tables1.Any())
                            {
                                continue;
                            }

                            var opt0   = new Optimizer(allpixels0, 32, 1);
                            var solns0 = new List <Solution>();
                            foreach (var ti in tables0)
                            {
                                var rs = Enumerable.Range(0, 32).Where(a => pixels0.All(c => lookup32big[ti][a].Contains(c.R))).ToArray();
                                var gs = Enumerable.Range(0, 32).Where(a => pixels0.All(c => lookup32big[ti][a].Contains(c.G))).ToArray();
                                var bs = Enumerable.Range(0, 32).Where(a => pixels0.All(c => lookup32big[ti][a].Contains(c.B))).ToArray();
                                solns0.AddRange(opt0.FindExactMatches(from r in rs from g in gs from b in bs select new RGB(r, g, b), modifiers[ti]));
                            }
                            if (!solns0.Any())
                            {
                                continue;
                            }

                            var opt1 = new Optimizer(allpixels1, 32, 1);
                            foreach (var ti in tables1)
                            {
                                var rs = Enumerable.Range(0, 32).Where(a => pixels1.All(c => lookup32big[ti][a].Contains(c.R))).ToArray();
                                var gs = Enumerable.Range(0, 32).Where(a => pixels1.All(c => lookup32big[ti][a].Contains(c.G))).ToArray();
                                var bs = Enumerable.Range(0, 32).Where(a => pixels1.All(c => lookup32big[ti][a].Contains(c.B))).ToArray();
                                foreach (var soln0 in solns0)
                                {
                                    var q = (from r in rs
                                             let dr = r - soln0.blockColor.R
                                                      where dr >= -4 && dr < 4
                                                      from g in gs
                                                      let dg = g - soln0.blockColor.G
                                                               where dg >= -4 && dg < 4
                                                               from b in bs
                                                               let db = b - soln0.blockColor.B
                                                                        where db >= -4 && db < 4
                                                                        select new RGB(r, g, b));
                                    var soln1 = opt1.FindExactMatches(q, modifiers[ti]).FirstOrDefault();
                                    if (soln1 != null)
                                    {
                                        block = new SolutionSet(flip, diff, soln0, soln1).ToBlock();
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
                block = default(Block);
                return(false);
            }