15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту




Печать в OpenGL


Автор: Jongwhan Lee.

Описание

Итак, вопрос: как правильно распечатать картинку, нарисованную посредствам OpenGL? Сразу оговорюсь, что само изображение это картинка в формате BMP. Теоретически весь процесс заключается в создании битмаповского изображения из картинки OpenGL, а затем распечатки этой картинки на принтере.

Сперва с помощью Class Wizard создаём функцию "OnPrint" в классе CBitmapView.

void CBitmapView::OnPrint(CDC* pDC, CPrintInfo* pInfo) ;

Если Вы хотите получить качественную распечатанную картинку:

double ar=(double)paper.Width()/(double)paper.Height();
CRect gl_paper(0,0,1000*ar,1000);

Увеличиваем размер OpenGL-евского bitmap-а.

CRect gl_paper(0,0,2000*ar,2000);

Если задать ещё больше размер, то соответственно качество изображения будет лучше, но и соответственно процессор не сможет быстро справиться с этой задачей. Следующая команда делает OpenGL-ский экран одинакового размера с размером бумаги на принтере:

CRect gl_paper=paper; 

Размер контекста устройства моего принтера позволяет задать размер 6000*6000, но когда я делаю размер GL экрана 6000 на 6000 , то мой компьютер зависает.

void CBitmapView::OnPrint(CDC* pDC, CPrintInfo* pInfo) 
{
 CRect paper(0,0,0,0);

 // получаем размер бумаги..
 if (pInfo->m_bPreview) // превью ..
 {
  PRINTDLG PrtDlg; // Диалог вывода на печать
  if (!AfxGetApp()->GetPrinterDeviceDefaults(&PrtDlg))
  {
   if (pDC->IsKindOf(RUNTIME_CLASS(CPreviewDC))) 
   {
    CPreviewDC *pPrevDC = (CPreviewDC *)pDC;
    //m_hAttribDC содержит print/fax аттрибуты ...
    paper.right = GetDeviceCaps(pPrevDC->m_hAttribDC, HORZRES);
    paper.bottom = GetDeviceCaps(pPrevDC->m_hAttribDC, VERTRES);
   }
  }
  else
  {
   CPrintDialog dlg(FALSE);
   dlg.m_pd.hDevMode = PrtDlg.hDevMode;
   dlg.m_pd.hDevNames = PrtDlg.hDevNames;
   HDC hdc = dlg.CreatePrinterDC();
   // Получаем размер страницы принтера
   paper.right = GetDeviceCaps(hdc, HORZRES);
   paper.bottom = GetDeviceCaps(hdc, VERTRES);
   // Освобождаем контекст устройства
   DeleteDC(hdc);
  }
 }
 else { // печатаем на бумагу
  paper.right = GetDeviceCaps(pDC->GetSafeHdc(), HORZRES);
  paper.bottom = GetDeviceCaps(pDC->GetSafeHdc(), VERTRES); 
 }

 pDC->RoundRect(0,0, paper.right, paper.bottom, 10, 10);

 double ar=(double)paper.Width()/(double)paper.Height();
 CRect gl_paper(0,0,1000*ar,1000);
 int width=((int)(gl_paper.Width()/4))*4;
 int height=gl_paper.Height();
 CGLPrintMan print;
 print.EnableOpenGL(gl_paper,GetSafeHwnd(), &print.m_hDC, &print.m_hRC);

 print.StartUpdate();

 print.KeepAspectRatio(width,height);
 glViewport(0,0,width,height);
 glDrawBuffer(GL_FRONT);
 print.SetViewVolume();
 glGetIntegerv(GL_VIEWPORT, print.m_nvVP);

 // рисуем
 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 {
  glClearColor(1,1,1,0);
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | 
  GL_STENCIL_BUFFER_BIT);
  glDisable(GL_LIGHTING);
  glEnable(GL_COLOR_MATERIAL);
  glColor3d(1,0,0);
  glutSolidSphere(5, 20,20 );
 }  

 // передаём на принтер
 {
  HDC hdc;
  HBITMAP bitmap;
  hdc = CreateCompatibleDC(pDC->GetSafeHdc());
  bitmap = CreateDIBitmap(hdc, &(print.m_BitmapInfo.bmiHeader),
  CBM_INIT,
  (GLubyte*)print.m_pBitmapBuffer,
  &print.m_BitmapInfo,
  DIB_RGB_COLORS);

  HGDIOBJ oldbitmap = SelectObject(hdc, bitmap);
  BOOL bRet = StretchBlt(pDC->GetSafeHdc(),
  0,0 , // смещение 
  paper.Width(), paper.Height(),// бумаги
  print.m_hDC,
  0, 0,
  print. m_BitmapInfo.bmiHeader.biWidth,
  print.m_BitmapInfo.bmiHeader.biHeight,
  SRCCOPY);
  if (oldbitmap != NULL)
  SelectObject(hdc, oldbitmap);
  // освобождаем битмап и контекст устройства битмапа
  DeleteObject(bitmap);
  DeleteDC(hdc);
 }

 print.EndUpdate();
 print.DisableOpenGL(GetSafeHwnd(), print.m_hDC, print.m_hRC);

 CView::OnPrint(pDC, pInfo);
}

Downloads

Скачать исходник демо-проекта - 130 Kb