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

C#:如何将数值范围[50,600]的一维数组转换为灰度位图?

解决16位灰度图像生成问题

为啥之前的代码出问题

你用Format16bppGrayScale创建的是16位灰度图,但SetPixel对这种格式的支持很差——你传的单值会被错误解析成ARGB通道,导致显示成蓝色。另外,16位灰度的有效值范围是0到65535,你那50-600的数值直接用肯定不对,得先映射到这个区间,而且不能用8位RGB的Color.FromArgb(val,val,val),因为那要求值必须在0-255之间。

正确的做法

直接操作位图的内存缓冲区,别用SetPixel,同时把你的数值线性映射到16位灰度的范围里。

完整代码示例

// 替换成你实际的宽度和高度
int imgWidth = xL;
int imgHeight = yL;
float minPixelVal = 50;
float maxPixelVal = 600;
float valueRange = maxPixelVal - minPixelVal;

// 创建16位灰度位图
var grayBitmap = new Bitmap(imgWidth, imgHeight, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
// 锁定位图内存,准备写入数据
var bitmapData = grayBitmap.LockBits(
    new System.Drawing.Rectangle(0, 0, imgWidth, imgHeight),
    System.Drawing.Imaging.ImageLockMode.WriteOnly,
    grayBitmap.PixelFormat);

// 准备存储像素的字节数组(16位灰度每个像素占2字节)
int stride = bitmapData.Stride;
int totalBytes = stride * imgHeight;
byte[] pixelBuffer = new byte[totalBytes];

int arrIndex = 0;
for (int y = 0; y < imgHeight; y++)
{
    for (int x = 0; x < imgWidth; x++)
    {
        // 把原数组的数值映射到0-65535的16位灰度范围
        float originalVal = arr[arrIndex];
        ushort gray16 = (ushort)(((originalVal - minPixelVal) / valueRange) * 65535);
        
        // 把16位值转成字节(小端存储,适配Windows系统)
        byte[] grayBytes = BitConverter.GetBytes(gray16);
        // 计算当前像素在缓冲区的位置
        int bufferIndex = y * stride + x * 2;
        pixelBuffer[bufferIndex] = grayBytes[0];
        pixelBuffer[bufferIndex + 1] = grayBytes[1];
        
        arrIndex++;
    }
}

// 把像素数据复制到位图内存里
System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, 0, bitmapData.Scan0, totalBytes);
// 解锁内存
grayBitmap.UnlockBits(bitmapData);

// 按需旋转图像(如果原方向不对)
grayBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
// 保存图像,建议用PNG避免压缩损失
grayBitmap.Save("output_gray.png", System.Drawing.Imaging.ImageFormat.Png);

注意点

  • 映射逻辑:代码里是把50对应纯黑(0),600对应纯白(65535),这样能最大化利用灰度范围,对比度最高。如果不想让50变成纯黑,也可以改映射公式,比如直接gray16 = (ushort)(originalVal * (65535f / maxPixelVal)),但这样对比度会低一些。
  • 效率问题:LockBits比SetPixel快得多,尤其是图像尺寸大的时候,后者会慢到离谱。
  • 字节顺序:Windows系统默认是小端存储,所以BitConverter.GetBytes生成的字节顺序刚好符合要求,不用额外调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:02:50