PDF format

Hi,

    We have to give the OpenGL scene rendered at that time in a PDF format for future use. For that we drawn the scene Bitmap and then taken the PDF format using Print command. But the resolution is very low while zooming in. The PDF format diagram itself become very blurred. Please help in this.

Following is the code:

CRect rcClient;
pView-> GetClientRect(&rcClient);

float fClientRatio = float(rcClient.Height())/rcClient.Width();

// Get page size
m_szPage.cx  = pDC->GetDeviceCaps(HORZRES);
m_szPage.cy = pDC->GetDeviceCaps(VERTRES);

CSize szDIB;

if (pInfo-> m_bPreview)
{

	// Use screen resolution for preview.
	szDIB.cx = rcClient.Width();
	szDIB.cy = rcClient.Height();

}
else  // Printing
{

	// Use higher resolution for printing.
	// Adjust size according screen's ratio.

	if (m_szPage.cy > fClientRatio*m_szPage.cx)
	{
	
		// View area is wider than Printer area
		szDIB.cx = m_szPage.cx;
		szDIB.cy = long(fClientRatio*m_szPage.cx);

	}
	else
	{

		// View area is narrower than Printer area
		szDIB.cx = long(float(m_szPage.cy)/fClientRatio);
		szDIB.cy = m_szPage.cy;

	}
	// Reduce the Resolution if the Bitmap size is too big.
	// Ajdust the maximum value, which is depends on printer's memory.
	// I use 20 MB. 

	while (szDIB.cx*szDIB.cy > 30e6)   
	{

		szDIB.cx = szDIB.cx / 2;
		szDIB.cy = szDIB.cy / 2;

	}

}

