From: jfa Date: Fri, 8 Oct 2021 15:10:09 +0000 (+0300) Subject: Implement bos #26449: SHAPER: save imported images X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fjfa%2F26449;p=modules%2Fshaper.git Implement bos #26449: SHAPER: save imported images --- diff --git a/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py b/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py index 3a714b066..da88d6c2a 100644 --- a/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py +++ b/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py @@ -68,8 +68,8 @@ class ExportFeature(ModelAPI.ModelAPI_Feature): for aResIndex in range(self.Part.size(aResultType)): anObject = self.Part.object(aResultType, aResIndex) aResult = model.objectToResult(anObject) - # do nt export picture - if aResult.hasTextureFile() is True: + # do not export picture + if aResult.hasTexture() is True: continue if not aResult is None: if (not aResult.shape() or aResult.shape().isNull()) and isPart: diff --git a/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py b/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py index 8da67a31e..a721ad73b 100644 --- a/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py +++ b/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py @@ -93,7 +93,7 @@ class PublishToStudyFeature(ModelAPI.ModelAPI_Feature): aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId) aRes = model.objectToResult(aResObject) #do not export images - if aRes.hasTextureFile() is True: + if aRes.hasTexture() is True: continue aResFeatureId = str(aPartDoc.feature(aRes).data().featureId()) if aResFeatureId in aFeaturesIndices: diff --git a/src/ExchangeAPI/CMakeLists.txt b/src/ExchangeAPI/CMakeLists.txt index d241e7fcb..33ac73255 100644 --- a/src/ExchangeAPI/CMakeLists.txt +++ b/src/ExchangeAPI/CMakeLists.txt @@ -18,6 +18,7 @@ # INCLUDE(Common) +INCLUDE(UseQtExt) SET(PROJECT_HEADERS ExchangeAPI.h @@ -34,6 +35,7 @@ SET(PROJECT_LIBRARIES ModelAPI ModelHighAPI GeomAlgoAPI + ${QT_LIBRARIES} ) INCLUDE_DIRECTORIES( @@ -41,6 +43,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/ModelAPI ${PROJECT_SOURCE_DIR}/src/ModelHighAPI ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI + ${QT_INCLUDES} ) # Plugin headers dependency @@ -51,6 +54,9 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/ExchangePlugin ) +# additional preprocessor / compiler flags +ADD_DEFINITIONS(${QT_DEFINITIONS}) + #TODO(spo): is ${OpenCASCADE_DEFINITIONS} necessary? ADD_DEFINITIONS(-DEXCHANGEAPI_EXPORTS ${OpenCASCADE_DEFINITIONS}) ADD_LIBRARY(ExchangeAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) diff --git a/src/ExchangeAPI/ExchangeAPI_Import.cpp b/src/ExchangeAPI/ExchangeAPI_Import.cpp index cee25a91a..5335d3d63 100644 --- a/src/ExchangeAPI/ExchangeAPI_Import.cpp +++ b/src/ExchangeAPI/ExchangeAPI_Import.cpp @@ -26,11 +26,14 @@ #include //-------------------------------------------------------------------------------------- #include +#include #include #include #include //-------------------------------------------------------------------------------------- #include +//-------------------------------------------------------------------------------------- +#include ExchangeAPI_Import::ExchangeAPI_Import( const std::shared_ptr & theFeature) @@ -245,7 +248,40 @@ void ExchangeAPI_Import_Image::dump(ModelHighAPI_Dumper& theDumper) const std::string aPartName = theDumper.name(aBase->document()); std::string aFilePath = - aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value(); + aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value(); + + /* + // Store image from result into a tmp file + ResultPtr aResult = aBase->firstResult(); + if (aResult.get() && aResult->hasTexture()) { + // get image data + int aWidth, aHeight; + std::string aFormat; + std::list aByteList; + AttributeImagePtr anImageAttr = + aResult->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + anImageAttr->texture(aWidth, aHeight, aByteList, aFormat); + + // convert image data to QPixmap + uchar* arr = new uchar[aByteList.size()]; + std::copy(aByteList.begin(), aByteList.end(), arr); + QImage image (arr, aWidth, aHeight, QImage::Format_ARGB32); + QPixmap pixmap = QPixmap::fromImage( image ); + + // get tmp file name + std::string aTmpFilePath = + "/dn25/salome/jfa/BUGS/SHAPER/2_2_5_Saving_Images/tmp_image."; + aTmpFilePath += aFormat; + + // write image to tmp file + if (pixmap.save(aTmpFilePath.c_str())) { + + // dump tmp file name + aFilePath = aTmpFilePath; + } + delete [] arr; + } + */ theDumper << aBase << " = model.addImportImage(" << aPartName << ", \"" << aFilePath << "\")" << std::endl; diff --git a/src/ExchangePlugin/CMakeLists.txt b/src/ExchangePlugin/CMakeLists.txt index e8db9c5e9..fb3c22a4d 100755 --- a/src/ExchangePlugin/CMakeLists.txt +++ b/src/ExchangePlugin/CMakeLists.txt @@ -19,6 +19,7 @@ INCLUDE(Common) INCLUDE(UnitTest) +INCLUDE(UseQtExt) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/Config @@ -32,8 +33,12 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/ConstructionPlugin ${PROJECT_SOURCE_DIR}/src/PartSetPlugin ${OpenCASCADE_INCLUDE_DIR} + ${QT_INCLUDES} ) +# additional preprocessor / compiler flags +ADD_DEFINITIONS(${QT_DEFINITIONS}) + SET(PROJECT_HEADERS ExchangePlugin.h ExchangePlugin_Plugin.h @@ -82,6 +87,7 @@ SET(PROJECT_LIBRARIES GeomAlgoAPI GeomValidators XAOShaper + ${QT_LIBRARIES} ) # default dump approaches (will be set if not initialized) diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp index 6ae4199ec..1da829a6f 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp @@ -211,7 +211,7 @@ void ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName, /// do not export pictures ResultPtr aBodyContext = std::dynamic_pointer_cast(anAttrSelection->context()); - if(aBodyContext->hasTextureFile()) + if (aBodyContext->hasTexture()) continue; std::shared_ptr aCurShape = anAttrSelection->value(); @@ -416,13 +416,13 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) AttributeSelectionListPtr aSelection = selectionList(XAO_SELECTION_LIST_ID()); bool aIsSelection = aSelection->isInitialized() && aSelection->size() > 0; if (aIsSelection) { // a mode for export to geom result by result - for(int a = 0; a < aSelection->size(); a++) { + for (int a = 0; a < aSelection->size(); a++) { AttributeSelectionPtr anAttr = aSelection->value(a); ResultPtr aBodyContext = std::dynamic_pointer_cast(anAttr->context()); if (aBodyContext.get() && !aBodyContext->isDisabled() && aBodyContext->shape().get()) { /// do not export pictures - if(aBodyContext->hasTextureFile()){ + if (aBodyContext->hasTexture()){ anExCludedIsImage = true; continue; } diff --git a/src/ExchangePlugin/ExchangePlugin_Import.cpp b/src/ExchangePlugin/ExchangePlugin_Import.cpp index 6178b2259..42601ee11 100644 --- a/src/ExchangePlugin/ExchangePlugin_Import.cpp +++ b/src/ExchangePlugin/ExchangePlugin_Import.cpp @@ -156,7 +156,7 @@ void ExchangePlugin_Import::execute() void ExchangePlugin_Import_Image::execute() { - AttributeStringPtr aFilePathAttr = string(ExchangePlugin_ImportBase::FILE_PATH_ID()); + AttributeStringPtr aFilePathAttr = string(ExchangePlugin_ImportBase::FILE_PATH_ID()); std::string aFilePath = aFilePathAttr->value(); if (aFilePath.empty()) { setError("File path is empty."); diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp index 65045f228..e077e4ca7 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ #include +#include /* * Request for initialization of data model of the feature: adding all attributes @@ -635,35 +637,50 @@ void ExchangePlugin_ImportFeatureBase::loadNamingDS( void ExchangePlugin_Import_ImageFeature::importFile(const std::string& theFileName) { - std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(theFileName); - std::string theTextureFileName = ""; - // Perform the import std::string anError; - std::shared_ptr aGeomShape; - if (anExtension == "PNG" || anExtension == "GIF" || - anExtension == "TIFF" || anExtension == "JPE" || - anExtension == "JPG" || anExtension == "JPEG" || - anExtension == "BMP"|| anExtension == "PPM" - ) { - aGeomShape = ImageImport(theFileName, anError); - if(anError == "") - theTextureFileName = theFileName; - } else { - anError = "Unsupported format: " + anExtension; - } - // Check if shape is valid - if (!anError.empty()) { - setError("An error occurred while importing " + theFileName + ": " + anError); - return; - } + if (anExtension == "PNG" || anExtension == "GIF" || + anExtension == "TIFF" || anExtension == "JPE" || + anExtension == "JPEG" || anExtension == "JPG" || + anExtension == "BMP" || anExtension == "PPM" + ) { + // Perform the import + QPixmap px (theFileName.c_str()); + int aWidth = px.width(); + int aHeight = px.height(); + if (aWidth < 1 || aHeight < 1) { + setError("An error occurred while importing " + theFileName + ": invalid image"); + return; + } - // Pass the results into the model - std::string anObjectName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); - data()->setName(Locale::Convert::toWString(anObjectName)); + std::shared_ptr aGeomShape = ImageImport(aWidth, aHeight, anError); + + // Check if shape is valid + if (!anError.empty()) { + setError("An error occurred while importing " + theFileName + ": " + anError); + return; + } + + // Pass the results into the model + std::string anObjectName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); + data()->setName(Locale::Convert::toWString(anObjectName)); + + auto resultBody = createResultBody(aGeomShape); - auto resultBody = createResultBody(aGeomShape); - resultBody->setTextureFile(theTextureFileName); - setResult(resultBody); + // Store image in result body attribute + AttributeImagePtr anImageAttr = resultBody->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (anImageAttr.get() != NULL) { + QImage aQImage = px.toImage(); + const uchar* aImageBytes = aQImage.bits(); + std::list aByteArray (aImageBytes, aImageBytes + aQImage.sizeInBytes()); + anImageAttr->setTexture(aWidth, aHeight, aByteArray, anExtension); + } + + setResult(resultBody); + } + else { + anError = "Unsupported format: " + anExtension; + setError("An error occurred while importing " + theFileName + ": " + anError); + } } diff --git a/src/ExchangePlugin/Test/TestImportImage_1.py b/src/ExchangePlugin/Test/TestImportImage_1.py index 1c529e196..a4b23c540 100755 --- a/src/ExchangePlugin/Test/TestImportImage_1.py +++ b/src/ExchangePlugin/Test/TestImportImage_1.py @@ -66,6 +66,9 @@ tol=1e-06 assert(abs(dx-400) <= tol) assert(abs(dy-258.5) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) #============================================================================= # Change the image : @@ -95,6 +98,9 @@ tol=1e-06 assert(abs(dx-448) <= tol) assert(abs(dy-296.8) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) # Close SALOME GUI diff --git a/src/ExchangePlugin/Test/TestImportImage_2.py b/src/ExchangePlugin/Test/TestImportImage_2.py index 94b328fb3..c292972e1 100755 --- a/src/ExchangePlugin/Test/TestImportImage_2.py +++ b/src/ExchangePlugin/Test/TestImportImage_2.py @@ -74,6 +74,9 @@ tol=1e-06 assert(abs(dx-400) <= tol) assert(abs(dy-258.5) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) #============================================================================= # Change the image : @@ -101,6 +104,9 @@ tol=1e-06 assert(abs(dx-560) <= tol) assert(abs(dy-361.9) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) # Close SALOME GUI diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp index e8caba9bf..a3f08292a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -166,9 +167,9 @@ void FeaturesPlugin_MultiRotation::performRotation1D() GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + ResultPtr aTextureSource; + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Parameters of rotation. @@ -225,7 +226,8 @@ void FeaturesPlugin_MultiRotation::performRotation1D() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Rotated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp index c507c7d50..5fafcb11a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -91,9 +92,9 @@ void FeaturesPlugin_MultiTranslation::execute() GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + ResultPtr aTextureSource; + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::shared_ptr aFirstDir, aSecondDir; @@ -171,7 +172,8 @@ void FeaturesPlugin_MultiTranslation::execute() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Translated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp index efc09092a..8b109aed1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp @@ -71,10 +71,10 @@ void FeaturesPlugin_Placement::execute() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID()); - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Verify the start shape @@ -181,7 +181,8 @@ void FeaturesPlugin_Placement::execute() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Placed"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp b/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp index 1fe9334eb..8627c4c64 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -184,10 +185,10 @@ void FeaturesPlugin_Rotation::performRotation(const GeomTrsfPtr& theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -226,7 +227,8 @@ void FeaturesPlugin_Rotation::performRotation(const GeomTrsfPtr& theTrsf) ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Rotated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp b/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp index 73cbd10bc..6766e10dc 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp @@ -32,6 +32,7 @@ #include #include #include +#include static const std::string SCALE_VERSION_1("v9.5"); @@ -92,10 +93,10 @@ void FeaturesPlugin_Scale::performScaleByFactor() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Getting the center point @@ -143,7 +144,8 @@ void FeaturesPlugin_Scale::performScaleByFactor() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Scaled"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } @@ -159,10 +161,10 @@ void FeaturesPlugin_Scale::performScaleByDimensions() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Getting the center point @@ -215,7 +217,8 @@ void FeaturesPlugin_Scale::performScaleByDimensions() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Scaled"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp index e877c4016..9a5830bcf 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -204,13 +205,14 @@ void FeaturesPlugin_Symmetry::buildResult( const std::shared_ptr& theAlgo, const std::list >& theOriginalShapes, std::shared_ptr theTargetShape, int& theResultIndex, - std::string & theTextureFile) + const ResultPtr& theTextureSource) { // Store and name the result. ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, theOriginalShapes, ListOfShape(), theAlgo, theTargetShape, "Symmetried"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(theTextureSource, aResultBody); setResult(aResultBody, theResultIndex++); } @@ -281,10 +283,10 @@ void FeaturesPlugin_Symmetry::performSymmetry(GeomTrsfPtr theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -312,7 +314,7 @@ void FeaturesPlugin_Symmetry::performSymmetry(GeomTrsfPtr theTrsf) ListOfShape aTopLevel; anObjects.topLevelObjects(aTopLevel); for (ListOfShape::iterator anIt = aTopLevel.begin(); anIt != aTopLevel.end(); ++anIt) - buildResult(aMakeShapeList, anOriginalShapes, *anIt, aResultIndex, theTextureFile); + buildResult(aMakeShapeList, anOriginalShapes, *anIt, aResultIndex, aTextureSource); // Remove the rest results if there were produced in the previous pass. removeResults(aResultIndex); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h index 5d73f9ec8..814dcdb7b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h @@ -23,6 +23,7 @@ #include #include +#include class GeomAPI_Trsf; class GeomAlgoAPI_MakeShapeList; @@ -137,7 +138,8 @@ private: void buildResult(const std::shared_ptr& theAlgo, const std::list >& theOriginalShapes, std::shared_ptr theTargetShape, - int& theResultIndex, std::string &theTextureFile); + int& theResultIndex, + const ResultPtr& theTextureSource); /// Create new result for the given part and transformation void buildResult(std::shared_ptr theOriginal, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp b/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp index 9a36609a4..d1a690ce1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp @@ -263,27 +263,21 @@ bool FeaturesPlugin_Tools::shapesFromSelectionList( const std::shared_ptr theSelectionList, const bool theStoreFullHierarchy, GeomAPI_ShapeHierarchy& theHierarchy, - std::list& theParts, std::string &theTextureFile) + std::list& theParts, ResultPtr& theTextureSource) { int aSize = theSelectionList->size(); - if(aSize == 1) - { + if (aSize == 1) { auto anObjectAttr = theSelectionList->value(0); - if(anObjectAttr.get()) - { + if (anObjectAttr.get()) { FeaturePtr aFeature = anObjectAttr->contextFeature(); - if(aFeature.get() && aFeature->results().size() == 1) - { - theTextureFile = aFeature->firstResult()->getTextureFile(); + if (aFeature.get() && aFeature->results().size() == 1) { + theTextureSource = aFeature->firstResult(); } - else - { - if(!aFeature.get()) - { - auto aResult = anObjectAttr->context(); - if(aResult.get()) - { - theTextureFile = aResult->getTextureFile(); + else { + if (!aFeature.get()) { + auto aResult = anObjectAttr->context(); + if (aResult.get()) { + theTextureSource = aResult; } } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Tools.h b/src/FeaturesPlugin/FeaturesPlugin_Tools.h index c9a138a37..e901063fd 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Tools.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Tools.h @@ -69,7 +69,8 @@ public: const std::shared_ptr theSelectionList, const bool theStoreFullHierarchy, GeomAPI_ShapeHierarchy& theHierarchy, - std::list& theParts, std::string& theTextureFile); + std::list& theParts, + ResultPtr& theTextureSource); }; #endif /* FeaturesPlugin_Tools_H_ */ diff --git a/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp b/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp index 11a0dca22..9586fea92 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -197,10 +198,10 @@ void FeaturesPlugin_Translation::performTranslation(const GeomTrsfPtr& theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID()); - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -241,7 +242,8 @@ void FeaturesPlugin_Translation::performTranslation(const GeomTrsfPtr& theTrsf) ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Translated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 2fa736470..19ace76ed 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -173,7 +173,6 @@ SET(PROJECT_LIBRARIES ${OpenCASCADE_DataExchange_LIBRARIES} ${OpenCASCADE_ModelingAlgorithms_LIBRARIES} ${OpenCASCADE_ApplicationFramework_LIBRARIES} - ${QT_LIBRARIES} ) ADD_DEFINITIONS(-DGEOMALGOAPI_EXPORTS ${OpenCASCADE_DEFINITIONS}) @@ -184,10 +183,7 @@ SET(CMAKE_SWIG_FLAGS -w325,321,362,383,302) SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES SWIG_DEFINITIONS "-shadow") -INCLUDE(UseQtExt) # additional include directories -INCLUDE_DIRECTORIES(${QT_INCLUDES}) - INCLUDE_DIRECTORIES( ../GeomAPI ../GeomAlgoImpl diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp index 1f73aeef1..d0077871a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp @@ -19,7 +19,6 @@ #include -#include #include #include #include @@ -36,18 +35,13 @@ #include #include -std::shared_ptr ImageImport(const std::string& theFileName, - std::string& theError) +std::shared_ptr ImageImport(const int width, + const int height, + std::string& theError) { TopoDS_Shape aResShape; try { - QPixmap* pixmap = new QPixmap(theFileName.c_str()); - int height = pixmap->height(); - int width = pixmap->width(); - - delete pixmap; - TopoDS_Vertex aTriVertexes[4]; gp_Pnt aPnt1( -0.5*width, -0.5*height, 0); gp_Pnt aPnt2( 0.5*width, -0.5*height, 0); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h index 4f9573b48..5a29f8fbf 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h @@ -23,10 +23,11 @@ #include #include -#include + /// Implementation of the import STL files algorithms GEOMALGOAPI_EXPORT -std::shared_ptr ImageImport(const std::string& theFileName, - std::string& theError); +std::shared_ptr ImageImport(const int theWidth, + const int theHeight, + std::string& theError); #endif /* GEOMALGOAPI_IMAGEIMPORT_H_ */ diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index 2f349c193..c270a9c13 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -34,6 +34,7 @@ SET(PROJECT_HEADERS Model_AttributeRefList.h Model_AttributeRefAttrList.h Model_AttributeBoolean.h + Model_AttributeImage.h Model_AttributeIntArray.h Model_AttributeString.h Model_AttributeStringArray.h @@ -72,6 +73,7 @@ SET(PROJECT_SOURCES Model_AttributeRefList.cpp Model_AttributeRefAttrList.cpp Model_AttributeBoolean.cpp + Model_AttributeImage.cpp Model_AttributeIntArray.cpp Model_AttributeString.cpp Model_AttributeStringArray.cpp diff --git a/src/Model/Model_AttributeImage.cpp b/src/Model/Model_AttributeImage.cpp new file mode 100644 index 000000000..c74e42945 --- /dev/null +++ b/src/Model/Model_AttributeImage.cpp @@ -0,0 +1,147 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +void Model_AttributeImage::setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated) +{ + if (theWidth > 0 && theHeight > 0 && theByteArray.size() > 0) { // set new data + // Find or create attributes + Handle_TDataStd_ByteArray aByteArray = + TDataStd_ByteArray::Set(myLab, 0, theByteArray.size() - 1); + Handle_TDataStd_IntegerArray aDimensions = + TDataStd_IntegerArray::Set(myLab, 0, 1); + Handle_TDataStd_Comment aFormat = TDataStd_Comment::Set(myLab, theFormat.c_str()); + + // Dimensions + aDimensions->SetValue(0, theWidth); + aDimensions->SetValue(1, theHeight); + + // Texture + Handle(TColStd_HArray1OfByte) aNewArray = + new TColStd_HArray1OfByte(0, theByteArray.size() - 1); + std::list::const_iterator itBA = theByteArray.begin(); + for (int j = 0; itBA != theByteArray.end(); ++itBA, ++j) { + aNewArray->SetValue(j, (Standard_Byte)(*itBA)); + } + aByteArray->ChangeArray(aNewArray); + + if (sendUpdated) + owner()->data()->sendAttributeUpdated(this); + } + else { // size is zero => arrays must be erased + bool isForgotten1 = myLab.ForgetAttribute(TDataStd_ByteArray::GetID()); + bool isForgotten2 = myLab.ForgetAttribute(TDataStd_IntegerArray::GetID()); + bool isForgotten3 = myLab.ForgetAttribute(TDataStd_Comment::GetID()); + + if (sendUpdated && (isForgotten1 || isForgotten2 || isForgotten3)) + owner()->data()->sendAttributeUpdated(this); + } +} + +bool Model_AttributeImage::hasTexture() +{ + Handle_TDataStd_ByteArray aByteArray; + Handle_TDataStd_IntegerArray aDimensions; + if (myLab.FindAttribute(TDataStd_ByteArray::GetID(), aByteArray) == Standard_True && + myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aDimensions) == Standard_True) { + + // Dimensions + if (aDimensions->Value(0) > 0 && aDimensions->Value(1) > 0) + // Byte array + return aByteArray->Length() > 0; + } + return false; +} + +bool Model_AttributeImage::texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat) +{ + // Init return values + theWidth = 0; + theHeight = 0; + theByteArray.clear(); + theFormat = ""; + + Handle_TDataStd_ByteArray aByteArray; + Handle_TDataStd_IntegerArray aDimensions; + Handle_TDataStd_Comment aFormat; + if (myLab.FindAttribute(TDataStd_ByteArray::GetID(), aByteArray) == Standard_True && + myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aDimensions) == Standard_True && + myLab.FindAttribute(TDataStd_Comment::GetID(), aFormat) == Standard_True) { + + // Dimensions + theWidth = aDimensions->Value(0); + theHeight = aDimensions->Value(1); + + // Texture + const Handle(TColStd_HArray1OfByte) byteArray = aByteArray->InternalArray(); + for (int j = byteArray->Lower(); j <= byteArray->Upper(); j++) { + theByteArray.push_back((unsigned char)byteArray->Value( j )); + } + + // Format + theFormat = TCollection_AsciiString(aFormat->Get()).ToCString(); + return true; + } + + return false; +} + +void Model_AttributeImage::copyTo(AttributeImagePtr theTarget) const +{ + std::shared_ptr aTarget = + std::dynamic_pointer_cast(theTarget); + if (aTarget) { + //Model_AttributeSelectionList::copyAttrs(myLab, aTarget->myLab); + TDF_CopyLabel aCopyAlgo (myLab, aTarget->myLab); + aCopyAlgo.Perform(); + aTarget->reinit(); + } +} + +Model_AttributeImage::Model_AttributeImage(TDF_Label& theLabel) +{ + myLab = theLabel; + reinit(); +} + +void Model_AttributeImage::reinit() +{ + myIsInitialized = myLab.IsAttribute(TDataStd_ByteArray::GetID()); +} diff --git a/src/Model/Model_AttributeImage.h b/src/Model/Model_AttributeImage.h new file mode 100644 index 000000000..c4827c322 --- /dev/null +++ b/src/Model/Model_AttributeImage.h @@ -0,0 +1,73 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef MODEL_ATTRIBUTEIMAGE_H_ +#define MODEL_ATTRIBUTEIMAGE_H_ + +#include +#include + +#include + +#include + +/**\class Model_AttributeImage + * \ingroup DataModel + * \brief API for the attribute that contains image inside. + * Represented as the following OCCT attributes: + * TDataStd_ByteArray for the pixmap texture data, + * TDataStd_IntArray(2) for image dimensions (widht and height), + * TDataStd_String for image format. + */ + +class Model_AttributeImage : public ModelAPI_AttributeImage +{ + /// Stores the label as the only reference to all data + TDF_Label myLab; + + public: + /// Defines the value of the image attribute + MODEL_EXPORT virtual void setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated = true); + + /// Returns true, if texture width and height are non-zero + MODEL_EXPORT virtual bool hasTexture(); + + /// Returns the value of the image attribute + MODEL_EXPORT virtual bool texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat); + + /// Copy the image data to the destination attribute + virtual void copyTo(std::shared_ptr theTarget) const; + + protected: + /// Initializes attibutes + Model_AttributeImage(TDF_Label& theLabel); + /// Reinitializes the internal state of the attribute (may be needed on undo/redo, abort, etc) + virtual void reinit(); + + friend class Model_Data; +}; + +#endif diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 817a9e407..599c65086 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -218,6 +219,8 @@ AttributePtr Model_Data::addAttribute( anAttr = new Model_AttributeDoubleArray(anAttrLab); } else if (theAttrType == ModelAPI_AttributeTables::typeId()) { anAttr = new Model_AttributeTables(anAttrLab); + } else if (theAttrType == ModelAPI_AttributeImage::typeId()) { + anAttr = new Model_AttributeImage(anAttrLab); } // create also GeomData attributes here because only here the OCAF structure is known else if (theAttrType == GeomData_Point::typeId()) { @@ -375,6 +378,7 @@ GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefAttrList, refattrlist); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeIntArray, intArray); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDoubleArray, realArray); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeTables, tables); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeImage, image); std::shared_ptr Model_Data::attribute(const std::string& theID) { diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index df833acc0..bb073eb11 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -155,6 +156,9 @@ class Model_Data : public ModelAPI_Data /// Returns the attribute that contains string values array MODEL_EXPORT virtual std::shared_ptr tables(const std::string& theID); + /// Returns the attribute that contains image + MODEL_EXPORT virtual std::shared_ptr + image(const std::string& theID); /// Returns the generic attribute by identifier /// \param theID identifier of the attribute diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 65b687519..32f439df6 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,13 @@ Model_ResultBody::~Model_ResultBody() delete myBuilder; } +void Model_ResultBody::initAttributes() +{ + ModelAPI_Result::initAttributes(); + // append the image attribute. It is empty, the attribute will be filled by a request + data()->addAttribute(IMAGE_ID(), ModelAPI_AttributeImage::typeId())->setIsArgument(false); +} + bool Model_ResultBody::generated(const GeomShapePtr& theNewShape, const std::string& theName, const bool theCheckIsInResult) { @@ -408,17 +416,6 @@ void Model_ResultBody::updateSubs( myHistoryCash.Clear(); } -void Model_ResultBody::setTextureFile(const std::string & theTextureFile) -{ - ModelAPI_Result::setTextureFile(theTextureFile); - for( auto sub : mySubs){ - sub->setTextureFile(theTextureFile); - } - for(auto map : mySubsMap){ - map.first->setTextureFile(theTextureFile); - } -} - bool Model_ResultBody::isConnectedTopology() { TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); @@ -448,6 +445,16 @@ void Model_ResultBody::cleanCash() } } +bool Model_ResultBody::hasTexture() +{ + AttributeImagePtr anImageAttr = + data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (anImageAttr.get()) { + return anImageAttr->hasTexture(); + } + return false; +} + // adds to the theSubSubs map all sub-shapes of theSub if it is compound of compsolid static void collectSubs( const GeomShapePtr theSub, TopTools_MapOfShape& theSubSubs, const bool theOneLevelMore) diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index 721312c3a..4a8479af5 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -58,6 +58,9 @@ public: /// Removes the stored builders MODEL_EXPORT virtual ~Model_ResultBody(); + /// Request for initialization of data model of the result body: adding all attributes + virtual void initAttributes(); + /// Records the subshape newShape which was generated during a topological construction. /// As an example, consider the case of a face generated in construction of a box. MODEL_EXPORT virtual bool generated(const GeomShapePtr& theNewShape, @@ -114,7 +117,7 @@ public: MODEL_EXPORT virtual void cleanCash() override; /// sets the texture file - MODEL_EXPORT virtual void setTextureFile(const std::string & theTextureFile) override; + MODEL_EXPORT virtual bool hasTexture() override; protected: diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index d2d565eee..bbef9d3e5 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -26,6 +26,7 @@ SET(PROJECT_HEADERS ModelAPI.h ModelAPI_Attribute.h ModelAPI_AttributeBoolean.h + ModelAPI_AttributeImage.h ModelAPI_AttributeIntArray.h ModelAPI_AttributeDocRef.h ModelAPI_AttributeDouble.h @@ -74,6 +75,7 @@ SET(PROJECT_HEADERS SET(PROJECT_SOURCES ModelAPI_Attribute.cpp ModelAPI_AttributeBoolean.cpp + ModelAPI_AttributeImage.cpp ModelAPI_AttributeIntArray.cpp ModelAPI_AttributeDocRef.cpp ModelAPI_AttributeDouble.cpp diff --git a/src/ModelAPI/ModelAPI_AttributeImage.cpp b/src/ModelAPI/ModelAPI_AttributeImage.cpp new file mode 100644 index 000000000..4caea4544 --- /dev/null +++ b/src/ModelAPI/ModelAPI_AttributeImage.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include + + +std::string ModelAPI_AttributeImage::attributeType() +{ + return typeId(); +} + +/// To virtually destroy the fields of successors +ModelAPI_AttributeImage::~ModelAPI_AttributeImage() +{ +} + +ModelAPI_AttributeImage::ModelAPI_AttributeImage() +{ +} diff --git a/src/ModelAPI/ModelAPI_AttributeImage.h b/src/ModelAPI/ModelAPI_AttributeImage.h new file mode 100644 index 000000000..14fc1e717 --- /dev/null +++ b/src/ModelAPI/ModelAPI_AttributeImage.h @@ -0,0 +1,78 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef ModelAPI_AttributeImage_H_ +#define ModelAPI_AttributeImage_H_ + +#include +#include + +#include +#include + + +/**\class ModelAPI_AttributeImage + * \ingroup DataModel + * \brief API for the attribute that contains binary data. + * Used for images storage for an example. By default size is one, zero-based. + */ + +class ModelAPI_AttributeImage : public ModelAPI_Attribute +{ + public: + /// Defines the value of the image attribute + MODELAPI_EXPORT virtual void setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated = true) = 0; + + /// Returns true, if texture width and height are non-zero + MODELAPI_EXPORT virtual bool hasTexture() = 0; + + /// Returns the value of the image attribute + MODELAPI_EXPORT virtual bool texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat) = 0; + + /// Copy the image data to the destination attribute + virtual void copyTo(std::shared_ptr theTarget) const = 0; + + /// Returns the type of this class of attributes + MODELAPI_EXPORT static std::string typeId() + { + return "Image"; + } + + /// Returns the type of this class of attributes, not static method + MODELAPI_EXPORT virtual std::string attributeType(); + + /// To virtually destroy the fields of successors + MODELAPI_EXPORT virtual ~ModelAPI_AttributeImage(); + + protected: + /// Objects are created for features automatically + MODELAPI_EXPORT ModelAPI_AttributeImage(); +}; + +//! Pointer on image attribute +typedef std::shared_ptr AttributeImagePtr; + +#endif diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index a8f22355e..a5907974a 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -48,6 +48,7 @@ class ModelAPI_Feature; class ModelAPI_AttributeSelection; class ModelAPI_AttributeSelectionList; class ModelAPI_AttributeIntArray; +class ModelAPI_AttributeImage; class ModelAPI_AttributeTables; class ModelAPI_Object; class GeomAPI_Shape; @@ -113,6 +114,8 @@ class MODELAPI_EXPORT ModelAPI_Data virtual std::shared_ptr intArray(const std::string& theID) = 0; /// Returns the attribute that contains string values array virtual std::shared_ptr stringArray(const std::string& theID) = 0; + /// Returns the attribute that contains image + virtual std::shared_ptr image(const std::string& theID) = 0; /// Returns the attribute that contains tables virtual std::shared_ptr tables(const std::string& theID) = 0; diff --git a/src/ModelAPI/ModelAPI_Object.h b/src/ModelAPI/ModelAPI_Object.h index 5710af6f9..32e48bc40 100644 --- a/src/ModelAPI/ModelAPI_Object.h +++ b/src/ModelAPI/ModelAPI_Object.h @@ -45,7 +45,6 @@ class ModelAPI_Object: public ModelAPI_Entity { std::shared_ptr myData; ///< manager of the data model of a feature std::shared_ptr myDoc; ///< document this object belongs to - std::string textureFile = ""; public: #ifdef DEBUG_NAMES std::wstring myName; // name of this object @@ -101,19 +100,9 @@ class ModelAPI_Object: public ModelAPI_Entity /// signal. MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay); - MODELAPI_EXPORT bool hasTextureFile() + MODELAPI_EXPORT virtual bool hasTexture() { - return (textureFile != ""); - } - - MODELAPI_EXPORT virtual void setTextureFile(const std::string & theTextureFile) - { - textureFile = theTextureFile; - } - - MODELAPI_EXPORT const std::string & getTextureFile() - { - return textureFile; + return false; } protected: diff --git a/src/ModelAPI/ModelAPI_Result.h b/src/ModelAPI/ModelAPI_Result.h index 05e48d1de..1fc3c1ab8 100644 --- a/src/ModelAPI/ModelAPI_Result.h +++ b/src/ModelAPI/ModelAPI_Result.h @@ -39,7 +39,7 @@ class ModelAPI_Result : public ModelAPI_Object public: /// Reference to the color of the result. - /// The integer array is used. It contains tree values for red green and blue values. + /// The integer array is used. It contains three values for red, green and blue values. /// The values are in [0, 255] range inline static const std::string& COLOR_ID() { diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index 5c19f711c..ec323ac28 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -58,6 +58,13 @@ protected: public: MODELAPI_EXPORT virtual ~ModelAPI_ResultBody(); + /// Reference to the image attribute of the result body. + inline static const std::string& IMAGE_ID() + { + static const std::string MY_IMAGE_ID("Image"); + return MY_IMAGE_ID; + } + /// Returns the group identifier of this result MODELAPI_EXPORT virtual std::string groupName(); diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index e15b280af..a2d820ef3 100644 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1021,6 +1022,30 @@ void copyVisualizationAttrs( } } + +void copyImageAttribute (std::shared_ptr theSource, + std::shared_ptr theDest) +{ + if (!theSource.get() || !theDest.get()) + return; + + // images allowed only for ResultBody + ResultBodyPtr aSourceBody = std::dynamic_pointer_cast(theSource); + ResultBodyPtr aDestBody = std::dynamic_pointer_cast(theDest); + if (!aSourceBody.get() || !aDestBody.get()) + return; + + AttributeImagePtr aSourceImage = + theSource->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aSourceImage.get() && aSourceImage->hasTexture()) { + AttributeImagePtr aDestImage = + theDest->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aDestImage.get()) { + aSourceImage->copyTo(aDestImage); + } + } +} + std::list referencedFeatures( std::shared_ptr theTarget, const std::string& theFeatureKind, const bool theSortResults) diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index e740cd1c9..cac6d7a45 100644 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -294,6 +294,13 @@ MODELAPI_EXPORT void setTransparency(std::shared_ptr theResult, MODELAPI_EXPORT void copyVisualizationAttrs(std::shared_ptr theSource, std::shared_ptr theDest); +/*! Copies image attribute from one result to another. +* \param theSource a result that contains the image data +* \param theDest a destination result that takes the image data +*/ +MODELAPI_EXPORT void copyImageAttribute(std::shared_ptr theSource, + std::shared_ptr theDest); + /*! Produces list of features that reference to the given target (directly or through sub-results) * \param theTarget the referenced result * \param theFeatureKind the resulting features filter: the feature kind or all for the empty string diff --git a/src/PartSet/PartSet_CustomPrs.cpp b/src/PartSet/PartSet_CustomPrs.cpp index 05f8d9b72..3da462996 100644 --- a/src/PartSet/PartSet_CustomPrs.cpp +++ b/src/PartSet/PartSet_CustomPrs.cpp @@ -171,9 +171,8 @@ bool PartSet_CustomPrs::displayPresentation( isModified = true; } else { - if (myFeature->firstResult().get() && myFeature->firstResult()->hasTextureFile()) - { - PartSet_Module::setTexture( myFeature->firstResult()->getTextureFile(), aPresentation); + if (myFeature->firstResult().get()) { + PartSet_Module::setTexture(aPresentation, myFeature->firstResult()); } anOperationPrs->Redisplay(); isModified = true; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 3999ae85e..b165740ff 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -147,9 +148,6 @@ #include #include -#ifdef HAVE_SALOME -#include -#endif #define FEATURE_ITEM_COLOR "0,0,225" @@ -1404,13 +1402,46 @@ double getResultTransparency(const ResultPtr& theResult) return aTransparency; } +static AttributeImagePtr findImage(const ObjectPtr& theResult) +{ + AttributeImagePtr anImageAttr; + + if (theResult.get()) { + ResultBodyPtr aResultBody = + std::dynamic_pointer_cast(theResult); + if (aResultBody.get()) { + anImageAttr = aResultBody->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (!anImageAttr.get() || !anImageAttr->hasTexture()) { + // try to find an image attribute in parents + ObjectPtr aParent = theResult->document()->parent(theResult); + anImageAttr = findImage(aParent); + } + } + } + + return anImageAttr; +} + //****************************************************** -void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObjectPtr& thePrs) +void PartSet_Module::setTexture(const AISObjectPtr& thePrs, + const ResultPtr& theResult) { -#ifdef HAVE_SALOME + ResultBodyPtr aResultBody = + std::dynamic_pointer_cast(theResult); + if (!aResultBody.get()) + return; + + AttributeImagePtr anImageAttr = findImage(theResult); + if (!anImageAttr.get() || !anImageAttr->hasTexture()) + return; + + int aWidth, aHeight; + std::string aFormat; + std::list aByteList; + anImageAttr->texture(aWidth, aHeight, aByteList, aFormat); + Handle(AIS_InteractiveObject) anAIS = thePrs->impl(); - if (!anAIS.IsNull()) - { + if (!anAIS.IsNull()) { /// set color to white and change material aspect, /// in order to keep a natural apect of the image. thePrs->setColor(255, 255, 255); @@ -1427,11 +1458,21 @@ void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObj myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(aMatAspect); myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(aMatAspect); - Handle(Image_PixMap) aPixmap; - QPixmap px(theTextureFile.c_str()); - - if (!px.isNull() ) - aPixmap = OCCViewer_Utilities::imageToPixmap( px.toImage()); + //aPixmap = OCCViewer_Utilities::imageToPixmap( px.toImage()); + Handle(Image_PixMap) aPixmap = new Image_PixMap(); + aPixmap->InitTrash(Image_PixMap::ImgBGRA, aWidth, aHeight); + std::list::iterator aByteIter = aByteList.begin(); + for (int aLine = 0; aLine < aHeight; ++aLine) { + // convert pixels from ARGB to renderer-compatible RGBA + for (int aByte = 0; aByte < aWidth; ++aByte) { + Image_ColorBGRA& aPixmapBytes = aPixmap->ChangeValue(aLine, aByte); + + aPixmapBytes.b() = (Standard_Byte) *aByteIter++; + aPixmapBytes.g() = (Standard_Byte) *aByteIter++; + aPixmapBytes.r() = (Standard_Byte) *aByteIter++; + aPixmapBytes.a() = (Standard_Byte) *aByteIter++; + } + } anAISShape->Attributes()->ShadingAspect()->Aspect()->SetTextureMap (new Graphic3d_Texture2Dmanual(aPixmap)); @@ -1440,7 +1481,6 @@ void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObj anAISShape->SetDisplayMode(AIS_Shaded); } } -#endif } //****************************************************** @@ -1485,10 +1525,8 @@ void PartSet_Module::customizePresentation(const ObjectPtr& theObject, thePrs->setDeflection(getResultDeflection(aResult)); thePrs->setTransparency(getResultTransparency(aResult)); - /// set texture parameters - if(aResult->hasTextureFile()) { - setTexture(aResult->getTextureFile(), thePrs); - } + /// set texture parameters, if any + setTexture(thePrs, aResult); } if (aFeature.get() && (aFeature->getKind() == SketchPlugin_Sketch::ID())) { thePrs->setWidth(2); diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index e47fabe9d..7a39b8998 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -400,7 +400,7 @@ public: virtual void createFeatures(); /// add texture - static void setTexture(const std::string &theTextureFile, const AISObjectPtr& thePrs); + static void setTexture(const AISObjectPtr& thePrs, const ResultPtr& theResult); public slots: /// Slolt called on object display