Issue creating accurate Jpeg on new computer

Hi everyone, I’m new here but have scoured every source I can think of to track down what this issue might be with no luck.

The short story is that I’ve designed a program which was working just peachy on my older computer (Vista, 32-bit, ATI graphics card, supported OpenGL 2.0) but now saves what should be primarily grayscale x-ray images (as jpegs) as “redscale” on my new system. The program is written in C++ using Visual Studio 9 with all the necessary updates and uses OpenGL to handle the graphics.

Specs of the new system:
Windows 7 Home Premium

Pentium Dual Core CPU T4300 2.10 GHz
4.0 Gig RAM
64-Bit OS

Graphics Card:
Intel GMA 4500MHD using Mobile Intel® 4 Series Express Chipset Family driver
OpenGL version: 2.1.0 - Build 8.15.10.1892

Here’s the code that should take the x-ray image from the screen, bind it to a texture, and save it as a jpeg. As I stated, it worked fine on my older computer and on some other 32-bit systems I’ve been able to test it on, but on 64-bit systems it seems to come out red. I’m hoping someone here can help point me to a solution.

<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>


void CDicomAnalyzerDoc::OnFileSaveAs()
{
	CString cstrFormat;
	cstrFormat += "JPEG Format(*.jpg)|*.jpg|";
	cstrFormat += "|";

	CFileDialog Dlg(FALSE,"jpg","*.jpg", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, cstrFormat);

	if(Dlg.DoModal()==IDOK){

		::SetCursor(::LoadCursor(NULL,IDC_WAIT));

		DICOM_SIZE  tSize = GetCanvas()->GetSize();

		if( tSize.cx == 0.0 || tSize.cy == 0.0)
			return;

		double fZoomScale = -1.0;

			GLint glMaxTexDim = 0;
			glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); 

			if( tSize.cx > glMaxTexDim || tSize.cy > glMaxTexDim ){

				fZoomScale = glMaxTexDim/(tSize.cx > tSize.cy ? tSize.cx : tSize.cy );

				tSize.cx *= fZoomScale;
				tSize.cy *= fZoomScale;
			}
		

		if( !m_pFBO ){

			glGenTextures(1, &m_nFBOTextureID);

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_TEXTURE_RECTANGLE_ARB);
			glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_nFBOTextureID);
				
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
		
			glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB8, tSize.cx, tSize.cy, 0, GL_RGB, GL_BYTE, 0);

			m_pFBO = new FramebufferObject();

			m_pFBO->AttachTexture(GL_TEXTURE_RECTANGLE_ARB, m_nFBOTextureID, GL_COLOR_ATTACHMENT0_EXT);

			m_pFBO->IsValid();

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
			glDisable(GL_TEXTURE_RECTANGLE_ARB);

			glActiveTextureARB(GL_TEXTURE0_ARB);
			glEnable(GL_TEXTURE_2D);
		}

		if( m_pFBO && m_nFBOTextureID != 0 ){

			GLint nCurrentDrawbuf, nCurrentReadbuf;

			glGetIntegerv(GL_DRAW_BUFFER, &nCurrentDrawbuf); 
			glGetIntegerv(GL_READ_BUFFER, &nCurrentReadbuf); 

			m_pFBO->Bind();

		  GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

		  bool isOK = true;

		  CString cstrInfo;

		  switch(status) {                
			  case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
				isOK = true;
				break;
			  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
					cstrInfo =  "ERROR: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
";
					isOK = false;
					break;
			case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
					cstrInfo = "ERROR: GL_FRAMEBUFFER_UNSUPPORTED_EXT
";
					isOK = false;
					break;
			default:
				cstrInfo = "Unknown FBO ERROR
";
				isOK = false;
			}

			if( !isOK )
				AfxMessageBox(cstrInfo);

			glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);

			glClearColor(0, 0, 0, 0);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			int vp[4];
			glGetIntegerv(GL_VIEWPORT, vp);

			glViewport(0, 0, tSize.cx, tSize.cy);

			glMatrixMode(GL_PROJECTION);
			glPushMatrix();	

			glLoadIdentity();
			glOrtho(0.0, tSize.cx, tSize.cy, 0.0, -1.0, 1.0);

			glMatrixMode(GL_MODELVIEW);
			glPushMatrix();	

			glLoadIdentity();

			if( fZoomScale > 0.0)
				glScaled(fZoomScale, fZoomScale, fZoomScale);

			GetCanvas()->OnRender(-1.0);

			glLoadIdentity();

			//////////////////////////////////////////////////////////////

			glScaled(1.0f, 1.0f, 1.0f);

			DICOM_SIZE tOldSize = GetScene()->GetOutputBox()->GetSize();
			GetScene()->GetOutputBox()->SetSize( tSize.cx, tSize.cy );

			GetScene()->GetOutputBox()->OnRender(-1.0);

			GetScene()->GetOutputBox()->SetSize(tOldSize.cx, tOldSize.cy);

			glDisable(GL_BLEND);

			//////////////////////////////////////////////////////////////
		
			glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);

			IplImage* pImage = cvCreateImage(cvSize(tSize.cx, tSize.cy), IPL_DEPTH_8U, 3);

			glReadPixels(0,0, tSize.cx, tSize.cy,GL_BGR_EXT, GL_UNSIGNED_BYTE, pImage->imageData);

			cvFlip(pImage);

			cvSaveImage(Dlg.GetPathName(), pImage);

			cvReleaseImage(&pImage);

			glMatrixMode(GL_MODELVIEW);
			glPopMatrix();

			glMatrixMode(GL_PROJECTION);
			glPopMatrix();

			glMatrixMode(GL_MODELVIEW);

			glUseProgramObjectARB(0);

			glViewport(vp[0], vp[1], vp[2], vp[3]);

			FramebufferObject::Disable();

			glDrawBuffer(nCurrentDrawbuf);
			glReadBuffer(nCurrentReadbuf);

			SAFE_DELET(m_pFBO);
			SAFE_DELET(m_pRenderBuffer);
	
			if( m_nFBOTextureID != 0 ){
				glDeleteTextures(1, &m_nFBOTextureID);
				m_nFBOTextureID = 0;
			}

		}

		::SetCursor(::LoadCursor(NULL,IDC_ARROW));

	}		

}

