Base64 Image not displaying as an image

I am trying to transfer base64 images from a website to Notes using HTML. As a test, iv’e written the script below which gets a “normal” image from a website via url. The second image is the base64 code of a simple image of a Red Dot (from Wikipedia). As described in the script comments, the first picture displays correctly in Notes but the second one doesn’t.

Can anybody help me to get both images to display (as images) in the Note when opened please?

Many thanks.

-- Creates a new Note On My Mac with a Body containing: Some text, a random image taken from the web, some more text and a Base64 coded Red Dot (code got from  wikipedia). 
-- The Note is created correctly but only the first image is displayed.  The second image is displayed as "File . 85 bytes" and will only display as an image if double clicked. 
-- When it does display, it opens in a new Preview window, not in the Note.

tell application "Notes"
	set the noteBody to "<html>
	<p>Picture of Bells.<p>
	<p><img src=\"https://cccbr.org.uk/wp-content/uploads/2016/05/howdenMinsterBells.jpg\"<p>
<p>Picture of Red Dot.<p>
<p><img src=\"data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==\" alt =\"Red dot\"<p>
</html>"
	
	set thisAccountName to "On My Mac" -- For testing (images appear immediately in the note)
	--set thisAccountName to "Icloud" -- (Sometimes a delay for the images to appear) 
	
	-- make a new note at the top application-level:
	make new note at folder "Notes" of account thisAccountName with properties {body:noteBody}
end tell

noteBody

Your HTML is broken, as the img tag is not closed. And I’m not certain that a space may follow the comma in the data URL.

Also, you might perhaps want to adjust the title of your post: the essential fact is that you’re using a data URL, not the image encoding.

1 Like

I think I have now closed off the Image tags correctly and I have removed the space after the comma. There has been no noticeable change to the result - both images and text appear in the Notes file but only the picture of the bell appears as an actual image, the red dot appears as a file. The file icon needs double clicking in order to reveal the red dot (in Preview).
NB: Once the red dot is revealed in Preview, it can be copied and pasted back into Notes and displays correctly.

Obviously, I am out of my depth with this but does anyone know how to get both images to appear as images in the Notes file please?

-- Creates a new Note On My Mac with a Body containing: Some text, a random image taken from the web, some more text and a Base64 coded Red Dot (code got from from wikipedia). 
-- The Note is created correctly but only the first image is displayed.  The second image is displayed as "File . 85 bytes" and will only display as an image if double clicked. 
-- When it does display, it opens in a new Preview window, not in the Note.

tell application "Notes"
	set the noteBody to "<html>
	<p>Picture of Bells.<p>
	<p><img src=\"https://cccbr.org.uk/wp-content/uploads/2016/05/howdenMinsterBells.jpg\"</img><p>
<p>Picture of Red Dot.<p>
<p><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==\" alt =\"Red dot\"</img><p>
</html>"
	
	set thisAccountName to "On My Mac" -- For testing (images appear immediately in the note)
	--set thisAccountName to "Icloud" -- (Sometimes a delay for the images to appear) 
	
	-- make a new note at the top application-level:
	make new note at folder "Notes" of account thisAccountName with properties {body:noteBody}
end tell

noteBody

