// returns all possible combinations of tile values. // this sets the ID for the resulting ValueSets which is an ordered number, // required for the un-mapping algo to know where things are. public unsafe static ValueSet[] Permutate(int numDimensions, float[] discreteNormalizedValuesPerTile) { // we will just do this as if each value is a digit in a number. that's the analogy that drives this. // actually this symbolizes the # of digits in the result, PLUS the number of possible values per digit. ulong numDigits = (ulong)discreteNormalizedValuesPerTile.Length; ulong theoreticalBase = numDigits; ulong totalPermutations = (ulong)Pow((long)numDigits, (uint)numDimensions); if (totalPermutations > int.MaxValue) { Log.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!"); Log.WriteLine("!!!!! Total map keys is just too big. Must be less than 2 billion."); Log.WriteLine("You requested a map with {0:N0} mappings", totalPermutations); Log.WriteLine("Which would result in a map ref image {0:N0} x {0:N0}", (int)Math.Sqrt(totalPermutations)); Log.WriteLine("And take {0:N0} MB on disk", totalPermutations / 1024 / 1024 * 3); throw new Exception("Map is too big to process"); } float[] normalizedValues = new float[numDimensions]; Log.WriteLine("Allocating {0:N0} valuesets. Valueset size = {1}, so {2:N0} bytes of memory", totalPermutations, sizeof(ValueSet), (ulong)totalPermutations * (ulong)sizeof(ValueSet)); ValueSet[] ret = new ValueSet[totalPermutations]; for (ulong i = 0; i < totalPermutations; ++i) { // just like digits in a number, use % and divide to shave off "digits" one by one. ulong a = i;// the value that originates from i and we shift/mod to enumerate digits //ValueSet n = NewValueSet(numTiles, i); for (int d = 0; d < numDimensions; ++d) { ulong thisIndex = a % theoreticalBase; a /= theoreticalBase; normalizedValues[d] = discreteNormalizedValuesPerTile[(int)thisIndex]; //ret[i].Values[d] = discreteValuesPerTile[(int)thisIndex]; } ValueSet.Init(ref ret[i], numDimensions, (long)i, normalizedValues); //ret.Add(n); //for (int xxx = 0; xxx < ret[i].ValuesLength; ++xxx) //{ // Debug.Assert(ret[14].ColorData[xxx] == 0 || ret[14].ColorData[xxx] == 0.5 || ret[14].ColorData[xxx] == 1.0); //} } //foreach (var r in ret) //{ // for (int i = 0; i < r.ValuesLength; ++ i) // { // Debug.Assert(r.ColorData[i] == 0 || r.ColorData[i] == 0.5 || r.ColorData[i] == 1.0); // } //} return(ret); }
public static ValueSet GetValueSetForSinglePixel(this ILCCColorSpace cs, ColorF color, bool useChroma) { // a value set normally consists of multiple luma & chroma components for a char (for example 5 luma + 2 chroma) // for this we just have the normal default 3-component. all our colorspaces are LCC (luma chroma chroma). LCCColorDenorm denorm = cs.RGBToLCC(color); ValueSet src = new ValueSet(); float[] normArray = new float[] { (float)cs.NormalizeL(denorm.L), (float)cs.NormalizeC1(denorm.C1), (float)cs.NormalizeC2(denorm.C2), }; ValueSet.Init(ref src, useChroma ? 3 : 1, 0, normArray); src.DenormalizedValues[0] = (float)denorm.L; src.DenormalizedValues[1] = (float)denorm.C1; src.DenormalizedValues[2] = (float)denorm.C2; return(src); }