如何使用SkiaSharp将PNG图片转换为1Bpp格式?
实现SkiaSharp编码1Bpp图像的方法
核心问题说明
你直接调用Encode返回null的原因是:原图并非1位深度的位图,SkiaSharp不会自动将高位深度图像转换为1Bpp格式,必须先将图像转为纯黑白的1位深度位图后再编码。
方案1:手动二值化+1位索引位图编码
通过灰度转换、手动阈值二值化,再创建带黑白调色板的索引位图,最终编码为1Bpp BMP:
byte[] imageBytes = /* 你的PNG字节数组 */; using var originalImage = SKImage.FromEncodedData(imageBytes); using var originalBitmap = originalImage.ToSKBitmap(); // 1. 转换为灰度图 using var grayBitmap = originalBitmap.Copy(SKColorType.Gray8, SKAlphaType.Opaque); // 2. 手动二值化处理(阈值设为128,可按需调整) var pixels = grayBitmap.Pixels; for (int i = 0; i < pixels.Length; i++) { var grayValue = pixels[i].Red; // Gray8格式下RGB值一致 pixels[i] = grayValue >= 128 ? SKColors.White : SKColors.Black; } grayBitmap.Pixels = pixels; // 3. 创建带黑白调色板的1位索引位图 var imageInfo = new SKImageInfo(originalBitmap.Width, originalBitmap.Height, SKColorType.Index8, SKAlphaType.Opaque); var palette = new SKPalette(new[] { SKColors.Black, SKColors.White }); using var oneBppBitmap = new SKBitmap(imageInfo); oneBppBitmap.Palette = palette; // 4. 绘制二值化图像并编码 using var canvas = new SKCanvas(oneBppBitmap); canvas.DrawBitmap(grayBitmap, 0, 0); using var encodedData = oneBppBitmap.Encode(SKEncodedImageFormat.Bmp, 100); byte[] resultBytes = encodedData.ToArray();
方案2:使用滤镜快速二值化
借助SkiaSharp颜色滤镜实现自动二值化,减少手动像素操作:
byte[] imageBytes = /* 你的PNG字节数组 */; using var originalImage = SKImage.FromEncodedData(imageBytes); using var originalBitmap = originalImage.ToSKBitmap(); // 创建二值化组合滤镜:先转灰度,再按阈值分割黑白 var grayMatrix = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0 }; var grayFilter = SKColorFilter.CreateColorMatrix(grayMatrix); var thresholdFilter = SKColorFilter.CreateThreshold(SKColorChannel.Red, 0.5f, SKColors.Black, SKColors.White); var binaryFilter = SKColorFilter.CreateCompose(thresholdFilter, grayFilter); // 创建1位索引位图并绘制 var imageInfo = new SKImageInfo(originalBitmap.Width, originalBitmap.Height, SKColorType.Index8, SKAlphaType.Opaque); var palette = new SKPalette(new[] { SKColors.Black, SKColors.White }); using var oneBppBitmap = new SKBitmap(imageInfo); oneBppBitmap.Palette = palette; using var canvas = new SKCanvas(oneBppBitmap); using var paint = new SKPaint { ColorFilter = binaryFilter }; canvas.DrawBitmap(originalBitmap, 0, 0, paint); // 编码为1Bpp BMP using var encodedData = oneBppBitmap.Encode(SKEncodedImageFormat.Bmp, 100); byte[] resultBytes = encodedData.ToArray();
补充说明
- WBMP格式本身是1Bpp标准,但SkiaSharp对其支持有限,实际使用中优先选择1Bpp BMP格式更可靠。
- 若需处理透明图像,需先将透明区域替换为白色/黑色,再进行二值化操作。
内容的提问来源于stack exchange,提问作者Juan P. Garces
相关产品推荐
相关产品推荐

