public unsafe static void ForEach(this UnmanagedImage <TPixel> src, TPixel *start, uint length, ActionOnPixel handler) { TPixel *end = start + src.Length; while (start != end) { handler(start); ++start; } }
public unsafe static void ForEach(this UnmanagedImage <TPixel> src, ActionOnPixel handler) { TPixel *start = (TPixel *)src.StartIntPtr; TPixel *end = start + src.Length; while (start != end) { handler(start); ++start; } }
public unsafe void Copy(UnmanagedImage <TPixel> src, System.Drawing.Point start, System.Drawing.Rectangle region, System.Drawing.Point destAnchor) { if (start.X >= src.Width || start.Y >= src.Height) { return; } int startSrcX = Math.Max(0, start.X); int startSrcY = Math.Max(0, start.Y); int endSrcX = Math.Min(start.X + region.Width, src.Width); int endSrcY = Math.Min(start.Y + region.Height, src.Height); int offsetX = start.X < 0? -start.X : 0; int offsetY = start.Y < 0? -start.Y : 0; offsetX = destAnchor.X + offsetX; offsetY = destAnchor.Y + offsetY; int startDstX = Math.Max(0, offsetX); int startDstY = Math.Max(0, offsetY); offsetX = offsetX < 0 ? -offsetX : 0; offsetY = offsetY < 0 ? -offsetY : 0; startSrcX += offsetX; startSrcY += offsetY; int endDstX = Math.Min(destAnchor.X + region.Width, this.Width); int endDstY = Math.Min(destAnchor.Y + region.Height, this.Height); int copyWidth = Math.Min(endSrcX - startSrcX, endDstX - startDstX); int copyHeight = Math.Min(endSrcY - startSrcY, endDstY - startDstY); if (copyWidth <= 0 || copyHeight <= 0) { return; } int srcWidth = src.Width; int dstWidth = this.Width; TPixel *srcLine = (TPixel *)(src.StartIntPtr) + srcWidth * startSrcY + startSrcX; TPixel *dstLine = this.Start + dstWidth * startDstY + startDstX; TPixel *endSrcLine = srcLine + srcWidth * copyHeight; while (srcLine < endSrcLine) { TPixel *pSrc = srcLine; TPixel *endPSrc = pSrc + copyWidth; TPixel *pDst = dstLine; while (pSrc < endPSrc) { *pDst = *pSrc; pSrc++; pDst++; } srcLine += srcWidth; dstLine += dstWidth; } }
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 FillImage(ImageChannel <TPixel> img, TPixel value) { int step = img.Step; TPixel *start = (TPixel *)img.StartIntPtr; TPixel *end = start += img.Length * img.Step; while (start != end) { *start = value; start += step; } }
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 unsafe static Int32 Count(this UnmanagedImage <TPixel> src, Predicate <TPixel> handler) { TPixel *start = (TPixel *)src.StartIntPtr; TPixel *end = start + src.Length; Int32 count = 0; while (start != end) { if (handler(*start) == true) { count++; } ++start; } return(count); }
public unsafe static void ForEach(this UnmanagedImage <TPixel> src, ActionWithPosition handler) { Int32 width = src.Width; Int32 height = src.Height; TPixel *p = (TPixel *)src.StartIntPtr; for (Int32 r = 0; r < height; r++) { for (Int32 w = 0; w < width; w++) { handler(w, r, p); p++; } } }
public unsafe static List <TPixel> Where(this UnmanagedImage <TPixel> src, PredicateOnPixel handler) { List <TPixel> list = new List <TPixel>(); TPixel *start = (TPixel *)src.StartIntPtr; TPixel *end = start + src.Length; while (start != end) { if (handler(start) == true) { list.Add(*start); } ++start; } return(list); }
public static unsafe void CopyToIntChannel(ImageChannel <TPixel> src, ImageChannel <Int32> dst) { if (src.Length != dst.Length) { throw new InvalidOperationException("The two channels are not the same length."); } int length = src.Length; int srcStep = src.Step; int dstStep = dst.Step; TPixel *srcStart = (TPixel *)src.StartIntPtr; TPixel *srcEnd = srcStart + length * srcStep; Int32 * dstStart = (Int32 *)dst.StartIntPtr; while (srcStart != srcEnd) { *dstStart = (Int32)(*srcStart); srcStart += srcStep; dstStart += dstStep; } }
/// <summary> /// 查找模板。模板中值代表实际像素值。负数代表任何像素。返回查找得到的像素的左上端点的位置。 /// </summary> /// <param name="template"></param> /// <returns></returns> public static unsafe List <System.Drawing.Point> FindTemplate(this UnmanagedImage <TPixel> src, int[,] template) { List <System.Drawing.Point> finds = new List <System.Drawing.Point>(); int tHeight = template.GetUpperBound(0) + 1; int tWidth = template.GetUpperBound(1) + 1; int toWidth = src.Width - tWidth + 1; int toHeight = src.Height - tHeight + 1; int stride = src.Width; TPixel *start = (TPixel *)src.StartIntPtr; for (int r = 0; r < toHeight; r++) { for (int c = 0; c < toWidth; c++) { TPixel *srcStart = start + r * stride + c; for (int rr = 0; rr < tHeight; rr++) { for (int cc = 0; cc < tWidth; cc++) { int pattern = template[rr, cc]; if (pattern >= 0 && srcStart[rr * stride + cc] != pattern) { goto Next; } } } finds.Add(new System.Drawing.Point(c, r)); Next: continue; } } return(finds); }
/// <summary> /// 使用众值滤波 /// </summary> public unsafe void ApplyModeFilter(int size) { if (size <= 1) { throw new ArgumentOutOfRangeException("size 必须大于1."); } else if (size > 127) { throw new ArgumentOutOfRangeException("size 最大为127."); } else if (size % 2 == 0) { throw new ArgumentException("size 应该是奇数."); } int * vals = stackalloc int[size * size + 1]; TPixel *keys = stackalloc TPixel[size * size + 1]; UnmanagedImage <TPixel> mask = this.Clone() as UnmanagedImage <TPixel>; int height = this.Height; int width = this.Width; TPixel *pMask = (TPixel *)mask.StartIntPtr; TPixel *pThis = (TPixel *)this.StartIntPtr; int radius = size / 2; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int count = 0; // 建立直方图 for (int y = -radius; y <= radius; y++) { for (int x = -radius; x <= radius; x++) { int yy = y + h; int xx = x + w; if (xx >= 0 && xx < width && yy >= 0 && yy < height) { TPixel color = pMask[yy * width + xx]; bool find = false; for (int i = 0; i < count; i++) { if (keys[i] == color) { vals[i]++; find = true; break; } } if (find == false) { keys[count] = color; vals[count] = 1; count++; } } } } if (count > 0) { // 求众数 int index = -1; int max = int.MinValue; for (int i = 0; i < count; i++) { if (vals[i] > max) { index = i; max = vals[i]; } } if (max > 1) { pThis[h * width + w] = keys[index]; } } } } mask.Dispose(); }
public static unsafe void ApplyConvolution(ImageChannel <TPixel> img, ConvolutionKernel k) { if (img.Width < 2 || img.Height < 2) { return; } int widthTypeScaled = img.Width * img.Step; int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; ImageChannel <TPixel> maskImage = new ImageChannel <TPixel>(img.Width + extend * 2, img.Height + extend * 2); FillImage(maskImage, (TPixel)0); //这里效率不高。原本只需要填充四周扩大的部分即可 CopyChannel(img, maskImage, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, img.Width, img.Height), new System.Drawing.Point(extend, extend)); int step = img.Step; int maskStep = maskImage.Step; int width = img.Width; int height = img.Height; TPixel *start = (TPixel *)img.StartIntPtr; TPixel *maskStart = (TPixel *)maskImage.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskStart + extend; int maskWidth = img.Width + extend * 2; int maskHeight = img.Height + extend * 2; TPixel *dstContentStart = maskStart + extend + maskWidth * extend; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制下方的像素 for (int y = height + extend; y < maskHeight; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart + height * maskWidth - maskWidth; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制左右两侧的像素 TPixel *dstLine = maskStart + maskWidth * extend; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { p = dstLine[extend]; for (int x = 0; x < extend; x++) { dstLine[x] = p; } p = dstLine[extend + width - 1]; for (int x = width + extend; x < maskWidth; x++) { dstLine[x] = p; } dstLine += maskWidth; } // 复制四个角落的像素 // 左上 p = dstContentStart[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右上 p = dstContentStart[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } // 左下 p = dstContentStart[(height - 1) * maskWidth]; for (int y = height + extend; y < maskHeight; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右下 p = dstContentStart[(height - 1) * maskWidth + width - 1]; for (int y = height + extend; y < maskHeight; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }
public unsafe void ApplyConvolution(ConvolutionKernel k) { int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2); maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可 maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend)); int width = this.Width; int height = this.Height; TPixel *start = (TPixel *)this.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskImage.Start + extend; int extendWidth = this.Width + extend * 2; int extendHeight = this.Height + extend * 2; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制下方的像素 for (int y = height + extend; y < extendHeight; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start + (height - 1) * width; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制左右两侧的像素 TPixel *dstLine = maskImage.Start + extendWidth * extend; TPixel *srcLine = start; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { for (int x = 0; x < extend; x++) { p = srcLine[0]; dstLine[x] = p; } p = srcLine[width - 1]; for (int x = width + extend; x < extendWidth; x++) { dstLine[x] = p; } dstLine += extendWidth; srcLine += width; } // 复制四个角落的像素 // 左上 p = start[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右上 p = start[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } // 左下 p = start[(height - 1) * width]; for (int y = height + extend; y < extendHeight; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右下 p = start[height * width - 1]; for (int y = height + extend; y < extendHeight; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }