2

My software is heavily based on Firemonkey TListView, that was customized based on the "SampleListViewMultiDetailAppearanceProject" found in the Delphi Samples project.

"C:\Users\Public\Documents\Embarcadero\Studio\14.0\Samples\Object Pascal\Mobile Samples\User Interface\ListView\"

This is how it looks like, using a PrototypeBindSource:

TListView Sample

Each record shows up 1 image and 4 text items.

I am using TMS Aurelius as a dataset, that is connected to a BindSource. It is a TDataset descendant using all the standard field types.

It implements the TBlobField that internally is:

  TBlob = record
  private
    FIntData: TArray<byte>;

On the DataSet this field is defined "like" a calculated field, since it is an entity based framework (ORM) each record represent an object, but at the end is the same stuff, the data retrieved is a field with raw data.

My intention is to set different images, loaded from the project resources (project->resources and images), according some state of the record. The image stored is a small PNG image (48x48).

To read the PNG image stored from resource I am using this:

procedure TEntity.AssignResource(AName: String; ABlob: TBlob);
var
  InStream: TResourceStream;
begin
  InStream := TResourceStream.Create(HInstance, AName, RT_RCDATA);
  try
    ABlob.LoadFromStream(InStream);
  except
    InStream.Free;
  end;
end;

When the TBlobField is retrieved by the livebinding system, the function called is this:

function TEntity.GetImage: TBlob;
begin
  if FImage.IsNull then
    AssignResource('default', FImage);

  result := FImage;
end;

FImage is a TBlob type with some helper functionality, but like I said is a TArray and there is no processing of any type, just a container.

So, FImage is going directly to the TBitmap of the FMX TListView.

Nothing happens, no image is displayed.

I have tried the following code:

  TValueRefConverterFactory.RegisterConversion(TypeInfo(TBlob), TypeInfo(TBitMap), TConverterDescription.Create(

    procedure(const I: TValue; var O: TValue)
    var
      Blob: TBlob;
      BitMap: TBitMap;
    begin
      Blob := I.AsType<TBlob>;

      BitMap := O.AsType<TBitMap>;
    end,

    'BlobToBitMap' + GetTypeName(TypeInfo(TBlob)), 'BlobToBitMap' + GetTypeName(TypeInfo(TBitMap)), 'Nahar.LiveBinding', True, '', nil
    ));

Got this code from other kind of conversion not related to image. But it is clearly wrong, besides the fact it compiles.

Problems in this code: - it seems to get registered, I placed a breakpoint, and the RegisterConversion does get executed, but a breakpoint inside, in the anonymous procedure, is never executed. I am registering this on the initialization part before any frame is created that contains TLisviews. - the conversion itself, in the anonymous procedure, is pure fiction; since I believe the Blob is stored as png and the output should be fmx bitmap. I have no idea what to write there.

The documentation is scarce on this topic and not helpful for my understanding.

I would like to know how to proper make the sequences on this process:

  • do I need to convert from png to bitmap? how?
  • do I need to have to register the conversion adapter? how? Why is not getting fired?
  • What is the correct conversion code inside this conversion adapter?

OR

I see there is a ftGraphic TField on TDataset, and I can create a field of that type. But there are this problems: - What is the expected TField return for such type? - My code is shared between platforms: VCL and FMX, and TBitMap or TGraphic are not the same on both. This sharing is made by a bpl package that is not scoped. It is needed since I was having conflicts of other bpls registered. I have one shared common bpl and others platform specific bpl that uses it.

Since I have not found a way to solve this bpl sharing and incompatibility of platform units I switched to the first option, trying to deal with raw data at database level, and letting the conversion happens at livebinding level, already in the domain of each platform

I am a complete ignorant related to image related manipulation specially when it comes to conversion and the correct object creation, to avoid memory leaking.

IMPORTANT: it has to be cross platform either, since the fmx application is used on android.

