DirectX & C# 2.0

L

Lloyd Dupont

In our WinForm / C# application relying on C# 2.0 I have a big canvas with
shapes on it.
I would like to display shadow (monochrome gaussian blur) with arbitrary
offset & dispersion radius under my shapes.
I try to draw to a bitmap and apply a plur filter myself on each bitmap (for
each shape), but it's awfully slow.

I was wondering if:
1. could DirectX be used to do the blur operation quickly?
2. would DirectX.NET be included in the 2.0 distribution or should I, as
with 1.1, download/install an additional package? how big it is?

--
Regards,
Lloyd Dupont

NovaMind development team
NovaMind Software
Mind Mapping Software
<www.nova-mind.com>
 
K

Kevin Spencer

Hi Lloyd,

I don't know if you could use DirectX to do this, but it can be done with
the System.Drawing and System.Drawing.Imaging namespaces alone, if you use
some unsafe C code in your app. Example:

public static bool Smooth(Bitmap b)
{
ConvMatrix m = new ConvMatrix(0);
SetAll(ref m, 1);
m.Pixel = 4;
m.Factor = 12;

return Conv3x3(b, m);
}

public static bool Conv3x3(Bitmap b, ConvMatrix m)
{
// Avoid divide by zero errors
if (0 == m.Factor) return false;

Bitmap bSrc = (Bitmap)b.Clone();

BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width,
bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

int stride = bmData.Stride;
int stride2 = stride * 2;
System.IntPtr Scan0 = bmData.Scan0;
System.IntPtr SrcScan0 = bmSrc.Scan0;

unsafe
{
byte * p = (byte *)(void *)Scan0;
byte * pSrc = (byte *)(void *)SrcScan0;

int nOffset = stride - b.Width*3;
int nWidth = b.Width - 2;
int nHeight = b.Height - 2;

int nPixel;

for(int y=0;y < nHeight;++y)
{
for(int x=0; x < nWidth; ++x )
{
nPixel = ( ( ( (pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8] *
m.TopRight) +
(pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) + (pSrc[8
+ stride] * m.MidRight) +
(pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid)
+ (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[5 + stride]= (byte)nPixel;

nPixel = ( ( ( (pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7] *
m.TopRight) +
(pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) + (pSrc[7
+ stride] * m.MidRight) +
(pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid)
+ (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[4 + stride] = (byte)nPixel;

nPixel = ( ( ( (pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6] *
m.TopRight) +
(pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) + (pSrc[6
+ stride] * m.MidRight) +
(pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid)
+ (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[3 + stride] = (byte)nPixel;

p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}

b.UnlockBits(bmData);
bSrc.UnlockBits(bmSrc);

return true;
}

public struct ConvMatrix
{
public int TopLeft, TopMid, TopRight;
public int MidLeft, Pixel, MidRight;
public int BottomLeft, BottomMid, BottomRight;
public int Factor;
public int Offset;

public ConvMatrix(int intOffSet)
{
TopLeft = 0;
TopMid = 0;
TopRight = 0;
MidLeft = 0;
Pixel = 1;
MidRight = 0;
BottomLeft = 0;
BottomMid = 0;
BottomRight = 0;
Factor = 1;
Offset = intOffSet;
}
}


--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Big things are made up of
lots of little things.
 
L

Lloyd Dupont

Hi Kevin!
Thanks for the tip ;-)
I already tryed some code but it was terribly slow.
Although I didn't try by using pointer, that's a good idea, I'll give it a
go...

Kevin Spencer said:
Hi Lloyd,

I don't know if you could use DirectX to do this, but it can be done with
the System.Drawing and System.Drawing.Imaging namespaces alone, if you use
some unsafe C code in your app. Example:

public static bool Smooth(Bitmap b)
{
ConvMatrix m = new ConvMatrix(0);
SetAll(ref m, 1);
m.Pixel = 4;
m.Factor = 12;

return Conv3x3(b, m);
}

public static bool Conv3x3(Bitmap b, ConvMatrix m)
{
// Avoid divide by zero errors
if (0 == m.Factor) return false;

Bitmap bSrc = (Bitmap)b.Clone();

BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width,
bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

int stride = bmData.Stride;
int stride2 = stride * 2;
System.IntPtr Scan0 = bmData.Scan0;
System.IntPtr SrcScan0 = bmSrc.Scan0;

unsafe
{
byte * p = (byte *)(void *)Scan0;
byte * pSrc = (byte *)(void *)SrcScan0;

int nOffset = stride - b.Width*3;
int nWidth = b.Width - 2;
int nHeight = b.Height - 2;

int nPixel;

for(int y=0;y < nHeight;++y)
{
for(int x=0; x < nWidth; ++x )
{
nPixel = ( ( ( (pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8]
* m.TopRight) +
(pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) +
(pSrc[8 + stride] * m.MidRight) +
(pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid)
+ (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[5 + stride]= (byte)nPixel;

nPixel = ( ( ( (pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7]
* m.TopRight) +
(pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) +
(pSrc[7 + stride] * m.MidRight) +
(pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid)
+ (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[4 + stride] = (byte)nPixel;

nPixel = ( ( ( (pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6]
* m.TopRight) +
(pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) +
(pSrc[6 + stride] * m.MidRight) +
(pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid)
+ (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;

p[3 + stride] = (byte)nPixel;

p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}

b.UnlockBits(bmData);
bSrc.UnlockBits(bmSrc);

return true;
}

public struct ConvMatrix
{
public int TopLeft, TopMid, TopRight;
public int MidLeft, Pixel, MidRight;
public int BottomLeft, BottomMid, BottomRight;
public int Factor;
public int Offset;

public ConvMatrix(int intOffSet)
{
TopLeft = 0;
TopMid = 0;
TopRight = 0;
MidLeft = 0;
Pixel = 1;
MidRight = 0;
BottomLeft = 0;
BottomMid = 0;
BottomRight = 0;
Factor = 1;
Offset = intOffSet;
}
}


--
HTH,

Kevin Spencer
Microsoft MVP
.Net Developer
Big things are made up of
lots of little things.

Lloyd Dupont said:
In our WinForm / C# application relying on C# 2.0 I have a big canvas
with shapes on it.
I would like to display shadow (monochrome gaussian blur) with arbitrary
offset & dispersion radius under my shapes.
I try to draw to a bitmap and apply a plur filter myself on each bitmap
(for each shape), but it's awfully slow.

I was wondering if:
1. could DirectX be used to do the blur operation quickly?
2. would DirectX.NET be included in the 2.0 distribution or should I, as
with 1.1, download/install an additional package? how big it is?

--
Regards,
Lloyd Dupont

NovaMind development team
NovaMind Software
Mind Mapping Software
<www.nova-mind.com>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top