3

I am struggling to understand if there is really a difference between both statements:

Image->Picture->Bitmap = bitmap; // bitmap is a TBitmap object
Image->Picture->Assign(bitmap);

The VCL help clearly says about the assignment via =:

Note: When assigning the Bitmap property, TPicture assigns the properties of a another TBitmap object. It does not take ownership of the specified value.

This means that the first statement does NOT copy the bitmap into Image->Picture->Bitmap but just the address of the bitmap is taken over by Image->Picture->Bitmap.

Why is then Image->Picture->Bitmap displaying the picture on the screen correctly even after I deleted the bitmap object?

asked Apr 28 at 3:25
8
  • 2
    Pure, unadulterated luck? Commented Apr 28 at 4:02
  • 4
    Welcome to UB (Undefined behavior) land. An incorrect program might still seem to show "normal" behavior (which is kind of "worst case", and that's what @Dúthomhas calls it bad luck) Commented Apr 28 at 4:11
  • There is no UB in this code. The behavior is quite well defined Commented Apr 28 at 5:33
  • @RemyLebeau - can you explain? I had the same feeling that there is no UB, but the statement of the VCL help is contradictary to the behavior. Are both statement above equal? Commented Apr 28 at 5:36
  • There is no UB in the shown code, but your last statement seems to indicate you do delete the bitmap at some point while you are still holding a reference to it. When you use Assign you should not delete the bitmap at a later point without removing it from picture first. Commented Apr 28 at 5:45

1 Answer 1

8

The two statements are functionally equivalent.

In this statement:

Image->Picture->Bitmap = bitmap;

What the documentation does not say, but what actually happens, is the TPicture::Bitmap property setter calls Assign() on the TBitmap returned by the TPicture::Bitmap property getter. IOW, it is identical to calling this:

Image->Picture->Bitmap->Assign(bitmap);

Where TPersistent::Assign() copies data from one object to another compatible object. In this case, TBitmap overrides Assign() to copy the pixel data from another TBitmap.

The TPicture::Bitmap property getter ensures the TPicture holds its own TBitmap, creating a new one if it does not already have one, and freeing any previous non-bitmap graphic.

This is roughly equivalent to doing this:

if (!dynamic_cast<TBitmap*>(Image->Picture->FGraphic))
// or:
// if ((Image->Picture->FGraphic != NULL) &&
// (!Image->Picture->FGraphic->InheritsFrom(__classid(TBitmap))))
{
 TBitmap *newBmp = new TBitmap;
 delete Image->Picture->FGraphic;
 Image->Picture->FGraphic = newBmp;
}
static_cast<TBitmap*>(Image->Picture->FGraphic)->Assign(bitmap);

In this statement:

Image->Picture->Assign(bitmap);

TPicture overrides the Assign() method to create a new TBitmap that is a copy of the passed bitmap and then takes ownership of it, freeing any previous graphic.

This is roughly equivalent to doing this:

TBitmap *newBmp = new TBitmap;
newBmp->Assign(bitmap);
delete Image->Picture->FGraphic;
Image->Picture->FGraphic = newBmp;

So, in both cases, the TPicture ends up holding its own TBitmap that has copied the data from the passed bitmap.

This means that the first statement does NOT copy the bitmap into Image->Picture->Bitmap but just the address of the bitmap is taken over by Image->Picture->Bitmap.

That is not correct, and counter to the documentation you quoted. Taking just the address would be taking ownership, and that is exactly what the documentation explicitly says does not happen.

Why is then Image->Picture->Bitmap displaying the picture on the screen correctly even after I deleted the bitmap object?

Because the TPicture has made its own copy of the pixel data. What you do with the original bitmap afterwards doesn't affect the TPicture at all.

answered Apr 28 at 5:53
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.