Is there a way to use a custom icon file for a marker
that is not hosted on a WebServer?
The samples show the custom icon file as a Web hosted
URL.
I have found some posts regarding custom markers that use
a non-URL file name when adding a Marker.
Icon :=
"abc.png";
TMSFMXWebGmaps1.Markers.Add(Latitude, Longitude, Description, Icon,
false, true, true, true, false, 0);
I found that when I compile in Windows 64 debug mode, My
custom Icon image does not show unless I compile with a fully qualified path
name such as Icon :=
"C:\temp\abc.png".
If I leave the Icon property blank, I get the default as
expected.
When I compile into IOSDevice64 even with a fully
qualified path name, I do not get an icon on my device.
Is there a way to compile my app with the custom icon and
have it deployed to the device so I do not have to get the image from Web Host?
I show markers on GMaps, that are even stored in a TImageList and are encoded in base64 on showing them. So you don't have to supply additional files with your app.
Thanks for the reply, Stefan.
I
checked out the post you referenced but am not sure how I would
implement the solution using the TMS Software GMaps Components in Delphi
RIO. I was able to use an ImageList and bitmaps with other components
and thought I could do the same with the GMaps components.
I
also issued this question directly to TMS Support and received an
answer that local image files are not currently supported on IOS.
I guess I will have to use images from a Web Host.
Instead of an URL or local path to an image file, you just post a string, that has a PNG image (from an ImageList) encoded in base64 encoding.
This should work independently from the OS and such, as this is a feature of the Google Maps API and its web server.
Thanks again for the response Stefan.
I will look into your suggestion to see how I can integrate it into my application.
Leonard
Here's a start (the interface might be different from what you have, as I have extended the methods of TMarker):
WebGMap.Markers.Add(GPSTracks[Track].Startpoint.Latitude, GPSTracks[Track].Startpoint.Longitude, //Koordinaten
StringToMarkerTitle(GPSTracks[Track].Startpoint.ToMarkerTitle('Start', MyFormatSettings)), //Titel
Encode64(pilMarkerImages.PngImages[pilStartpoint].PngImage), //Icon, Base64-Encoded oder File-URI
False, //Draggable
True, //Visible
True, //Clickable
True, //Flat
TMarkerAnimation(rgGMMarkerAnimation.ItemIndex), //Animation
ziMarkerStartEnd, //zIndex
MarkerCoordinates[pilStartpoint].Width, //IconWidth
MarkerCoordinates[pilStartpoint].Height, //IconHeight
-1, //IconZoomWidth
-1, //IconZoomHeight
MarkerCoordinates[pilStartpoint].AnchorWidth, //IconAnchorWidth
MarkerCoordinates[pilStartpoint].AnchorHeight, //IconAnchorHeight
0, //IconOriginWidth
0 //IconOriginHeight
);
function Encode64(Src, Dest: TStream): Boolean;
const
Map: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'+
'abcdefghijklmnopqrstuvwxyz'+
'0123456789+/';
var
Size: Integer;
Data: array[0..2] of Byte;
EncodedData: array[0..3] of AnsiChar;
begin
Result:=false;
if not assigned(Src) or not assigned(Dest)
then Exit;
while Src.Position<Src.Size do
begin
Size:=Src.Read(Data,SizeOf(Data));
EncodedData[0]:=Map[Data[0] shr 2];
EncodedData[1]:=Map[((Data[0] shl 4) or (Data[1] shr 4)) and $3F];
EncodedData[2]:=Map[((Data[1] shl 2) or (Data[2] shr 6)) and $3F];
EncodedData[3]:=Map[Data[2] and $3F];
case Size of
0: Exit;
1: begin
EncodedData[2]:='=';
EncodedData[3]:='=';
end;
2: EncodedData[3]:='=';
3: ;
end;
Dest.Write(EncodedData,SizeOf(EncodedData));
end;
end;
function Encode64(Data: TStream; const MediaType: String): String;
var
Stream: TStringStream;
begin
Result := '';
if not assigned(Data)
then Exit;
Stream := TStringStream.Create('data:'+MediaType+';base64,');
try
Stream.Seek(0, soFromEnd);
Encode64(Data, Stream);
Stream.Seek(0, soFromBeginning);
Result := Stream.DataString;
finally
Stream.Free;
end;
end;
function Encode64(Image: TPNGImage): String;
var
Stream: TMemoryStream;
begin
Result := '';
if not assigned(Image)
then Exit;
Stream := TMemoryStream.Create;
try
Image.SaveToStream(Stream);
Stream.Seek(0, soFromBeginning);
Result := Encode64(Stream, 'image/png');
finally
Stream.Free;
end;
end;
The sources for encode64() are from the net somewhere I can't remember.
The PNG image is loaded from pilMarkerImages, a TPNGImageList.
Thanks for the code, Stefan,
I found and installed the pngcomponents from here:
The documentation says it should be Delphi RIO compatible.
However, I am getting compiler errors when trying to use the components.
[dcc64 Error] pngzlib.pas(149): E2045 Bad object file format: '..\Components\PNGComponents-master\PngObject\obj\adler32.obj'.
[dcc64 Error] pngzlib.pas(45): E2065 Unsatisfied forward or external declaration: 'inflateInit_'
I like your solution and will work on the compiler errors when I come back from holidays in a week. :)
I appreciate all your help.
Here are the original PNGComponents by Uwe Raabe, that I'm using since ages.
Though not officially stated, they work fine with Rio.
https://bitbucket.org/uweraabe/pngcomponents/src/default/