views:

5060

answers:

9

I have an array of int pixels in my C# program and I want to convert it into an image. The problem is I am converting Java source code for a program into equivalent C# code. In java the line reads which displays the array of int pixels into image:

Image output = createImage(new MemoryImageSource(width, height, orig, 0, width));

can someone tell me the C# equivalent?

Here orig is the array of int pixels. I searched the Bitmap class and there is a method called SetPixel but the problem is it takes a x,y coordinate number. But what I have in my code is an array of int pixels. Another weird thing is my orig array has negative number and they are way far away from 255. In Java this is the same case (meaning both the array in C# and Java have equivalent value) and the values is working fine in Java.

But I can't get that line translated into C#. Please help.

+2  A: 

You can use Bitmap.LockBits to obtain the bitmap data that you can then manipulate directly, rather than via SetPixel. (How to use LockBits)

mackenir
+1. If you need to process the whole picture, then SetPixel/GetPixel are SLOW.
Vilx-
A: 

Well, I'm assuming each int is the composite ARGB value? If there isn't an easy option, then LockBits might be worth looking at - it'll be a lot quicker than SetPixel, but is more complex. You'll also have to make sure you know how the int is composed (ARGB? RGBA?). I'll try to see if there is a more obvious option...

Marc Gravell
A: 

hi thank you so much for replying. I have no idea what the int is composite of. Actually i am converting a java source code into c# its a corner detection algorithm of harris. I Couldnt find any source code for a corner detector in c#, but i found one in java. So converting it into c# was my only bet. The thing is i dont know how its compsing the int. But i can tell you

output[y * width + x] = 0xff000000 | ((int)(val) << 16 | (int)(val) << 8 | (int)(val));

this output array is wat the function is returning as the orig array. So this must show its composition.

Marc Gravell
It's a standard thing. An int consists of 4 bytes. One is for Red, one for Green, one for Blue, and the last for Alpha (aka transparency). You just have to figure out which is which. Most likely it's ARGB, but could be BGRA too. Or something weirder theoretically, but I'd doubt that.
Vilx-
+2  A: 

Using WPF, you can create a bitmap (image) directly from your array. You can then encode this image or display it or play with it:

int width = 200;
int height = 200;

//
// Here is the pixel format of your data, set it to the proper value for your data
//
PixelFormat pf = PixelFormats.Bgr32;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;

//
// Here is your raw data
//
int[] rawImage = new int[rawStride * height / 4];


//
// Create the BitmapSource
//
BitmapSource bitmap = BitmapSource.Create(
    width, height,
    96, 96, pf, null,
    rawImage, rawStride);
Frank Krueger
A: 

I would recommend using LockBits but a slower SetPixel based algorithm might look something like


// width - how many int's per row        
// array - array of integers
Bitmap createImage(int width, int[] array)
{            
  int height = array.Length / width;
  Bitmap bmp = new Bitmap(width, height);
  for (int y = 0; y < height; y++)
  {
    for (int x = 0; x < array.Length; x += width)
    {
      bmp.SetPixel(x, y, Color.FromArgb(array[i]));
    }
  }
  return bmp;
}
A: 

Thank you so much for the algos. But please tell me if the algo of CreateImage(int widht, int [] array) is inline with the java code i posted above? Bcoz i am not sure about the composition of my int array but the values in it are working fine withthe java code i posted above.thanks

If the Java int array is in ARGB format then you shouldn't have to convert the array to any other format. It should just work. Why don't you try it and see if it works!
A: 

MemoryImageSource's constructor's 3rd argument is an array of ints composed of argb values in that order

The example in that page creates such an array by;

pix[index++] = (255 << 24) | (red << 16) | blue;

You need to decompose that integer array to a byte array (shift operator would be useful), but it should be in bgr order, for LockBits method to work.

tafa
A: 

I have no clue how to decompose the integer array to a byte array in bgr order and how to make it work with LockBits. I will be very very very very grateful if anyone can tell me

A: 

I like the WPF option already presented, but here it is using LockBits and Bitmap:

        // get the raw image data
        int width, height;
        int[] data = GetData(out width, out height);

        // create a bitmap and manipulate it
        Bitmap bmp = new Bitmap(width,height, PixelFormat.Format32bppArgb);
        BitmapData bits = bmp.LockBits(new Rectangle(0, 0, width, height),
            ImageLockMode.ReadWrite, bmp.PixelFormat);
        unsafe
        {
            for (int y = 0; y < height; y++)
            {
                int* row = (int*)((byte*)bits.Scan0 + (y * bits.Stride));
                for (int x = 0; x < width; x++)
                {
                    row[x] = data[y * width + x];
                }
            }
        }
        bmp.UnlockBits(bits);

With (as test data):

    public static int[] GetData(out int width, out int height)
    {
        // diagonal gradient over a rectangle
        width = 127;
        height = 128;
        int[] data =  new int[width * height];
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int val = x + y;
                data[y * width + x] = 0xFF << 24 | (val << 16) | (val << 8) | val;
            }
        }
        return data;
    }
Marc Gravell