Dec 22, 2006

Embedding .NET GUI components in Java GUIs

We’ve released JNBridgePro v3.1, which incorporates the support libraries described below, which makes embedding .NET GUI components in Java GUIs even simpler. See the announcement here. The 3.1 installer includes a version of this example targeted toward 3.1.

One feature request we frequently get is for a way to embed .NET GUI components in Java GUIs, or, conversely, to embed Java GUI components in .NET GUIs. In this post, we’ll show you how to put a .NET component inside a Java GUI, and to have the Java GUI react to events in the .NET component.

Start by downloading the sample code. Unpack the zip file. In addition to the sample code, there are a couple of dlls and jar files containing helper classes that assist in the interop. These helper classes will eventually be included in the JNBridgePro runtime components themselves, but in the meantime, you can use these assemblies when creating your own GUI interop projects.

We’ll start with a .NET control in JNBControl.cs, that looks like this:

Note that the control has several parts, including a label, a text box, and a button. The text box and its contents can be accessed through a field, and there is a method to register a delegate that will be called when the button is pressed. The control has been compiled, is called JNBTest.JNBControl and is in the assembly JNBTest.dll.

The proxies have already been generated, and are in the file dotNetControlProxies.jar. If you want, you can re-create the proxy jar file by launching the proxy generation tool and creating a new Java-to-.NET. Add JNBTest.dll to the assembly list, plus the assemblies System and System.Windows.Forms from the GAC (either the .NET 1.1 or 2.0 versions, depending on which version you’re using). Then, load JNBTest.JNBControl plus supporting classes, and generate proxies for all the classes.

Next, we examine the Java GUI-based application in javaTest\ This is a simple AWT-based application. Note the simple code sequence in the middle of the main() method:

// create the .NET control
JNBControl c = new JNBControl();
// register any callbacks
c.registerClickDelegate(new ClickEventHandler());
// wrap it so it can be embedded
DotNetControl dnc = new DotNetControl(c);
// size it
dnc.setSize(224, 104);
// embed it
f.add(dnc, dncConstraints);

First, create the .NET control by instantiating its proxy. Next, register callbacks; we have a Java-side event handler that, when fired, will get the contents of the .NET textbox and copy it to the Java text box. Once the .NET control has been set up, we wrap it in a special wrapper class com.jnbridge.embedding.DotNetControl. DotNetControl is derived from java.awt.Component (actually, java.awt.Canvas, which is a subclass of Component), and contains the linkages necessary to allow embedding of the .NET control in the Java component. We then size it like any other AWT component, and add it to the enclosing frame using graphical constraints that have already been prepared.

This is all that’s needed to embed a .NET component inside a Java GUI.

When compiling, make sure the build classpath contains the proxy jar file and the helper jar file jnbtools.jar, as well as the usual jnbcore.jar and bcel-5.1-jnbridge.jar.

Finally, let’s run the program. Note that GUI component embedding will only work with shared memory communications. Make sure that jnbshare.dll, jnbsharedmem.dll, and jnbjavaentry2.dll are in the GAC. Also, make sure that jnbtools.dll and jnbtools.jar are together in the same file. Finally, examine Note that we are loading JNBTest.dll and JNBTools2.dll, as well as System.Windows.Forms. Make sure that all paths in the file are correct for your machine.

To run the application, make sure that the classpath contains all the files in the build classpath. You can use runJava.bat, but first make sure that all the paths are correct for your machine.

Running the application, we see this:

Yes, that’s really a .NET control inside a Java AWT window! When we fill in the .NET text box and click on the button, the event fires and the Java-side callback is executed, copying the text into the Java text box. You can make more complex interactions, and even have bidirectional communications between the .NET and Java GUI elements.

The key to the interop is the DotNetControl wrapper class. Once you instantiate the .NET control’s proxy and wrap it, you can plug it in wherever an AWT component would go.

As I mentioned before, to do any embedding now, use the helper assemblies and jar files; in the future, they will be incorporated into the JNBridgePro runtime components.

We’d love to get your feedback on this. How many of you see a use for it?

In an upcoming article, we’ll go in the other direction and show how to embed Java GUI components in WinForms.
continue reading Embedding .NET GUI components in Java GUIs

Dec 8, 2006

Image Processing for Dummies with C# and GDI+ Part 1 - Per Pixel Filters

Welcome to this, my first article in C#, and the first in a series on image processing. I figure between Nish and Chris Losinger waiting to bust my chops, I should learn as much as anyone from this article.

