UWP环境下InkCanvas绘制内容到8bpp图像自动转32bpp问题求解
核心原因
Win2D的CanvasRenderTarget默认使用32位BGRA格式作为渲染缓存,无论输入源的位深是多少,绘制过程都会统一转换为32位处理,直接调用SaveAsync方法仅支持输出24/32位色深的图像,原生不支持直接导出8bpp格式。
解决方案
你可以跳过Win2D的默认保存逻辑,手动将渲染结果转换为8bpp格式后再编码输出,具体实现步骤如下:
- 从渲染完成的
CanvasRenderTarget中读取32位原始像素数据 - 根据使用场景配置8bpp对应调色板,签名场景推荐使用256级灰度调色板即可满足需求
- 将32位像素映射为8bpp索引值,使用
BitmapEncoder指定8bpp格式完成编码
修改后的实现代码
Image imgToEdit; InkCanvas inkCanvas; file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(Ambiente.imgBlankFirma); await file.CopyAsync(photoFolder, NomeFile, NameCollisionOption.ReplaceExisting); file = await photoFolder.GetFileAsync(NomeFile); imgToEdit = imgFirma; inkCanvas = inkCanvasFirma; if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count <= 0) { errore = true; return; } var randomAccessStream = await file.OpenReadAsync(); CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight, 96); using (var ds = renderTarget.CreateDrawingSession()) { var image = await CanvasBitmap.LoadAsync(device, randomAccessStream); ds.DrawImage(image); ds.DrawInk(inkCanvas.InkPresenter.StrokeContainer.GetStrokes()); } randomAccessStream.Dispose(); // 新增:将渲染结果转换为8bpp灰度Tiff int pixelWidth = renderTarget.SizeInPixels.Width; int pixelHeight = renderTarget.SizeInPixels.Height; // 读取32位像素数据 byte[] pixelData32bpp = renderTarget.GetPixelBytes(); // 构造8bpp像素数组 byte[] pixelData8bpp = new byte[pixelWidth * pixelHeight]; for (int i = 0; i < pixelData32bpp.Length; i += 4) { // 用BT.601灰度公式计算灰度值:Y = 0.299 R + 0.587 G + 0.114 B byte b = pixelData32bpp[i]; byte g = pixelData32bpp[i + 1]; byte r = pixelData32bpp[i + 2]; byte gray = (byte)(r * 0.299 + g * 0.587 + b * 0.114); pixelData8bpp[i / 4] = gray; } // 生成256级灰度调色板 var palette = new BitmapPalette(new List<Color>()); for (int i = 0; i < 256; i++) { palette.Colors.Add(Color.FromArgb(255, (byte)i, (byte)i, (byte)i)); } // 编码保存 using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) { BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.TiffEncoderId, fileStream); encoder.SetPixelData( BitmapPixelFormat.Gray8, BitmapAlphaMode.Ignore, (uint)pixelWidth, (uint)pixelHeight, 96, 96, pixelData8bpp); encoder.BitmapPalette = palette; await encoder.FlushAsync(); }
内容的提问来源于stack exchange,提问作者SonicMast3r
相关产品推荐
相关产品推荐

