Как сделать конвертер LiveBinding из TBlob в TBitmap
Мое программное обеспечение в значительной степени основано на Firemonkey TListView, которое было настроено на основе "SampleListViewMultiDetailAppearanceProject", найденного в проекте Delphi Samples.
"C: \ Users \ Public \ Documents \ Embarcadero \ Studio \ 14.0 \ Samples \ Object Pascal \ Mobile Samples \ Пользовательский интерфейс \ListView\"
Вот как это выглядит, используя PrototypeBindSource:
Каждая запись показывает 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);
Внесение этих изменений исправило проблемы и недели поиска и мучений.