Esempio n. 1
0
        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;
            }
        }
Esempio n. 2
0
        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;
            }
        }
Esempio n. 3
0
        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;
            }
        }
Esempio n. 4
0
        public unsafe void Fill(TPixel pixel)
        {
            TPixel *p   = this.Start;
            TPixel *end = p + this.Length;

            while (p != end)
            {
                *p = pixel;
                p++;
            }
        }
Esempio n. 5
0
        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;
            }
        }
Esempio n. 6
0
        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++;
            }
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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++;
                }
            }
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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;
            }
        }
Esempio n. 11
0
        /// <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);
        }
Esempio n. 12
0
        /// <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();
        }
Esempio n. 13
0
        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();
        }
Esempio n. 14
0
        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();
        }