Bitmap.Release()



  • On 14/12/2013 at 03:10, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R14 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi Folks,

    I have a function that returns a bitmap. The draw and returned bitmap is all fine, but I'm a little unsure on how to deal with the alpha bitmap that is used in it, and in particular on how to free/release it without affecting the returned bitmap. Can an AutoAloc<BaseBitmap> be used for the internal channel?

      
    BaseBitmap* MyFuntion(void)   
    {   
        AutoAlloc<BaseBitmap> BMP;   
        BaseBitmap *Alpha = BaseBitmap::Alloc();   
      
        Alpha = BMP->GetInternalChannel();   
        Alpha = BMP->AddChannel(TRUE,TRUE);   
      
        // DO ALL THE DRAWS ETC HERE   
      
        return BMP.release();   
    }   
    

    Using "Alpha = NULL;" and "BaseBitmap::Free(Alpha);" after the drawing and before the return prevents it from working correctly. I can just leave the bitmap without NULL/Freeing it etc., but doesn't that leave the alpha bitmap pointlessly in memory after the function has finished?

    Or can an AutoAlloc'd bitmap be used instead? How are the GetInternalChannel calls done in this case?

    Or.. does the final BMP.release() cover all of that for me in the return call?

    Cheers,

    WP.



  • On 14/12/2013 at 07:59, xxxxxxxx wrote:

    You should never free AutoAlloc by hand. At least I've never had to do it.
    The memory is handled automatically based on the surrounding scope where you create it.

    if(condition)  
    {  
      //<---Scope begins  
      
      AutoAlloc<BaseBitmap> BMP;  
      
      //Use the BMP instance in some manner....  
      
      //<---Scope ends and the memory is automatically freed  
    }
    

    In a custom method scenario.
    The lifetime of the memory assigned by AutoAlloc is based on the scope where you insert your method.

    if(condition)  
    {  
      //<---Scope begins  
      
      MyFunction(void);                      //The method runs and allocates memory  
      
      //Or possibly something like this  
      BaseBitmap *myBMP = MyFunction(void);  //The method runs and allocates memory  
      
      //Do some stuff with myBMP here....  
      
      
      //<---Scope ends and the memory used by MyFunction(void) is freed automatically  
    }
    

    I personally always try use AutoAlloc for bitmaps whenever I can. Because it handles the memory for me.
    However. It is fairly easy to accidentally try and use an allocated bitmap beyond the scope where it was created. And what happens is your bitmap either gets killed unexpectedly. Or never shows up at all...And you can't figure out why that's happening.
    So you have to be very aware of your scopes when using it.

    -ScottA



  • On 14/12/2013 at 14:54, xxxxxxxx wrote:

    Hi there Scott,

    yeah, normally I alloc/free my bitmaps manually, but this one was a little different because of the returned bitmap, and as you say the end of scope scenario.

    How does one then AutoAlloc a bitmap for use with the internal channel? I get compile errors when exchanging "BaseBitmap *Alpha:" for "AutoAlloc<...> Alpha;". Example:

      
    AutoAlloc<BaseBitmap> Alpha;   
    Alpha = mybmp->GetInternalChannel();   
    Alpha = mybmp->AddChannel(TRUE,TRUE);   
      
    // mybmp above is just a reference to the main drawing image,   
    // which is autoalloc'd, but neither of the two last lines compile   
    // when autoalloc'ing the bitmap for the alpha channel, due to a   
    // c2248 error (trying to access a private member).   
    

    How is that solved? Or are we just not able to use an autoalloc'd bitmap for the alpha channel in this instance?

    WP.

    EDIT:: update to the code text to keep it in reading width!



  • On 14/12/2013 at 16:50, xxxxxxxx wrote:

    I don't have that much alpha writing experience.
    But this is what I have in my notes about the AddChannel() function for creating them.

    //Saving .png image with an alpha  
      
       IMAGERESULT result;  
      
       BaseBitmap *bmp = BaseBitmap::Alloc();  
      
       BaseBitmap *alpha;  
      
       LONG bw,bh;  
       UCHAR *line = NULL;       
      
       bw=bm->GetBw();  
       bh=bm->GetBh();       
      
       bmp->Init(bw,bh);  
      
       BaseContainer rdata = GetActiveDocument()->GetActiveRenderData()->GetData();  
      
       LONG x,y;  
      
       if(savebits & SAVEBIT_ALPHA)  
      
       {  
            alpha = bmp->GetInternalChannel();  
            if(!alpha)alpha = bmp->AddChannel(TRUE,rdata.GetBool(RDATA_STRAIGHTALPHA));  
      
      
            // you have to copy the alpha over  
            for(y=0; y<bh; y++)  
            {  
                 for(x=0; x<bw; x++)  
                 {  
                       UWORD value = 0;  
                       bm->GetAlphaPixel(bm->GetChannelNum(0),x,y,&value);  
                       bmp->SetAlphaPixel(alpha,x,y,value);  
                 }  
            }  
      
       }  // end of alpha check  
      
      
       // images with straight alpha require color conversion for some reason  
       ColorProfileConvert* converter = ColorProfileConvert::Alloc();  
      
       converter->PrepareTransform(COLORMODE_RGB,ColorProfile::GetDefaultLinearRGB(),COLORMODE_RGB,ColorProfile::GetDefaultSRGB(),false);  
      
       line = GeAllocType(UCHAR,3*bw);  
      
       if (!line)  
       {  
          GeFree(line);  
          return IMAGERESULT_OUTOFMEMORY;  
       }  
      
       // copy the image  
       for (y=0; y<bh; y++)  
       {  
          bm->GetPixelCnt(0,y,bw,line,COLORBYTES_RGB,COLORMODE_RGB,PIXELCNT_0,converter);  
          bmp->SetPixelCnt(0,y,bw,line,COLORBYTES_RGB,COLORMODE_RGB,PIXELCNT_0);  
       }  
      
      
       GeFree(line);   
      
       ColorProfileConvert::Free(converter);  
      
       result = bmp->Save(name,FILTER_PNG,data,savebits);  
      
       BaseBitmap::Free(bmp);  
      
       return result;
    

    -ScottA



  • On 19/12/2013 at 13:51, xxxxxxxx wrote:

    Hi WP,

    I hope you are trying to use either of these lines, not all of them?

    > BaseBitmap *Alpha = BaseBitmap::Alloc();
    >
    > Alpha = BMP->GetInternalChannel();
    >
    > Alpha = BMP->AddChannel(TRUE,TRUE);

    Because here, after you've allocated a new Bitmap, you drop your only reference to it, resulting
    in a memory leak.

    > BaseBitmap* Alpha = BMP->GetInternalChannel();
    >
    > // If there is not already an internal alpha channel, create one.
    >
    > if (Alpha == NULL) {
    >
    > Alpha = BMP->AddChannel(TRUE, TRUE);
    >
    > }

    The memory of internal channels are managed by the bitmap itself. If the main bitmap is destroyed,
    it will automatically destroy all its channels.

    The BMP.Release() call won't do anything but to transfer the owner of the memory to you. After
    the method was called, you are responsible for freeing the bitmap. If you would not have called this
    method, the AutoAlloc class would deallocate the bitmap when the function exits.

    To clarify, the following three snippets are equal in their semantics and treat the memory correctly.

    > BaseBitmap* bmp = BaseBitmap::Alloc();
    > if (bmp) {
    > // Do some stuff
    > BaseBitmap::Free(bmp);
    > }
    >
    >
    > // ==================================================
    >
    >
    > AutoAlloc<BaseBitmap> bmp;
    > if (bmp) {
    > // Do some stuff
    > }
    >
    > // ==================================================
    >
    >
    > AutoAlloc<BaseBitmap> bmp;
    > if (bmp) {
    > // Do some stuff
    > BaseBitmap* released_bmp = bmp.Release();
    > BaseBitmap::Free(released_bmp);
    > }

    Best,
    -Niklas



  • On 19/12/2013 at 17:40, xxxxxxxx wrote:

    Hi there Niklas,

    Originally posted by xxxxxxxx

    I hope you are trying to use either of these lines, not all of them?

    BaseBitmap *Alpha = BaseBitmap::Alloc();
    Alpha = BMP->GetInternalChannel();
    Alpha = BMP->AddChannel(TRUE,TRUE);

    I must admit, I was allocating the bitmap before adding it to the main bitmap's channel. So the alloc'ing in this instance (when the bitmap is for alpha channel use) is not needed then?

    Originally posted by xxxxxxxx

    The BMP.Release() call won't do anything but to transfer the owner of the memory to you.

    Could you clarify this a little further? If I use the Release() on the main bitmap, what happens to the second bitmap that is used for the internal alpha channel? Is the 'ownership' of that bitmap also transfered with the .Release() of the main bitmap? And is it also destroyed when the main bitmap is freed later on?

    Or do you have to go in and dig out the internal channel and destroy that separately first, before freeing the main bitmap?

    WP.


Log in to reply