Copy bitmap to bitmap

On 29/08/2017 at 12:51, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R17 
Language(s) :     C++  ;

I have been trying to copy part of a small bitmap to a larger bitmap.
There need no scaling to be involved, but since the Blit function is only available to GeClipmap I have been trying with BaseBitmap::CopyPartTo.
Hoping that this would only copy a part of the source bitmap onto the destination bitmap, leaving the original size of the destination bitmap as is. Apparently, the function isn't meant to be used that way, since the destination bitmap gets the size of the copied part.

Then I tried ScaleBicubic, since no scaling is required I used same values for source as for destination.
The documentation states:
This function can currently only scale down, i.e. the destination needs to be smaller or equal to the source in size
But again, this function doesn't seem to work this way, since the destination size needs to be SMALLER to work, if only by a single pixel, but it needs to be smaller. So the part mentioning "equal" in the documentation is plain rubbish to me.

Having no other options I then tried to work with GeClipmap and using Blit, but got sidetracked and never got a clean solution, so just gave up on the whole thing ... and came looking here for an anwer.

So, how would I go about copying the content of bitmap A which is sized 100x50 to bitmap B, which is sized 150x100? No scaling, and destination x,y at 0,0 in bitmap B is fine.

On 30/08/2017 at 06:11, xxxxxxxx wrote:

Hi Daniel, thanks for writing us.

With reference to your concerns I confirm that BaseBitmap::CopyPartTo() doens't do the work you're looking for nor the ScaleBicubic does. The fastest way to make it working is arranging something like this:

const Bool CopyBitmapToLargerBitmap(BaseBitmap *sourceBmp, BaseBitmap *destBmp, const Int32 xOffset, const Int32 yOffset)  
  if (!sourceBmp || !destBmp)  
      return false;  
  // check sizes  
  if (sourceBmp->GetBh() + yOffset > destBmp->GetBh() || sourceBmp->GetBw() + xOffset > destBmp->GetBw())  
      GePrint("Copying buffer from source to dest failed.");  
      return false;  
  // allocate buffers and res variable  
  Bool res = true;  
  UChar* sourceBuf = NewMemClear(UChar, sourceBmp->GetBw() * 3);  
  UChar* destBuf = NewMemClear(UChar, destBmp->GetBw() * 3);  
  if (!sourceBuf || !destBuf)  
      GePrint("Copying buffer from source to dest failed.");  
      return false;  
  // loop through the pixels and copy accordingly  
  for (Int32 y = yOffset; y < destBmp->GetBh() && y - yOffset <= sourceBmp->GetBh(); ++y)  
      sourceBmp->GetPixelCnt(0, y - yOffset, sourceBmp->GetBw(), sourceBuf, COLORBYTES_RGB, COLORMODE_RGB, PIXELCNT_0);  
      for (Int32 x = 0; x < sourceBmp->GetBw() * 3; ++x)  
          destBuf[x + xOffset * 3] = sourceBuf[x];  
      res &= destBmp->SetPixelCnt(0, y, destBmp->GetBw(), destBuf, COLORBYTES_RGB, COLORMODE_RGB, PIXELCNT_0);  
  // delete the allocated buffers  
  return res;  

This should work as expected even with x/y offset (in case you need it)
Cheers, Riccardo.

On 30/08/2017 at 11:50, xxxxxxxx wrote:

Hello Riccardo,
I was so focused on the available methods for scaling and copying that I completely overlooked the "low level" functions to get/set pixels.
Thank you for the example code.

However, from the documentation I still get the impression that ScaleBicubic should be able to simply copy without scaling. Or did I misinterpret the doc?
I was looking for a one-liner solution to copy from/to bitmap, so maybe I was reading in the documentation what I wanted to have, not what it actually does.

Thanks again for the working example.

On 31/08/2017 at 00:35, xxxxxxxx wrote:

Hi Daniel, yesterday i also gave a go to the ScaleBicubic function and I confirm that in the end there's nothing (in the docs) preventing it to be used the way you intended to but in the end it didn't worked.

The method is also more complex than expected and this didn't gave me yday the chance to investigate what's getting wrong right there.

I'll look at it again and get back to you.

Best, Riccardo