【问题标题】:Convert 32bpp to 8bpp UWP将 32bpp 转换为 8bpp UWP
【发布时间】:2021-12-13 11:08:32
【问题描述】:

我正在尝试将 InkCanvas 绘制到 8bpp 图像,但是当我尝试这样做时,图像将自身转换为 32bpp,我得到的较低的是 24bpp 但不是 8bpp。任何人都可以帮助我吗?我作为输入提供的图像是使用绘画创建的 8bpp BMP 图像。

        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); //inkCanvas.ActualWidth inkCanvas.ActualHeight
        
        using (var ds = renderTarget.CreateDrawingSession())
        {
            var image = await CanvasBitmap.LoadAsync(device, randomAccessStream);
            // draw your image first
            ds.DrawImage(image);
            // then draw contents of your ink canvas over it
            ds.DrawInk(inkCanvas.InkPresenter.StrokeContainer.GetStrokes());
        }

        randomAccessStream.Dispose();

        // save results
        using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Tiff, 1f);
        }

【问题讨论】:

  • 我会假设渲染始终以 32bpp 完成,因此您可能需要在稍后的步骤中进行颜色转换。见32bpp to 8bpprender target to bitmapImage
  • 嗨,我已经尝试过这个解决方案,但问题是使用 gif 我可以创建 8bpp 图像,但无法将其上传到需要 8bpp 格式的 BMP 图像的服务器。跨度>

标签: c# uwp uwp-xaml


【解决方案1】:

这显示了如何手动进行转换。它需要direct pointer access 到图像数据。因此,只需为转换目标创建一个具有正确大小的新 8bpp(即 Format8bppIndexed)位图。所以转换数据应该是这样的:

public static unsafe void Bgr24ToMono8(byte* source, byte* target, int sourceStride, int targetStride, int width, int height)
{

        for(var y = 0; y < height; y++)
        {
            var sourceRow = source + y * sourceStride;
            var targetRow = y * targetStride;
            for (int x = 0; x < width; x++)
            {
                var sourceIndex = (sourceRow + x * 3);
                var value = (byte)(sourceIndex[0] * 0.11f + sourceIndex[1] * 0.59f + sourceIndex[2] * 0.3f);
                target[targetRow + x] = value;
            }
        }
}

如果您有 32bpp 数据,则应该只是将 x * 3 更改为 x * 4 的问题。请注意,关于 Bgr 与 Rbg 存在一些混淆,不同的上下文对同一事物使用不同的术语。

请注意,这会将位图转换为 8bpp 灰度。如果您需要 8bpp 颜色索引,这将是更多工作,因为理想情况下您需要找到最佳颜色映射,在所述映射中找到最接近的颜色,并应用抖动以避免条带。为此,我会推荐一些图像处理库。我不认为有任何内置函数可以做到这一点,而且在这里演示的工作量很大。

【讨论】:

  • 抱歉 JonasH 回复晚了,但我不知道如何使用该 Parallel,也不知道什么是 sourceStride 以及如何获取它。
  • @SonicMast3r 您可以使用常规 for 循环而不是并行循环。步幅是一行中的字节数,这应该在某些属性中可用,例如BitmapData.Stride,请查看链接。
  • 非常感谢,我明天可能会试试这个代码。
  • 嗨@JonasH 我尝试了上面的代码,但我无法使用库 System.Drawing,因为我在 UWP 上。
  • @sonicMast3r 对于 Wpf,您可以使用 BitmapSource.CopyPixels 和/或 writableBitmap 来访问 pixelData。
猜你喜欢
  • 2011-09-15
  • 2014-03-17
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2013-02-10
  • 2019-02-10
相关资源
最近更新 更多