13 Replies - 1335 Views - Last Post: 13 January 2012 - 04:49 AM Rate Topic: -----

#1 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

How do I display 8bit values in an array as a Raster Type Image

Posted 04 January 2012 - 09:11 AM

Hello there, I use Geographic Information System (GIS) as part of my degree and am trying to add functionality to a program I have already written for a project. I am simply trying to expand my programmign knowledge, which is why I'm here and think it could be the place to be for the help I need. The research I have done on my own has got me this far and I'm pretty stuck on what to do next. This might be down to me not knowing enough about the language to get about the task easily, but I have searched for hours, over days trying to find a simple explanation, and I have brought myself here! :D

My Knowledge:
Logically, Syntactically good knowledge. Understanding of algorithms and programming etiquette. I find mathematical programming quite easy. Been self teaching myself for about 2 years now, sticking to the stuff I essentially NEED to know.

Graphical programming knowledge is VERY basic.
File I/O understanding isnt great.
SQL/Database is Basic.

My problem:
Array of Double[,] Double[] Byte[,] or Byte[] being displayed as a BitMap type image or similar.

So Far:
I have managed to create a method that 'successfully' converts an array double[,] to byte[,] presuming all the values in the double array can be represented as 8bit integers, which....so far I havent actually come across data that works completely with this. Then using code snippets I have found on the internet to 'convert' this numerical data into an object of image (or so i think I have, like I said my graphic knowledge is very poor)

Now what?:
So alternatively and preferably, some ideas on just using the double values between 0-255 as colour values even though they can go deep into the decimal place (whether or not this is possible I don't yet know), OR a method to round each number to its closest 8bit integer for convertion aspects of the data to type Byte[] or Byte[,] (Probably easiest way?) making it more conventional. Absolute accuracy of colour value isnt vital, its just going to be a graphical representation of the data to easily see contrasting areas.

Can I get a result similar to this with what I'm trying to do?:
(not necessarily so complex, best example I could find)
Raster Grid Example

What the program currently does:
Its essentially a raster data manipulation software, with simple and advanced raster calculation being applied to raster data in the ascii grid format (used typically in ArcGIS) and then saved back to disk as a new table. The functionality of this is 100% ok and the only thing I'm trying to do is display the data im working on for a visual confirmation of the data manipulation.

It loads the data into an object Grid which has a double field Values[,] systematically, after reading the header in the file. The dataset also contains a value for no value, generally -9999, this can probably be changed to 0 for the sake of the pallette.


Example Raster Grid Input Data


Code snippet that calls the conversion process:
g1 = new Grid(fname);
            g1 = g1.LinearScale8Bit();
            byte[,] Values = new byte[g1.Values.GetLength(0), g1.Values.GetLength(1)];
            Image img;
            Bitmap bmp;
                                    
            for (int i = 0; i <= g1.Cols; i++)
            {
                for (int j = 0; j <= g1.Rows; j++)
                {
                    Values[i, j] = Convert.ToByte(g1.Values[i, j]);                    
                }
            }
            img = Grid.ByteArrayToImage(Values);
            bmp = new Bitmap(img);
            Form frm2 = new Form2(bmp);            
            frm2.Show();




Code Grid.LinearScale8Bit()
public Grid LinearScale8Bit()
        {
            Grid newgrid = new Grid();
            double min = this.GridGlobalMin();
            double max = this.GridGlobalMax();
            int r, c;

            newgrid.Cols = this.Cols;
            newgrid.Rows = this.Rows;
            newgrid.XCorner = this.XCorner;
            newgrid.YCorner = this.YCorner;
            newgrid.CellSize = this.CellSize;
            newgrid.NoData = this.NoData;
            newgrid.Values = new double[newgrid.Rows, newgrid.Cols];

            for (r = 0; r < this.Rows; r++)
                for (c = 0; c < this.Cols; c++)
                    newgrid.Values[r, c] = (this.Values[r, c] - min) / (min - max) * -255;
            
            return newgrid;
        }



Code Grid.ByteArrayToImage(Byte[,])
public static Image ByteArrayToImage(byte[,] byteArrayIn)
        {
            Byte[] byteArrayCopy = byteArrayIn.Cast<byte>().ToArray();
            MemoryStream ms = new MemoryStream(byteArrayCopy);
            Image returnImage = Image.FromStream(ms);
            return returnImage;
        } 




Entire Grid Class


I have supplied the entire grid class just incase you want to familiarise yourself with the class more than the code supplied.

ANY help is much appreciated, I have been looking through the internet, but I'm either searching for the 'wrong' thing or my problem isnt usually a problem to most people, or its not a problem yet needed answering.

I can post a screenshot of the program itsself if necessary.

Cheers for reading

earlbob91

Is This A Good Question/Topic? 4
  • +

Replies To: How do I display 8bit values in an array as a Raster Type Image

#2 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6110
  • View blog
  • Posts: 23,670
  • Joined: 23-August 08

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 04 January 2012 - 03:50 PM

Welcome to DIC!

Unfortunately I cannot be of any service as I'm blissfully unaware of image handling, but I'm sure someone will be along who is well-versed in the subject.

Just wanted to thank you for providing such a completely thorough explanation of your situation and problem. It's such a welcome change from the norm!
Was This Post Helpful? 1
  • +
  • -

#3 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 04 January 2012 - 04:33 PM

I actually feel very awry (guilty, crooked) because the only time in one month when someone actually posts a question properly and MORE then that, I can't help. Those neanderthals inexperienced bunch of new members who post 'this isn't work' in the end get some kind of an answer and I can't give you anything. DAMN! This seriously pissed me off. Anyway I applaud you for your very thorough post of your problem, but I can't help you. The most I can do is that I will try to find something on the internet, since I can't help you here (put plainly I don't know anything about image manipulation).

