Compare ImageFill objects

Is there any way to compare the ImageFill object of two graphicNodes?
I just want to make sure the fileOrDataURI are the same.

1 Like

ImageFill object has no fileOrDataURI property. Try to compare .toString() function results of two ImageFill objects or convert objects to json strings with JSON.stringify and compare them :man_shrugging:

1 Like

The problem here is that it might be possible to check the “outer parameters”, to my knowledge, Adobe XD stores images as part of a .xd file (the last time I’ve checked, at least, that was the case), and not as a reference to some file in your file system (you can easily check this by opening a .xd file on another machine).

Therefore, a fileURI doesn’t exist any longer as soon as XD has imported the image, or at least, it can’t be the same for two objects.

All in all, the only way to really check whether two fills are the same would be to somehow check their actual content, i.e., e.g., a data URI.

To my knowledge, there’s no way to do so directly inside XD (at least, no way is clearly documented). Therefore, the only solution I could image would be to

  1. Create some sort of “neutral rectangle”, which, when exported with a specific image fill, always exports it the same way.
  2. Apply the fill (a clone, thereof, with ImageFill.clone()) to that rectangle and export it programmatically
  3. Read the file and compare its raw data to another set of data fetched this way

While I can’t check right now, I firmly believe this would only compare the “metadata” in the ImageFill, i.e., mimeType, naturalWidth etc., which could be the same in many cases (e.g., multiple portrait photos with 512px*512px). Therefore, this might get you the results you’re looking for, but probably would result in false positives. Also, this would evaluate to false if, say, scaleBehaviour is different, although the image might be the same (which is what should get compared here).

Basically, that’s probably a question someone from Adobe has to answer, but I’m rather sure there’s no trivial way to check fills’ image datas for equality.

PS: @wata.hia Welcome to the forums :wave:!

2 Likes

.toString() of ImageFill object returns something like ImageFill(/Users/user/Downloads/image.png) (for file), so first will be equal to second (in case of original question - fileOrDataURI are the same). Anyway, need to clarify the original question: need to compare fileUrl/base64 strings only, or compare whole objects, or compare raw content of images.

3 Likes

Wow, that’s interesting. I’ll have to check what happens when one opens an XD document on another machine. It wouldn’t be exactly ideal when an XD document provides info on the file structure of the creator’s system… (not really a vulnerability, but still, not ideal)

2 Likes

Thanks for the reply everyone! I will try the different options out.

1 Like

@afuchs / @schenglooi is this actually expected behavior – for ImageFill.toString() to leak file paths like this?

1 Like

I’ve converted this into a feature request post type so folks can upvote it to indicate interest.

It’s not possibly to reliably do this today – toString() isn’t a safe bet since its output isn’t a frozen API contract… and it already will not work the way you want for images that came from a data URI or the clipboard.

1 Like

Does XD internally track duplications of objects in any way? I’m guessing that even duplicate data URI or clipboard insertions count as separate images as far as the internal model goes…

So I’m not sure there’s a great way to do this that doesn’t involve somehow computing that the bytes of the image is the same (and that seems somewhat expensive), especially for documents with large (or a large number) of images.

If you paste from the clipboard twice and it happens to contain the exact same bitmap data both times, I’m not sure if XD will auto-detect that they are identical… But certainly if you paste once and then clone that object in your design a bunch of times (or use it in a Component, a Repeat Grid, etc.) XD knows they are all the same image asset – but plugins won’t be able to tell that right now.

1 Like

Ok, I did some research regarding this. Here are the (literal) results of

console.log(selection.items[0].fill.toString());

where a rectangle with an image fill is selected for different cases:


Image dragged from Chrome into existing rectangle

(apperently some temporary folder. I’m on a German system, - Kopie is the default “duplicate” appendix of Windows for files)

ImageFill(C:\Users\pablo\AppData\Local\Packages\Adobe.CC.XD_adky2gkssdxte\TempState\NoPath - Kopie.png)

Image dragged frome Chrome into existing rectangle duplicated

Same results

ImageFill(C:\Users\pablo\AppData\Local\Packages\Adobe.CC.XD_adky2gkssdxte\TempState\NoPath - Kopie.png)

Image copied and pasted from Chrome:

ImageFill(<data URI>)

Rectangle node with image copied and pasted from Chrome duplicated

ImageFill(<data URI>)

Image directly dragged into XD from Chrome (not into a rectangle)

ImageFill(C:\Users\pablo\AppData\Local\Packages\Adobe.CC.XD_adky2gkssdxte\TempState\NoPath.jpg)

[…] duplicated

ImageFill(C:\Users\pablo\AppData\Local\Packages\Adobe.CC.XD_adky2gkssdxte\TempState\NoPath.jpg)

Image dragged from file system into XD

ImageFill(C:\Users\pablo\OneDrive\Pictures\DSC00258.JPG)

:exclamation: exposing the path

The previous node after saving and re-opening the document as cloud document

ImageFill(C:\Users\pablo\OneDrive\Pictures\DSC00258.JPG)

:exclamation: Still exposing the original file path. This, potentially, is not good :neutral_face:.


All of this was tested on Windows 10, XD 25.1.12.7, Creative Cloud Sync 4.3.24.11.

2 Likes

XD 29 has cleaned up this area a bunch:

  • To tell if two ImageFills use the same underlying raster asset, compare their assetId properties.

    • Two ImageFills with the same assetId may still look different in the XD document though, due to cropping, rotation, flipping, masks, opacity/blendmode, border/blur/shadow styles, etc.
  • toString() no longer includes a path, which as @pklaschka pointed out could be surprising data disclosure in some cases, and also is tempting to erroneously use for comparisons (even though it won’t work in those “data URI” cases).

  • toString() now displays just the image filename (if available) and adds the image’s natural size – two bits of info that seem useful when debugging and printing ImageFill objects to the console. But for programmatic purposes in production code, don’t rely on this string – toString() output is always subject to change. Use layer name if you need a label, and use the naturalWidth / naturalHeight getters for size.

2 Likes