Extracting Image Files from OdDbOle2Frame Entities

Yuri Moskovsky

August 01, 2017

When trying to extract image files from OLE2 frame entities, OdDbOle2Frame has the getCompoundDocument() method to get the streamBuf, but this is a stream of compound documents and not an image. Usually the OdOleItemHandler module is used to work with compound documents, but this module doesn’t have functionality to extract images and also it uses a WinAPI and is accessible on Microsoft® Windows® only.

Teigha contains an alternative OdOleSsItemHandler module to draw OLE preview images for non-Windows platforms. Functionality of the module is somewhat limited, but it supports the ability to extract image files for external use. This module should be loaded before a loading database. If a database was already loaded, you should reload it again. For example:

exractOleImageFiles(pDb->appServices(), pDb->getFilename());

Some OLE entities contain only WMF previews, for example, entities with Microsoft Excel® content. Teigha does not have the cross-platform ability to draw WMFs, but you can extract WMFs as a file. For example:

void exractOleImageFiles(OdDbHostAppServices* pAppServ,
                         const OdString& sDatabaseFileName)
{
  OdRxModulePtr pModule = odrxDynamicLinker()->loadModule(OdOleSsItemHandlerModuleName);
  if (pModule.isNull())
    throw OdError(L"OdOleSsItemHandler module is missing.");
  OdRxRasterServicesPtr pRasSvcs = odrxDynamicLinker()
                                     ->loadApp(RX_RASTER_SERVICES_APPNAME);
  if (pRasSvcs.isNull())
    throw OdError(L"OdRxRasterServices module is missing");

  OdDbDatabasePtr pDb = pAppServ->readFile(sDatabaseFileName);
  if (pDb.isNull())
    throw OdError(eNoDatabase);

  OdDbBlockTableRecordPtr pSpace = pDb->getActiveLayoutBTRId()
                                          .safeOpenObject(OdDb::kForRead);
  for (OdDbObjectIteratorPtr pItr = pSpace->newIterator(); !pItr->done(); pItr->step())
  {
    OdDbOle2FramePtr pOle2Frame = OdDbOle2Frame::cast(pItr->entity());
    if (pOle2Frame.isNull())
      continue;

    OdOleItemHandlerBasePtr pHandler = pOle2Frame->getItemHandler();
    if (pHandler.isNull())
      continue;
    if (pOle2Frame.isNull())
      continue;
    
    OdString sImageFileName = sDatabaseFileName;
    sImageFileName += L".";
    sImageFileName += pOle2Frame->objectId().getHandle().ascii();

    OdGiRasterImagePtr pImage = pHandler->getRaster();
    if (pImage.get())
    {
      if (pRasSvcs->isRasterImageTypeSupported(OdRxRasterServices::kPNG))
      {
        sImageFileName += L".png";

        OdStreamBufPtr pIO = ::odrxSystemServices()->createFile(sImageFileName,
                                                                Oda::kFileWrite,
                                                                Oda::kShareDenyNo,
                                                                Oda::kCreateAlways);
        if (pIO.get())
          pRasSvcs->convertRasterImage(pImage, OdRxRasterServices::kPNG, pIO);
      }
      continue;
    }

    OdBinaryData data;
    if (pHandler->getWmfData(data))
    {
      sImageFileName += L".wmf";
      OdStreamBufPtr pIO = ::odrxSystemServices()->createFile(sImageFileName,
                               Oda::kFileWrite, Oda::kShareDenyNo, Oda::kCreateAlways);
      if (pIO.get())
        pIO->putBytes(data.asArrayPtr(), data.size());
    }
  }
}