Labelling points with attached photos

3934
8
01-26-2022 04:29 AM
Labels (1)
MatthewLaw_MM
New Contributor III

Could anyone help me work out how to use photos, stored as attachments, to label points in ArcGIS Pro?

From the documentation here (shown in the screenshot below), I'm fairly sure that this is possible, but I can't work out how to go about doing it and haven't been able to find any walkthroughs/tutorials/similar questions.

MatthewLaw_MM_0-1643199279392.png

I have a layer of points with images attached as below:

MatthewLaw_MM_1-1643199881045.png

and have got as far as trying to set attribute-level image marker symbols for the points, but when I click the highlighted button to set the attribute mapping, there are no available options to use the attached images.

MatthewLaw_MM_2-1643199968621.png

Do I need to attach the images in a different format in order to be able to use them in this context?

Additionally (and I fear this may be a deal breaker), I need the actual points to be visible, ie the images should be plotted around the points and not directly on top of them, ideally using the labelling engine used for text labels. There are several areas where there are many points close to each other, and so if I can't control where the images get plotted relative to the point location, I'll end up with lots of images on top of each other and their corresponding points obscured.

0 Kudos
8 Replies
jcarlson
MVP Esteemed Contributor

In order to place things using the labeling engine, they've got to be labels. But within the labeling settings, you can configure a point symbol to function as a label. I think that's under callout or background, but I'm not at my workstation with Pro at the moment.

Labels don't have quite the same ability to access feature attributes, though. And even if they could, I am not sure that an attachment can be accessed in this way... For instance, how would Pro know which attachment to use, in the event that there were multiple? And what if the attachment were not an image?

- Josh Carlson
Kendall County GIS
MatthewLaw_MM
New Contributor III

Thanks for your speedy response Josh! I've tried to get the functionality I want using labels before, but run into the issue you mention of labels not being able to access feature attributes in the same way that point marker symbols can (or at least should be able to) - do you think there would be any way to do what I want without using labels themselves?

0 Kudos
JohannesLindner
MVP Frequent Contributor

A working, but basic approach:

  1. Join the Attachment table to the feature class.
    JohannesLindner_1-1643210744993.png

  2. You can now choose the DATA field of the attachment table as input for the picture marker
    JohannesLindner_2-1643210883792.png

     

Basically, that's it. To make it prettier:

  1. Set size and quality, set position to "Center bottom"
    JohannesLindner_3-1643211071173.png

     

  2. Add a marker layer on top of the picture layer, style it
    JohannesLindner_4-1643211172494.png

     

  3. rotate the whole symbol using a rotation field
    JohannesLindner_5-1643211268989.png

     

 

 

Before:

JohannesLindner_0-1643210513139.png

After:

JohannesLindner_6-1643211316927.png

 

I'm sure you could hack together a border around the picture somehow.

Unlike labels, symbols don't seem to have options for dynamic placement. Position and offset are either taken as values provided by the user or by a table field.

 

I haven't found a way to use labels for this task. You can't use the Attachments() and FeatureSetBy*() function in the Arcade label expression, and the DATA field of the joined attachment table is also not available.

 

I thought I had something using a Python label expression and trying to return an HTML <img> tag with a data uri, but it doesn't seem to work (it's because there are only a few text formatting tags allowed; I'll still leave the code here, maybe it helps):

def FindLabel([GlobalID]):
    import arcpy
    import base64
    att_table = 'path:/to/database.sde/Fotos__ATTACH'
    sql = "REL_GLOBALID = '{}'".format([GlobalID])
    cur = arcpy.da.SearchCursor(att_table, ['CONTENT_TYPE', 'DATA'], sql)
    for row in cur:
        b64 = base64.encodebytes(row[1])
        data_uri = 'data:{};base64,{}'.format(row[0], b64)
        #return data_uri[:30]  # this returns the start of the data_uri correctly
        return '<img src="{}"/>'.format(data_uri)  # this returns without error, but doesn't do anything
    return "N/A"

 

Don't know anything about JScript, maybe you can do something with that.


Have a great day!
Johannes
MatthewLaw_MM
New Contributor III

Thanks Johannes! What format do the photos in the attachment table need to be? The ones I have now are saved as attachments (I think they were collected via Field Maps and automatically stored in this way) but I also have them all downloaded to a local folder so could re-upload as a given file type if necessary.

