Встраивание изображения в чертеж - 2
В этом статье мы рассмотрим создание пользовательского объекта, унаследованного от класса AcDbRasterImageDef, который сохраняет/загружает растровые данные в/из рисунка при помощи ATIL. Это гарантирует независимость чертежа от внешнего файла изображения и данные будут доступны если будет загружен ваш arx-файл в AutoCAD.Другие способы встраивания растра в чертеж без зависимости от внешнего растрового файла описаны в этой статье:
Встраивание изображения в чертеж
- // AcDbMyRasterImageDef.h
- class DLLIMPEXP AcDbMyRasterImageDef :
- public AcDbRasterImageDef
- {
- protected :
- static Adesk::UInt32 kCurrentVersionNumber;
- public :
- ACRX_DECLARE_MEMBERS(AcDbMyRasterImageDef) ;
- AcDbMyRasterImageDef () ;
- virtual ~AcDbMyRasterImageDef () ;
- virtual Acad::ErrorStatus
- dwgOutFields (AcDbDwgFiler *pFiler) const ;
- virtual Acad::ErrorStatus dwgInFields
- (AcDbDwgFiler *pFiler) ;
- //----- deepClone
- virtual Acad::ErrorStatus
- subDeepClone (AcDbObject *pOwnerObject,
- AcDbObject *&pClonedObject, AcDbIdMapping &idMap,
- Adesk::Boolean isPrimary =true ) const ;
- //----- wblockClone
- virtual Acad::ErrorStatus subWblockClone
- (AcRxObject *pOwnerObject, AcDbObject *&pClonedObject,
- AcDbIdMapping &idMap, Adesk::Boolean isPrimary =true )
- const ;
- Acad::ErrorStatus
- setEmbeddedImage(const ACHAR* imageFilePath);
- private :
- void *operator new [](size_t) throw (){ return (void *)0;}
- void operator delete [](void *) {};
- void *operator new [](size_t , const char *, int ) throw ()
- { return (void *)0;}
- Atil::Image *m_pAtilImage;
- };
- // AcDbMyRasterImageDef.cpp
- AcDbMyRasterImageDef::AcDbMyRasterImageDef ()
- : AcDbRasterImageDef ()
- {
- m_pAtilImage = NULL;
- }
- AcDbMyRasterImageDef::~AcDbMyRasterImageDef()
- {
- if (m_pAtilImage != NULL)
- {
- delete m_pAtilImage;
- m_pAtilImage = NULL;
- }
- }
- Acad::ErrorStatus AcDbMyRasterImageDef::dwgOutFields
- (AcDbDwgFiler *pFiler) const {
- assertReadEnabled () ;
- //----- Сначала сохраняем информацию родительского класса.
- Acad::ErrorStatus es =
- AcDbRasterImageDef::dwgOutFields (pFiler) ;
- if ( es != Acad::eOk )
- return (es) ;
- //----- Теперь сохраним версию объекта
- if ( (es =pFiler->writeUInt32
- (AcDbMyRasterImageDef::kCurrentVersionNumber))
- != Acad::eOk )
- return (es) ;
- if (m_pAtilImage)
- {
- Atil::Size size = m_pAtilImage->size();
- Int32 width = size.width;
- Int32 height = size.height;
- pFiler->writeInt32(width);
- pFiler->writeInt32(height);
- // Считываем данные растра из Atil изображения
- // при помощи контекста изображения
- Atil::Offset upperLeft(0,0);
- Atil::ImageContext *pImgContext
- = m_pAtilImage->createContext(
- Atil::ImageContext::kRead,
- size,
- upperLeft);
- if (pImgContext != NULL)
- {
- for (int xf=0;xf<width;xf++)
- {
- for (int yf=0;yf<height;yf++)
- {
- Atil::RgbColor p;
- p = pImgContext->get32(xf, yf);
- pFiler->writeInt32(p.packed);
- }
- }
- }
- pImgContext->flush();
- delete pImgContext;
- }
- return (pFiler->filerStatus ()) ;
- }
- Acad::ErrorStatus AcDbMyRasterImageDef::dwgInFields
- (AcDbDwgFiler *pFiler)
- {
- assertWriteEnabled () ;
- Acad::ErrorStatus es =
- AcDbRasterImageDef::dwgInFields (pFiler) ;
- if ( es != Acad::eOk )
- return (es) ;
- Adesk::UInt32 version =0 ;
- if ( (es =pFiler->readUInt32 (&version))
- != Acad::eOk )
- return (es) ;
- if ( version >
- AcDbMyRasterImageDef::kCurrentVersionNumber)
- return (Acad::eMakeMeProxy) ;
- Int32 width = 0;
- Int32 height = 0;
- pFiler->readInt32(&width);
- pFiler->readInt32(&height);
- // Создаём Atil::Image.
- // Он требуется для AcDbRasterImageDef::setImage
- Atil::ImagePixel initialImage;
- initialImage.setToZero();
- initialImage.type
- = Atil::DataModelAttributes::kBgra;
- initialImage.value.rgba = 0xff000000;
- Atil::Size size(width, height);
- const Atil::RgbModel *pDm
- = new Atil::RgbModel(
- Atil::RgbModelAttributes::k4Channels,
- Atil::DataModelAttributes::kBlueGreenRedAlpha);
- if (m_pAtilImage != NULL)
- {
- delete m_pAtilImage;
- m_pAtilImage = NULL;
- }
- m_pAtilImage
- = new Atil::Image(size, pDm, initialImage);
- // Записываем данные растра в Atil изображение
- // при помощи контекста изображения
- Atil::Offset upperLeft(0,0);
- Atil::ImageContext *pImgContext
- = m_pAtilImage->createContext(
- Atil::ImageContext::kWrite,
- size,
- upperLeft);
- if (pImgContext != NULL)
- {
- for (int xf=0;xf<width;xf++)
- {
- for (int yf=0;yf<height;yf++)
- {
- Int32 value;
- pFiler->readInt32(&value);
- pImgContext->put32(xf, yf, value);
- }
- }
- }
- pImgContext->flush();
- delete pImgContext;
- setImage (m_pAtilImage, NULL) ;
- return (pFiler->filerStatus ()) ;
- }
- //----- deepClone
- Acad::ErrorStatus AcDbMyRasterImageDef::subDeepClone
- (AcDbObject *pOwnerObject, AcDbObject *&pClonedObject,
- AcDbIdMapping &idMap, Adesk::Boolean isPrimary) const
- {
- assertReadEnabled () ;
- return (AcDbRasterImageDef::subDeepClone
- (pOwnerObject, pClonedObject, idMap, isPrimary)) ;
- }
- //----- wblockClone
- Acad::ErrorStatus AcDbMyRasterImageDef::subWblockClone
- (AcRxObject *pOwnerObject, AcDbObject *&pClonedObject,
- AcDbIdMapping &idMap, Adesk::Boolean isPrimary) const
- {
- assertReadEnabled () ;
- return (AcDbRasterImageDef::subWblockClone
- (pOwnerObject, pClonedObject, idMap, isPrimary)) ;
- }
- Acad::ErrorStatus AcDbMyRasterImageDef::setEmbeddedImage
- (const ACHAR* imageFilePath)
- {
- AcString imagePath(imageFilePath);
- AcTcImage tc;
- tc.Load(imagePath);
- HBITMAP bmp=0;
- tc.GetHBITMAP(RGB(0xff,0xff,0xff),bmp);
- if (bmp == NULL)
- return Acad::eFileNotFound;
- BITMAP _bmp={0};
- GetObject(bmp,sizeof BITMAP,&_bmp);
- HDC hdcScr=GetDC(NULL);
- HDC hdcMem=CreateCompatibleDC(hdcScr);
- SelectObject(hdcMem,bmp);
- Atil::ImagePixel initialImage;
- initialImage.setToZero();
- initialImage.type = Atil::DataModelAttributes::kBgra;
- initialImage.value.rgba = 0xff000000;
- Atil::Size size(_bmp.bmWidth, _bmp.bmHeight);
- const Atil::RgbModel *pDm = new Atil::RgbModel(
- Atil::RgbModelAttributes::k4Channels,
- Atil::DataModelAttributes::kBlueGreenRedAlpha);
- if (m_pAtilImage != NULL)
- {
- delete m_pAtilImage;
- m_pAtilImage = NULL;
- }
- m_pAtilImage
- = new Atil::Image(size, pDm, initialImage);
- Atil::Offset upperLeft(0,0);
- Atil::ImageContext *pImgContext
- = m_pAtilImage->createContext(
- Atil::ImageContext::kWrite,
- size,
- upperLeft);
- if (pImgContext != NULL)
- {
- for (int xf=0;xf<_bmp.bmWidth;xf++)
- {
- for (int yf=0;yf<_bmp.bmHeight;yf++)
- {
- BYTE alpha= 0xff;
- COLORREF pix=GetPixel(hdcMem,xf,yf);
- BYTE rr = (pix&0xff);
- BYTE gg = (pix>>8)&0xff;
- BYTE bb = (pix>>16)&0xff;
- Atil::RgbColor p;
- p.set(rr, gg, bb, alpha);
- pImgContext->put32(xf, yf, p);
- }
- }
- }
- pImgContext->flush();
- delete pImgContext;
- bool isImageValid = m_pAtilImage->isValid();
- assert(isImageValid);
- // Очищаем
- DeleteDC(hdcMem);
- ReleaseDC(NULL,hdcScr);
- DeleteObject( bmp);
- return setImage (m_pAtilImage, NULL) ;
- }
- // Команда внедрения растра
- static void AdskMyTestEmbedImage(void )
- {
- AcDbMyRasterImageDef *pImageDef
- = new AcDbMyRasterImageDef();
- pImageDef->setEmbeddedImage(
- ACRX_T("D:\\TestFiles\\MyTexture.jpg" ));
- Acad::ErrorStatus es
- = InsertImageInDwg(pImageDef);
- if (es != Acad::eOk)
- {
- delete pImageDef;
- return ;
- }
- }
- static Acad::ErrorStatus
- InsertImageInDwg(AcDbRasterImageDef *pImageDef)
- {
- Acad::ErrorStatus es;
- if (! pImageDef->isLoaded())
- {
- es = pImageDef->load();
- if (es != Acad::eOk)
- return es;
- }
- AcApDocument *pActiveDoc
- = acDocManager->mdiActiveDocument();
- AcDbDatabase *pDB = pActiveDoc->database();
- // Получаем словарь растров, а если его еще нет -
- // создаём его
- AcDbObjectId dictID
- = AcDbRasterImageDef::imageDictionary(pDB);
- if (dictID == AcDbObjectId::kNull)
- {
- es = AcDbRasterImageDef::createImageDictionary
- (pDB, dictID);
- if (es != Acad::eOk)
- return es;
- }
- AcDbDictionary* pDict;
- es = acdbOpenObject(pDict, dictID, AcDb::kForWrite);
- if (es != Acad::eOk)
- return es;
- ACHAR *DICT_NAME = ACRX_T("RASTER_USING_BUFFER" );
- BOOL bExist = pDict->has(DICT_NAME);
- AcDbObjectId objID = AcDbObjectId::kNull;
- if (!bExist)
- {
- es = pDict->setAt(DICT_NAME, pImageDef, objID);
- if (es != Acad::eOk)
- {
- pDict->close();
- return es;
- }
- }
- else
- {
- pDict->getAt(DICT_NAME,
- (AcDbObject*&)pImageDef,
- AcDb::kForWrite);
- objID = pImageDef->objectId();
- }
- // Закрываем словарь и определение.
- pDict->close();
- pImageDef->close();
- // Создаём растр, используя RasterImage Def
- AcDbRasterImage* pImage = new AcDbRasterImage;
- es = pImage->setImageDefId(objID);
- if (es != Acad::eOk)
- {
- delete pImage;
- return es;
- }
- // Добавляем растр в Пространство Модели
- AcDbBlockTable* pBlockTable;
- AcDbBlockTableRecord* pBTRecord;
- es = acdbCurDwg()->getBlockTable(pBlockTable,
- AcDb::kForRead);
- assert(es == Acad::eOk);
- es = pBlockTable->getAt(ACDB_MODEL_SPACE,
- pBTRecord,
- AcDb::kForWrite);
- assert(es == Acad::eOk);
- es = pBTRecord->appendAcDbEntity(pImage);
- assert(es == Acad::eOk);
- pBTRecord->close();
- pBlockTable->close();
- AcDbObjectId entID = pImage->objectId();
- AcDbObjectPointer<AcDbRasterImageDefReactor>
- rasterImageDefReactor;
- rasterImageDefReactor.create();
- es = rasterImageDefReactor->setOwnerId(
- pImage->objectId());
- if (es == Acad::eOk)
- {
- AcDbObjectId defReactorId;
- es = curDoc()->database()->addAcDbObject(
- defReactorId,
- rasterImageDefReactor.object());
- if (es == Acad::eOk)
- {
- pImage->setReactorId(defReactorId);
- AcDbObjectPointer<AcDbRasterImageDef>
- rasterImagedef
- (pImage->imageDefId(), AcDb::kForWrite);
- if (rasterImagedef.openStatus() == Acad::eOk)
- {
- rasterImagedef->addPersistentReactor
- (defReactorId);
- }
- }
- }
- pImageDef->close();
- pImage->close();
- return Acad::eOk;
- }
- virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt)
- {
- AcRx::AppRetCode retCode =
- AcRxArxApp::On_kInitAppMsg (pkt) ;
- acrxDynamicLinker->loadModule
- (L"acismobj20.dbx" ,true );
- AcDbMyRasterImageDef::rxInit();
- acrxBuildClassHierarchy();
- return (retCode) ;
- }
Проект с примером можно загрузить отсюда:
Если вы ищете, как создать встроенное растровое изображение с помощью 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Отредактировано 17.11.2015 в 23:36:14