当前位置: 移动技术网 > IT编程>开发语言>c# > c#扫描图片去黑边(扫描仪去黑边)

c#扫描图片去黑边(扫描仪去黑边)

2019年07月18日  | 移动技术网IT编程  | 我要评论

自动去除图像扫描黑边

复制代码 代码如下:

/// <summary>
        /// 自动去除图像扫描黑边
        /// </summary>
        /// <param name="filename"></param>
        public static void autocutblackedge(string filename)
        {
            //打开图像
            bitmap bmp = openimage(filename);

            removeblackedge(bmp);
            //保存图像
            saveimage(bmp, filename);
        }

        private static byte[] rgbvalues; // 目标数组内存

        /// <summary>
        /// 图像去黑边
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        private static bitmap removeblackedge(bitmap bmp)
        {
            rectangle rect = new rectangle(0, 0, bmp.width, bmp.height);
            bitmapdata bmpdata = bmp.lockbits(rect, imagelockmode.readwrite, bmp.pixelformat);

            // 获取图像参数 
            int w = bmpdata.width;
            int h = bmpdata.height;
            int stride = bmpdata.stride;  // 扫描线的宽度
            double picbytesize = getpicbytesize(bmp.pixelformat);
            int bwidth = (int)math.ceiling(picbytesize * w); //显示宽度
            int offset = stride - bwidth;  // 显示宽度与扫描线宽度的间隙 
            intptr ptr = bmpdata.scan0;   // 获取bmpdata的内存起始位置 
            int scanbytes = stride * h;  // 用stride宽度,表示这是内存区域的大小

            // 分别设置两个位置指针,指向源数组和目标数组 
            int posscan = 0;
            rgbvalues = new byte[scanbytes];  // 为目标数组分配内存 
            marshal.copy(ptr, rgbvalues, 0, scanbytes);  // 将图像数据拷贝到rgbvalues中 

            bool ispass = true;
            int i = 0, j = 0;
            int cutw = (int)(bwidth * 0.02); //2%宽度(可修改)
            int cuth = (int)(h * 0.02);      //2%高度(可修改)
            int poslen = (int)(picbytesize * 8); //继续查找深度为8的倍数(可修改)
            //左边
            for (i = 0; i < h; i++)
            {
                for (j = 0; j < bwidth; j++)
                {
                    ispass = true;
                    if (rgbvalues[posscan] < 255) rgbvalues[posscan] = 255;

                    if (rgbvalues[posscan + 1] == 255)
                    {
                        for (int m = 1; m <= poslen; m++)
                        {
                            if (rgbvalues[posscan + m] < 255) ispass = false;
                        }
                    }
                    if (rgbvalues[posscan + 1] < 255 || bwidth / 2 < j) ispass = false;
                    reccheck(ref rgbvalues, posscan, h, stride, true);

                    posscan++;
                    if (j >= cutw && ispass) break;
                }
                // 跳过图像数据每行未用空间的字节,length = stride - width * byteperpixel 
                if (j == bwidth) posscan += offset;
                else posscan += (offset + bwidth - j - 1);
            }
            //右边
            posscan = scanbytes - 1;
            for (i = h - 1; i >= 0; i--)
            {
                posscan -= offset;
                for (j = bwidth - 1; j >= 0; j--)
                {
                    ispass = true;
                    if (rgbvalues[posscan] < 255) rgbvalues[posscan] = 255;

                    if (rgbvalues[posscan - 1] == 255)
                    {
                        for (int m = 1; m <= poslen; m++)
                        {
                            if (rgbvalues[posscan - m] < 255) ispass = false;
                        }
                    }
                    if (rgbvalues[posscan - 1] < 255 || bwidth / 2 > j) ispass = false;
                    reccheck(ref rgbvalues, posscan, h, stride, false);

                    posscan--;
                    if (cuth < (h - i))
                        if (j < (bwidth - cutw) && ispass) break;
                }
                // 跳过图像数据每行未用空间的字节,length = stride - width * byteperpixel
                if (j != -1) posscan -= j;
            }

            // 内存解锁 
            marshal.copy(rgbvalues, 0, ptr, scanbytes);
            bmp.unlockbits(bmpdata);  // 解锁内存区域 

            return bmp;
        }

        /// <summary>
        /// 上下去除黑边时,临近黑点去除
        /// </summary>
        /// <param name="rgbvalues"></param>
        /// <param name="posscan"></param>
        /// <param name="h"></param>
        /// <param name="stride"></param>
        /// <param name="islleft"></param>
        private static void reccheck(ref byte[] rgbvalues, int posscan, int h, int stride, bool islleft)
        {
            int scanbytes = h * stride;
            int cuth = (int)(h * 0.01); //临近最大1%高度(可修改)
            for (int i = 1; i <= cuth; i++)
            {
                int befrow = 0;
                if (islleft && (posscan - stride * i) > 0)
                {
                    befrow = posscan - stride * i;
                }
                else if (!islleft && (posscan + stride * i) < scanbytes)
                {
                    befrow = posscan + stride * i;
                }
                if (rgbvalues[befrow] < 255) rgbvalues[befrow] = 255;
                else break;
            }
        }

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网