/*
         * for analyzing an image, we don't want to sample every single pixel. but we
         * also don't want to only sample once per tile. since conceptually each
         * outer tile is supposed to cover multiple important regions, sample those
         * regions and average.
         */
        public int GetMapIndexOfRegion(Bitmap img, int x, int y, Size sz)
        {
            ColorF charRGB = ColorF.Init;

            ColorF[] lumaRGB     = new ColorF[LumaComponentCount];
            int[]    pixelCounts = new int[LumaComponentCount];
            for (int i = 0; i < LumaComponentCount; ++i)
            {
                lumaRGB[i]     = ColorF.Init;
                pixelCounts[i] = 0;
            }

            float[] vals = new float[DimensionCount];

            for (int py = 0; py < sz.Height; ++py)
            {
                for (int px = 0; px < sz.Width; ++px)
                {
                    ColorF pc = ColorF.From(img.GetPixel(x + px, y + py));
                    charRGB = charRGB.Add(pc);
                    int lumaIdx = Tessellator.GetLumaTileIndexOfPixelPosInCell(px, py, sz);
                    lumaRGB[lumaIdx] = lumaRGB[lumaIdx].Add(pc);
                    pixelCounts[lumaIdx]++;
                }
            }

            for (int i = 0; i < LumaComponentCount; ++i)
            {
                ColorF       lc   = lumaRGB[i].Div(pixelCounts[i]);
                LCCColorNorm lccc = RGBToNormalizedLCC(lc);
                vals[i] = (float)lccc.L;
            }

            if (UseChroma)
            {
                charRGB = charRGB.Div(Utils.Product(sz));
                LCCColorNorm charLAB = RGBToNormalizedLCC(charRGB);
                vals[GetValueC1Index()] = (float)charLAB.C1;
                vals[GetValueC2Index()] = (float)charLAB.C2;
            }

            int ID = NormalizedValueSetToMapID(vals);

            return(ID);
        }
        public int GetMapIndexOfRegion(Bitmap img, int x, int y, Size sz)
        {
            ColorF         rgb  = ColorF.Init;
            LCCColorDenorm lab  = LCCColorDenorm.Init;
            LCCColorNorm   norm = LCCColorNorm.Init;

            float[] vals    = new float[DimensionCount];
            ColorF  charRGB = ColorF.Init;

            for (int ty = LumaTiles.Height - 1; ty >= 0; --ty)
            {
                for (int tx = LumaTiles.Width - 1; tx >= 0; --tx)
                {
                    Point tilePos = GetTileOrigin(sz, LumaTiles, tx, ty);
                    // YES this just gets 1 pixel per char-sized area.
                    rgb = ColorF.From(img.GetPixel(x + tilePos.X, y + tilePos.Y));
                    lab = Colorspace.RGBToLCC(rgb);

                    norm = RGBToNormalizedLCC(rgb);
                    vals[GetValueLIndex(tx, ty)] = (float)norm.L;
                    charRGB = charRGB.Add(rgb);
                }
            }

            if (UseChroma)
            {
                int numTiles = Utils.Product(LumaTiles);
                charRGB = charRGB.Div(numTiles);
                norm    = RGBToNormalizedLCC(charRGB);
                vals[GetValueC1Index()] = (float)norm.C1;
                vals[GetValueC2Index()] = (float)norm.C2;
            }

            int ID = NormalizedValueSetToMapID(vals);

            return(ID);
        }