views:

440

answers:

2

Hello.

I need fast implementation of popular interpolation algorithms. I figured it out that C# in such simple algorithms will be much slower than C++ so i think of writing some native code and using it in my C# GUI.

First of all i run some tests and few operations on 1024x1024x3 matrix took 32ms in C# and 4ms in C++ and that's what i basicly need.

Interpolation however is not a good word because i need them only for downscaling. But the question is: Will it be faster than C# methods in Drawing2D

Image outputImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
Graphics grPhoto = Graphics.FromImage(outputImage);

grPhoto.InterpolationMode = InterpolationMode.*; //all of them

grPhoto.DrawImage(bmp, new Rectangle(0, 0, destWidth, destHeight),
Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel);

grPhoto.Dispose();

Some of these method run in 20ms and some in 80. Is there a way to do it faster?


EDIT 1:

First of all i'm using XNA in this application but there seems to be no way to select different interpolation method. Of course it's working very fast.

Ideal way would be to implement those methods on graphic card.


EDIT 2:

Here is my whole method:

private unsafe Texture2D Scale(GraphicsDevice gd, Texture2D texture, float scale)
    {

        int sourceWidth = texture.Width;
        int sourceHeight = texture.Height;

        int destWidth = (int)(sourceWidth * scale);
        int destHeight = (int)(sourceHeight * scale);

        StopwatchEx sw = new StopwatchEx();
        sw.IntervalStart();
        //convert texture into bitmap
        byte[] textureData = new byte[4 * sourceWidth * sourceHeight];
        texture.GetData<byte>(textureData);

        System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sourceWidth, sourceHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly,
                       System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        IntPtr safePtr = bmpData.Scan0;
        System.Runtime.InteropServices.Marshal.Copy(textureData, 0, safePtr, textureData.Length);
        bmp.UnlockBits(bmpData);


        //output bitmap
        System.Drawing.Image outputImage = new System.Drawing.Bitmap(destWidth, destHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        System.Drawing.Graphics grPhoto = System.Drawing.Graphics.FromImage(outputImage);

        grPhoto.InterpolationMode = (System.Drawing.Drawing2D.InterpolationMode)(interpolationMode);
        grPhoto.SmoothingMode = (System.Drawing.Drawing2D.SmoothingMode)smoothingMode;
        grPhoto.PixelOffsetMode = (System.Drawing.Drawing2D.PixelOffsetMode)pixelOffsetMode;

        grPhoto.DrawImage((System.Drawing.Image)bmp, new System.Drawing.Rectangle(0, 0, destWidth, destHeight),
            new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.GraphicsUnit.Pixel);

        grPhoto.Dispose();

        textureData = new byte[4 * sourceWidth * sourceHeight];

        MemoryStream ms = new MemoryStream();
        ((System.Drawing.Bitmap)outputImage).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);

        ms.Seek(0, SeekOrigin.Begin);
        Texture2D result = Texture2D.FromFile(gd, ms);
        ms.Dispose();
        sw.IntervalStop();
        sw.AppendResults("MEGS.txt");    

        return result;
    }

Funny thing is that HighQualityBicubic is much faster than Bicubic. (40ms vs 100ms)

+1  A: 

Have you tried this with the GetThumbnailImage method?

To further extend Adam Robinson's comment: I hope you timed this using the Stopwatch class?

Codesleuth
Of course i used stopwatch. And tell me where to set interpolation method in `GetThumbnailImage`
Kaminari
`GetThumbnailImage` is very limited, and according to the MSDN documentation it won't work well for larger thumbnail image sizes.
stakx
+1  A: 

How did you implement your matrix in C#?

In your case a lot of speed could be lost due to .Net having to do bounds checks in a matrix array by default. In that case you could make your code much faster using unsafe C# (and thus removing any bounds checks).

But if it already works fast enough with the external methods why not use them?

Foxfire
It's not working fast enough. And i don't have any external methods yet - another problem.
Kaminari
Well then try the unsafe C# method. I've done that with writing custom image filters (grayscale, edgedetect and blur) and the performance has been quite good.
Foxfire
@Foxfire can You post some example? I tried unsafe in this method but performance was the same.
Kaminari