public unsafe void Replace(TPixel pixel, TPixel replaced)
 {
     TPixel* p = this.Start;
     TPixel* end = p + this.Length;
     while (p != end)
     {
         if (*p == pixel)
         {
             *p = replaced;
         }
         p++;
     }
 }
 public static unsafe UnmanagedImage<TPixel> ForEach(this UnmanagedImage<TPixel> src, TPixel* start, uint length, ActionOnPixel handler)
 {
     TPixel* end = start + src.Length;
     while (start != end)
     {
         handler(start);
         ++start;
     }
     return src;
 }
        public unsafe TImage GaussPyramidDown()
        {
            int width = Width;
            int height = Height;
            int ww = width * 2;
            int hh = height * 2;

            TImage imgDown = new TImage(ww, hh);
            TPixel* imgStart = this.Start;
            TPixel* imgPyDownStart = imgDown.Start;
            int hSrc, wSrc;
            TPixel* lineSrc;
            TPixel* lineDst;

            TPixel p0, p1, p2, p3;

            // 分四种情况进行处理:
            // (1) h,w 都是偶数;
            // (2) h 是偶数, w 是奇数
            // (3) h 是奇数, w 是偶数
            // (4) h 是奇数, w 是奇数

            // h 是偶数
            for (int h = 0; h < hh; h += 2)
            {
                hSrc = h / 2;
                lineDst = imgPyDownStart + h * ww;
                lineSrc = imgStart + hSrc * width;

                // w 是偶数
                for (int w = 0; w < ww; w += 2)
                {
                    wSrc = w / 2;
                    lineDst[w] = lineSrc[wSrc];
                }

                // w 是奇数
                for (int w = 1; w < ww; w += 2)
                {
                    // 防止取到最后一列
                    wSrc = Math.Min(w / 2,width-2);

                    p0 = lineSrc[wSrc];
                    p1 = lineSrc[wSrc + 1];
                    lineDst[w] = new TPixel((TChannel)((p0.Red + p1.Red) >> 1),
                        (TChannel)((p0.Green + p1.Green) >> 1),
                        (TChannel)((p0.Blue + p1.Blue) >> 1),
                        (TChannel)((p0.Alpha + p1.Alpha) >> 1));
                }
            }

            // h 是奇数
            for (int h = 1; h < hh; h += 2)
            {
                // 防止取到最后一行
                hSrc = Math.Min(h / 2, height - 2);

                lineDst = imgPyDownStart + h * ww;
                lineSrc = imgStart + hSrc * width;

                // w 是偶数
                for (int w = 0; w < ww; w += 2)
                {
                    wSrc = w / 2;
                    p0 = lineSrc[wSrc];
                    p1 = lineSrc[wSrc + width];
                    lineDst[w] = new TPixel((TChannel)((p0.Red + p1.Red) >> 1),
                        (TChannel)((p0.Green + p1.Green) >> 1),
                        (TChannel)((p0.Blue + p1.Blue) >> 1),
                        (TChannel)((p0.Alpha + p1.Alpha) >> 1));
                }

                // w 是奇数
                for (int w = 1; w < ww; w += 2)
                {
                    // 防止取到最后一列
                    wSrc = Math.Min(w / 2, width - 2);

                    p0 = lineSrc[wSrc];
                    p1 = lineSrc[wSrc + 1];
                    p2 = lineSrc[wSrc + width];
                    p3 = lineSrc[wSrc + width + 1];
                    lineDst[w] = new TPixel((TChannel)((p0.Red + p1.Red + p2.Red + p3.Red) >> 2),
                        (TChannel)((p0.Green + p1.Green + p2.Green + p3.Green) >> 2),
                        (TChannel)((p0.Blue + p1.Blue + p2.Blue + p3.Blue) >> 2),
                        (TChannel)((p0.Alpha + p1.Alpha + p2.Alpha + p3.Alpha) >> 2));
                }
            }

            return imgDown;
        }
        public unsafe TImage GaussPyramidUp()
        {
            int width = this.Width;
            int height = this.Height;
            int ww = width / 2;
            int hh = height / 2;

            TImage imgUp = new TImage(ww, hh);
            TPixel* imgStart = Start;
            TPixel* imgPyUpStart = imgUp.Start;
            int hSrc, wSrc;
            TPixel* lineSrc;
            TPixel* lineDst;
            for (int h = 0; h < hh; h++)
            {
                hSrc = 2 * h;
                lineSrc = imgStart + hSrc * width;
                lineDst = imgPyUpStart + h * ww;
                for (int w = 0; w < ww; w++)
                {
                    wSrc = 2 * w;

                    // 对于四边不够一个高斯核半径的地方,直接赋值
                    if (hSrc < 2 || hSrc > height - 3 || wSrc < 2 || wSrc > width - 3)
                    {
                        lineDst[w] = lineSrc[wSrc];
                    }
                    else
                    {
                        // 计算高斯

                        TPixel* p = lineSrc + wSrc - 2 * width;

                        TPixel p00 = p[-2];
                        TPixel p01 = p[-1];
                        TPixel p02 = p[0];
                        TPixel p03 = p[1];
                        TPixel p04 = p[2];

                        p += width;
                        TPixel p10 = p[-2];
                        TPixel p11 = p[-1];
                        TPixel p12 = p[0];
                        TPixel p13 = p[1];
                        TPixel p14 = p[2];

                        p += width;
                        TPixel p20 = p[-2];
                        TPixel p21 = p[-1];
                        TPixel p22 = p[0];
                        TPixel p23 = p[1];
                        TPixel p24 = p[2];

                        p += width;
                        TPixel p30 = p[-2];
                        TPixel p31 = p[-1];
                        TPixel p32 = p[0];
                        TPixel p33 = p[1];
                        TPixel p34 = p[2];

                        p += width;
                        TPixel p40 = p[-2];
                        TPixel p41 = p[-1];
                        TPixel p42 = p[0];
                        TPixel p43 = p[1];
                        TPixel p44 = p[2];

                        //int alpha =
                        //      1 * p00.Alpha + 04 * p01.Alpha + 06 * p02.Alpha + 04 * p03.Alpha + 1 * p04.Alpha
                        //    + 4 * p10.Alpha + 16 * p11.Alpha + 24 * p12.Alpha + 16 * p13.Alpha + 4 * p14.Alpha
                        //    + 6 * p20.Alpha + 24 * p21.Alpha + 36 * p22.Alpha + 24 * p23.Alpha + 6 * p24.Alpha
                        //    + 4 * p30.Alpha + 16 * p31.Alpha + 24 * p32.Alpha + 16 * p33.Alpha + 4 * p34.Alpha
                        //    + 1 * p40.Alpha + 04 * p41.Alpha + 06 * p42.Alpha + 04 * p43.Alpha + 1 * p44.Alpha;

                        int red =
                              1 * p00.Red + 04 * p01.Red + 06 * p02.Red + 04 * p03.Red + 1 * p04.Red
                            + 4 * p10.Red + 16 * p11.Red + 24 * p12.Red + 16 * p13.Red + 4 * p14.Red
                            + 6 * p20.Red + 24 * p21.Red + 36 * p22.Red + 24 * p23.Red + 6 * p24.Red
                            + 4 * p30.Red + 16 * p31.Red + 24 * p32.Red + 16 * p33.Red + 4 * p34.Red
                            + 1 * p40.Red + 04 * p41.Red + 06 * p42.Red + 04 * p43.Red + 1 * p44.Red;

                        int green =
                              1 * p00.Green + 04 * p01.Green + 06 * p02.Green + 04 * p03.Green + 1 * p04.Green
                            + 4 * p10.Green + 16 * p11.Green + 24 * p12.Green + 16 * p13.Green + 4 * p14.Green
                            + 6 * p20.Green + 24 * p21.Green + 36 * p22.Green + 24 * p23.Green + 6 * p24.Green
                            + 4 * p30.Green + 16 * p31.Green + 24 * p32.Green + 16 * p33.Green + 4 * p34.Green
                            + 1 * p40.Green + 04 * p41.Green + 06 * p42.Green + 04 * p43.Green + 1 * p44.Green;

                        int blue =
                              1 * p00.Blue + 04 * p01.Blue + 06 * p02.Blue + 04 * p03.Blue + 1 * p04.Blue
                            + 4 * p10.Blue + 16 * p11.Blue + 24 * p12.Blue + 16 * p13.Blue + 4 * p14.Blue
                            + 6 * p20.Blue + 24 * p21.Blue + 36 * p22.Blue + 24 * p23.Blue + 6 * p24.Blue
                            + 4 * p30.Blue + 16 * p31.Blue + 24 * p32.Blue + 16 * p33.Blue + 4 * p34.Blue
                            + 1 * p40.Blue + 04 * p41.Blue + 06 * p42.Blue + 04 * p43.Blue + 1 * p44.Blue;

                        lineDst[w] = new TPixel(red >> 8, green >> 8, blue >> 8, 255);
                    }
                }
            }
            return imgUp;
        }
        public void FloodFill(System.Drawing.Point location, TPixel anchorColor, TPixel replecedColor)
        {
            int width = this.Width;
            int height = this.Height;
            if (location.X < 0 || location.X >= width || location.Y < 0 || location.Y >= height) return;

            if (anchorColor == replecedColor) return;
            if (this[location.Y, location.X] != anchorColor) return;

            Stack<System.Drawing.Point> points = new Stack<System.Drawing.Point>();
            points.Push(location);

            int ww = width - 1;
            int hh = height - 1;

            while (points.Count > 0)
            {
                System.Drawing.Point p = points.Pop();
                this[p.Y, p.X] = replecedColor;
                if (p.X > 0 && this[p.Y, p.X - 1] == anchorColor)
                {
                    this[p.Y, p.X - 1] = replecedColor;
                    points.Push(new System.Drawing.Point(p.X - 1, p.Y));
                }

                if (p.X < ww && this[p.Y, p.X + 1] == anchorColor)
                {
                    this[p.Y, p.X + 1] = replecedColor;
                    points.Push(new System.Drawing.Point(p.X + 1, p.Y));
                }

                if (p.Y > 0 && this[p.Y - 1, p.X] == anchorColor)
                {
                    this[p.Y - 1, p.X] = replecedColor;
                    points.Push(new System.Drawing.Point(p.X, p.Y - 1));
                }

                if (p.Y < hh && this[p.Y + 1, p.X] == anchorColor)
                {
                    this[p.Y + 1, p.X] = replecedColor;
                    points.Push(new System.Drawing.Point(p.X, p.Y + 1));
                }
            }
        }
 public unsafe void Fill(TPixel pixel)
 {
     TPixel* p = this.Start;
     TPixel* end = p + this.Length;
     while (p != end)
     {
         *p = pixel;
         p++;
     }
 }
        public static unsafe void ToSignedArgb64(Byte* from, SignedArgb64* to, int length = 1)
        {
            if (length < 1) return;

            Byte* end = from + length;
            while (from != end)
            {
                Byte val = *from;
                to->Blue = val;
                to->Green = val;
                to->Red = val;
                to->Alpha = 255;
                from++;
                to++;
            }
        }
        public static unsafe void ToSignedArgb64(Argb32* from, SignedArgb64* to, int length = 1)
        {
            if (length < 1) return;

            Argb32* end = from + length;
            while (from != end)
            {
                to->Blue = from->Blue;
                to->Green = from->Green;
                to->Red = from->Red;
                to->Alpha = from->Alpha;
                from++;
                to++;
            }
        }
        public static unsafe void ToArgb32(SignedArgb64* from, Argb32* to, int length = 1)
        {
            if (length < 1) return;

            SignedArgb64* end = from + length;
            while (from != end)
            {
                to->Blue = (byte)from->Blue;
                to->Green = (byte)from->Green;
                to->Red = (byte)from->Red;
                to->Alpha = (byte)from->Alpha;
                from++;
                to++;
            }
        }