loading
 
How to use GetImage API method in C#?
Anonymous
15 year
Hello,

Could someone please provide a simple example of how to use the RoboRealm API's GetImage method in a C# or VB.NET program?

The API GetImage method has signature:

GetImage(string name, out object image, out object width, out object height)

Alas, I can't make any sense of this.  I would have thought that the returned image would be a byte array but try as I might, I cannot turn the type "object" into a byte[].

I've been using the RoboRealm API to read variables without trouble.  I do this by making a reference to RR_COM_API.dll that is included with the RoboRealm distribution.

I've looked at all the other related postings I could find on this forum but none of them include a simple example of how to make this work in C#--at least none that work for me.

So a simple example would be greatly appreciated!

Thanks,
patrick


Anonymous 15 year
Hi Patrick

Try the following, we used the trennet camera as a current source example and it saves it to the temp folder

       RR_API rr = new RR_API();

            if (!rr.connect("localhost"))
            {
                MessageBox.Show("Could not connect to localhost!");
                return;
            }
            Byte[] image = new Byte[1280*960];

            Dimension d = rr.getDimension();
            // get the current processed image from RoboRealm and save as a PPM
            d = rr.getImage(image, 1280 * 960);
            if (d != null)
            {
                //rr.savePPM(@"c:\temp\test.ppm", image, d.width, d.height);
                rr.saveImage(null, @"c:\temp\test.jpg");
            }

            // disconnect from API Server
            rr.disconnect();

program.robo
Anonymous 15 year
Many thanks for your reply.  However, I am using the DLL version of the API that comes with the main RoboRealm distribution.  It is included as the file RR_COM_API.dll.  In that version, the signature for GetImage is different than the one you are using, namely:

GetImage(string name, out object image, out object width, out object height)

so it won't work the way you describe.  I'm starting to wonder if the RR_COM_API.dll version of the API is out of sync with the source code?

Thanks,
patrick
Anonymous 15 year
Well if you must use a com interop, its not a full c# implementation then  :)  Note to other C# users trying this you will need to run TlbImp.exe on the RR_COM_API.dll and then reference  RR_COM_APILib.dll in your code and not the RR_COM_API.dll directly. You may also need to run regsvr32 on RR_COM_API.dll in order for it to compile correctly. This code was tested on VS Express 2008

============================================

            RR_COM_APILib.API_WrapperClass rr = new RR_COM_APILib.API_WrapperClass();

            object height = "";
            object width = "";
            object image = "";

            if (rr.Connect("localhost") == 0)
            {
                MessageBox.Show("Could not connect to localhost!");
                return;
            }

            int d = rr.GetImage("Processed", out image, out width, out height);
            if (d != 0)
                {
                    rr.SaveImage("Processed",@"c:\temp\test.jpg");
                }

            // disconnect from API Server
            rr.Disconnect();
Anonymous 15 year
Thanks for the followup.  Before you replied, I got it working by adding the C# API source directly to my project.  But for completeness, I just now tried it with your com interop solution using VS2005 and that worked too.

One last question: I don't really want to write the image to a file: instead, I want to create a bitmap in memory from the RoboRealm image byte array.  So using your original code, why does the following modification fail with error: "Parameter is not valid at ... System.Drawing.Image.FromStream(etc...)"?

       RR_API rr = new RR_API();

            if (!rr.connect("localhost"))
            {
                MessageBox.Show("Could not connect to localhost!");
                return;
            }
            Byte[] image = new Byte[1280*960];

            Dimension d = rr.getDimension();
            // get the current processed image from RoboRealm and save as a PPM
            d = rr.getImage(image, 1280 * 960);
            if (d != null)
            {
                //rr.savePPM(@"c:\temp\test.ppm", image, d.width, d.height);
                //rr.saveImage(null, @"c:\temp\test.jpg");
                memoryStream ms = new MemoryStream(image);
                Bitmap testImage = (Bitmap)Bitmap.FromStream(ms);
            }

            // disconnect from API Server
            rr.disconnect();
