ADN Open CIS
Сообщество программистов Autodesk в СНГ

17/11/2015

Встраивание изображения в чертеж - 2

В этом статье мы рассмотрим создание пользовательского объекта, унаследованного от класса AcDbRasterImageDef, который сохраняет/загружает растровые данные в/из рисунка при помощи ATIL. Это гарантирует независимость чертежа от внешнего файла изображения и данные будут доступны если будет загружен ваш arx-файл в AutoCAD.

Другие способы встраивания растра в чертеж без зависимости от внешнего растрового файла описаны в этой статье:

Встраивание изображения в чертеж

Код - C++: [Выделить]
  1. // AcDbMyRasterImageDef.h
  2.  class  DLLIMPEXP AcDbMyRasterImageDef :
  3.         public  AcDbRasterImageDef
  4.  {
  5.  protected :
  6.         static  Adesk::UInt32 kCurrentVersionNumber;
  7.  
  8.  public :
  9.  
  10.         ACRX_DECLARE_MEMBERS(AcDbMyRasterImageDef) ;
  11.        
  12.         AcDbMyRasterImageDef () ;
  13.         virtual  ~AcDbMyRasterImageDef () ;
  14.  
  15.         virtual  Acad::ErrorStatus
  16.                dwgOutFields (AcDbDwgFiler *pFiler) const  ;
  17.  
  18.         virtual  Acad::ErrorStatus dwgInFields
  19.                (AcDbDwgFiler *pFiler) ;
  20.  
  21.         //----- deepClone
  22.         virtual  Acad::ErrorStatus
  23.                subDeepClone (AcDbObject *pOwnerObject,
  24.                AcDbObject *&pClonedObject, AcDbIdMapping &idMap,
  25.                Adesk::Boolean isPrimary =true ) const  ;
  26.  
  27.         //----- wblockClone
  28.         virtual  Acad::ErrorStatus subWblockClone
  29.                (AcRxObject *pOwnerObject, AcDbObject *&pClonedObject,
  30.                AcDbIdMapping &idMap, Adesk::Boolean isPrimary =true )
  31.                const  ;
  32.     
  33.         Acad::ErrorStatus
  34.                setEmbeddedImage(const  ACHAR* imageFilePath);
  35.  
  36.  private :
  37.         void  *operator  new [](size_t) throw (){ return  (void *)0;}
  38.      void  operator  delete [](void  *) {};
  39.      void  *operator  new [](size_t , const  char  *, int  ) throw ()
  40.         { return  (void *)0;}
  41.  
  42.         Atil::Image *m_pAtilImage;
  43.  };
  44.  
  45.  
  46.  // AcDbMyRasterImageDef.cpp
  47.  AcDbMyRasterImageDef::AcDbMyRasterImageDef ()
  48.         : AcDbRasterImageDef ()
  49.  {
  50.         m_pAtilImage = NULL;
  51.  }
  52.  
  53.  AcDbMyRasterImageDef::~AcDbMyRasterImageDef()
  54.  {
  55.         if (m_pAtilImage != NULL)
  56.         {
  57.                delete  m_pAtilImage;
  58.                m_pAtilImage = NULL;
  59.         }
  60.  }
  61.  
  62.  Acad::ErrorStatus AcDbMyRasterImageDef::dwgOutFields
  63.         (AcDbDwgFiler *pFiler) const  {
  64.         assertReadEnabled () ;
  65.         //----- Сначала сохраняем информацию родительского класса.
  66.         Acad::ErrorStatus es =
  67.                AcDbRasterImageDef::dwgOutFields (pFiler) ;
  68.         if  ( es != Acad::eOk )
  69.                return  (es) ;
  70.         //----- Теперь сохраним версию объекта
  71.         if  ( (es =pFiler->writeUInt32
  72.                (AcDbMyRasterImageDef::kCurrentVersionNumber))
  73.                != Acad::eOk )
  74.                return  (es) ;
  75.  
  76.         if (m_pAtilImage)
  77.         {
  78.                Atil::Size size = m_pAtilImage->size();
  79.                Int32 width = size.width;
  80.                Int32 height = size.height;
  81.  
  82.                pFiler->writeInt32(width);
  83.                pFiler->writeInt32(height);
  84.  
  85.                // Считываем данные растра из Atil изображения
  86.                // при помощи контекста изображения
  87.                Atil::Offset upperLeft(0,0);
  88.                Atil::ImageContext *pImgContext
  89.                        = m_pAtilImage->createContext(
  90.                                Atil::ImageContext::kRead,
  91.                                size,
  92.                                upperLeft);
  93.  
  94.                if  (pImgContext != NULL)
  95.                {
  96.                        for  (int  xf=0;xf<width;xf++)
  97.                        {
  98.                                for  (int  yf=0;yf<height;yf++)
  99.                                {
  100.                                       Atil::RgbColor p;
  101.                                       p = pImgContext->get32(xf, yf);
  102.                                       pFiler->writeInt32(p.packed);
  103.                                }
  104.                        }
  105.  
  106.                }
  107.                pImgContext->flush();
  108.                delete  pImgContext;
  109.         }
  110.  
  111.         return  (pFiler->filerStatus ()) ;
  112.  }
  113.  
  114.  Acad::ErrorStatus AcDbMyRasterImageDef::dwgInFields
  115.         (AcDbDwgFiler *pFiler)
  116.  {
  117.         assertWriteEnabled () ;
  118.         Acad::ErrorStatus es =
  119.                AcDbRasterImageDef::dwgInFields (pFiler) ;
  120.         if  ( es != Acad::eOk )
  121.                return  (es) ;
  122.        
  123.         Adesk::UInt32 version =0 ;
  124.         if  ( (es =pFiler->readUInt32 (&version))
  125.                != Acad::eOk )
  126.                return  (es) ;
  127.         if  ( version >
  128.                AcDbMyRasterImageDef::kCurrentVersionNumber)
  129.                return  (Acad::eMakeMeProxy) ;
  130.  
  131.         Int32 width = 0;
  132.         Int32 height = 0;
  133.  
  134.         pFiler->readInt32(&width);
  135.         pFiler->readInt32(&height);
  136.  
  137.         // Создаём Atil::Image.
  138.      // Он требуется для AcDbRasterImageDef::setImage
  139.      Atil::ImagePixel initialImage;
  140.      initialImage.setToZero();
  141.      initialImage.type
  142.                = Atil::DataModelAttributes::kBgra;
  143.      initialImage.value.rgba = 0xff000000;
  144.  
  145.      Atil::Size size(width, height);
  146.      const  Atil::RgbModel *pDm
  147.                = new  Atil::RgbModel(
  148.          Atil::RgbModelAttributes::k4Channels,
  149.          Atil::DataModelAttributes::kBlueGreenRedAlpha);
  150.  
  151.         if (m_pAtilImage != NULL)
  152.         {
  153.                delete  m_pAtilImage;
  154.                m_pAtilImage = NULL;
  155.         }
  156.      m_pAtilImage
  157.                = new  Atil::Image(size, pDm, initialImage);
  158.  
  159.         // Записываем данные растра в Atil изображение
  160.         // при помощи контекста изображения
  161.         Atil::Offset upperLeft(0,0);
  162.         Atil::ImageContext *pImgContext
  163.                = m_pAtilImage->createContext(
  164.                                Atil::ImageContext::kWrite,
  165.                                size,
  166.                                upperLeft);
  167.         if  (pImgContext != NULL)
  168.         {
  169.                for  (int  xf=0;xf<width;xf++)
  170.                {
  171.                        for  (int  yf=0;yf<height;yf++)
  172.                        {
  173.                                Int32 value;
  174.                                pFiler->readInt32(&value);
  175.                                pImgContext->put32(xf, yf, value);
  176.                        }
  177.                }
  178.         }
  179.         pImgContext->flush();
  180.         delete  pImgContext;
  181.  
  182.         setImage (m_pAtilImage, NULL) ;
  183.  
  184.         return  (pFiler->filerStatus ()) ;
  185.  }
  186.  
  187.  //----- deepClone
  188.  Acad::ErrorStatus AcDbMyRasterImageDef::subDeepClone
  189.         (AcDbObject *pOwnerObject, AcDbObject *&pClonedObject,
  190.         AcDbIdMapping &idMap, Adesk::Boolean isPrimary) const 
  191.  {
  192.         assertReadEnabled () ;
  193.         return  (AcDbRasterImageDef::subDeepClone
  194.                (pOwnerObject, pClonedObject, idMap, isPrimary)) ;
  195.  }
  196.  
  197.  //----- wblockClone
  198.  Acad::ErrorStatus AcDbMyRasterImageDef::subWblockClone
  199.         (AcRxObject *pOwnerObject, AcDbObject *&pClonedObject,
  200.         AcDbIdMapping &idMap, Adesk::Boolean isPrimary) const 
  201.  {
  202.         assertReadEnabled () ;
  203.         return  (AcDbRasterImageDef::subWblockClone
  204.                (pOwnerObject, pClonedObject, idMap, isPrimary)) ;
  205.  }
  206.  
  207.  Acad::ErrorStatus  AcDbMyRasterImageDef::setEmbeddedImage
  208.                                                      (const  ACHAR* imageFilePath)
  209.  {
  210.      AcString imagePath(imageFilePath);
  211.  
  212.      AcTcImage tc;
  213.      tc.Load(imagePath);
  214.  
  215.      HBITMAP bmp=0;
  216.      tc.GetHBITMAP(RGB(0xff,0xff,0xff),bmp);
  217.  
  218.      if  (bmp == NULL)
  219.                return  Acad::eFileNotFound;
  220.  
  221.      BITMAP _bmp={0};
  222.      GetObject(bmp,sizeof  BITMAP,&_bmp);
  223.  
  224.      HDC hdcScr=GetDC(NULL);
  225.      HDC    hdcMem=CreateCompatibleDC(hdcScr);
  226.      SelectObject(hdcMem,bmp);
  227.  
  228.      Atil::ImagePixel initialImage;
  229.      initialImage.setToZero();
  230.         initialImage.type = Atil::DataModelAttributes::kBgra;
  231.      initialImage.value.rgba = 0xff000000;
  232.  
  233.      Atil::Size size(_bmp.bmWidth, _bmp.bmHeight);
  234.      const  Atil::RgbModel *pDm = new  Atil::RgbModel(
  235.          Atil::RgbModelAttributes::k4Channels,
  236.          Atil::DataModelAttributes::kBlueGreenRedAlpha);
  237.  
  238.         if (m_pAtilImage != NULL)
  239.         {
  240.                delete  m_pAtilImage;
  241.                m_pAtilImage = NULL;
  242.         }
  243.      m_pAtilImage
  244.                = new  Atil::Image(size, pDm, initialImage);
  245.  
  246.      Atil::Offset upperLeft(0,0);
  247.      Atil::ImageContext *pImgContext
  248.          = m_pAtilImage->createContext(
  249.                      Atil::ImageContext::kWrite,
  250.                      size,
  251.                      upperLeft);
  252.      if  (pImgContext != NULL)
  253.      {
  254.          for  (int  xf=0;xf<_bmp.bmWidth;xf++)
  255.          {
  256.              for  (int  yf=0;yf<_bmp.bmHeight;yf++)
  257.              {
  258.                  BYTE alpha= 0xff;
  259.                  COLORREF pix=GetPixel(hdcMem,xf,yf);
  260.  
  261.                  BYTE rr = (pix&0xff);
  262.                  BYTE gg = (pix>>8)&0xff;
  263.                  BYTE bb = (pix>>16)&0xff;
  264.  
  265.                  Atil::RgbColor p;
  266.                  p.set(rr, gg, bb, alpha);
  267.                  pImgContext->put32(xf, yf, p);
  268.              }
  269.          }
  270.      }
  271.      pImgContext->flush();
  272.      delete  pImgContext;
  273.  
  274.      bool  isImageValid = m_pAtilImage->isValid();
  275.      assert(isImageValid);
  276.  
  277.      // Очищаем
  278.      DeleteDC(hdcMem);
  279.      ReleaseDC(NULL,hdcScr);
  280.  
  281.      DeleteObject( bmp);
  282.  
  283.         return  setImage (m_pAtilImage, NULL) ;
  284.  }
  285.  
  286.  // Команда внедрения растра
  287.  static  void  AdskMyTestEmbedImage(void )
  288.  {
  289.         AcDbMyRasterImageDef *pImageDef
  290.                = new  AcDbMyRasterImageDef();
  291.         pImageDef->setEmbeddedImage(
  292.                ACRX_T("D:\\TestFiles\\MyTexture.jpg" ));
  293.         Acad::ErrorStatus es
  294.                = InsertImageInDwg(pImageDef);
  295.         if (es != Acad::eOk)
  296.         {
  297.                delete  pImageDef;
  298.                return ;
  299.         }
  300.  }
  301.  
  302.  static  Acad::ErrorStatus
  303.         InsertImageInDwg(AcDbRasterImageDef *pImageDef)
  304.  {
  305.         Acad::ErrorStatus es;
  306.         if (! pImageDef->isLoaded())
  307.         {
  308.                es = pImageDef->load();
  309.                if (es != Acad::eOk)
  310.                        return  es;
  311.         }
  312.  
  313.         AcApDocument *pActiveDoc
  314.                = acDocManager->mdiActiveDocument();
  315.         AcDbDatabase *pDB = pActiveDoc->database();
  316.  
  317.         // Получаем словарь растров, а если его еще нет -
  318.         // создаём его
  319.         AcDbObjectId dictID
  320.         = AcDbRasterImageDef::imageDictionary(pDB);
  321.  
  322.         if (dictID == AcDbObjectId::kNull)
  323.         {
  324.                es = AcDbRasterImageDef::createImageDictionary
  325.                        (pDB, dictID);
  326.  
  327.                if (es != Acad::eOk)
  328.                        return  es;
  329.         }
  330.  
  331.         AcDbDictionary* pDict;
  332.         es = acdbOpenObject(pDict, dictID, AcDb::kForWrite);
  333.         if (es != Acad::eOk)
  334.                        return  es;
  335.  
  336.         ACHAR *DICT_NAME = ACRX_T("RASTER_USING_BUFFER" );
  337.         BOOL bExist = pDict->has(DICT_NAME);
  338.         AcDbObjectId objID = AcDbObjectId::kNull;
  339.         if  (!bExist)
  340.         {
  341.                es = pDict->setAt(DICT_NAME, pImageDef, objID);
  342.                if (es != Acad::eOk)
  343.                {
  344.                        pDict->close();
  345.                        return  es;
  346.                }
  347.         }
  348.         else
  349.         {
  350.                pDict->getAt(DICT_NAME,
  351.                                       (AcDbObject*&)pImageDef,
  352.                                       AcDb::kForWrite);
  353.                objID = pImageDef->objectId();
  354.         }
  355.  
  356.         // Закрываем словарь и определение.
  357.         pDict->close();
  358.         pImageDef->close();
  359.  
  360.         // Создаём растр, используя RasterImage Def
  361.         AcDbRasterImage* pImage = new  AcDbRasterImage;
  362.         es = pImage->setImageDefId(objID);
  363.         if  (es != Acad::eOk)
  364.         {
  365.                delete  pImage;
  366.                return  es;
  367.         }
  368.  
  369.         // Добавляем растр в Пространство Модели
  370.         AcDbBlockTable* pBlockTable;
  371.         AcDbBlockTableRecord* pBTRecord;
  372.         es = acdbCurDwg()->getBlockTable(pBlockTable,
  373.                                                      AcDb::kForRead);
  374.         assert(es == Acad::eOk);
  375.         es = pBlockTable->getAt(ACDB_MODEL_SPACE,
  376.                                                      pBTRecord,
  377.                                                      AcDb::kForWrite);
  378.         assert(es == Acad::eOk);
  379.  
  380.         es = pBTRecord->appendAcDbEntity(pImage);
  381.         assert(es == Acad::eOk);
  382.  
  383.         pBTRecord->close();
  384.         pBlockTable->close();
  385.  
  386.         AcDbObjectId entID = pImage->objectId();
  387.  
  388.         AcDbObjectPointer<AcDbRasterImageDefReactor>
  389.                                               rasterImageDefReactor;
  390.         rasterImageDefReactor.create();
  391.  
  392.         es = rasterImageDefReactor->setOwnerId(
  393.                                                      pImage->objectId());
  394.         if  (es == Acad::eOk)
  395.         {
  396.                AcDbObjectId defReactorId;
  397.                es = curDoc()->database()->addAcDbObject(
  398.                                defReactorId,
  399.                                rasterImageDefReactor.object());
  400.  
  401.                if  (es == Acad::eOk)
  402.                {
  403.                        pImage->setReactorId(defReactorId);
  404.                        AcDbObjectPointer<AcDbRasterImageDef>
  405.                                rasterImagedef
  406.                                (pImage->imageDefId(), AcDb::kForWrite);
  407.                        if  (rasterImagedef.openStatus() == Acad::eOk)
  408.                        {
  409.                                rasterImagedef->addPersistentReactor
  410.                                               (defReactorId);
  411.                               
  412.                        }
  413.                }
  414.         }
  415.  
  416.         pImageDef->close();
  417.         pImage->close();
  418.  
  419.         return  Acad::eOk;
  420.  }
  421.  
  422.  virtual  AcRx::AppRetCode On_kInitAppMsg (void  *pkt)
  423.  {
  424.         AcRx::AppRetCode retCode =
  425.                AcRxArxApp::On_kInitAppMsg (pkt) ;
  426.         acrxDynamicLinker->loadModule
  427.                (L"acismobj20.dbx" ,true );
  428.         AcDbMyRasterImageDef::rxInit();
  429.         acrxBuildClassHierarchy();
  430.         return  (retCode) ;
  431.  }

 

Проект с примером можно загрузить отсюда:

Загрузить EmbedImage

Если вы ищете, как создать встроенное растровое изображение с помощью  AutoCAD .Net API – необходимо создать управляемую оболочку для пользовательского объекта, который мы создали. Чистого .NET решения для этой задачи в настоящее время нет, так как пользовательские объекты могут быть созданы только с помощью C++. Кроме того, Atil является C ++ библиотекой, которая используется в примере.

Пример использования .NET обертки показан в следующем примере. Чтобы попробовать этот пример, загрузите командой APPLOAD arx-файл и командой NETLOAD управляемую оболочку и пользовательский модуль .Net. Выполните команду "EmbedImageMgd".

Загрузить CustomRasterImageDef

 

Источник: http://adndevblog.typepad.com/autocad/2015/04/embedding-an-image-in-a-drawing.html

 

Автор перевода: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=3211

Опубликовано 17.11.2015
Отредактировано 18.11.2015 в 00:36:14