Как сделать конвертер LiveBinding из TBlob в TBitmap

Мое программное обеспечение в значительной степени основано на Firemonkey TListView, которое было настроено на основе "SampleListViewMultiDetailAppearanceProject", найденного в проекте Delphi Samples.

"C: \ Users \ Public \ Documents \ Embarcadero \ Studio \ 14.0 \ Samples \ Object Pascal \ Mobile Samples \ Пользовательский интерфейс \ListView\"

Вот как это выглядит, используя PrototypeBindSource:

Образец TListView

Каждая запись показывает 1 изображение и 4 текстовых элемента.

Я использую TMS Aurelius в качестве набора данных, который подключен к BindSource. Это потомок TDataset, использующий все стандартные типы полей.

Он реализует TBlobField, который внутренне является:

  TBlob = record
  private
    FIntData: TArray<byte>;

В DataSet это поле определено "как" вычисляемое поле, так как оно представляет собой основанную на сущности структуру (ORM), каждая запись представляет объект, но в конце то же самое, извлеченные данные - это поле с необработанными данными.

Мое намерение состоит в том, чтобы установить различные изображения, загруженные из ресурсов проекта (проект-> ресурсы и изображения), в соответствии с некоторым состоянием записи. Сохраненное изображение является небольшим PNG-изображением (48x48).

Чтобы прочитать изображение PNG, хранящееся на ресурсе, я использую это:

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;

Когда TBlobField извлекается системой livebinding, вызывается функция:

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

  result := FImage;
end;

FImage - это тип TBlob с некоторой вспомогательной функциональностью, но, как я уже сказал, это TArray, и здесь нет обработки какого-либо типа, только контейнер.

Итак, FImage направляется непосредственно к TBitmap FMX TListView.

Ничего не происходит, изображение не отображается.

Я пробовал следующий код:

  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
    ));

Получил этот код от другого вида конвертации, не связанной с изображением. Но это явно неправильно, кроме того, что компилируется.

Проблемы в этом коде: - кажется, что он зарегистрирован, я установил точку останова, и RegisterConversion действительно выполняется, но точка прерывания внутри, в анонимной процедуре, никогда не выполняется. Я регистрирую это в части инициализации перед созданием любого фрейма, который содержит TLisviews. - само преобразование в анонимной процедуре является чистой выдумкой; поскольку я считаю, что BLOB-объект хранится в формате png, а на выходе должно быть растровое изображение fmx. Понятия не имею, что там написать.

Документация по этой теме недостаточна и не помогает в моем понимании.

Я хотел бы знать, как правильно сделать последовательности в этом процессе:

  • мне нужно конвертировать из PNG в растровое изображение? как?
  • мне нужно зарегистрировать адаптер преобразования? как? Почему не увольняют?
  • Какой правильный код преобразования находится внутри этого адаптера преобразования?

ИЛИ ЖЕ

Я вижу, что в TDataset есть ftGraphic TField, и я могу создать поле этого типа. Но есть следующие проблемы: - Какова ожидаемая доходность TField для такого типа? - Мой код распределяется между платформами: VCL и FMX, а TBitMap или TGraphic не одинаковы на обеих. Этот обмен сделан пакетом bpl, который не ограничен. Это необходимо, так как у меня были зарегистрированы конфликты других bpls. У меня есть один общий общий bpl и другие специфичные для платформы bpl, которые его используют.

Поскольку я не нашел способа решить проблему совместного использования bpl и несовместимости модулей платформы, я перешел к первому варианту, пытаясь работать с необработанными данными на уровне базы данных, и позволяя преобразованию происходить на уровне livebinding, уже в домене каждой платформы.

Я совершенно невежественен в отношении манипуляций с изображениями, особенно когда речь идет о преобразовании и правильном создании объектов, чтобы избежать утечки памяти.

ВАЖНО: он также должен быть кроссплатформенным, так как приложение fmx используется на Android.

1 ответ

Решение

Там нет необходимости делать какие-либо преобразования.

Следуя информации Дэвида Хеффернана о том, что TBitmap в FMX распознает формат PNG, естественно, я обнаружил, что ошибка была в том, как я вызывал свою функцию AssignResource:

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

однако это правильно:

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

Внесение этих изменений исправило проблемы и недели поиска и мучений.

Другие вопросы по тегам