I have a MySQL database that saves customer signatures as base64 BLOB field. Is there a way to show that data as an image on the report using TDBImage?
You can use the TDBImage.OnGetPicture event to get the image data before it is assigned to the Picture property. Inside this event, you would need to retrieve the encoded image data, decode it, and assign it to the aPicture parameter.
ReportBuilder does not have the ability to decode base64 data automatically. When needed, we use the NetEncoding routines to do so:
It appears you are trying to accomplish this in RAP. RAP does not support the complete Delphi object library so pass-thru function(s) will need to be used to decode the image data. See the main RAP demo for how to implement RAP Pass-thru functions.
My suggestion is to get this working in Delphi first to be sure the streaming and decoding is functioning correctly. Then move your code to RAP including pass-thru functions for the unsupported aspects (TNetEncoding, TMemoryStream, etc.).
I once had a case where base64 data was stored in memo/text fields.
So, I created a RAP system function, placed an image component on the form, and then passed both the base64 string and the image component to a function.
TmyUserGetBase64ToPicture = class (TraSystemFunction) public class function Category: string; override; end;
TmyGetUserGetBase64ToPicture = class (TmyUserGetBase64ToPicture) procedure ExecuteFunction(aParams: TraParamList); override; class function GetSignature: string; override; end;
class function TmyGetUserGetBase64ToPicture.GetSignature: string; begin result := 'function GetBase64ToPicture(b64string:string; var myPicture:TPicture):Boolean;'; end;
class function TmyUserGetBase64ToPicture.Category: string; begin result := 'MyFuncs' ; end;
procedure TmyGetUserGetBase64ToPicture.ExecuteFunction(aParams: TraParamList); var cString: string; myPicture: TPicture; lbResult: boolean; begin GetParamValue(0, cString); GetParamValue(1, myPicture);
myPicture.Bitmap := nil; if cString <> '' then begin lbResult := GetBase64ToPicture(cString, myPicture); end else lbResult := False;
function GetBase64ToPicture(const b64string: string; var myPicture: TPicture): Boolean; var DecodedBytes: TBytes; ByteStream: TBytesStream; Base64Content: string; CommaPos: Integer; begin Result := False;
// Check if there is a data URL prefix and remove it if necessary CommaPos := Pos(',', b64string); if CommaPos > 0 then Base64Content := Copy(b64string, CommaPos + 1, MaxInt) else Base64Content := b64string;
// Decode base64 string into bytes DecodedBytes := TNetEncoding.Base64.DecodeStringToBytes(Base64Content);
// Convert bytes to a stream and load into TPicture ByteStream := TBytesStream.Create(DecodedBytes); try myPicture.LoadFromStream(ByteStream); Result := True; finally ByteStream.Free; end; end;
Then, the base64 string is read into the image (TPicture) component.
Comments
You can use the TDBImage.OnGetPicture event to get the image data before it is assigned to the Picture property. Inside this event, you would need to retrieve the encoded image data, decode it, and assign it to the aPicture parameter.
ReportBuilder does not have the ability to decode base64 data automatically. When needed, we use the NetEncoding routines to do so:
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
I tried with a TStream, but also have a problem RB not knowing TMemoryStream. How do I add uses System.NetEncoding, to the RP template?
It appears you are trying to accomplish this in RAP. RAP does not support the complete Delphi object library so pass-thru function(s) will need to be used to decode the image data. See the main RAP demo for how to implement RAP Pass-thru functions.
My suggestion is to get this working in Delphi first to be sure the streaming and decoding is functioning correctly. Then move your code to RAP including pass-thru functions for the unsupported aspects (TNetEncoding, TMemoryStream, etc.).
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
just read this.
I once had a case where base64 data was stored in memo/text fields.
So, I created a RAP system function, placed an image component on the form, and then passed both the base64 string and the image component to a function.
TmyUserGetBase64ToPicture = class (TraSystemFunction)
public
class function Category: string; override;
end;
TmyGetUserGetBase64ToPicture = class (TmyUserGetBase64ToPicture)
procedure ExecuteFunction(aParams: TraParamList); override;
class function GetSignature: string; override;
end;
class function TmyGetUserGetBase64ToPicture.GetSignature: string;
begin
result := 'function GetBase64ToPicture(b64string:string; var myPicture:TPicture):Boolean;';
end;
class function TmyUserGetBase64ToPicture.Category: string;
begin
result := 'MyFuncs' ;
end;
procedure TmyGetUserGetBase64ToPicture.ExecuteFunction(aParams: TraParamList);
var
cString: string;
myPicture: TPicture;
lbResult: boolean;
begin
GetParamValue(0, cString);
GetParamValue(1, myPicture);
myPicture.Bitmap := nil;
if cString <> '' then
begin
lbResult := GetBase64ToPicture(cString, myPicture);
end
else lbResult := False;
SetParamValue(0, cString);
SetParamValue(1, myPicture);
SetParamValue(2, lbResult);
end;
Function to Decode Base64 and Assign to TPicture
function GetBase64ToPicture(const b64string: string; var myPicture: TPicture): Boolean;
var
DecodedBytes: TBytes;
ByteStream: TBytesStream;
Base64Content: string;
CommaPos: Integer;
begin
Result := False;
// Check if there is a data URL prefix and remove it if necessary
CommaPos := Pos(',', b64string);
if CommaPos > 0 then
Base64Content := Copy(b64string, CommaPos + 1, MaxInt)
else
Base64Content := b64string;
// Decode base64 string into bytes
DecodedBytes := TNetEncoding.Base64.DecodeStringToBytes(Base64Content);
// Convert bytes to a stream and load into TPicture
ByteStream := TBytesStream.Create(DecodedBytes);
try
myPicture.LoadFromStream(ByteStream);
Result := True;
finally
ByteStream.Free;
end;
end;
Then, the base64 string is read into the image (TPicture) component.
Hope this helps!
Best Regards,
Ralf