vmsgman's picture

Grayscale Image Viewer

Processor: Intel(R) Core(TM)2 CPU T7200 @ 2.00GHz (1997 MHz)
Operating System: Microsoft Windows XP (Service Pack 3)
DirectX version: 9.0c
GPU processor: Quadro NVS 110M
ForceWare version: 175.97
Total available graphics memory: 256 MB
Dedicated video memory: 64 MB
System video memory: 192 MB
Shared system memory: 0 MB
Video BIOS version: 5.72.22.21.fc
IRQ: 16
Bus: PCI Express x16
Total RAM 2Gb

Hello, I am trying to remember my OpenGL programming class information from 15 yrs ago, and also translate that into Windows.Forms programming with OpenTK. I love working with your API thanks for the hard work and great results. I will post this code after it is worthy to be posted as an example for others. Can you help with a few things?

I am opening images that are 16bpp grayscale, they have a header that has some info in it. But the ImageArray portion is an ushort[]. So I am having a hard time trying to figure out the best place to put the OpenGL code. What I have so far works okay except that I need to resize the image to keep the aspect ratio the same and minify the image by factors of 2 if it is too big to be displayed in the current window size. I am using my crappy laptop for development because I need this application to be used on older hardware. Lets just consider my laptop as the minimum requirements.

I am new, except for a class eons ago, to graphics programming, so please be gentle.

/*
 * Created by SharpDevelop.
 * User: ggerber
 * Date: 10/20/2009
 * Time: 2:26 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
 
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Vip.Images;
 
namespace ViVA.Net
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		private int textureId;
		private int appWidth;
		private int appHeight;
		private int viewWidth;
		private int viewHeight;
		private bool isCreated;
		private int panelWidth = 150;
		private VipImage vipImage;
 
		public MainForm()
		{
			InitializeComponent();
			int scrWidth = SystemInformation.PrimaryMonitorSize.Width;
			int scrHeight = SystemInformation.PrimaryMonitorSize.Height;
			appWidth = scrWidth - 250;
			appHeight = scrHeight - 100;
			this.Width = appWidth;
			this.Height = appHeight;
			this.Location = new Point(125, 50);
			isCreated = true;
		}
 
		void MainFormLoad(object sender, EventArgs e)
		{
			GL.Enable(EnableCap.Texture2D);
			MainFormResize(sender, e);
		}
 
		void MainFormResize(object sender, EventArgs e)
		{
			if(isCreated)
			{
				appWidth = this.Width;
				appHeight = this.Height;
				glControl1.Width = appWidth - panelWidth;
				glControl1.Height = appHeight;
				glControl1.Location = new Point(panelWidth, 0);
				//if (vipImage == null)
					SetupViewport(glControl1.Width, glControl1.Height);
				//else 
				//{
					/*if (vipImage.Width > vipImage.Height)
					{
						viewWidth = vipImage.Width;
						viewHeight = vipImage.Height;
						while (viewWidth > appWidth)
						{
							viewWidth /= 2;
							viewHeight /= 2;
						}
					} 
					else
					{
						viewHeight = vipImage.Height;
						viewWidth = vipImage.Width;
						while (viewHeight > appHeight)
						{
							viewWidth /= 2;
							viewHeight /= 2;
						}
					}*/
					//SetupViewport(viewWidth, viewHeight);
				//}
			}
		}
 
		void ExitMenuClick(object sender, EventArgs e)
		{
			this.Close();
		}
 
		#region OpenGL Methods
		void GlControl1Paint(object sender, PaintEventArgs e)
		{
			glControl1.MakeCurrent();
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			GL.Color3(Color.White);
 
			GL.MatrixMode(MatrixMode.Modelview);
			GL.LoadIdentity();
			GL.Translate(glControl1.Width / 2 - (viewWidth / 2), glControl1.Height / 2 - (viewHeight / 2), 0.0f);
 
			GL.Begin(BeginMode.Quads);
				GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0.0f, 0.0f, 1.0f);
				GL.TexCoord2(1.0f, 0.0f); GL.Vertex3((float)viewWidth, 0.0f, 1.0f);
				GL.TexCoord2(1.0f, 1.0f); GL.Vertex3((float)viewWidth, (float)viewHeight, 1.0f);
				GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0.0f, (float)viewHeight, 1.0f);
			GL.End();
 
			glControl1.SwapBuffers();
		}
 
		void SetupViewport(int w, int h)
		{
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadIdentity();
			//GL.Ortho(0, w, 0, h, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
			GL.Ortho(0, w, h, 0, -1, 1); // Upper-left corner pixel has coordinate (0, 0)
			GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
			glControl1.Invalidate();
		}
		#endregion
 
		void MainFormFormClosed(object sender, FormClosedEventArgs e)
		{
			glControl1.Dispose();
		}
 
		void ButOpenClick(object sender, EventArgs e)
		{
			OpenFileDialog ofd = new OpenFileDialog();
			ofd.Filter = "ViVA Files (*.viv,*.raw,*.bin,*.dat)|*.viv;*.raw;*.dat;*.bin";
			ofd.FilterIndex = 1;
 
			if (ofd.ShowDialog() == DialogResult.OK)
			{
				glControl1.MakeCurrent();
				vipImage = new VipImage();
				vipImage.Read(ofd.FileName);
				treeViewImages.Nodes.Add(new TreeNode(ofd.FileName));
				if (vipImage.Width > vipImage.Height)
				{
					viewWidth = vipImage.Width;
					viewHeight = vipImage.Height;
					while (viewWidth > appWidth)
					{
						viewWidth /= 2;
						viewHeight /= 2;
					}
				} 
				else
				{
					viewHeight = vipImage.Height;
					viewWidth = vipImage.Width;
					while (viewHeight > appHeight)
					{
						viewWidth /= 2;
						viewHeight /= 2;
					}
				}
				textureId = GL.GenTexture();
				GL.BindTexture(TextureTarget.Texture2D, textureId);
				GL.PixelStore(PixelStoreParameter.PackAlignment, 2);
				GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (float)TextureEnvMode.Modulate);
				GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance, vipImage.Width, vipImage.Height, 0, PixelFormat.Luminance, PixelType.UnsignedShort, vipImage.ImageArray);
				GL.TexParameter(TextureTarget.Texture2D,
				                TextureParameterName.TextureMinFilter,
				                (float)TextureMinFilter.Linear);
				GL.TexParameter(TextureTarget.Texture2D,
				                TextureParameterName.TextureMagFilter,
				                (float)TextureMagFilter.Nearest);
				//SetupViewport(viewWidth, viewHeight);
				glControl1.Invalidate();
				MainFormResize(sender, e);
			}
		}
	}
}