And do you think there would be a way to dynamically offset all the labels so that the points don't get obscured (maybe in Python)? If not, seeing as using actual labels won't work with feature-level attribute mapping, I don't think I'm going to be able to do what I want/need to.

0 Kudos
JohannesLindner
MVP Frequent Contributor

What format do the photos in the attachment table need to be?

The field mapping only recognizes BLOB (Binary Large OBject, so byte data) fields. If you have an ArcGIS Attachment table, there should be a BLOB field in there. If not, you can also create a BLOB field in your feature class and store the images there.

 

And do you think there would be a way to dynamically offset all the labels so that the points don't get obscured (maybe in Python)?

Dynamically? Probably not, for that you need to work with labels, not symbology. Maaaaaybe with Point Clustering in 2.9, but it doesn't seem likely.

With Python? You could map X and Y offset to fields in your feature class. You could then calculate these fields with Python, using the distance to nearby points as input. This could work for a fixed map scale and picture marker size. But as soon as you zoom out, the images will overlap each other again.

A simple approach to that with Arcade:

// calculate field OffsetX

// load other features
var gid = $feature.GlobalID
var fs = Filter(FeatureSetByName($datastore, "FeatureClass"), "GlobalID <> @gid")
// get nearby features
var nearby_features = Intersects(fs, Buffer($feature, 50))
// gravitational force in horizontal direction
var force = 0
for(var f in nearby_features) {
  var dist = Distance($feature, f)
  var dx = Geometry(f).X - Geometry($feature).X
  force -= dx / (dist * dist)
}
// magical number dependent on map scale and picture marker size
var magic_factor = 100

return force * magic_factor
// calculate field OffsetY

// load other features
var gid = $feature.GlobalID
var fs = Filter(FeatureSetByName($datastore, "FeatureClass"), "GlobalID <> @gid")
// get nearby features
var nearby_features = Intersects(fs, Buffer($feature, 50))
// gravitational force in vertical direction
var force = 0
for(var f in nearby_features) {
  var dist = Distance($feature, f)
  var dy = Geometry(f).Y - Geometry($feature).Y
  force -= dy / (dist * dist)
}
// magical number dependent on map scale and picture marker size
var magic_factor = 100

return force * magic_factor

 

Without offsets:

JohannesLindner_0-1643285830423.png

 

With offsets:

JohannesLindner_1-1643286262933.png

 

But it only works for a fix scale. When you zoom out, the images overlap again:

JohannesLindner_2-1643286369465.png

 


Have a great day!
Johannes
LindsayRaabe_FPCWA
Occasional Contributor III

Hi Johannes. I'm keen to try this out (while I patiently wait for the Dev team as ESRI to implement my ideas below!). Could this be done using ArcGIS Online feature service features and attachments? I can't figure out where to find the attachments table data source path to try. Don't want to have to download attachments if possible!

Add feature attachment as callout to map - Esri Community

Create dynamic feature attachment element in ArcGI... - Esri Community

Lindsay Raabe
GIS Officer
Forest Products Commission WA
0 Kudos
JohannesLindner
MVP Frequent Contributor

I don't think so.

Attachments in AGOL/Portal aren't stored as joinable table. Instead, each attachment has its own url:

"portal/rest/services/ServiceName/FeatureServer/LayerID/FeatureOID/attachments/AttachmentID"

For example:

"https://services.arcgis.com/xxxyyyzzz/arcgis/rest/services/TestService/FeatureServer/1/5/attachments/5"

 

Things I tried:

  • I haven't found a way to use that url in the symbology. The picture marker layer expects the actual byte data, not a path to the data.
  • I tried calculating a BLOB field with the Arcade Attachments() function, but that doesn't return the actual data.
  • I tried doing the join and symbology in Pro before publishing, but "in-memory joins are not supported"
  • I tried including the attachment table in the feature service, but it got removed when I published
  • I tried to publish the attachment table as standalone service, but I got the "Staging failed" error and don't want to spend too much time here... I think this is your best bet though, assuming you can publish the attachment table, you could then do the join.

Have a great day!
Johannes
LindsayRaabe_FPCWA
Occasional Contributor III

Thanks for trying - if you tried all that, I doubt I'm going to make it work. Will look at options for modelling a download of the data to feed to a pre-configured layer. 

Lindsay Raabe
GIS Officer
Forest Products Commission WA
0 Kudos