青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

OpenGL打印&&預覽

Printing and Print Preview OpenGL in MFC
Rating:

Wenfei Wu (view profile)
February 14, 2001

Wrapping OpenGL with MFC can take the advantages of both APIs: fast rendering and an elegant GUI. However, due to the fact that many printer drivers do not work with the SetPixelFormat() API function, it is not feasible to render an OpenGL scene to a printer directly. A widely used technique is to render an OpenGL scene to a DIB section, then copy it to a DC for printing or print preview. This article demonstrates this approach.
(continued)

I use Document/View architecture in the demo. The view class CGLView is multiple-derived from CView and CGLObj. The later class bundles all the OpenGL implementation - including printing. The CGLView::OnPrint function wraps three methods as follows:

void CGLView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{	CGLObj::OnPrint1(pDC, pInfo, this);
	// TODO: Render header here.
	OnDraw(pDC);
	// TODO: Render footer here.
	CGLObj::OnPrint2(pDC);
}

The CGLObj::OnPrint1 is designed to prepare for off-screen rendering. The major purposes of the method are to create a DIB section, and a memory RC. The memory RC will be used for OpenGL off-screen rendering later on. Following is the sequential of the method. After rendering, CGLObj::OnPrint2 copies the image in DIB section to the printer or preview DC, then releases the memory.

Preparing for OpenGL Off-Screen Rendering - OnPrint1()

  1. Determine the DIB size for either printing or print preview.

    The size of the DIB section depends on the size of the display device. For print previewing, I use screen resolution. For printing, I use the reduced printer's resolution. Ideally, I hope I can use the printer's full resolution if memory and speed is not a problem. However, for a printer with 720 DPI and using letter-sized paper, the memory of a DIB section is easily to excess of 100MB. That is why I reduce the printing resolution.

  2. Create DIB Section

    I call Windows function CreateDIBSection() to create a DIB section with this size mentioned above.

  3. Create memory DC, and associate it with the DIB section

    Calling Win32 function CreateCompatibleDC() creates a memory DC and returns a handle of it. Then I select the DIB section into a memory DC.

  4. Setup memory DC's pixel format

    Setting memory DC's pixel format is similar to setup a screen DC. The only difference is a flag specifying properties of the pixel buffer. I set PFD_DRAW_TO_WINDOW and PFD_DOUBLEBUFFER for the screen DC, but I need PFD_DRAW_TO_BITMAP for the memory DC. Thus, I made a helper function SetDCPixelFormat() to reuse this part of code.

  5. Create memory RC

    I use the above memory DC to create a memory RC for OpenGL off-screen rendering. The life of memory DC and RC will end when the printing is finished.

  6. Store old DC and RC

    The DC and RC for screen rendering should be stored. They will be restored after printing is finished.

  7. Make the memory RC current

    The function wglMakeCurrent() sets the memory RC current. From now, OpenGL will render with the memory RC, not screen RC. However, before rendering with the memory RC, I have to initialize the RC just like that working with screen RC.

  8. Set OpenGL state for memory RC

    The OpenGL state and frustum of the memory RC must be the same as the screen RC's so that we can get the same image rendered to the memory RC. I made SetOpenGLState() and SetFrustum() functions work for both RCs

  9. Create display list with the newly created memory RC.

    If you use OpenGL display list, you must create it again with the newly created memory RC. Keep in mind the display list is not reusable across RCs.

Following is the source code of CGLObj::OnPrint1

void CGLObj::OnPrint1(CDC* pDC, CPrintInfo* pInfo, CView* pView)
{
 // 1. Determine the DIB size for either printing or print preview.
 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 > 20e6)
  {
   szDIB.cx = szDIB.cx/2;
   szDIB.cy = szDIB.cy/2;
  }
 }

 TRACE("Buffer size: %d x %d = %6.2f MB\n",
 szDIB.cx, szDIB.cy, szDIB.cx*szDIB.cy*0.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
 CreateDisplayList(1);
}

Off-Screen Rendering

Now we can render with the memory RC. It is a common practice and a good idea to reuse the rendering scenario, but do not use double buffering for the memory RC.
Printing - OnPrint2()
This method handles the real "printing", and then free the memory.
  1. Release memory RC, and restore the old DC and RC.

    After rendering, we can delete the memory RC right away, and restore the old DC and RC for screen rendering.

  2. Calculate the target size according to the image size, and orientation of the paper.

    Now the image is stored in the memory, particularly in the DIB section. In general, the page size and orientation are different from the image's. We need to work out a target area on the page, to which the image will be copied. The target area should have the same orientation and elongation as the image in the DIB section.

  3. Stretch image to fit in the target size.

    The Win32 API StretchDIBits() copies the image in the DIB section to the destination, a handle to DC for either printing or print preview. The image is stretched to fit in the target area with the same elongation.

  4. Release memory.

    The job is finished. Release the memory for DIB section and memory DC now.