I would like the image to stay the same size when resizing unless it can't be displayed with the correct aspect ratio, then it should be displayed half as big.
Thanks for any help you can provide!

P.S. I would be happy to supply the rest of the project with sample images, or screenshots if this will help in troubleshooting, but I suspect that my problems are easily solved by putting the code in the right places!

Greg


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rakkarage's picture

do you mean "stay same aspect when resizing?
does

Quote:

9.140 How do I keep my aspect ratio correct after a window resize?
It depends on how you are setting your projection matrix. In any case, you'll need to know the new dimensions (width and height) of your window. How to obtain these depends on which platform you're using. In GLUT, for example, the dimensions are passed as parameters to the reshape function callback.
The following assumes you're maintaining a viewport that's the same size as your window. If you are not, substitute viewportWidth and viewportHeight for windowWidth and windowHeight.
If you're using gluPerspective() to set your Projection matrix, the second parameter controls the aspect ratio. When your program catches a window resize, you'll need to change your Projection matrix as follows:
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov, (float)windowWidth/(float)windowHeight, zNear, zFar);
If you're using glFrustum(), the aspect ratio varies with the width of the view volume to the height of the view volume. You might maintain a 1:1 aspect ratio with the following window resize code:
float cx, halfWidth = windowWidth*0.5f; float aspect = (float)windowWidth/(float)windowHeight; glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* cx is the eye space center of the zNear plane in X */ glFrustum(cx-halfWidth*aspect, cx+halfWidth*aspect, bottom, top, zNear, zFar);
glOrtho() and gluOrtho2D() are similar to glFrustum().

that help? from http://www.opengl.org/resources/faq/technical/transformations.htm

so i guess you just have to modify the width and height u pass into Ortho?

vmsgman's picture

Rakkarage,
Thanks for taking the time to respond. Yes I need to keep the aspect ratio the same after resizing. Most of my trouble is coming from trying to recycle most of the code samples and snippets which use a C callback mechanism to this new idea of only redrawing on Form resize but have the glControl doing it's own painting on it's own schedule. I will work on it some more today. Thanks for your help.

Greg

rakkarage's picture

np... i am not good at math but i dont think the witdth and height parameters to ortho even have to be related to window or viewport size... you can just put two constants that give that aspect you want (800, 600) (ya there is a smaller number then that that will give same result... its just a ratio right idk) and always use those?

rakkarage's picture

just had same prob with my ortho, fixed by applying some factor of the window width to x and some factor of the window height to y

// background window
GL.Color4(Color);
GL.Vertex3(BottomLeft.X, BottomLeft.Y, 0.0f);
GL.Vertex3(TopRight.X, BottomLeft.Y, 0.0f);
GL.Vertex3(TopRight.X, TopRight.Y, 0.0f);
GL.Vertex3(BottomLeft.X, TopRight.Y, 0.0f);
 
float x = WindowSize.Width * 0.00001f;
float y = WindowSize.Height * 0.00001f;
 
// a little closer and a little smaller forground window
GL.Vertex3(BottomLeft.X + y, BottomLeft.Y + x, 0.5f);
GL.Vertex3(TopRight.X - y, BottomLeft.Y + x, 0.5f);
GL.Vertex3(TopRight.X - y, TopRight.Y - x, 0.5f);
GL.Vertex3(BottomLeft.X + y, TopRight.Y - x, 0.5f);
vmsgman's picture

Hi All,
I am back with many of the previous issues solved but I am still having issues with being able to drag the mouse to move the image (left,right,up,down). When I zoom (scroll mouse wheel) the center x,y of the image pixel changes. I am trying to keep the x,y coords the same on zooming. I am attaching the code with an image in the bin\Debug directory. If you can help me I would appreciate. I had to delete the OpenTK.dll file as it was too big to include. I am using the 0.9.9.3 release

THX greg

AttachmentSize
ViVA.Net_.zip126.94 KB