简体   繁体   中英

Why is rotation much faster on Image than using BitmapEncoder?

Rotating an Image using

image.RenderTransform = new RotateTransform()...

is almost immediate. On the other hand, using

bitmapEncoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees...

is much slower (in the FlushAsync() ) - more than half a second.

Why is that? And is there a way to harness the fast rotation in order to rotate bitmaps?

The first one image.RenderTransform will render the bitmap by using hardware rendering. (GPU) The image isn't rotate but will be displayed rotated/scaled. (will access only visible pixels directly from/in the videomemory)

The second one will rotate the image itself by the CPU (all pixels). It will create new memory for the result. (non-video memory)


update:

Is there a way to use the GPU to edit bitmaps? Depends on what you need:

If you want to use a GPU. You could use an managed wrapper (like Slim DX/Sharp DX) This will take much time to get results. Don't forget, rerasterizing images via gpu could lead to quality lost.

If you want to rotate images only (0, 90, 180, 270)? you could use a Bitmap class with de ScanLine0 option. (this is to preserve quality and size) and you could create a fast implementation.

Look here: Fast work with Bitmaps in C#

I would create an algoritm foreach angle (0,90,180,270). Because you don't want to calculate the x, y position for each pixel. Something like below..


Tip:

try to lose the multiplies/divides.

/*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
    }
}

Becomes something like:

/*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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM