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++; } }