Was this what you were looking for:

Creating an Image from an Array of Color-Indexed Pixel Values (Not the Mandlebrot part but the above...)
How can I display an image from an array of pixels' values in java?

Ignore the fact that it's in Java it can be easily translated into C#. I'll be more than happy to translate that for you (If you can't do it yourself) if it's the thing you're looking for.
Was This Post Helpful? 0
  • +
  • -

#4 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 04 January 2012 - 08:06 PM

Thanks for the positive feedback, happy I made a good first impression, A piece of code I am interested in is from the second link you posted RexGrammer.

public static Image getImageFromArray(int[] pixels, int width, int height) {
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    WritableRaster raster = (WritableRaster) image.getData();
    System.out.println(pixels.length + " " + width + " " + height);
    raster.setPixels(0,0,width,height,pixels);
    return image;
}



Cant really work out a way of changing this to C#, I thought BufferedImage might be similar to the Image class and WriteableRaster similar to Bitmap but I can't change the code so well, I also looked in the object browser and on MSDN for any raster related classes but nothing jumped out at me.

Any help translating this would be decent :D

Cheers
earlbob91
Was This Post Helpful? 0
  • +
  • -

#5 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 05 January 2012 - 04:49 AM

Just giving you an update on my work:

BufferedImage ===== Bitmap
WritableRaster ====== N/A

This can't really be translated into C#, but I'm making progress towards making the WritableRaster functionality in the program.

public static Image getImageFromArray(int[] pixels, int width, int height)
        {
            Bitmap image = new Bitmap(width, height);
            int numberOfPixels = height * width;
            int w = 0;
            int h = 0;
            Color color = Color.Blue;
            for (int i = 0; i < numberOfPixels; i++)
            {
                image.SetPixel(pixels[w], pixels[h], color);
                if (w > image.Width)
                {
                    w = image.Width;
                }
                if (h > image.Height)
                {
                    h = image.Height;
                }
                if ((w >= image.Width) && (h >= image.Height))
                {
                    break;
                }
                w++;
                h++;
            }
            //WritableRaster raster = (WritableRaster)image.getData();
            //image.getPixel
            //System.out.println(pixels.length + " " + width + " " + height);
            //raster.setPixels(0,0,width,height,pixels);
            //return image;
            return image;
        }



Update: The pixels writing isn't good. Gonna fix it.

This post has been edited by RexGrammer: 05 January 2012 - 04:51 AM

Was This Post Helpful? 0
  • +
  • -

#6 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 05 January 2012 - 05:15 AM

Finally got it working:

public static Image getImageFromArray(int[,] pixels, Color[] colors, int width, int height)
        {
            Bitmap image = new Bitmap(width, height);
            int counter = 0;
            int[] widthPixels = new int[pixels.Length / 2];
            int[] heightPixels = new int[pixels.Length / 2];
            int widthCounter = 0;
            int heightCounter = 0;
            foreach (int i in pixels)
            {
                if (counter % 2 == 0)
                {
                    widthPixels[widthCounter] = i;
                    widthCounter++;
                }
                else
                {
                    heightPixels[heightCounter] = i;
                    heightCounter++;
                }
                counter++;
            }

            for (int i = 0; i < widthPixels.Length; i++)
            {
                image.SetPixel(widthPixels[i], heightPixels[i], colors[i]);
            }

            return image;
        }
    }



