You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中按指定最大色深从屏幕获取像素颜色

C# 实现 Clickermann ColorMode(n) 等效色深压缩功能

核心实现逻辑

Clickermann 的 ColorMode(n) 本质是通过位量化机制压缩图像调色板,核心特性是按亮度层级合并相近颜色,不会在渐变区域出现突兀的色阶断层。
要对齐该功能效果,核心要遵循两个规则:

  • 按人眼对色彩的敏感度分配位宽:绿色通道分配最多有效位,红色次之,蓝色最少,保证人眼感知最自然
  • 对每个颜色通道做整层级量化,不做随机颜色映射,保证渐变区域的过渡连贯性

关键参数匹配

你给出的效果参考中,最大色深为8指总色深位宽为8,对应RGB通道的位宽分配为:绿色通道3位、红色通道3位、蓝色通道2位,总位宽刚好8位,和官方实现的效果对齐。

实现步骤

  • 获取屏幕指定区域的原始像素数据,通过内存块直接操作像素,避免逐像素API带来的性能损耗
  • 根据传入的总色深值,按优先级计算RGB三个通道各自的有效位宽
  • 对每个通道的0-255亮度值计算对应量化步长,把同层级的相近颜色合并到同一亮度值
  • 重组量化后的像素数据,输出处理后的图像

示例代码

首先引入依赖命名空间:

using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

屏幕区域捕获方法:

public static Bitmap CaptureScreenRegion(Rectangle captureArea)
{
    Bitmap captureResult = new Bitmap(captureArea.Width, captureArea.Height, PixelFormat.Format32bppArgb);
    using (Graphics g = Graphics.FromImage(captureResult))
    {
        g.CopyFromScreen(captureArea.Left, captureArea.Top, 0, 0, captureArea.Size);
    }
    return captureResult;
}

色深压缩核心方法:

public static Bitmap ApplyColorMode(Bitmap source, int totalColorDepth)
{
    // 校验参数范围:总色深最大24位(无透明通道的真彩)
    if (totalColorDepth < 1 || totalColorDepth > 24)
        throw new ArgumentOutOfRangeException(nameof(totalColorDepth), "色深参数需在1-24区间内");

    // 按人眼敏感度分配位宽:绿色通道最多,红色次之,蓝色最少
    int bitsGreen = totalColorDepth / 3 + (totalColorDepth % 3 != 0 ? 1 : 0);
    int bitsRed = (totalColorDepth - bitsGreen) / 2;
    int bitsBlue = totalColorDepth - bitsGreen - bitsRed;

    // 计算每个通道的量化步长
    int stepRed = 256 / (1 << bitsRed);
    int stepGreen = 256 / (1 << bitsGreen);
    int stepBlue = 256 / (1 << bitsBlue);

    // 锁定位图内存,直接操作字节数组提升处理速度
    Rectangle imageRect = new Rectangle(0, 0, source.Width, source.Height);
    BitmapData rawData = source.LockBits(imageRect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
    int bufferSize = Math.Abs(rawData.Stride) * source.Height;
    byte[] pixelBuffer = new byte[bufferSize];
    Marshal.Copy(rawData.Scan0, pixelBuffer, 0, bufferSize);

    // 遍历所有像素执行量化
    // 32位ARGB像素的内存顺序为B、G、R、A,每4字节对应一个像素
    for (int i = 0; i < pixelBuffer.Length; i += 4)
    {
        pixelBuffer[i] = (byte)((pixelBuffer[i] / stepBlue) * stepBlue);
        pixelBuffer[i+1] = (byte)((pixelBuffer[i+1] / stepGreen) * stepGreen);
        pixelBuffer[i+2] = (byte)((pixelBuffer[i+2] / stepRed) * stepRed);
    }

    // 将处理后的数据写回位图
    Marshal.Copy(pixelBuffer, 0, rawData.Scan0, bufferSize);
    source.UnlockBits(rawData);
    return source;
}

使用示例

如果要实现等效于 Clickermann ColorMode(8) 的效果,直接调用方法即可:

// 捕获整个屏幕
Rectangle screenArea = Screen.PrimaryScreen.Bounds;
Bitmap screenCapture = CaptureScreenRegion(screenArea);
// 应用8位总色深压缩
Bitmap processed = ApplyColorMode(screenCapture, 8);

效果说明

该实现的量化规则会把相近颜色归到同一亮度层级,对渐变区域的处理和参考效果一致,不会出现随机色值跳变;处理大尺寸截图时,直接操作内存数组的性能比逐像素调用GetPixel/SetPixel高2个数量级以上。如果需要对齐 Clickermann 的具体位宽分配规则,只需要调整方法内的bitsGreen、bitsRed、bitsBlue三个变量的计算逻辑即可。

内容的提问来源于stack exchange,提问作者FreePhoenix888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 12:24:04