No, you haven’t. If you need HTML, you must learn and use the correct syntax. There’s no point fiddling around. Head over to Mozilla Developer Network and read.
I’d try to get the HTML to correctly display in a browser. If that works, you know how it has to look and can copy the HTML into your AppleScript.
Personally, I’d use JavaScript for that because then you don’t need to escape the quotes. Reduces the risk of errors and makes the code easier to read.
[

2 Likes

I have Catalina OS. I didn’t find any errors in HTML, except for the fact that p tags should be closed like this: /p

I fixed it and the note were created correctly with both images.

NOTE: Also, some additional steps are needed for the change to be reflected in the interface. And even so, the image may appear with a delay of 1-5 seconds…
 

-- Creates a new Note On My Mac with a Body containing: Some text, a random image taken from the web, some more text and a Base64 coded Red Dot (code got from  wikipedia). 
-- The Note is created correctly but only the first image is displayed.  The second image is displayed as "File . 85 bytes" and will only display as an image if double clicked. 
-- When it does display, it opens in a new Preview window, not in the Note.

tell application "Notes"
	activate
	set the noteBody to "<html>
	<p>Picture of Bells.</p>
	<p><img src=\"https://cccbr.org.uk/wp-content/uploads/2016/05/howdenMinsterBells.jpg\"></p>
<p>Picture of Red Dot.</p>
<p><img src=\"data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==\" alt =\"Red dot\"></p>
</html>"
	
	set thisAccountName to "On My Mac" -- For testing (images appear immediately in the note)
	tell account thisAccountName to tell folder "Notes"
		make new note with properties {body:noteBody}
	end tell
	save
end tell

seeTheChangesTakedPlace()
tell application "Notes" to show folder "Notes" of account thisAccountName

on seeTheChangesTakedPlace() -- optional
	tell application "Notes"
		quit
		repeat while running
			delay 0.2
		end repeat
		activate
	end tell
end seeTheChangesTakedPlace

 

Ah! Thanks. Regrettably, the code still does not work for me but I am running Monterey 12.6.3.
I wonder if there is some setting that I have not selected.

Notes version 4.9 (2010).

You answered too quickly. I added something else. See post carefully.

An img tag must be closed:
<img src="…">
Something like
<p><img src="…"</p>
is invalid HTML. That your browser tries to somehow fix it, does not make it correct HMTL. There’s no point in discussing if a given program displays broken HTML or not. The HTML must be fixed first.

Yes you are right. There really should be added a “>” in the 2 lines with images. Now I’ve made these corrections to the script too. Thanks.

Thanks for all your help here but this is what I am getting in Notes even with your latest updates to the script. If it is working correctly for you, then it must be something to do with my set up?

As I already said: load the pure HTML in Safari. What do you see? If if works there, it should work in notes. If not, your HTML is faulty. Or your Safari/WebKit is so old that they can’t display data URLs properly.

1 Like

HTML Tester

I have removed the escapes from the quotes and it seems to be working fine here (W3Schools Tryit Editor). Regrettably, I am still not seeing the Red dot in Notes.

Notes

I’m Baffled!

I can’t repeat what you have going on Ventura. Both images appear in my Notes.app interface (as you have in the 1st screenshot). This seems to be related either to something on your computer or to a Notes.app bug on Ventura.

Try the usual preventative methods for your computer, for example, using the CleanMyMacX program. If that doesn’t help, report the possible bug to Apple.

I am on Catalina.

1 Like

Thank you both for your help with this. Although, I am still not able to successfully transfer the images directly from the website to Notes using AppleScript, I have made much more progress using your help.

I have to log on to the website where the images are, so regrettably, I can’t show you the exact problems that I am having - I think that it is based on a mySQL database?

However, I can now get the images from the website using the code below

-- The output below (ReportPictures) can be copied direct to TextEdit - File Name MyFile.html.  Opened.. with "Option - Ignore rich text commands" checked. 
-- In TextEdit, use Find and Replace to change the escaped quote marks back to normal quotes (\" to ")
-- Once saved, the TextEdit file can be double clicked from Finder and it will open with the pictures displayed. 
-- Select all, copy and paste into Notes.

tell application "Safari"
	set FrontPictureLst to {}
	set ReportPictureLst to {}
	
	-- Get the Front picture
	set theItem to "m-auto" -- **** With OuterHTML gets the Front Elevation picture *****
	set myWindow to current tab of first window
	tell myWindow
		set classCount to do JavaScript "document.getElementsByClassName('" & theItem & "').length"
		repeat with itemCount from 0 to (classCount - 1)
			set theName to do JavaScript "document.getElementsByClassName('" & theItem & "')[" & itemCount & "].outerHTML"
			copy theName & return & return to the end of FrontPictureLst
			set FrontTest to theName
		end repeat
	end tell
	
	-- Get the Report pictures
	set theItem to "block h-full w-full" -- **** With OuterHTML gets all the Report pictures *****
	set myWindow to current tab of first window
	tell myWindow
		set classCount to do JavaScript "document.getElementsByClassName('" & theItem & "').length"
		repeat with itemCount from 0 to (classCount - 1)
			set theName to do JavaScript "document.getElementsByClassName('" & theItem & "')[" & itemCount & "].outerHTML"
			copy theName & return & return to the end of ReportPictureLst
		end repeat
	end tell
	
	-- Join the Front picture to the rest of the images
	set ReportPictures to (FrontPictureLst) & ReportPictureLst
end tell

ReportPictures

In the output format, all of the quote marks are escaped with backslashes (\ ) .
as follows (NB: I’ve had to add an extra space after the backslash in this post, in order to show that)…
{"<div class=\ "m-auto\ " style=\ "margin:10% 10% 10% !important;\ ">
<img src=\ "data:image/jpeg;base64,/9j/4AAQ…etc…

… so I have to do a manual Find and Replace in TextEdit to get rid of the backslashes. I can then reopen the TextEdit file (in html mode) and the images are displayed.
Then - Copy and Paste into Notes.

Not very slick, but it works.

Is there any way to get the code to output ReportPictures without the backslashes please? For instance, if I add…

display dialog "" & ReportPictures

… then the dialog box displays without the backslashes and therefore can be copied direct and pasted to TextEdit without the need to do the Find and Replace. Still very manual, but limited progress.

Ok… Got it :roll_eyes:.

set the clipboard to every item of ReportPictures as text

Personally, I’d write this in JavaScript, since you need that anyway to access the images. And probably use querySelectorAll('img'), perhaps with a more specific selector instead of the slightly convoluted approach with length and a repeat loop.

Thanks, I will certainly look at that. I am away from the laptop for a few weeks, so holiday first!

I thought I would try this but having never used JavaScript and hours of Googling, I seem to have fallen at the first hurdle! How do I access a website without falling foul of the Same Origin Policy?

The example AppleScript below gets some text from a website that is open on my Mac. Is it possible for someone to translate this into JavaScript for me (if that is possible) please?

I can at least then make a start!
Many thanks,

-- Website open for example purposes in Safari tag 1 is https://cccbr.org.uk/bellringing/what-is-bell-ringing/

tell application "Safari"
	set theItem to "elementor-text-editor elementor-clearfix"
	set myWindow to current tab of first window
	tell myWindow
		set classCount to do JavaScript "document.getElementsByClassName('" & theItem & "').length"
		repeat with itemCount from 0 to (classCount - 1)
			set theName to do JavaScript "document.getElementsByClassName('" & theItem & "')[0].outerText"
			set theText to theName
		end repeat
	end tell
end tell

theText

Why would the SOP come into play when you inject JavaScript into a page with JavaScript as opposed to injecting JavaScript with AppleScript?

(() => {
	const browser = Application("Safari");
	const tab = browser.windows[0].currentTab();
	const result = browser.doJavaScript(`[...document.getElementsByClassName("elementor-text-editor elementor-clearfix")].map(e => e.outerText).join('\\n')`, {in: tab});
	console.log(result);
})()

Which outputs

For centuries church bells have sounded, calling people to worship, in celebration of special occasions, in remembrance and to mark special events. In the very early days, the ………

(abbreviated here) .

I won’t explain everything here. For details on JavaScript for Automation, see my website.

As to the line const result=:

  • document.getElementsByClassName(...) returns a HTMLCollection
  • [... ] converts that to an Array
  • map iterates over this Array, returning a new Array consisting of the outerText properties
  • the final join concatenates all these outerText elements, adding a linefeed between each of them.

One could, of course, write it in many more lines, similar to your “get length, loop over 0 to length-1 elements getting their outerText”. But that’s a bit too winded for my taste, especially because you’re using document.getElementsByClassName (a potentially costly operation) twice – once to get the length, and the second time to access the elements.

Also, there’s very little point in defining a loop variable itemCount and then always retrieving the outerText of the first element of the collection.

But all this is not what you were asking originally, is it? What I suggest doing:

  • create your complete JavaScript code (i.e. the one to be executed by Safari) as a “template string” (included in backticks). That way, you do not have to escape quotes inside the code and can use newlines freely. Only backslashes have to be doubled.
  • put that code into a constant
  • use app.doJavaScript(constant, {in: tab}) to pass the code to Safari.
  • in your code (the one in constant), make sure that whatever you want to use in your calling code is the last expression. And it should be a string or a number. You can’t return Arrays, HTMLCollections etc. If you need a complex structure, use JSON.stringify(structure) to create a JSON string. You can then recreate the structure by calling JSON.parse() with the returned value as parameter.

Many thanks for all of this information. I had never even heard of JXA before I looked at your website, hence my confusion about SOP (and other things!).
Thanks for the supplied code - a very good start.
I don’t fully understand your last paragraph yet but I will work on that.

Ta