在 C# 中实现颜色过滤

发布于 2024-08-23 22:40:00 字数 1087 浏览 4 评论 0原文

我正在尝试在我的应用程序中实现 Photoshop 风格的颜色过滤功能。我有一个位图和 4 个复选框(R、G、B、A)。我想知道最快的方法是什么

目前我正在按如下方式执行此操作

        Byte[] rgbValues = new Byte[data.Stride * data.Height];
        for (int row = 0; row < data.Height; row++)
        {
            // Loop through each pixel on this scan line
            int bufPos = (m_height - row - 1) * m_width;
            int index = row * data.Stride;
            for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
            {
                bool drawCheckerBoard = true; // for alpha
                UInt32 rgba = m_image[bufPos];
                UInt32 r =  EnableRedChannel ? ((rgba >> 0) & 0xFF) : 0x00;
                UInt32 g =  EnableGreenChannel ? ((rgba >> 8) & 0xFF) : 0x00;
                UInt32 b =  EnableBlueChannel ? ((rgba >> 16) & 0xFF) : 0x00;
                UInt32 a = (rgba >> 24) & 0xFF;
                ...
                ...
            }
        }

,然后是通常的 Marshal.Copy 和解锁位等...

如您所见,这并不是真正的优化方法,我想要一些建议更快的方法。

谢谢

I am trying to implement a Photoshop style color filtering feature in my application. I have a Bitmap, and 4 check-boxes (R,G,B,A). I wanted to know what is the fastest way of doing it

Currently I am doing it as follows

        Byte[] rgbValues = new Byte[data.Stride * data.Height];
        for (int row = 0; row < data.Height; row++)
        {
            // Loop through each pixel on this scan line
            int bufPos = (m_height - row - 1) * m_width;
            int index = row * data.Stride;
            for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
            {
                bool drawCheckerBoard = true; // for alpha
                UInt32 rgba = m_image[bufPos];
                UInt32 r =  EnableRedChannel ? ((rgba >> 0) & 0xFF) : 0x00;
                UInt32 g =  EnableGreenChannel ? ((rgba >> 8) & 0xFF) : 0x00;
                UInt32 b =  EnableBlueChannel ? ((rgba >> 16) & 0xFF) : 0x00;
                UInt32 a = (rgba >> 24) & 0xFF;
                ...
                ...
            }
        }

and then the usual Marshal.Copy and unlock bits etc...

As you can see it is not really an optimized way, I wanted some suggestions for a faster method.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

二手情话 2024-08-30 22:40:00

目前尚不清楚您想对单独的 r、g、b 和 做什么。 a 值,但我立即看到的一件事是您可以将启用标志移出循环。

   UInt32 rMask = EnableRedChannel   ? 0x000000FF : 00;
   UInt32 gMask = EnableGreenChannel ? 0x0000FF00 : 00;
   UInt32 bMask = EnableBlueChannel  ? 0x00FF0000 : 00;
   UInt32 aMask = 0xFF000000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos];
            UInt32 r =  (rgba & aMask) >> 0;
            UInt32 g =  (rgba & gMask) >> 8;
            UInt32 b =  (rgba & bMask) >> 16;
            UInt32 a =  (rgba & aMask) >> 24;
            ...
            ...
        }
    }

更进一步,如果您实际上不需要拉出 r、g、b& 图像,则可以构建一个复合蒙版。一个值。

   UInt32 mask  = 0xFF000000;
   if (EnableRedChannel)
      mask |= 0x000000FF;
   if (EnableGreenChannel)
      mask |= 0x0000FF00;
   if (EnableBlueChannel)
      mask |= 0x00FF0000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos] & mask;
            ...
            ...
        }
    }

您可能还会发现将 m_image[] 设为字节数组很有帮助,这样只需调整偏移量并跨过数据即可更轻松地挑选出各个颜色通道。

It's unclear what you want to do with the individual r,g,b & a values, but one thing I see right off is that you can move your enable flags out of the loop.

   UInt32 rMask = EnableRedChannel   ? 0x000000FF : 00;
   UInt32 gMask = EnableGreenChannel ? 0x0000FF00 : 00;
   UInt32 bMask = EnableBlueChannel  ? 0x00FF0000 : 00;
   UInt32 aMask = 0xFF000000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos];
            UInt32 r =  (rgba & aMask) >> 0;
            UInt32 g =  (rgba & gMask) >> 8;
            UInt32 b =  (rgba & bMask) >> 16;
            UInt32 a =  (rgba & aMask) >> 24;
            ...
            ...
        }
    }

Going one step beyond that, you can build a composite mask if you don't actually need to pull out the r,g,b& a values.

   UInt32 mask  = 0xFF000000;
   if (EnableRedChannel)
      mask |= 0x000000FF;
   if (EnableGreenChannel)
      mask |= 0x0000FF00;
   if (EnableBlueChannel)
      mask |= 0x00FF0000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos] & mask;
            ...
            ...
        }
    }

You might also find it helpful to have your of your m_image[] be an array of bytes, this would make it easier to pick out the individual color channels just by adjusting your offset and stride through the data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文