TRACE("Buffer size: %d x %d = %6.2f MB

", szDIB.cx, szDIB.cy, szDIB.cxszDIB.cy0.000001);
// 2. Create DIB Section
memset(&m_bmi, 0, sizeof(BITMAPINFO));
m_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_bmi.bmiHeader.biWidth = szDIB.cx;
m_bmi.bmiHeader.biHeight = szDIB.cy;
m_bmi.bmiHeader.biPlanes = 1;
m_bmi.bmiHeader.biBitCount = 24;
m_bmi.bmiHeader.biCompression = BI_RGB;
m_bmi.bmiHeader.biSizeImage = szDIB.cx * szDIB.cy * 3;

HDC	hDC = ::GetDC(pView -> m_hWnd);
m_hDib = ::CreateDIBSection(hDC, &m_bmi, DIB_RGB_COLORS, &m_pBitmapBits, NULL, (DWORD)0);
::ReleaseDC(pView -> m_hWnd, hDC);

/***************/
// 3. Create memory DC, and associate it with the DIB.
m_hMemDC = ::CreateCompatibleDC(NULL);

if (!m_hMemDC)
{

	DeleteObject(m_hDib);
	m_hDib = NULL;
	return;

}

SelectObject(m_hMemDC, m_hDib);
// 4. Setup memory DC's pixel format.

if (!SetDCPixelFormat(m_hMemDC, PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_STEREO_DONTCARE))
{

	DeleteObject(m_hDib);
	m_hDib = NULL;
	DeleteDC(m_hMemDC);
	m_hMemDC = NULL;
	return;

}

// 5. Create memory RC
m_hMemRC = ::wglCreateContext(m_hMemDC);

if (!m_hMemRC)
{

	DeleteObject(m_hDib);
	m_hDib = NULL;
	DeleteDC(m_hMemDC);
	m_hMemDC = NULL;
	return;

}

// 6. Store old DC and RC
m_hOldDC = ::wglGetCurrentDC();
m_hOldRC = ::wglGetCurrentContext(); 

// 7. Make the memory RC current
::wglMakeCurrent(m_hMemDC, m_hMemRC);

// 8. Set OpenGL state for memory RC. 
// The state is the same as the screen RC's.

// SetOpenGLState();
::glViewport(0, 0, szDIB.cx, szDIB.cy);
SetFrustum();
// 9. Create display list with the newly created memory RC

Draw();
     
   CreateDisplayList();

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

void CDocumentationView::CreateDisplayList(UINT nList)
{
::glNewList(1, GL_COMPILE);
Draw();
::glEndList();

}

Please help to solve it.

Help me in Printing an OpenGL scene to a PDF file

You usually can’t simply print to a pdf-file. My guess is, that you need to configure whatever program you use that simulates the printing. Anyway, as soon as the image is moved into a windows bitmap, the question is no longer OpenGL-related.

I’m not really sure of what you try to do exactly, but why not doing it such this way:

  1. Get the printer resolution
  2. In GL set your viewport to match the printer resolution
  3. Draw
  4. Use glReadPixel to get what you drawn
  5. Save the data into whatever format you want

Of course zooming will still produce bad things just because PDF is not an image manipulator. Does PDF is an obligation ?

Hope that could help a bit.

You should not draw directly to the bitmap as it won’t give you hardware acceleration (reducing the image quality). About printing I can say nothing, never did it.

dpi on a printer are typically magnitudes higher than dpi thus if u print out the screen is only gonna use a small area of the piece of paper. if u resize it larger its gonna have to interpolate the data (hence the blurring) practically nothing u can do about it.
pdfs text dont suffer from that when u zoom is the contents are not stored as pixels but as curves (i assume)

Hi Jide,

   Yeah.. We have to give the output in PDF format only. I will work out in the way as per your ideas.

Thanks Mikkel Gjoel, Zengar, and Zed.

With Regards,
Sangeetha.

google for “opengl to postscript”.
a .ps file can be easily converted to pdf then.

Be aware of the limitations, ie. textures will not be supported etc. But you end up with a real scalable vector output.

If you need really high resolution you have to render your scene multiple times, read-back the results and combine them to get your high res image.

If you’re rendering 2D content (glOrtho…) you just have to change your viewpoint.

In the 3D case you can get arbitrary high resolution by rendering the scene with different off-axis projections using glFrustum.

-ag

Hi ZbuffeR,

      Thank you a lot for your suggestion to convert the OpenGL Scene to PostScript and then to PDF.. Really its working well.. I thank you a lot..

And thanks to all who replied me…

With Regards,
Sangeetha.

Hi,

  The Conversion of OpenGLScene to PostScript is working well. But the larger files cannot be converted.  Taking lot of memory. How to convert larger files to PostScript? We are allocating the size to feeback buffer as,

feedbackBuffer =(GLfloat*) calloc(size, sizeof(GLfloat));

How to provide larger values to feebackBuffer.

Thanks in advance,
Sangeetha

put this line just before before:

size *= 4;

Seriously, can you be more specific ? what is “lot of memory” ?

Hi ZbuffeR,

 The function used is the following..

void OutPutPostScript(int size, int doSort, char *filename)
{

GLfloat *feedbackBuffer;
GLint returned;
FILE *file;

feedbackBuffer =(GLfloat*) calloc(size, sizeof(GLfloat));
glFeedbackBuffer(size, GL_3D_COLOR, feedbackBuffer);

(void) glRenderMode(GL_FEEDBACK);
render();
returned = glRenderMode(GL_RENDER);

if (filename)
{

	file = fopen(filename, "w");

	if (file)
	{

		spewWireFrameEPS(file, doSort, returned, feedbackBuffer, "rendereps");

	} 
	else
	{

		printf("Could not open %s

", filename);

	}

} 
else
{
/* Helps debugging to be able to see the decode feedback
buffer as text. */
	printBuffer(returned, feedbackBuffer);
}

free(feedbackBuffer);

In this, the feedbackbuffer values returned for smaller files is somewhat like 5324478 for the “size” variable. But for larger files nothing is coming. How to give values for feedbackbuffer then… For larger files, the value of size is very large. And hence the file cannot be converted.

Please forgive me for not clearly defining the problem…

Thank you,
Sangeetha.

}

Hi,

  Sorry i added my lines inside the function, instead of typing after the cloased brace. I just didnt noticed.

For the function i had given, that is the void OutPutPostScript(int size, int doSort, char *filename), How to give the value for size of the feedback buffer…? As i am declaring it as int it is having a limit… But for larger files, have to more value for size… Anyone please help me…

Sangeetha. J