Following is the source code of CGLObj::OnPrint2

void CGLObj::OnPrint2(CDC* pDC)
{
 // Now the image is in the DIB already. We don't need the
 // memory RC anymore. We'll copy the image to the DC for
 // printing or print preview.

 // 1. Release memory RC, and restore the old DC and RC.
 ::wglMakeCurrent(NULL, NULL);
 ::wglDeleteContext(m_hMemRC);

 // Restore last DC and RC
 ::wglMakeCurrent(m_hOldDC, m_hOldRC);

 // 2. Calculate the target size according to the image size,
 //    and orientation of the paper.
 float fBmiRatio =
 float(m_bmi.bmiHeader.biHeight) / m_bmi.bmiHeader.biWidth;

 CSize szTarget;
 if (m_szPage.cx > m_szPage.cy)	 // Landscape page
 {
  if(fBmiRatio<1)	  // Landscape image
  {
   szTarget.cx = m_szPage.cx;
   szTarget.cy = long(fBmiRatio * m_szPage.cx);
  }
  else			  // Portrait image
  {
   szTarget.cx = long(m_szPage.cy/fBmiRatio);
   szTarget.cy = m_szPage.cy;
  }
 }
 else		    // Portrait page
 {
  if(fBmiRatio<1)	  // Landscape image
  {
   szTarget.cx = m_szPage.cx;
   szTarget.cy = long(fBmiRatio * m_szPage.cx);
  }
  else			  // Portrait image
  {
   szTarget.cx = long(m_szPage.cy/fBmiRatio);
   szTarget.cy = m_szPage.cy;
  }
 }

 CSize szOffset((m_szPage.cx - szTarget.cx) / 2,
                (m_szPage.cy - szTarget.cy) / 2);

 // 3. Stretch image to fit in the target size.
 int nRet = ::StretchDIBits(pDC->GetSafeHdc(),
                            szOffset.cx, szOffset.cy,
                            szTarget.cx, szTarget.cy,
                            0, 0,
                            m_bmi.bmiHeader.biWidth,
                            m_bmi.bmiHeader.biHeight,
                            GLubyte*) m_pBitmapBits,
                            m_bmi,
                            DIB_RGB_COLORS,
                            SRCCOPY);

 if(nRet == GDI_ERROR)
  TRACE0("Failed in StretchDIBits()");

 // 4. Release memory.
 DeleteObject(m_hDib);
 m_hDib = NULL;
 DeleteDC(m_hMemDC);
 m_hMemDC = NULL;
 m_hOldDC = NULL;
}

Notice

This demo requires at least 16 bit colors. If your computer displays blank in print preview, check out the color setting in the Control Panel.

Not all video cards work well with OpenGL. When you involve any problem, try with machines with different video chards.

Downloads

Download source - 37 Kb

