예제 #1
0
        public static int FindMatch(this ColorPalette pal, ARGBPixel pixel)
        {
            int bestDist = Int32.MaxValue, bestIndex = 0;

            for (int i = 0, c = pal.Entries.Length; i < c; i++)
            {
                int dist = pixel.DistanceTo(pal.Entries[i]);
                if (dist < bestDist)
                {
                    bestIndex = i;
                    if (dist == 0)
                    {
                        break;
                    }
                    bestDist = dist;
                }
            }
            return(bestIndex);
        }
예제 #2
0
        public static unsafe Bitmap IndexColors(this Bitmap src, ColorPalette palette, PixelFormat format)
        {
            int w = src.Width, h = src.Height;

            int entries = palette.Entries.Length;

            switch (format)
            {
            case PixelFormat.Format4bppIndexed: { entries = Math.Min(entries, 16); break; }

            case PixelFormat.Format8bppIndexed: { entries = Math.Min(entries, 256); break; }

            default: { throw new ArgumentException("Pixel format is not an indexed format."); }
            }

            Bitmap dst = new Bitmap(w, h, format);

            dst.Palette = palette;

            BitmapData sData = src.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData dData = dst.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, format);

            ARGBPixel *sPtr = (ARGBPixel *)sData.Scan0;

            for (int y = 0; y < h; y++)
            {
                byte *dPtr = (byte *)dData.Scan0 + (y * dData.Stride);
                for (int x = 0; x < w; x++)
                {
                    ARGBPixel p = *sPtr++;

                    int bestDist = Int32.MaxValue, bestIndex = 0;
                    for (int z = 0; z < entries; z++)
                    {
                        int dist = p.DistanceTo(palette.Entries[z]);
                        if (dist < bestDist)
                        {
                            bestDist  = dist;
                            bestIndex = z;
                        }
                    }

                    if (format == PixelFormat.Format4bppIndexed)
                    {
                        byte val = *dPtr;
                        if ((x % 2) == 0)
                        {
                            *dPtr = (byte)((bestIndex << 4) | (val & 0x0F));
                        }
                        else
                        {
                            *dPtr++ = (byte)((val & 0xF0) | (bestIndex & 0x0F));
                        }
                    }
                    else
                    {
                        *dPtr++ = (byte)bestIndex;
                    }
                }
            }

            dst.UnlockBits(dData);
            src.UnlockBits(sData);

            return(dst);
        }
예제 #3
0
        public static CMPRBlock Encode(ARGBPixel *block, int width, bool fast)
        {
            CMPRBlock p = new CMPRBlock();

            uint *     pData  = stackalloc uint[16];
            ARGBPixel *pColor = (ARGBPixel *)pData;

            bool isSingle = true, hasAlpha = false, allAlpha = true;

            for (int y = 0, i = 0; y < 4; y++, block += width)
            {
                for (int x = 0; x < 4; i++)
                {
                    pColor[i] = block[x++];
                    if (pData[i] != pData[0])
                    {
                        isSingle = false;
                    }
                    if (pColor[i].A < 0x80)
                    {
                        hasAlpha = true;
                    }
                    else
                    {
                        allAlpha = false;
                    }
                }
            }

            /*
             *  Foreach block:
             *      copy block to buffer
             *      mirror remaning colors?
             *
             *      If block is single color:
             *          run optiml compress?
             *      else
             *          Initialize color set
             *          Compress block using color set
             *
             *
             */

            //BlockDecoder decoder = new BlockDecoder(width, 4, 4, 4);
            //bool isSingle = true, hasAlpha = false, allAlpha = true;
            //for (int i = 0; i < 16; i++)
            //{
            //    int index = decoder[i];
            //    pColor[i] = block[index];
            //    if (pData[i] != pData[0]) isSingle = false;
            //    if (pColor[i].A < 0x80) hasAlpha = true;
            //    else allAlpha = false;
            //}

            //bool isSingle = true, hasAlpha = false, allAlpha = true;
            //ARGBPixel* ptr = block;
            //int index = 0;
            //for (int y = 0; y < 4; y++, ptr += width - 4)
            //{
            //    for (int x = 0; x < 4; x++, ptr++, index++)
            //    {
            //        pColor[index] = block[(y * width) + x];
            //        if (pData[0] != pData[index]) isSingle = false;
            //        if (pColor[index].A < 0x80) hasAlpha = true;
            //        else allAlpha = false;
            //    }
            //}

            //if (allAlpha)
            //{
            //    p._root0._data = 0;
            //    p._root1._data = 0xFFFF;
            //    p._lookup = 0xFFFFFFFF;
            //}
            //else if (isSingle)
            //{
            //    p._root0 = (RGB565Pixel)(*block);
            //    p._root1._data = 0;
            //    p._lookup = 0x00000000;
            //}
            //else
            //{
            uint *     palData = stackalloc uint[4];
            ARGBPixel *palCol  = (ARGBPixel *)palData;

            int bestDist = -1;

            for (int i = 0; i < 16; i++)
            {
                ARGBPixel p1 = pColor[i];
                for (int x = i + 1; x < 16; x++)
                {
                    ARGBPixel p2 = pColor[x];
                    int       d  = p1.DistanceTo(p2);
                    if (d > bestDist)
                    {
                        bestDist  = d;
                        palCol[2] = p1;
                        palCol[3] = p2;
                    }
                }
            }

            wRGB565Pixel smax = (wRGB565Pixel)palCol[2];
            wRGB565Pixel smin = (wRGB565Pixel)palCol[3];

            if (smax < smin)
            {
                smax = (wRGB565Pixel)palCol[3]; smin = (wRGB565Pixel)palCol[2];
            }

            if (hasAlpha)
            {
                p._root0  = smin;
                p._root1  = smax;
                palCol[0] = (ARGBPixel)smin;
                palCol[1] = (ARGBPixel)smax;
                palCol[2] = new ARGBPixel(255, (byte)((palCol[0].R + palCol[1].R) >> 1), (byte)((palCol[0].G + palCol[1].G) >> 1), (byte)((palCol[0].B + palCol[1].B) >> 1));
                palCol[3] = new ARGBPixel();
            }
            else
            {
                p._root0  = smax;
                p._root1  = smin;
                palCol[0] = (ARGBPixel)smax;
                palCol[1] = (ARGBPixel)smin;
                palCol[2] = new ARGBPixel(255, (byte)(((palCol[0].R << 1) + palCol[1].R) / 3), (byte)(((palCol[0].G << 1) + palCol[1].G) / 3), (byte)(((palCol[0].B << 1) + palCol[1].B) / 3));
                palCol[3] = new ARGBPixel(255, (byte)(((palCol[1].R << 1) + palCol[0].R) / 3), (byte)(((palCol[1].G << 1) + palCol[0].G) / 3), (byte)(((palCol[1].B << 1) + palCol[0].B) / 3));
            }

            uint indicies = 0;

            for (int i = 0, shift = 30; i < 16; i++, shift -= 2)
            {
                uint index = 3;
                if (pColor[i].A >= 0x80)
                {
                    int bd = int.MaxValue;
                    for (int x = 0; x < ((hasAlpha) ? 4 : 3); x++)
                    {
                        int dist = palCol[x].DistanceTo(pColor[i]);
                        if (dist < bd)
                        {
                            bd = dist; index = (uint)x;
                        }
                    }
                }
                indicies |= index << shift;
            }
            p._lookup = indicies;

            //p = DXT1Fast.Compress(pColor);
            //}


            return(p);
        }