[/QUOTE]</div>

Now I know from reading that Intel graphics cards have poor OpenGL support compared to NVidia or ATI, but I have other people using the program on non-intel cards that are still having the same issue.

You should try a simpler testcase, without opencv or whatever FBO/texture (why do you need that in the first place?), just read a pixel pixels and check if all 3 color channels have the same value.
Not sure about the data alignment expected by OpenCV/IPL, but you may hit something with the change from 32 to 64 bits.
Try that somewhere before texturing/reading pixels :
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);

Try to specifically debug step by step this sequence of code, the problem is likely to happen inside :


IplImage* pImage = cvCreateImage(cvSize(tSize.cx, tSize.cy), IPL_DEPTH_8U, 3);
glReadPixels(0,0, tSize.cx, tSize.cy,GL_BGR_EXT, GL_UNSIGNED_BYTE, pImage->imageData);
cvFlip(pImage);
cvSaveImage(Dlg.GetPathName(), pImage);

Thanks for the response, ZbuffeR. I’ll mess around with it some tonight and see what I can sort out from what you’ve mentioned.

To be honest, I am an absolute beginner when it comes to OpenGL … I designed the structure of the program but had someone else with more graphics experience write it for me. I have programmed in numerous languages in the past though, so I can take what’s there and modify in most cases (which is good because my partner left the country and is no longer interested in the project), but some of the basics for many people are not within my current level of understanding.

I’ll post an update once I’ve exhausted the possibilities of your suggestions. Thanks again!