The purpose of the series will be to build a class that allows any C# programmer access to common, and not so common, image processing functionality. The reason we are doing it in C# is simply that I want to learn it, but the functionality we use is available through GDI+ in C++, and indeed the code to do the same thing using a DIBSECTION is not terribly different. This first article will focus on per pixel filters, in other words, filters that apply the same algorithm to each pixel 'in place' with no regard for the values in any other pixels. You will see as we progress that the code becomes somewhat more complex when we start moving pixels or changing values based on calculations that take into account surrounding pixel values.

The App
The app we will use is a basic Windows Forms application ( it is in fact my first ). I've included code to load and save images using GDI+, and a menu to which I will add filters. The filters are all static functions in a class called BitmapFilter, so that an image can be passed in ( C# passes complex types in by reference ) and a bool returned to indicate success or failure. As the series progresses I am sure the app will get some other nice functionality, such as scaling and warping, but that will probably happen as the focus of an article after the core functionality is in place. Scrolling is achieved in the standard manner, the Paint method uses the AutoScrollPosition property to find out our scroll position, which is set by using the AutoScrollMinSize property. Zooming is achieved through a double, which we set whenever we change the scale, and which is used to set the AutoScrollMinSize anew, as well as to scale the Rectangle we pass into DrawImage in the Paint method.

Pixel Access, a.k.a. Unsafe code, and other nastiness
My first real disappointment in building this code was to find that the BitmapData class in GDI+ does not allow us to access the data it stores, except through a pointer. This means we need to use the unsafe keyword to scope the block of code which accesses the data. The net effect of this is that a highly security level is required for our code to execute, i.e. any code using the BitmapData class is not likely to be run from a remote client. This is not an issue for us right now, though, and it is our only viable option, as GetPixel/SetPixel is simply too slow for us to use iterating through bitmaps of any real size.

The other down side is that this class is meant to be portable, but anyone using it will need to change their project settings to support compiling of unsafe code.

A quirk I noticed from the first beta of GDI+ continues to this day, namely requesting a 24bitRGB image will return a 24bitBGR image. BGR ( that is, pixels are stored as blue, green, red values ) is the way Windows stored things internally, but I'm sure more than a few people will get a surprise when they first use this function and realise they are not getting what they asked for.

Invert Filter
Here, then is our first, and most simple filter - it simply inverts a bitmap, meaning that we subtract each pixel value from 255.

public static bool Invert(Bitmap b)
// GDI+ still lies to us - the return format is BGR, NOT RGB.
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y < b.Height;++y)
for(int x=0; x < nWidth; ++x )
p[0] = (byte)(255-p[0]);
p += nOffset;


return true;
This example is so simple that it doesn't even matter that the pixels are out of order. The stride member tells us how wide a single line is, and the Scan0 member is the pointer to the data. Within our unsafe block we grab the pointer, and calculate our offset. All bitmaps are word aligned, and so there can be a difference between the size of a row and the number of pixels in it. This padding must be skipped, if we try and access it we will not simply fail, we will crash. We therefore calculate the offset we need to jump at the end of each row and store it as nOffset.

The key thing when image processing is to do as much outside the loop as possible. An image of 1024x768 will contain 786432 individual pixels, a lot of extra overhead if we add a function call, or create a variable inside the loops. In this case, our x loop steps through Width*3 iterations, when we care about each individual color, we will step the width only, and increment our pointer by 3 for each pixel.

That should leave the rest of the code pretty straightforward. We are stepping through each pixel, and reversing it, as you can see here:

Grayscale filter
Subsequent examples will show less and less of the code, as you become more familiar with what the boilerplate part of it does. The next, obvious filter is a grayscale filter. You might think that this would involve simply summing the three color values and dividing by three, but this does not take into effect the degree to which our eyes are sensitive to different colors. The correct balance is used in the following code:

byte * p = (byte *)(void *)Scan0;

int nOffset = stride - b.Width*3;

byte red, green, blue;

for(int y=0;y < b.Height;++y)
for(int x=0; x < b.Width; ++x )
blue = p[0];
green = p[1];
red = p[2];

p[0] = p[1] = p[2] = (byte)(.299 * red
+ .587 * green
+ .114 * blue);

p += 3;
p += nOffset;

