Putting Layers Inside of Folders?



  • On 17/08/2014 at 16:13, xxxxxxxx wrote:

    I guess GeFree() is made for another allocation type "from documentation it says GeAlloc()"

    from the class there is a static function:

    static void [Free](http://www.maxonexchange.de/sdk/CINEMA4DSDK/help/pages/c4d_basebitmap/class_MultipassBitma1134.html#free23)([MultipassBitmap](http://www.maxonexchange.de/sdk/CINEMA4DSDK/help/pages/c4d_basebitmap/class_MultipassBitma1134.html)\*& bc);
    


  • On 17/08/2014 at 16:33, xxxxxxxx wrote:

    I tried that one too.
    But it does not work on AutoFree.

    MultipassBitmap::Free(clonedImg);   //<--Nope Not allowed to use this on AutoFree
      MultipassBitmap::Free(layer);           //Works
      MultipassBitmap::Free(myFolder);    //works

    What I don't understand is why the memory needs to be manually freed in the first place?
    In any other usage. Auto is handled by C4D automatically and frees the memory for me.
    But this function is doing something weird: MultipassBitmap::AllocWrapper(sourceImage);

    The leak stops if I remove this line of code:  clonedImg->Init(fn);
    But then the code does not work. And it does not create my custom folder and layers.
    There's something very strange going on with this wrapper.

    -ScottA



  • On 17/08/2014 at 16:46, xxxxxxxx wrote:

    then do it the normal way

    MultiPassBitmap *clonedImg = MultipassBitmap::AllocWrapper(sourceImage);

    also don't use AutoAlloc for the sourceImage

    from documentation:

    static MultipassBitmap* AllocWrapper(BaseBitmap* bmp)_<_h4_>_

    Allocates a multipass wrapper for bmp. The wrapped bitmap has to stay alive and not be freed until after the allocated wrapper has been freed. The returned multipass wrapper can be modified freely.

    Ret_<_h5_>_h5>

    > MultipassBitmap*
    >
    >> The allocated wrapper bitmap, or nullptr if the allocation failed.

    _Paramete_ <_h5_>_>

    > BaseBitmap* bmp
    >
    >> Bitmap to wrap. The caller owns the pointed object.
    >



  • On 17/08/2014 at 16:49, xxxxxxxx wrote:

    a question here about "The caller owns the pointed object." , does that mean that clonedImg contains all data of sourceImage and when I free clonedImg it will internally free sourceImage?



  • On 17/08/2014 at 17:17, xxxxxxxx wrote:

    Nope.
    I tried BaseBitmap *sourceImage = BaseBitmap::Alloc();
    Still the same problem.

    The only reason why I'm using that wrapper is because I don't know how to copy the color values from the source image into the new MultipassBitmap object.
    I've seen some posts where people have used a nested for loop (y,x) with GetPixelCnt() to copy the color values. But I could never get it to work.
    That's why I'm using the wrapper function.

    But this stupid wrapper won't let go of the memory it's given. 😠

    -ScottA



  • On 17/08/2014 at 17:35, xxxxxxxx wrote:

    not sure how you free them, but I guess it should be like this:

    MultipassBitmap::Free(clonedImg);  
        MultipassBitmap::Free(layer);          
        MultipassBitmap::Free(myFolder);  
        BaseBitmap::Free(sourceImage);

    try to post your updated code here



  • On 17/08/2014 at 17:54, xxxxxxxx wrote:

    It means that the BaseBitmap passed is owned by the caller and you have to free it.  Anything resulting is owned by whomever they assign it to (probably the class and its free method).



  • On 17/08/2014 at 18:17, xxxxxxxx wrote:

    The problem is coming from clonedImg->Init(fn);

    -The sourceImage BaseBitmap gets the color values from the file(fn).
    -After I wrap the sourceImage BaseBitmap into the MultipassBitmap *clonedImg. I'm expecting the clonedImg to inherit that color info from sourceImage.
    But if I try to add folders and layers to it. It does nothing.
    It's as if MultipassBitmap *clonedImg does not exist.

    But when I add clonedImg->Init(fn); to re initialize the wrapped clonedImg. Somehow it forces it to become a real thing that I can add layers and folders to it.
    So whatever is going on with the wrapper. It's not doing what I expected. And by using Init(fn) on it. I'm somehow able to cheat and trick it to work. But this "trick" comes with a memory leak error.

    All I'm trying to do is:
    -Get an image from a file on my desktop.
    -Load it into a MultipassBitmap object. So I can then add layers and folders to it.
    -Then save the image back to another file on my desktop

    That's it.
    Should be easy peezy... but it's proving to be a royal pain.

    -ScottA



  • On 17/08/2014 at 18:39, xxxxxxxx wrote:

    looks weird, but I don't know where the problem lies :(
    off topic as I'm stuck in preparing my first plugin, I cloned the SDK, removed what I don't want, then just left a simple example "double circle object"

    it compiles fine, runs fine, I can create the object and play with it, but for some reason the whole description doesn't appear "can't see radius, interpolation, ..."

    what am I missing?



  • On 17/08/2014 at 19:14, xxxxxxxx wrote:

    ^I can't help much with that plugin problem because I don't make plugins that way.
    I hate doing it that way. Because it's too easy to delete something important. Which is probably what you've done.

    I build my plugins from scratch. Without the api loaded in the solution.
    I don't do that whole copy &delete stuff.
    I'm a rebel.Wink

    -ScottA



  • On 17/08/2014 at 20:53, xxxxxxxx wrote:

    Lol. Check this out.
    I figured out how to copy the colors over without using that crazy wrapper method. And look what other insanity pops up in my face to deal with.

    Bool SimplePlugin::Execute(BaseDocument *doc)  
    {  
      //The path to the image we want to copy  
      Filename fn = GeGetC4DPath(C4D_PATH_DESKTOP) + "sourceImage.jpg";  
      if(!GeFExist(fn, FALSE)) return FALSE;  
      
      //Put the image into a BaseBitmap object  
      AutoAlloc<BaseBitmap> sourceImage;  
      //BaseBitmap *sourceImage = BaseBitmap::Alloc();  
      sourceImage->Init(fn);  
      
      //Create a new MultipassBitmap using the sourceImage BaseBitmap's data  
      MultipassBitmap *clonedImg = MultipassBitmap::Alloc(sourceImage->GetBw(), sourceImage->GetBh(), COLORMODE_ARGBf);  
      
      //loop through the source image and copy the color values to the MultipassBitmap *clonedImg  
      UCHAR *buffer = GeAllocType(UCHAR, 3*sourceImage->GetBw());  
      for (LONG y=0; y<sourceImage->GetBh(); y++)  
      {  
          sourceImage->GetPixelCnt(0,y, sourceImage->GetBw(), buffer, COLORBYTES_RGB, COLORMODE_RGB, PIXELCNT_0);      
          clonedImg->SetPixelCnt(0,y, sourceImage->GetBw(), buffer, 3, COLORMODE_RGB, PIXELCNT_0);  
      }  
      
      
      //At this point it works with zero memmory leaks..hurray!!!  
      //Problems solved right?....Dream on Scott...Now we get a new problem to deal with  
      
      //Check out what happens when I add a new layer to it  
      //sure..it's adds the new layer fine...But...it also makes the base layer with the copied colors HIDDEN!!!!????:angry:  
      //Why on earth does it make the thebase image Hidden!!!  
      clonedImg->AddLayer(NULL, COLORMODE_ARGBf, FALSE);   
      
      clonedImg->Save(GeGetC4DPath(C4D_PATH_DESKTOP) + Filename("testImg.tif"), FILTER_TIF, 0, SAVEBIT_MULTILAYER);  
      
      //Free the memory  
      MultipassBitmap::Free(clonedImg);  
      GeFree(buffer);  
      
      EventAdd();  
      return TRUE;  
    }
    

    If you don't add any folders or layers. The base image is not set as hidden as expected.
    But if you add layers of folders to the MultipassBitmap. Poof! It sets the base image to hidden!
    Whuuut?😵

    Is Peter Funt going to jump out and say "Smile...you're on Candid Camera"

    -ScottA



  • On 18/08/2014 at 09:04, xxxxxxxx wrote:

    After a nights sleep and a fresh brain. I attacked this thing again conquered it.
    There's a bug (or a feature as the devs would probably call it 😂) that turns the visibility of the BG layer off when we add a layer or folder. But I found a way to turn it back on.

    Here's the full working example with no memory leaks.

    //This code copies a bitmap source image and creates a new one using a MultipassBitmap()  
    //Then it adds a new layer to it and sets the various layer options  
      
    Bool SimplePlugin::Execute(BaseDocument *doc)  
    {  
      //The path to the image we want to copy  
      Filename fn = GeGetC4DPath(C4D_PATH_DESKTOP) + "sourceImage.jpg";  
      if(!GeFExist(fn, FALSE)) return FALSE;  
      
      //Put the image into a BaseBitmap object  
      AutoAlloc<BaseBitmap> sourceImage;  
      sourceImage->Init(fn);  
      
      //Convert the sourceImage bitmap into a new MultipassBitmap using the sourceImage BaseBitmap's data  
      MultipassBitmap *sourceToMpb = MultipassBitmap::Alloc(sourceImage->GetBw(), sourceImage->GetBh(), COLORMODE_ARGBf);  
      
      //Loop through the source image and copy the colors to the MultipassBitmap *sourceToMpb so we can add layers and folders to it later on  
      UCHAR *buffer = GeAllocType(UCHAR, 3*sourceImage->GetBw());  
      for (LONG y=0; y<sourceImage->GetBh(); y++)  
      {  
          sourceImage->GetPixelCnt(0,y, sourceImage->GetBw(), buffer, COLORBYTES_RGB, COLORMODE_RGB, PIXELCNT_0);      
          sourceToMpb->SetPixelCnt(0,y, sourceImage->GetBw(), buffer, 3, COLORMODE_RGB, PIXELCNT_0);  
      }  
      
      ///////////////////////////////////////////////////////////////////////////////////  
      //Ok STOP!!...  
      //When we add our first layer or folder. C4D for some God-for-saken reason turns the background layer's visibilty off!!  
      //So we have to make sure that we turn it back on using MPBTYPE_SHOW!!!!  
      ///////////////////////////////////////////////////////////////////////////////////  
      
        
      //Create a new layer folder  
      MultipassBitmap *myFolder = sourceToMpb->AddFolder(NULL, FALSE);  
      myFolder->SetParameter(MPBTYPE_NAME, "My Folder");  
      
      //Now lets go back and turn on the visibilty for the background layer (Yeah..it's lame and probably a bug)  
      //Reminder: Layer 0 is the topmost layer. So the BGLayer is currently on layer1  
      MultipassBitmap *bgLayer = sourceToMpb->GetLayerNum(1);  
      bgLayer->SetParameter(MPBTYPE_SHOW, TRUE);  
      
      //Now create a new layer in the new folder so that we can draw on top of the orignal image without destroying it  
      myFolder->AddLayer(NULL, COLORMODE_ARGBf, FALSE);  
      
      
      //Retrieve a specific layer  
      //NOTE: ID#s are from ..\..\..\..\resource\res\description\bplayer.h  
      
      //LONG layercount = myFolder->GetLayerCount();  
      //GePrint(LongToString(layercount));  
       
      MultipassBitmap *layer1 = myFolder->GetLayerNum(0); if(!layer1) return FALSE;  
      layer1->SetParameter(MPBTYPE_NAME, "My First New Layer");  
      layer1->SetParameter(MPBTYPE_BLENDMODE, LAYER_MULTIPLY);   //Sets the blend mode  
      layer1->SetParameter(MPBTYPE_PERCENT, 0.5);                //Sets the layer's opacity value  
      layer1->SetParameter(MPBTYPE_USERID, 123456);              //Assigns a userID to the layer  
      layer1->SetParameter(MPBTYPE_SAVE, TRUE);                  //Saves the layer  
      
      LONG colmode = layer1->GetParameter(MPBTYPE_COLORMODE).GetLong();  
      GePrint(LongToString(colmode));  
      LONG DPI = layer1->GetParameter(MPBTYPE_DPI).GetLong();  
      GePrint(LongToString(DPI));  
      
      //Adds another layer and inserts it after the first layer created above  
      MultipassBitmap *layer2 = myFolder->AddLayer(layer1, COLORMODE_ARGBf, FALSE);  
      layer2->SetParameter(MPBTYPE_NAME, "My Second New Layer");  
      
      sourceToMpb->Save(GeGetC4DPath(C4D_PATH_DESKTOP) + Filename("testImg.tif"), FILTER_TIF, 0, SAVEBIT_MULTILAYER);  
      
      //Free the memory  
      MultipassBitmap::Free(sourceToMpb);  
      GeFree(buffer);  
      
      EventAdd();  
      return TRUE;  
    }
    

    -ScottA



  • On 18/08/2014 at 09:32, xxxxxxxx wrote:

    it seems like a feature for dynamic UI, so when you add a new layer it collapses old stuff



  • On 18/08/2014 at 09:40, xxxxxxxx wrote:

    Maybe.

    I'm probably doing a task with it that the developers never considered when writing the SDK functions.
    I'm just glad they wrote the MPBTYPE_SHOW option. I would have been screwed without it.

    -ScottA



  • On 18/08/2014 at 09:46, xxxxxxxx wrote:

    :) , I have also found the problem in my first plugin res problems xD

    check your messages Scotta


Log in to reply