1

我不知道如何标记这个问题,请尽可能编辑。

工作:创建一个可以在批量运行中自动裁剪图像中的黑色边框的应用程序。图像的质量从 100-300dpi、1bpp-24bpp 不等,一批可以从 10 到 10 000 张图像不等。

计划:将图像转换为 1bpp(双色调,黑/白,如果还没有的话)并在“清理”白点/污垢/噪声后找到黑色结束和白色开始的位置,这些是新的坐标图像裁剪,将它们应用于原始图像的克隆。删除旧图像,保存新图像。

进展:以上所有都已完成,并且有效,但是......

问题:当转换为 1bpp 时,我无法控制“阈值”值。我需要这个。很多暗图像被裁剪太多。

尝试:我试过了

Bitmap imgBitonal = imgOriginal.Clone(new Rectangle(0, 0, b.Width, b.Height), PixelFormat.Format1bppIndexed)

还有这个。两者都有效,但似乎都没有让我手动设置阈值的可能性。我需要用户能够设置此值等,并在运行批处理之前使用我的“预览”功能,以查看设置是否有任何好处。

哭声:我在这里不知所措。我现在不知道该做什么或如何去做。请帮助一位程序员。指出一个方向,告诉我在链接中找到的代码中找到阈值的位置(我还没有找到,或者不知道在哪里看),或者只是给我一些有效的代码。任何帮助表示赞赏。

4

1 回答 1

2

试试这个,从非常快的 1bpp 转换

从这里复制将 24bpp 位图转换为 1bpp

        private static unsafe void Convert(Bitmap src, Bitmap conv)
        {
            // Lock source and destination in memory for unsafe access
            var bmbo = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadOnly,
                                     src.PixelFormat);
            var bmdn = conv.LockBits(new Rectangle(0, 0, conv.Width, conv.Height), ImageLockMode.ReadWrite,
                                     conv.PixelFormat);

            var srcScan0 = bmbo.Scan0;
            var convScan0 = bmdn.Scan0;

            var srcStride = bmbo.Stride;
            var convStride = bmdn.Stride;

            byte* sourcePixels = (byte*)(void*)srcScan0;
            byte* destPixels = (byte*)(void*)convScan0;

            var srcLineIdx = 0;
            var convLineIdx = 0;
            var hmax = src.Height-1;
            var wmax = src.Width-1;
            for (int y = 0; y < hmax; y++)
            {
                // find indexes for source/destination lines

                // use addition, not multiplication?
                srcLineIdx += srcStride;
                convLineIdx += convStride;

                var srcIdx = srcLineIdx;
                for (int x = 0; x < wmax; x++)
                {
                    // index for source pixel (32bbp, rgba format)
                    srcIdx += 4;
                    //var r = pixel[2];
                    //var g = pixel[1];
                    //var b = pixel[0];

                    // could just check directly?
                    //if (Color.FromArgb(r,g,b).GetBrightness() > 0.01f)
                    if (!(sourcePixels[srcIdx] == 0 && sourcePixels[srcIdx + 1] == 0 && sourcePixels[srcIdx + 2] == 0))
                    {
                        // destination byte for pixel (1bpp, ie 8pixels per byte)
                        var idx = convLineIdx + (x >> 3);
                        // mask out pixel bit in destination byte
                        destPixels[idx] |= (byte)(0x80 >> (x & 0x7));
                    }
                }
            }
            src.UnlockBits(bmbo);
            conv.UnlockBits(bmdn);
        }
于 2014-03-07T16:56:39.703 回答