As you can see, we are now iterating through the row b.Width times, and stepping through the pointer in increments of 3, extracting the red, green and blue values individually. Recall that we are pulling out bgr values, not rgb. Then we apply our formula to turn them into the grey value, which obvious is the same for red, green and blue. The end result looks like this:

A note on the effects of filters
It's worthwhile observing before we continue that the Invert filter is the only non-destructive filter we will look at. That is to say, the grayscale filter obviously discards information, so that the original bitmap cannot be reconstructed from the data that remains. The same is also true as we move into filters which take parameters. Doing a Brightness filter of 100, and then of -100 will not result in the original image - we will lose contrast. The reason for that is that the values are clamped - the Brightness filter adds a value to each pixel, and if we go over 255 or below 0 the value is adjusted accordingly and so the difference between pixels that have been moved to a boundary is discarded.

Brightness filter
Having said that, the actual filter is pretty simple, based on what we already know:

for(int y=0;y{
for (int x = 0; x < nWidth; ++x)
nVal = (int) (p[0] + nBrightness);

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

p[0] = (byte)nVal;

p += nOffset;
The two examples below use the values of 50 and -50 respectively, both on the original image

The operation of contrast is certainly the most complex we have attempted. Instead of just moving all the pixels in the same direction, we must either increase or decrease the difference between groups of pixels. We accept values between -100 and 100, but we turn these into a double between the values of 0 and 4.

if (nContrast < -100) return false;
if (nContrast > 100) return false;

double pixel = 0, contrast = (100.0+nContrast)/100.0;

contrast *= contrast;
My policy has been to return false when invalid values are passed in, rather than clamp them, because they may be the result of a typo, and therefore clamping may not represent what is wanted, and also so users can find out what values are valid, and thus have a realistic expectation of what result a given value might give.

Our loop treats each color in the one iteration, although it's not necessary in this case to do it that way.

red = p[2];

pixel = red/255.0;
pixel -= 0.5;
pixel *= contrast;
pixel += 0.5;
pixel *= 255;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[2] = (byte) pixel;

We turn the pixel into a value between 0 and 1, and subtract .5. The net result is a negative value for pixels that should be darkened, and positive for values we want to lighten. We multiply this value by our contrast value, then reverse the process. Finally we clamp the result to make sure it is a valid color value. The following images use contrast values of 30 and -30 respectively.

First of all, an explanation of this filter. The following explanation of gamma was found on the web: In the early days of television it was discovered that CRT's do not produce a light intensity that is proportional to the input voltage. Instead, the intensity produced by a CRT is proportional to the input voltage raised to the power gamma. The value of gamma varies depending on the CRT, but is usually close to 2.5. The gamma response of a CRT is caused by electrostatic effects in the electron gun. In other words, the blue on my screen might well not be the same as the blue on your screen. A gamma filter attempts to correct for this. It does this by building a gamma ramp, an array of 256 values for red, green and blue based on the gamma value passed in (between .2 and 5). The array is built like this:

byte [] redGamma = new byte [256];
byte [] greenGamma = new byte [256];
byte [] blueGamma = new byte [256];

for (int i = 0; i < 256; ++i)
redGamma[i] = (byte)Math.Min(255, (int)(( 255.0
* Math.Pow(i/255.0, 1.0/red)) + 0.5));
greenGamma[i] = (byte)Math.Min(255, (int)(( 255.0
* Math.Pow(i/255.0, 1.0/green)) + 0.5));
blueGamma[i] = (byte)Math.Min(255, (int)(( 255.0
* Math.Pow(i/255.0, 1.0/blue)) + 0.5));

You'll note at this point in development I found the Math class.

Having built this ramp, we step through our image, and set our values to the values stored at the indices in the array. For example, if a red value is 5, it will be set to redGamma[5]. The code to perform this operation is self evident, I'll jump right to the examples. I've used Gamma values of .6 and 3 for the two examples, with the original as always first for comparison. I used the same values for red, green and blue, but the filter allows them to differ.

Color Filter
Our last filter is a color filter. It is very simple - it just adds or subracts a value to each color. The most useful thing to do with this filter is to set two colors to -255 in order to strip them and see one color component of an image. I imagine by now you'd know exactly what that code will look like, so I'll give you the red, green and blue components of my son to finish with. I hope you found this article informative, the next will cover convolution filters, such as edge detection, smoothing, sharpening, simple embossing, etc. See you then !!!

About Christian Graus
continue reading Image Processing for Dummies with C# and GDI+ Part 1 - Per Pixel Filters