C# 为什么图像上的旋转比使用位图编码器快得多?

C# 为什么图像上的旋转比使用位图编码器快得多?,c#,xaml,win-universal-app,uwp,uwp-xaml,C#,Xaml,Win Universal App,Uwp,Uwp Xaml,使用旋转图像 image.RenderTransform = new RotateTransform()... 这几乎是立竿见影的。 另一方面,使用 bitmapEncoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees... 在FlushAsync中速度要慢得多-超过半秒 为什么呢?有没有办法利用快速旋转来旋转位图?第一幅图像。RenderTransform将使用硬件渲染来渲染位图。GPU图像不会旋转,但会旋转/

使用旋转图像

image.RenderTransform = new RotateTransform()...
这几乎是立竿见影的。 另一方面,使用

bitmapEncoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees...
在FlushAsync中速度要慢得多-超过半秒

为什么呢?有没有办法利用快速旋转来旋转位图?

第一幅图像。RenderTransform将使用硬件渲染来渲染位图。GPU图像不会旋转,但会旋转/缩放显示。只能直接从视频存储器中访问可见像素

第二个将通过CPU旋转图像本身所有像素。它将为结果创建新内存。非视频存储器

更新:

有没有办法使用GPU编辑位图? 取决于您需要什么:

如果你想使用GPU。您可以使用像Slim DX/Sharp DX这样的托管包装器—这将需要很多时间才能获得结果。别忘了,通过gpu重新命名图像可能会导致质量损失

如果只想旋转图像0、90、180、270?您可以使用带有反扫描线0选项的位图类。这是为了保持质量和规模,您可以创建一个快速的实现

看这里:

我会为每个角度0,90180270创建一个算法。因为您不想计算每个像素的x,y位置。下面是一个例子

提示:

试着把乘法/除法去掉

/*This time we convert the IntPtr to a ptr*/
byte* scan0 = (byte*)bData.Scan0.ToPointer();

for (int i = 0; i < bData.Height; ++i)
{
    for (int j = 0; j < bData.Width; ++j)
    {
        byte* data = scan0 + i * bData.Stride + j * bitsPerPixel / 8;

        //data is a pointer to the first byte of the 3-byte color data
    }
}
变得像:

/*This time we convert the IntPtr to a ptr*/
byte* scan0 = (byte*)bData.Scan0.ToPointer();

byte* data = scan0;

int bytesPerPixel = bitsPerPixel / 8;

for (int i = 0; i < bData.Height; ++i)
{
    byte* data2 = data;
    for (int j = 0; j < bData.Width; ++j)
    {
        //data2 is a pointer to the first byte of the 3-byte color data

        data2 += bytesPerPixel;
    }
    data += bData.Stride;
}
第一个image.RenderTransform将使用硬件渲染来渲染位图。GPU图像不会旋转,但会旋转/缩放显示。只能直接从视频存储器中访问可见像素

第二个将通过CPU旋转图像本身所有像素。它将为结果创建新内存。非视频存储器

更新:

有没有办法使用GPU编辑位图? 取决于您需要什么:

如果你想使用GPU。您可以使用像Slim DX/Sharp DX这样的托管包装器—这将需要很多时间才能获得结果。别忘了,通过gpu重新命名图像可能会导致质量损失

如果只想旋转图像0、90、180、270?您可以使用带有反扫描线0选项的位图类。这是为了保持质量和规模,您可以创建一个快速的实现

看这里:

我会为每个角度0,90180270创建一个算法。因为您不想计算每个像素的x,y位置。下面是一个例子

提示:

试着把乘法/除法去掉

/*This time we convert the IntPtr to a ptr*/
byte* scan0 = (byte*)bData.Scan0.ToPointer();

for (int i = 0; i < bData.Height; ++i)
{
    for (int j = 0; j < bData.Width; ++j)
    {
        byte* data = scan0 + i * bData.Stride + j * bitsPerPixel / 8;

        //data is a pointer to the first byte of the 3-byte color data
    }
}
变得像:

/*This time we convert the IntPtr to a ptr*/
byte* scan0 = (byte*)bData.Scan0.ToPointer();

byte* data = scan0;

int bytesPerPixel = bitsPerPixel / 8;

for (int i = 0; i < bData.Height; ++i)
{
    byte* data2 = data;
    for (int j = 0; j < bData.Width; ++j)
    {
        //data2 is a pointer to the first byte of the 3-byte color data

        data2 += bytesPerPixel;
    }
    data += bData.Stride;
}

谢谢+1.如果你有这方面的文档,那就太好了。更重要的是:有没有一种方法可以使用GPU来编辑位图?这些微优化根本不会起什么作用。不要低估编译器的优化器。始终查看编译器的输出。在应用任何更改时都要进行配置文件。根据我的经验,执行时间有很大差异。我同意你的观点,你永远不应该对代码进行预优化,因为它的可读性会降低,并且会占用更多的开发时间。谢谢。不幸的是,UWP不允许我们使用位图,只允许使用类似的对象。但我明白了,谢谢+1.如果你有这方面的文档,那就太好了。更重要的是:有没有一种方法可以使用GPU来编辑位图?这些微优化根本不会起什么作用。不要低估编译器的优化器。始终查看编译器的输出。在应用任何更改时都要进行配置文件。根据我的经验,执行时间有很大差异。我同意你的观点,你永远不应该对代码进行预优化,因为它的可读性会降低,并且会占用更多的开发时间。谢谢。不幸的是,UWP不允许我们使用位图,只允许使用类似的对象。但我明白了。