/// <summary>
        /// 誤差拡散しつつ減色
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns>変換結果</returns>
        private BlockColor[,] Convert(Bitmap bmp)
        {
            using (var accessor = new BitmapAccessor((Bitmap)bmp.Clone()))
            {
                var w = bmp.Width;
                var h = bmp.Height;

                var result = new BlockColor[w, h];

                int[][] ditherData = { new int[w * 3], new int[w * 3] };

                for (var y = 0; y < h; y++)
                {
                    // Recycle
                    var shift = ditherData[0];
                    Array.Copy(ditherData, 1, ditherData, 0, ditherData.Length - 1);
                    for (var i = 0; i < shift.Length; i++)
                    {
                        shift[i] = 0;
                    }
                    ditherData[ditherData.Length - 1] = shift;

                    for (var x = 0; x < w; x++)
                    {
                        var color = accessor.GetPixel(x, y);

                        var r = Math.Max(0, Math.Min(255, color.R + ditherData[0][x * 3 + 0]));
                        var g = Math.Max(0, Math.Min(255, color.G + ditherData[0][x * 3 + 1]));
                        var b = Math.Max(0, Math.Min(255, color.B + ditherData[0][x * 3 + 2]));

                        var nearestMatch = FindNearest(r, g, b);
                        result[x, y] = nearestMatch;
                        bmp.SetPixel(x, y, Color.FromArgb(nearestMatch.R, nearestMatch.G, nearestMatch.B));

                        var rDiff = r - nearestMatch.R;
                        var gDiff = g - nearestMatch.G;
                        var bDiff = b - nearestMatch.B;

                        for (var k = 0; k < DitherX.Length; k++)
                        {
                            var tmpX = DitherX[k] + x;
                            var tmpY = DitherY[k];

                            if ((tmpY < h) && (tmpX < w) && (tmpX > 0))
                            {
                                ditherData[tmpY][tmpX * 3 + 0] += (int)Math.Floor(DitherErr[k] * rDiff);
                                ditherData[tmpY][tmpX * 3 + 1] += (int)Math.Floor(DitherErr[k] * gDiff);
                                ditherData[tmpY][tmpX * 3 + 2] += (int)Math.Floor(DitherErr[k] * bDiff);
                            }
                        }
                    }


                    convertFile.Complete++;
                }

                return(result);
            }
        }
        /// <summary>
        /// 最も近い色を持つ BlockColor を返す
        /// </summary>
        /// <param name="r">R</param>
        /// <param name="g">G</param>
        /// <param name="b">B</param>
        /// <returns>BlockColor</returns>
        private BlockColor FindNearest(int r, int g, int b)
        {
            var bestDiff  = double.MaxValue;
            var bestMatch = new BlockColor();

            double diff;

            foreach (var block in blockColors)
            {
                var rDiff = block.R - r;
                var gDiff = block.G - g;
                var bDiff = block.B - b;

                if ((diff = Math.Sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff)) < bestDiff)
                {
                    bestDiff  = diff;
                    bestMatch = block;
                }
            }

            return(bestMatch);
        }
        /// <summary>
        /// 近似色のみで減色
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns>変換結果</returns>
        private BlockColor[,] Convert(Bitmap bmp)
        {
            using (var accessor = new BitmapAccessor((Bitmap)bmp.Clone()))
            {
                var w = bmp.Width;
                var h = bmp.Height;

                var result = new BlockColor[w, h];

                int[][] ditherData = { new int[w * 3], new int[w * 3] };

                for (var y = 0; y < h; y++)
                {
                    // Recycle
                    var shift = ditherData[0];
                    Array.Copy(ditherData, 1, ditherData, 0, ditherData.Length - 1);
                    for (var i = 0; i < shift.Length; i++)
                    {
                        shift[i] = 0;
                    }
                    ditherData[ditherData.Length - 1] = shift;

                    for (var x = 0; x < w; x++)
                    {
                        var color = accessor.GetPixel(x, y);

                        var nearestMatch = FindNearest(color.R, color.G, color.B);
                        result[x, y] = nearestMatch;
                        bmp.SetPixel(x, y, Color.FromArgb(nearestMatch.R, nearestMatch.G, nearestMatch.B));
                    }
                    convertFile.Complete++;
                }

                return(result);
            }
        }