9

In C, I can define a pointer to an array like this:

char b1[SOME_SIZE];
char (*b3)[3]=(char(*)[3])b1;

so that b3[i][j] == b1[i*3+j].

Can I declare such a pointer, b3, in unsafe C#?

My intention is to access bitmap channels as:

///...
unsafe {
    //...
    byte *target; //8bpp
    byte (*source)[3]; //24bpp
    //...
    target[x]=(source[x][0]+source[x][1]+source[x][2])/3;
    //...

I hope this way, using source[x][ch] instead of source[x*3+ch] to get some compiler optimization.

Andrei
  • 42,814
  • 35
  • 154
  • 218
LS_ᴅᴇᴠ
  • 10,823
  • 1
  • 23
  • 46
  • Hope-based optimization doesn't make any sense really. You can make a pointer `byte*[]` but it's probably not what you intend to have - [look in the docs](http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx). – BartoszKP Dec 11 '13 at 10:12
  • @BartoszKP Maybe you're right, I'm probably over-optimizing! My point is that in C/C++, well made declarations give often better performance (and legibility) against heavy code, as compiler can optimize former but not latter. – LS_ᴅᴇᴠ Dec 11 '13 at 10:29
  • In C# [this](http://stackoverflow.com/a/1563170/2642204) is the recommended way to work with bitmaps in terms of performance. – BartoszKP Dec 11 '13 at 10:56
  • I know, but I'm trying to get a clearer code using pointer to array. – LS_ᴅᴇᴠ Dec 11 '13 at 11:20
  • 3
    In your question you say that you want to "get some compiler optimization", not "get a clearer code". Make up your mind, you can't have both. – BartoszKP Dec 11 '13 at 11:21
  • Just a word of advice, **avoid unsafe code** in C#. If this optimization is absolutely necessary, then do so but most times you can avoid accessing unmanaged code/pointers by using the `Marshal` class in `System.Runtime.InteropServices`. – Erik Dec 17 '13 at 22:35

1 Answers1

6
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct FastPixel
{
    public readonly byte R;
    public readonly byte G;
    public readonly byte B;
}


private static void Main()
{
    unsafe
    {
        // 8-bit.
        byte[] b1 =
        {
            0x1, 0x2, 0x3,
            0x6, 0x7, 0x8,
            0x12, 0x13, 0x14
        };


        fixed (byte* buffer = b1)
        {
            var fastPixel = (FastPixel*) buffer;
            var pixelSize = Marshal.SizeOf(typeof (FastPixel));

            var bufferLength = b1.Length / pixelSize;
            for (var i = 0; i < bufferLength; i++)
            {
                Console.WriteLine("AVERAGE {0}", (fastPixel[i].R + fastPixel[i].G + fastPixel[i].B)/pixelSize);
            }
        }
    }
}

}

This should be pretty much identical what you have. Note that I don't expect any performance gains. This is not micro-optimization, it's nano-optimization.

If dealing with huge images, look into parallel programming & SSE and how cache lines work(they have saved me actually 3-4 seconds - crazy right?!)

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78