Going to leave it to settle, then I'm goint to refactor it.

A warning:

You must specify the same number of colors as the number of coordinate pairs

In the end, I think I wrote most of the code, rather than translating it from Java. :D

It works for me. Test it and bring feedback. :D

This post has been edited by RexGrammer: 05 January 2012 - 05:18 AM

Was This Post Helpful? 0
  • +
  • -

#7 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 05 January 2012 - 05:35 AM

Thanks a lot for your help Rex, I'm going to get onto this right away here, will let you know the results soon as I can.

Cheers
earlbob91
Was This Post Helpful? 0
  • +
  • -

#8 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 05 January 2012 - 05:54 AM

Here's the refactored, commented and polished version of the method if you're interested:

        /// <summary>
        /// A method to draw an image from an array of pixels
        /// </summary>
        /// <param name="pixels">The 2D array of pixels holding the pixel coordinate pairs</param>
        /// <param name="colors">The Color array holding the colors of the pixels</param>
        /// <param name="width">The width of the image</param>
        /// <param name="height">The height of the image</param>
        /// <returns>Returns a image from the specified pixel information</returns>
        public static Image GetImageFromArray(int[,] pixels, Color[] colors, int width, int height)
        {
            //Check to see if the user specified the same number of colors
            //as the number of pixels.
            if (pixels.Length / 2 != colors.Length)
                //If the didn't throw a new exception
                throw new ArgumentOutOfRangeException("colors", "Please specify an appropriate number of colors.");

            //Create a new image
            Bitmap image = new Bitmap(width, height);
            //Create a array of ints to hold the x coordinates of the pixels
            int[] xCoordinates = new int[pixels.Length / 2];
            //Create a array of ints to hold the y coordinates of the pixels
            int[] yCoordinates = new int[pixels.Length / 2];
            //Create a counter to check the position of the int in the array of pixels
            int counter = 0;
            //Declare counters to hold the postitions of coordinates in the arrays
            int xPosition = 0;
            //--||--
            int yPosition = 0;

            //Check each int in the pixel array
            foreach (int i in pixels)
            {
                //Every second pixel
                if (counter % 2 == 0)
                {
                    //Add it into the x coordinates
                    xCoordinates[xPosition] = i;
                    //Increase the x position counter
                    xPosition++;
                }
                else
                {
                    //Add everything else to the y coordinates
                    yCoordinates[yPosition] = i;
                    //Increase the y position counter
                    yPosition++;
                }
                //Increase the counter
                counter++;
            }

            //For each pair of x/y coordinates
            for (int i = 0; i < xCoordinates.Length; i++)
            {
                //Set the pixel in the image with the appropriate coordinates to the appropriate color
                image.SetPixel(xCoordinates[i], yCoordinates[i], colors[i]);
            }
            //Return the image
            return image;
        }


Was This Post Helpful? 1
  • +
  • -

#9 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 05 January 2012 - 09:58 AM