posted on 2006-01-25 00:25 zmj 閱讀(2664) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲专区免费| 久久精品日韩| 国产色综合久久| 欧美伦理视频网站| 亚洲——在线| 久久亚洲精品一区| 在线观看三级视频欧美| 欧美精品久久天天躁| 午夜一区二区三区不卡视频| 亚洲黄色成人网| 久久性天堂网| 午夜精品在线观看| 99亚洲视频| 亚洲国产合集| 国产日韩综合| 国产精品成人一区二区艾草| 欧美ed2k| 久久综合色8888| 亚洲欧美日韩精品久久亚洲区| 亚洲欧洲在线观看| 欧美成人在线免费视频| 久久精品在线| 亚洲女女做受ⅹxx高潮| 欧美日韩ab| 午夜亚洲伦理| 亚洲高清免费| 欧美在线一二三四区| 国语自产精品视频在线看| 国产日韩av一区二区| 国产精品免费看片| 国产精品麻豆欧美日韩ww | 欧美不卡视频一区发布| 亚洲欧美精品在线| 亚洲视频自拍偷拍| av成人免费在线观看| 夜夜狂射影院欧美极品| 一区二区三区精密机械公司| 欧美一级专区| 久久亚洲一区| 久久国产精品久久久久久| 午夜精品美女自拍福到在线| 羞羞答答国产精品www一本 | 亚洲高清久久久| 欧美高清视频在线观看| 欧美电影在线免费观看网站 | 欧美一区二区三区在线| 亚洲欧美怡红院| 午夜日韩在线观看| 欧美一区免费视频| 久久夜色精品国产| 亚洲黄一区二区| 中文av一区二区| 欧美一区二区成人6969| 久久亚洲精品一区| 欧美激情视频网站| 久久久www免费人成黑人精品 | 91久久精品日日躁夜夜躁国产| 亚洲国产精品日韩| 亚洲一二三区精品| 久久夜精品va视频免费观看| 亚洲国产精品t66y| 中文一区字幕| 久久久亚洲人| 国产精品蜜臀在线观看| 亚洲国产视频a| 亚洲一区二区在线看| 麻豆精品在线观看| 一区二区三区高清视频在线观看| 欧美亚洲免费电影| 欧美日韩一级大片网址| 好男人免费精品视频| 在线视频亚洲欧美| 免费成人小视频| 一区二区三区久久久| 久久综合网络一区二区| 国产精品一区二区黑丝| 欧美色播在线播放| 极品日韩av| 影音国产精品| 亚洲国产精品国自产拍av秋霞| 黄色精品一区| 中文网丁香综合网| 亚洲午夜伦理| 亚洲欧美日韩国产一区二区三区 | 亚洲国产精品t66y| 激情欧美亚洲| 国产精品午夜av在线| 激情六月婷婷久久| 亚洲永久免费观看| 亚洲成人在线视频网站| 久久尤物视频| 亚洲欧美日韩视频一区| 欧美日韩色综合| 亚洲人成在线免费观看| 麻豆久久婷婷| 欧美一级一区| 国产午夜精品麻豆| 亚洲欧美三级在线| 一二三区精品福利视频| 欧美日韩国语| 99精品国产在热久久| 欧美大片在线看免费观看| 久久久999| 国产一区二区三区成人欧美日韩在线观看 | 久久国内精品自在自线400部| 国产麻豆精品theporn| 亚洲综合日韩在线| 亚洲尤物影院| 国产精品有限公司| 久久riav二区三区| 久久av免费一区| 在线观看欧美成人| 欧美高清一区| 欧美日韩国产一区二区三区| 日韩系列在线| 亚洲人成在线观看| 国产精品久久久久秋霞鲁丝 | 欧美激情第4页| 欧美激情女人20p| 99在线精品观看| 亚洲天堂av图片| 国产视频在线观看一区二区三区| 久久久久国色av免费看影院 | 亚洲素人在线| 国语自产精品视频在线看| 欧美不卡视频| 国产精品二区在线观看| 久久精品亚洲一区二区三区浴池| 久久爱www久久做| 亚洲另类黄色| 亚洲午夜精品国产| 极品尤物av久久免费看| 亚洲高清色综合| 欧美性猛片xxxx免费看久爱| 久久久久久久久久久成人| 欧美黄色网络| 欧美一区二区国产| 欧美成人精品一区二区三区| 欧美国产日韩在线观看| 99视频在线精品国自产拍免费观看 | 国产精品99久久久久久白浆小说| 亚洲深夜福利| 一区二区三区在线免费观看| 亚洲精品日产精品乱码不卡| 国产精品亚洲综合天堂夜夜| 蜜臀av一级做a爰片久久| 欧美日韩情趣电影| 久久综合网hezyo| 欧美日韩亚洲不卡| 欧美aa国产视频| 国产精品高清免费在线观看| 美女视频一区免费观看| 国产精品国码视频| 欧美高清在线视频| 欧美人牲a欧美精品| 亚洲黄色免费网站| 亚洲砖区区免费| 国产精品热久久久久夜色精品三区| 一区二区欧美视频| 久久久久国产一区二区三区四区 | 久久一区二区三区四区| 欧美喷水视频| 久久久福利视频| 欧美性色综合| 亚洲高清成人| 久久精品国产99国产精品澳门| 国产喷白浆一区二区三区| 亚洲福利电影| 免费日本视频一区| 久久综合五月天婷婷伊人| 国产精品日本精品| 亚洲视频在线播放| 亚洲私人影吧| 欧美性生交xxxxx久久久| 亚洲精品黄网在线观看| 亚洲精品日韩在线观看| 久久av资源网| 免费不卡在线观看av| 国产欧美视频一区二区三区| 亚洲一区二区欧美日韩| 亚洲午夜日本在线观看| 欧美视频一区二区三区| 亚洲最新合集| 亚洲一区二区三区四区中文 | 午夜免费在线观看精品视频| 亚洲国产欧美一区二区三区丁香婷| 欧美午夜电影网| 麻豆精品一区二区av白丝在线| 亚洲一区二区三区乱码aⅴ| 亚洲电影免费观看高清| 欧美亚洲在线视频| 夜夜嗨av一区二区三区中文字幕| 国产日产欧产精品推荐色 | 激情综合视频| 国产精品国产三级国产普通话99| 久久夜色精品国产欧美乱| 午夜久久久久| 亚洲一二三四区| 日韩亚洲欧美一区二区三区|