how to dump a picture (png or jpg) without vizualizing the situation first

David

Active CAD practitioner
I am using OpenCasade to without vizualization in my app. But I need to present to the user of my app a picture (e.g. png or jpg) of a geometrical situation calculated with OpenCascade. What approach is here recommended? I can write a step file but is there a simple way to create something more fancy (shading, transparent, color, camera position,...) ?
 

Quaoar

Administrator
Staff member
Hey @David, sounds like you're needing offscreen rendering. I wouldn't say it's fancy, but it works for us for generating preview images:

C++:
Handle(Image_AlienPixMap)
  Utils::Graphics::GeneratePixmap(const TopoDS_Shape& shape,
                                  const int           width,
                                  const int           height)
{
  Handle(Aspect_DisplayConnection)
    _displayConnection = new Aspect_DisplayConnection();

  // don't waste the time waiting for VSync when window is not displayed on the screen
  OpenGl_Caps _caps;
  _caps.buffersNoSwap = true;

  Handle(OpenGl_GraphicDriver)
    _graphicDriver = new OpenGl_GraphicDriver(_displayConnection, false);
  //
  _graphicDriver->ChangeOptions() = _caps;
  _graphicDriver->InitContext();

  //* Viewer setup
  Handle(V3d_Viewer) _viewer = new V3d_Viewer(_graphicDriver);
  Quantity_Color bgColor(255./255, 255./255, 255./255, Quantity_TOC_RGB);
  _viewer->SetDefaultBackgroundColor(bgColor);
  _viewer->SetDefaultLights();
  _viewer->SetLightOn();

  Handle(V3d_View)
    _view = new V3d_View(_viewer, _viewer->DefaultTypeOfView());

#ifdef _WIN32
  /* Window - create a so called "virtual" WNT window that is a pure WNT window
     redefined to be never shown. */
  Handle(WNT_WClass) _wClass = new WNT_WClass("GW3D_Class", (void*) DefWindowProcW,
    CS_VREDRAW | CS_HREDRAW, 0, 0,
    ::LoadCursor(NULL, IDC_ARROW));

  Handle(WNT_Window) _win = new WNT_Window("",
    _wClass,
    WS_POPUP,
    0, 0,
    width, height,
    Quantity_NOC_BLACK);

  _win->SetVirtual(true);
  _view->SetWindow(_win);

#else // Linux
  Handle(Xw_Window) _win = new Xw_Window(_graphicDriver->GetDisplayConnection(),
                                         "",
                                         0, 0,
                                         width, height);
  _win->SetVirtual(true);
  _view->SetWindow(_win);
#endif

  //* View setup
  _view->SetWindow(_win);
  _view->SetComputedMode(false);
  _view->SetProj(V3d_XposYnegZpos);
  _view->AutoZFit();

  //* AIS context
  Handle(AIS_InteractiveContext) _context = new AIS_InteractiveContext(_viewer);
  _context->SetDisplayMode(AIS_Shaded, false);
  _context->DefaultDrawer()->SetFaceBoundaryDraw(true);

  // Render immediate structures into back buffer rather than front.
  _view->View()->SetImmediateModeDrawToFront(false);

  //* Dump
  Handle(Image_AlienPixMap) pixmap = new Image_AlienPixMap;
  Quantity_Color _shapeColor(200./255, 200./255, 200./255, Quantity_TOC_RGB);

  Handle(AIS_Shape) _shapePrs = new AIS_Shape(shape);
  _shapePrs->SetColor(_shapeColor);
  _context->Display(_shapePrs, false);
  _view->FitAll(0.1, true);

  bool isOk = _view->ToPixMap(*pixmap, width, height);

  return isOk ? pixmap : nullptr;
}

Then, for Image_AlienPixMap you can call its Save() method. If you built OpenCascade with freeimage 3-rd party enabled, it would generate a PNG image for you. If you're not satisfied with the quality (and you won't be, I promise), consider generating the image with higher dimensions of the viewport and then scaling it down.
 

natalia

Moderator
Staff member
Hi @David, @Quaoar. It's also possible using Aspect_NeutralWindow inside the similar method implementation. It uses visualization engine of OCCT for offscreen rendering:

#include <BRepPrimAPI_MakeCone.hxx> #include <AIS_InteractiveContext.hxx> #include <AIS_Shape.hxx> #include <AIS_DisplayMode.hxx> #include <Aspect_DisplayConnection.hxx> #include <Aspect_NeutralWindow.hxx> #include <OpenGl_GraphicDriver.hxx> #include <Image_AlienPixMap.hxx> #include <V3d_View.hxx> TopoDS_Shape prepareTestShape() { gp_Ax2 axes(gp::Origin(), gp::DZ()); BRepPrimAPI_MakeCone conMakerIn(axes, 40/*r1*/, 60/*r2*/, 110/*height*/); return conMakerIn.Shape(); } bool dumpShape(const TopoDS_Shape& shape, const Standard_Integer width, const Standard_Integer height, const TCollection_AsciiString& fileName) { // prepare viewer Handle(Aspect_DisplayConnection) displayConnection = new Aspect_DisplayConnection(); Handle(OpenGl_GraphicDriver) graphicDriver = new OpenGl_GraphicDriver(displayConnection); Handle(V3d_Viewer) viewer = new V3d_Viewer(graphicDriver); viewer->SetDefaultLights(); viewer->SetLightOn(); // prepare context Handle(AIS_InteractiveContext) context = new AIS_InteractiveContext(viewer); // prepare off-screen view Handle(V3d_View) view = viewer->CreateView(); Handle(Aspect_NeutralWindow) wnd = new Aspect_NeutralWindow(); wnd->SetSize(width, height); wnd->SetVirtual(true); view->SetWindow(wnd); view->SetBackgroundColor(Quantity_Color(Quantity_NOC_BLACK)); view->MustBeResized(); // prepare presentation filled by shape Handle(AIS_Shape) presentation = new AIS_Shape(shape); context->Display(presentation, Standard_False); context->SetDisplayMode(presentation, AIS_Shaded, Standard_False); view->FitAll(); view->Redraw(); // prepare pixmap image Image_AlienPixMap img; if (!view->ToPixMap(img, width, height)) return false; // save image into a file return img.Save(fileName); } int main(int argc, char **argv) { TopoDS_Shape testShape = prepareTestShape(); dumpShape(testShape, 300, 300, "D:/test.png"); return 0; }

The result is an image in the entered directory:
test.png
 
Last edited:
Top