5

I have a control derived from TImage32:

TChromaDisplay = class(TImage32)

Everything is fine except that when I drop my TChromaDisplay on the form, the resulted DFM file is huge (300KB instead of <1KB) because I have garbage data (it is just a gray image) saved in the Bitmap.Data field. The Bitmap image is created and filled with gray color every time I drop my control on a form. I don't want to save the content of the image (garbage) to the DFM file since it makes the EXE larger but I don't know how.

Probably I need to write somewhere in TChromaDisplay.Create that I don't have any image data saved/stored in my TChromaDisplay. But I don't know where/how to do it.

  object Display: TChromaDisplay
    Left = 0
    Top = 0
    Width = 1465
    Height = 246
    Bitmap.Data = {
      C0000000C0000000EBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFF
      EBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFF
      EBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFF
      etc
      etc
      etc

I have tried this in Create but won't help:

Bitmap.Width := 1;
Bitmap.Height:= 1;
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • Anyway the same (setting the 0x0 bitmap size) will also do `Bitmap.Delete`, but still I think it's not a good idea to do so, since `TImage32` creates the bitmap internally in its constructor and this bitmap will have its meaning in the control. How would you handle the need of that bitmap when you try to render something on it for instance ? – TLama Jun 10 '12 at 13:28
  • @TLama - I am painting only Bitmap like this: with Bitmap do Pixels[x, y]:= PixelColor. I don't have other layers. I use Graphics32 only because I want to paint antialised lines. – Gabriel Jun 10 '12 at 13:39
  • Should I call SetupBitmap in Create? – Gabriel Jun 10 '12 at 13:47
  • I think a more suitable title would be `Removing garbage DFM data from TImage32` – Jerry Dodge Jun 10 '12 at 14:22
  • I've tried to simulate what you described with no success. I just used `Component / New VCL Component` and in the wizard I derived the new control from the `TImage32`, but when I put this new control on the form and save it, the form source has no `Bitmap.Data` field stored in the form stream. – TLama Jun 10 '12 at 15:08
  • 1
    @Altar: Can you post the interface and the constructor body of your TChromaDisplay class? – Alan Jun 10 '12 at 15:18
  • If your TChromaDisplay is setup in a package, maybe have you included a Res file ? (then for a reason or another it would contain the default data ?). – az01 Jun 10 '12 at 16:12
  • Try to move Bitmap property outside of published section in your TChromaDisplay component, in public section for example. – pani Jun 10 '12 at 16:46
  • Very stange! By default in Timage32 the Bitmap is Empty, and hence no data should be stored in the dfm. The fact that you have Bitmap data in the DFM tells me that you actually in your derived Timage32 component set the Bitmap size. – iamjoosy Jun 11 '12 at 13:05
  • @iamjoosy. I never call SetupBitmap. This is the procedure that sets the size of the internal Bitmap (to match the size of the control). Otherwise, I don't touch the Bitmap in any way (in the Create constructor) – Gabriel Jun 11 '12 at 20:54

2 Answers2

3

This is not "garbage". It's an image (whether it's one you assigned or one that the control creates in it's constructor). It's a bitmap located at position 0, 0 with a width and height of 1465, 246.

The BitmapData is the data in the bitmap (the pixels, etc.), encoded as a hex string so it will go in the text dfm.

The solution is to figure out how the bitmap is being assigned. It's either:

  • In the component's constructor (a default image?)
  • On your form (you've assigned an image in the IDE)
  • It's not being removed from the DFM from a previous time it was assigned.

The first one requires that you closely examine the source code of the component to figure out where it's being assigned. You can check to see what the bitmap property is called internally (for instance, FBitmap or FImage), and then search for places it gets an image assigned (LoadFromFile, LoadFromStream, LoadFromResource, Assign, and so forth).

The second and third: Backup your dfm just in case. Delete the component from your form. Comment out any code related to it, so your unit will compile. Right-click it, and choose View as Text. Search for TChromaDisplay (or just TChroma), and delete everything you find in the dfm related to it. Right-click and chhose View as Form, and then build your project. Go back into the dfm and make sure all traces of TChroma are still gone.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • The 'garbage' image is created every time I drop the control on form. So, I guess it is created in the constructor of the TImage32. It is just a gray image. – Gabriel Jun 11 '12 at 20:45
  • :-) See my first bullet (and the first paragraph following the bulleted list). I don't have `TImage32` (don't have `Graphics32` installed anywhere currently) to check, but you might be able to get away with creating a descendant and clearing the image (or probably better replacing it with a new 1 x 1 blank image instead). – Ken White Jun 11 '12 at 20:52
  • @altar: The other option would be to not create the component in the IDE, but to create it in code at runtime instead. This would prevent anything from being stored in the .DFM at all. :-) If the position is important, you could put an empty panel in it's place, create the `TChroma` with the panel as it's parent, and size it to fit the panel (or set it's `Alignment` to `alClient`, if it has that property). – Ken White Jun 11 '12 at 22:09
3

Update:

Looking at design time image dialog GR32_Dsgn_Bitmap.pas for TImage32.Bitmap property, the Clear button there uses the Bitmap.Delete procedure what just sets the bitmap size to 0x0. So you can try to call it to clear the bitmap before the form stream is saved:

type
  TChromaDisplay = class(TImage32)
  protected
    procedure WriteState(Writer: TWriter); override;
  end;

implementation

procedure TChromaDisplay.WriteState(Writer: TWriter);
begin
  Bitmap.Delete;
  inherited;
end;

But it still doesn't explain why you have a bitmap data when you put a control on the form. You can also call the Bitmap.Delete in your control constructor after inherited part is done (when the Bitmap is already instantiated).

Still untested, since I can't simulate your problem.

TLama
  • 75,147
  • 17
  • 214
  • 392
  • I doesn't explain why I have the problem but I think it will solve it. – Gabriel Jun 12 '12 at 08:25
  • I couldn't simulate your problem nor understand why would this happen. The `Data` property defined here is used only for storing and loading bitmap data to and from the form source stream, but I don't get why the `WriteData` is invoked when you put the control on the form, keep it without loaded image and save. What version of Delphi are you using anyway ? – TLama Jun 12 '12 at 08:33