Tom from United States  [1 posts] 13 year
Hi,

Is there is solution to this problem of how to use image with C# MemoryStream without getting "Parameter is not valid"?
Thanks.
Anonymous 13 year
Tom,

Can you be a little more specific with your request? Can you post an example of your code that is generating the error? Or is this code from our API? Or is this even a RoboRealm related question?

Thanks,
STeven.
Anonymous 13 year
Hi Steven,

My question was specific to the post before mine. The Anon. asked about how to get access to a Bitmap object and showed his code:

memoryStream ms = new MemoryStream(image);
Bitmap testImage = (Bitmap)Bitmap.FromStream(ms);

I also tried this and got the same parameter error. It looks to me like the image (that is the argument of MemoryStream) is not compatible with c# Bitmap.FromStream(ms);

The reason for doing this is to be able to post process the image outside of RoboRealm. With a Bitmap object it is very easy to analyse and show in c# form.

Thanks
Tom

from United States  [214 posts] 13 year
Hi Tom,

These are the methods I have been using in C# to get a Bitmap from RoboRealm.  You don't have to use the imageBytes and imageDimensions arrays--I just use them for convenience.  One in place, I use them like this:

            getImageBytes("MyMarker");
            Bitmap MyBitmap = getImageBitmap("MyMarker");

-----

        private static SortedList<string, byte[]> imageBytes = new SortedList<string, byte[]>();
        private static SortedList<string, int[]> imageDimensions = new SortedList<string, int[]>();

        private static RR_API.RR_API RR;
        RR = new RR_API.RR_API();
        RR.connect("localhost");

        public void getImageBytes(string marker)
        {
            int width = 1280;
            int height = 960;

            byte[] imageData = new byte[width * height];

            Dimension d = null;

            while (d == null)
            {
                d = RR.getImage(marker, imageData, width * height);
                RR.waitImage(1);
            }

            if (imageBytes.ContainsKey(marker))
            {
                imageBytes[marker] = imageData;
                imageDimensions[marker][0] = d.width;
                imageDimensions[marker][1] = d.height;
            }
            else
            {
                imageBytes.Add(marker, imageData);
                imageDimensions.Add(marker, new int[2]);
                imageDimensions[marker][0] = d.width;
                imageDimensions[marker][1] = d.height;
            }
        }

        public Bitmap getImageBitmap(string marker)
        {
            return BitsToBitmapRGB24(imageBytes[marker], imageDimensions[marker][0], imageDimensions[marker][1]);
        }

        // Create RGB24 bitmap from Byte array
        public Bitmap BitsToBitmapRGB24(Byte[] bytes, int width, int height)
        {
            //swap RGB to BGR
            Byte tmp;
            for (int x = 3; x < bytes.GetLength(0); x += 3)
            {
                tmp = bytes[(x + 2)];
                bytes[x + 2] = bytes[x];
                bytes[x] = tmp;
            }

            if (bytes.GetLength(0) < width * height * 3)
            {
                return null;
            }

            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            int i;

            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);

            if (data.Stride == width * 3)
            {
                Marshal.Copy(bytes, 0, data.Scan0, width * height * 3);
            }
            else
            {
                for (i = 0; i < bmp.Height; i++)
                {
                    IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
                    Marshal.Copy(bytes, i * bmp.Width * 3, p, bmp.Width * 3);
                }
            }

            bmp.UnlockBits(data);

            return bmp;
        }

--patrick

http://www.pirobot.org

Anonymous 13 year
Patrick,

Thanks for that code. We merged the two routines in getImageBitmap and placed that into the API to help others with the same issue.

Thanks!
STeven.
from United States  [214 posts] 13 year
Cool!

--patrick

This forum thread has been closed due to inactivity (more than 4 months) or number of replies (more than 50 messages). Please start a New Post and enter a new forum thread with the appropriate title.

 New Post   Forum Index