Wow, this is really good work Rex thanks a lot :D not fully implemented it yet though :( been doing washing and law revision all day what a pain in the arse! But don't worry I'll be sure to post you on the results I get!

Cheers again mate
earlbob91
Was This Post Helpful? 0
  • +
  • -

#10 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 11 January 2012 - 07:35 PM

Ok first of all I am grateful of your help, converting that snippet didnt prove as simple as I'de first thought, so cheers for that.

Next thing is, I did get it working in the end and here is the final 'product'.

Attached Image

And heres how I did it (with a little bit of help from my lecturer)
 public Bitmap ToImage(int colourscheme)
        {
            double[,] modifiedvalues = null;
            double diff = this.GridGlobalMax() - this.GridGlobalMin();
            int a = 0;
            int b = 0;
            double c = 0;
            modifiedvalues = new double[this.Cols, this.Rows];
            a = 0;
            b = 0;
            c = 0;
            while (!(b == this.Rows)) //- 1
            {
                c = Values[a, b];
                if (c != this.NoData & (c >= this.GridGlobalMin() && c <= (this.GridGlobalMax() + 1)))
                {
                    c = ((c - this.GridGlobalMin()) / diff) * 255;
                }
                else
                {
                    c = 0;
                }
                modifiedvalues[a, b] = c;
                if (a == this.Cols - 1)
                {
                    a = 0;
                    b = b + 1;
                }
                else
                {
                    a = a + 1;
                }
            }
            // Raster Data 'wrong way round' kept loops in same format, changed array
            modifiedvalues = this.FlipArray(modifiedvalues);
            int n = this.Cols; //- 1
            int m = this.Rows; //- 1
            //size of grid in pixels
            int cellsizeint;

            cellsizeint = this.CellSize/10;
            System.Drawing.Bitmap flag = new System.Drawing.Bitmap(n*cellsizeint, m*cellsizeint);            
            int xcord = 0;
            int ycord = 0;
            Color col = Color.Black;
            for (xcord = 0; xcord < n; xcord++)
            {
                for (ycord = 0; ycord < m; ycord++)
                {
                    int p = (int)modifiedvalues[xcord, ycord];
                    if (colourscheme == 0)
                    {
                        col = System.Drawing.Color.FromArgb(255, p, p, p);
                    }
                    else if (colourscheme == 1)
                    {
                        col = System.Drawing.Color.FromArgb(255, p, 0, 0);
                    }
                    else if (colourscheme == 2)
                    {
                        col = System.Drawing.Color.FromArgb(255, 0, p, 0);
                    }
                    else if (colourscheme == 3)
                    {
                        col = System.Drawing.Color.FromArgb(255, 0, 0, p);
                    }
                    Graphics gimage = Graphics.FromImage(flag);
                    gimage.FillRectangle(new SolidBrush(col), xcord * cellsizeint, ycord * cellsizeint, cellsizeint, cellsizeint);
                    
                }
            }
            //returns the bitmap
            return flag;
        }



And then made use of

g1 = g1.LinearScale8Bit();
Bitmap bmp = g1.ToImage(cbxColourRamp.SelectedIndex);
bmp.RotateFlip(RotateFlipType.Rotate90FlipY);
pbxRasterImage.SizeMode = PictureBoxSizeMode.StretchImage;
pbxRasterImage.Image = bmp;



Any comments are welcome, use the code if you want for your own projects I don't mind :bananaman:


Cheers
earlbob91
Was This Post Helpful? 0
  • +
  • -

#11 Curtis Rutland  Icon User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4577
  • View blog
  • Posts: 8,019
  • Joined: 08-June 10

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 11 January 2012 - 10:44 PM

Consider starting a github account and posting this project. If nothing else, learning a source control system will be useful, and it's a great way to share projects.
Was This Post Helpful? 0
  • +
  • -

#12 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 12 January 2012 - 05:44 AM

Just a few refactors:

1. You already initialized your variables to zero no need to do it twice
int a = 0; //You declare and initialize the
int b = 0; //variables here
double c = 0;

//...

//a = 0; //This is not needed
//b = 0; //since you already
//c = 0; //initialized the variables



2. You can easily put the declaration and initialization of a variable in one row:

Instead of this:
double[,] modifiedvalues = null;
modifiedvalues = new double[this.Cols, this.Rows];



Use this:
double[,] modifiedvalues = new double[this.Cols, this.Rows];



Same here:

int cellsizeint; 
cellsizeint = this.CellSize/10;



To this:

int cellsizeint = = this.CellSize/10;



3. When you only have only one line in a if statement you don't have to use code brackets:

if (c != this.NoData & (c >= this.GridGlobalMin() && c <= (this.GridGlobalMax() + 1)))
	               {
	                   c = ((c - this.GridGlobalMin()) / diff) * 255;
	               }



To this:

if (c != this.NoData & (c >= this.GridGlobalMin() && c <= (this.GridGlobalMax() + 1)))
	 c = ((c - this.GridGlobalMin()) / diff) * 255;



Same goes for else statements:

else
   {
      c = 0;
   }



To this:

else
   c = 0;



NOTE: All of this is just my style and if you don't like it you don't have to use it.
Was This Post Helpful? 1
  • +
  • -

#13 earlbob91  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 10
  • Joined: 04-January 12

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 12 January 2012 - 06:42 PM

I went over the code again today and cleaned it up pretty much to how you pointed out. Most of those things I would generally tend to do myself especially the variable declaration/assignment and using single line statements after if flow of control statements. But cheers anyway, I think it is good advice and practice anyway, I would recommend them to anyone I'm helping.

Off topic but, I've read Apress Illustrated C# 2010 and previously Wrox Beginning C# 4.0. I have much preferred the Apress but it doesnt seem to have any practical work or excercises, any recommendations for my next book to read that might have a bit more writing of code than learning the language?

Cheers
Was This Post Helpful? 0
  • +
  • -

#14 RexGrammer  Icon User is offline

  • Coding Dynamo
  • member icon

Reputation: 182
  • View blog
  • Posts: 783
  • Joined: 27-October 11

Re: How do I display 8bit values in an array as a Raster Type Image

Posted 13 January 2012 - 04:49 AM

Recommended C# Books

My favorite: Microsoft Visual C# 2010 Step by Step...
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1