C#图片转指定格式十六进制数组适配OLED显示异常问题
问题
需要将图片转换为0x00, 0x00,...格式的十六进制数组,用于Arduino OLED显示屏,但现有C#代码输出的是连续的PNG原始十六进制字符串(如89504e47...),调整格式后内容比目标输出长,写入Arduino后无法正常显示图片。
现有代码:
private void btnImg2ByteArray_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Select Valid Image(*.png)|*.png"; dialog.Multiselect = true; if (dialog.ShowDialog() == DialogResult.OK) { foreach (string fileName in dialog.FileNames) { using (var ms = new MemoryStream()) { Image imageIn = new Bitmap(fileName); imageIn.Save(ms, imageIn.RawFormat); //System.Drawing.Imaging.ImageFormat.Png byte[] b = ms.ToArray(); txtImage2byte.Text += "[" + Path.GetFileName(fileName) + "]" + Environment.NewLine; StringBuilder hex = new StringBuilder(b.Length * 2); foreach (byte _b in b) { hex.AppendFormat("{0:x2}", _b); } txtImage2byte.Text += hex.ToString(); } } } }
问题分析与解决
核心问题
你当前的代码是直接读取PNG文件的原始字节流(包含PNG文件头、压缩编码等冗余数据),但OLED显示屏需要的是图像的单色点阵压缩数据(比如128x64屏幕需要1024字节,每字节对应8个像素的黑白状态),两者完全不是同一类型的数据,所以长度不符且无法显示。
修改后的代码
下面的代码会将图片转换为OLED所需的点阵字节数组,并格式化为指定的0xXX, 格式:
private void btnImg2ByteArray_Click(object sender, EventArgs e) { // 按你的OLED屏幕尺寸调整,这里以128x64为例 int oledWidth = 128; int oledHeight = 64; OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Image Files(*.png;*.jpg)|*.png;*.jpg"; dialog.Multiselect = true; if (dialog.ShowDialog() == DialogResult.OK) { foreach (string fileName in dialog.FileNames) { txtImage2byte.Text += $"[{Path.GetFileName(fileName)}]{Environment.NewLine}"; // 加载图片并缩放到OLED尺寸 using (Bitmap originalBmp = new Bitmap(fileName)) using (Bitmap resizedBmp = new Bitmap(originalBmp, oledWidth, oledHeight)) { // 计算需要的字节数:每8个像素占1字节 int byteCount = oledWidth * oledHeight / 8; byte[] oledData = new byte[byteCount]; // 遍历OLED的每一页(共8页,每页8行像素) for (int page = 0; page < oledHeight / 8; page++) { // 遍历每一列 for (int x = 0; x < oledWidth; x++) { byte currentByte = 0; // 遍历当前页的8行像素 for (int bit = 0; bit < 8; bit++) { int y = page * 8 + bit; Color pixelColor = resizedBmp.GetPixel(x, y); // 将像素转为黑白:亮度低于阈值则视为黑色(OLED点亮),否则白色(熄灭) bool isBlack = (pixelColor.R + pixelColor.G + pixelColor.B) / 3 < 128; if (isBlack) { currentByte |= (byte)(1 << bit); } } // 填充到数组对应位置 oledData[page * oledWidth + x] = currentByte; } } // 格式化为0xXX, 形式的字符串 StringBuilder hexBuilder = new StringBuilder(); foreach (byte b in oledData) { hexBuilder.Append($"0x{b:x2}, "); } // 移除最后一个多余的逗号和空格 if (hexBuilder.Length > 0) { hexBuilder.Length -= 2; } txtImage2byte.Text += hexBuilder.ToString() + Environment.NewLine + Environment.NewLine; } } } }
关键说明
- 尺寸匹配:必须将图片缩放到和OLED屏幕一致的分辨率(比如128x64),否则点阵数据无法正确映射。
- 单色转换:通过像素亮度阈值将彩色/灰度图转为黑白,适配OLED的单色显示特性。
- 点阵存储规则:按照OLED的页存储模式(每页8行,每列8个像素组成一个字节)生成数据,和大多数OLED驱动库的要求一致。
内容的提问来源于stack exchange,提问作者StealthRT
相关产品推荐
相关产品推荐