Eduardo Elias
  • 1,742
  • 1
  • 22
  • 49
  • `ftGraphic` is a bitmap, as is stated in the [documentation](http://docwiki.embarcadero.com/Libraries/XE6/en/Data.DB.TFieldType). It's based on the VCL.Graphics bitmap. – Ken White Aug 13 '14 at 01:27
  • 1
    @KenWhite ok, but is the same bitmap for FMX? For the little I know seems to have 2 different bitmaps not direct compatible. And the problem is that using ftGraphic i will need to add the units that are not common for both VCL and FMX, and at the end I cannot generate my common bpl that uses the entities and should be platform agnostic. – Eduardo Elias Aug 13 '14 at 02:07
  • 1
    My point was that a) it's a bitmap, and b) it's a VCL bitmap. Note that there's no FMX there anywhere, and no mention of the PNG format you said you were using. `ftGraphic` has been around since Delphi 1 and before, in the days of Paradox being a major database type. It's not appropriate for what you're trying to do here. (And I can't answer your question, or I would have done so instead of posting a comment. I was just noting that one of the options you had mentioned was most likely not going to be useful.) If the `ftGraphic` field type is based on VCL.Graphics, it's not the proper type. – Ken White Aug 13 '14 at 02:16
  • 1
    @KenWhite Sorry to not be clear. The question was tagged Firemonkey, I should be clearer on the text. I have edited and added that the TListVIew is a Firemonkey one. And that the Image retrieved from the project resource is of PNG type. (however it was there). – Eduardo Elias Aug 13 '14 at 02:24
  • :-) No, you misunderstood what I said. The question was clearly about FMX; I was saying that `ftGraphic` was not proper **because** your question was about FMX, and because `ftGraphic` has been around since before PNGs existed. Your question was fine, but `ftGraphic` isn't really an option you should be considering. – Ken White Aug 13 '14 at 02:53
  • @eelias What Ken's trying to tell you is that you're asking us how to essentially put a square block into a triangle hole. The answer is that you can't. – Jerry Dodge Aug 13 '14 at 04:02
  • AssignResource is odd. It swallows exceptions. Why? And the `if Assigned()` test is needless. Remove that. No need for png to bmp conversions. The fmx TBitmap is based on png. – David Heffernan Aug 13 '14 at 06:31
  • @JerryDodge I have got the message :) but i was trying to put down all the possibilities I have to make a complete question. – Eduardo Elias Aug 13 '14 at 11:11
  • @DavidHeffernan if tbitmap is png why is not showing, I followed the code and found that livebingind is doing the connection: TPersistent(oOut).Assign(TPersistent(oIn)) (at system.bindings.outputs) if there is no need of conversion why is not showing? – Eduardo Elias Aug 13 '14 at 11:21
  • What I am saying is that you simply write `Bitmap.LoadFromStream(RscStream)` where `RscStream` is the resource stream containing the PNG file. You don't need to convert from PNG to bitmap explicitly because an FMX `TBitmap` already understands PNG and loads it natively. And the exception swallowing? Are you happy with that? – David Heffernan Aug 13 '14 at 11:36
  • @DavidHeffernan I understood the bitmap<>png part. What I am not happy is with the image not showing, the rest I can fix. – Eduardo Elias Aug 13 '14 at 11:51
  • You asked *do I need to convert from png to bitmap? how?* which led to my comments – David Heffernan Aug 13 '14 at 11:53

1 Answers1

2

There is no need to make any conversion.

Following David Heffernan information that TBitmap in FMX recognizes the PNG format naturally I have found that the error was in the way I was calling my AssignResource function:

procedure TEntity.AssignResource(AName: String; ABlob: TBlob);

however this is the correct:

procedure TEntity.AssignResource(AName: String; VAR ABlob: TBlob);

Making this change corrected the problems and weeks of searching and agony.

Eduardo Elias
  • 1,742
  • 1
  • 22
  • 49