We volunteer not for recognition; we volunteer because it’s the right thing to do.

If you follow me on social media, you know that I am a dedicated volunteer in the FIRST Robotics Competition and FIRST Lego League programs. I’ve been a volunteer mentor for FIRST Team 172 Northern Force and a Game Announcer at events, such as the World Championship event in Detroit each spring. This year, 2019, my team was fortunate to be selected to attend the Detroit Championship tournament, and they had their best outing ever, which is pretty awesome in its own right. Not only were they ranked #8 going into the playoffs in the Daly Subdivision, but they also received the Team Spirit award for the Carson/Daly Division, which contains 136 schools.

FRC Team 172 Northern Force receives Team Spirit award for Carson/Daly Division

FRC Team 172 Northern Force receives Team Spirit award for Carson/Daly Division

In addition to being an event volunteer and team mentor, I also make a tool for Game Announcers that provides them with real time scoring, ranking, schedules and team data. Never one for fancy names, we call it gatool. It eliminates paper at events (which can be up to 150+ sheets just for match schedules) and uses crowdsourcing to deliver better data to the Game Announcers from previous events. It’s a mobile-friendly web app, built with Adobe tools and modern Web frameworks (of course!), and it’s available to all of the Game Announcers and Masters of Ceremonies across all of FRC. Here’s a youtube demo of the tool, which has matured since this recording. In its 4 years of life, it has seen widespread adoption around the world.

Global usage of gatool since Jan. 2017

Global usage of gatool since Jan. 2017

Imagine my surprise when, during the round robin playoffs, I am named the Outstanding Volunteer of the Year for the Detroit Championship. Of course, I was so focused on the job at hand (we were in the playoffs, after all), that I had to be prevented from moving between the fields and missed the citation because I was trying to escape to do my job. Here’s a video of the citation and my emotional reaction.

My entire family is involved in this program, as student participants, mentors, alumni and volunteers. You’ll see my wife and youngest son in the video, and my oldest son is the one mentioned in the citation. My middle son is an FLL and FRC alum and is a volunteer at events. We firmly believe in the power of sports combined with electrical and mechanical engineering, software development, business planning, program management, persuasion, creative design and thinking, and of course team spirit. Sports provides a focus for communities as well as the team members who compete, and we firmly believe that we can focus communities to not only embrace Science, Technology, Engineering and Mathematics (STEM), but also to support and respect students who choose to go on to careers in STEM. Adobe is a creative company, so we add Arts to the list and get STEAM. FIRST promotes all of these concepts, despite it being a Robotics sports league. The highest award in FIRST, the Chairman’s award, is not for the quality or performance of a robot. It’s for the team who embraces the ideals of FIRST, as embodied in its Mission and Vision statements (below).

FIRST Mission

The mission of FIRST® is to inspire young people to be science and technology leaders and innovators, by engaging them in exciting mentor-based programs that build science, engineering, and technology skills, that inspire innovation, and that foster well-rounded life capabilities including self-confidence, communication, and leadership.

FIRST Vision

“To transform our culture by creating a world where science and technology are celebrated and where young people dream of becoming science and technology leaders.”  Dean Kamen, Founder

Core to achieving these is diversity. Cultural, socioeconomic, gender and racial diversity are embedded in the operational goals of FIRST across all of its programs. It’s a global program, so what may seem like diversity in one place are the norm in another. There are many girls-only teams, many religiously diverse teams in places where religion is a point of conflict, and many teams in schools with only hand drills and hand saws for tools. FIRST teams help each other, so when new teams form, other teams will lend a hand either in person or virtually. This culture of assistance applies to mentors as well as students, and there are several vibrant online communities where FIRST volunteers and students share ideas, best (and worst!) practices, and advice.

FIRST partners with the Lego Group to deliver FIRST Lego League Jr. and FIRST Lego League programs to hundreds of thousands of Elementary and Middle school students and their mentors worldwide. These programs are affordable and portable, designed for maximum impact with minimal investment for schools or parents. Competition involves three measured components: Core Values, the Problem, and Robot Performance. Core values looks at how the team aligns with FIRST Core Values. The Problem is a presentation (much like a science fair) where the students discuss their solution to the overarching issue for that year. Issues include subjects like water quality, life in space, recycling, elder care, and more. Robot Performance tracks how well a robot, built entirely of Lego bricks and powered by a Lego micro-controller, can navigate a field of obstacles and perform skill tasks on its own. The robots operate entirely on their own during this period.

FIRST has a crossover middle school-high school program called FIRST Tech Challenge. This program had harder challenges and larger robots, powered by low cost Android-based controllers. This program serves a very large base of schools around the world with events that can fit in a school library or half of a gymnasium. Competition involves two alliances of two robots competing to solve a technical challenge. There is an autonomous period where the robots perform the game tasks on their own, followed by a tele-operated period, during which the drivers must remotely control their robots to score points by moving resources around the playing field. It is usually a frenetic game that is fun to watch and fun to play.

FIRST has a high school program called FIRST Robotics Competition. This is the “big leagues,” with robots topping 120lbs and often the size of a kitchen appliance. Competition involves two alliances of three teams, each alliance working together to score points via physical and skills challenges. There is often, but not always, a portion of each match that is autonomous, and there is often but not always an opportunity for a team to play defense. The playing field takes up most of a regulation basketball court, and events happen in arenas and high school gymnasia.

FTC and FRC have tournaments with qualification rounds, where teams play with randomly selected partners. Each team will play 8 or more matches, depending on the tournament format. Each team will carefully observe all of the other teams, because the top 4 (FTC) or 8 (FRC) teams will select partners to join them for playoff rounds. From this point, the alliances do not change, and teams who win their pairings advance in the tournament. The Winner of the tournament is the alliance who wins the final pairing, and the loser of that pairing is known as the Finalist. Both receive performance awards.

As mentioned before, the highest award is the Chairman’s award, so winning the tournament is only one of the ways teams can receive recognition. As mentioned at the beginning of this post, there’s also awards for Team Spirit, Business Plan, Imagery, Gracious Professionalism™, Autonomous Code, Engineering Excellence, Engineering Inspiration, volunteer service, Mentorship, and individual student character among others. There’s even an award for making a video to promote safe practices in the shop and at competitions.

I am very fortunate to work at a company that encourages volunteering and community involvement. Volunteering and philanthropy are core to the character of Adobe, and our Founders, John Warnock and Chuck Geschke, often remind us to share our talents in our communities. Adobe firmly believes that corporations have a responsibility to their employees, communities and to their shareholders, and that by forging strong bonds between the employees and their communities, we can all benefit. Adobe offers several incentives to volunteer, including rewards for volunteer time (currently $250 for each 10 hours of recorded volunteer service, capped at $10,000) and for serving on Boards of Directors (amount varies depending on the employee’s job at Adobe, but offered in addition to the funding for volunteering and matching grants).

Having an incentive plan to encourage volunteering is a very nice thing, but I would volunteer without it and did for many years prior to joining Adobe. Whether as Game Announcer or robotics team mentor or Cubmaster or Alumni Board Member or President of the local Chamber of Commerce, the community is stronger from direct involvement in programs. None of these programs work without financial support, of course, and for many years, our family could not provide financial support and chose to volunteer as our tithe (or more than tithe in the case of the Scouts!). Adobe makes it possible now for us to provide both volunteer hours and financial support to the organizations that mean the most to us and to our communities. Thank you, John and Chuck, for making it possible for us to spread your vision so far and wide.

Automatically synchronize CC Color Settings via a script

Color Settings Synchronization in Bridge

Color Settings Synchronization in Bridge

I have been asked many times over the years about Color Settings and how to synchronize them. Most people use Bridge’s Synchronize Color Settings tool, found at Edit>Color Settings…, but there are cases where organizations want to ensure that all workstations have the same Color Settings. It is possible to install a script that will set the Color Settings to a specific value. In this article, we’ll learn how to set the Color Settings in Photoshop, Illustrator and InDesign.

Photoshop, Illustrator, InDesign and many other CC desktop applications are scriptable using Javascript. You can launch scripts from the applications’ Scripts menu, or you can trigger scripts via events. In this case, we’ll use the Startup event. InDesign and Illustrator have Startup Scripts folders, and each will execute any scripts you put there when they start. Photoshop has an event manager that lets you attach specific scripts to events, such as startup or document open. We’ll look at the scripts first, and then we’ll see how to activate them.

The script

I’ve prepared a script that works for Illustrator, InDesign and Photoshop, which we can do by detecting which application is running the script. For InDesign and Photoshop, we need to set the value of an application property to set the Color Settings file, and for Illustrator, we need to call a function to set the Color Settings file. For InDesign and Photoshop, the property will be the name of the Color Settings as shown in the Color Settings dialog, so you will need to open a CC desktop app and choose Edit>Color Settings… in order to see the name of the Color Settings file you want. For Illustrator, you need the name of the .csf file. For this example, we’ll use “North America Prepress 2,” which is a built-in Color Settings file that ships will all CC installations, and which is included as “North America Prepress.csf” in all CC installations. If you make a custom Color Settings file, you will need to make note of its file name and the name that shows in the Color Settings dialog.

The property we need to set in Photoshop is called app.colorSettings. In InDesign, this property is called app.colorSettings.cmsSettings. In Illustrator, we need to call the app.loadColorSettings() method with a pointer to the specific file we want to set as the Color Settings. The script below tests for which host application and selects the proper method for setting the Color Settings. View SetColorSettings.jsx on gist.

#targetengine main
try {
	//for PS and ID, we need the display name of the Color Settings file. 
        //This is what you see in Edit>ColorSettings
	var colorSettingsFile = "North America Prepress 2";
    if (app.name === "Adobe InDesign") {
		//InDesign uses app.colorSettings.cmsSettings
		app.colorSettings.cmsSettings = colorSettingsFile;
		//alert("Color Settings are now: " + app.colorSettings.cmsSettings);
	} else if (app.name === "Adobe Photoshop") {
		//PS uses app.colorSettings
		app.colorSettings = colorSettingsFile;
		//alert("Color Settings are now: " + app.colorSettings);
	} else if (app.name === "Adobe Illustrator") {
		//Special case for AI, which has an array of all available Color Settings.
		//We need to find the specific color settings file in the array, then get
		//its display name so we can use it to set the Color Settings
        //for AI, we need the file name of the specific Color Settings file you want to select.
        var settingFile = getAIColorSettingFile('North America Prepress.csf');

		if (settingFile) {
			//alert("Color Settings are now: " + settingFile.displayName);


	//this function finds the Display Name of the Color Settings file and returns that file.
	function getAIColorSettingFile(name) {
		var settingIdx = app.colorSettingsList.length - 1;
		var matchToFileLowerCaseName = name.toLowerCase();
		var settingFile = null;
		while (!settingFile && settingIdx >= 0) {
			settingFile = app.colorSettingsList[settingIdx];
			var settingFileLowerCaseName = settingFile.displayName.toLowerCase();
			if (settingFileLowerCaseName != matchToFileLowerCaseName) {
				settingFile = null;

		return settingFile;

} catch (e) {
	alert("Could not set Color Settings to " + colorSettingsFile, "Color Setting Warning", true);

Installation and activation

As seen below, you can create a folder in the InDesign and Illustrator application folder for startup scripts. For Illustrator, make a folder called Startup Scripts in the application folder. For InDesign, there should already be a folder called startup scripts in the Scripts folder. Create these folders in Illustrator and InDesign, and copy SetColorSettings.jsx into the two Startup Scripts folders.

Startup Folders in AI and ID

Startup Folders in AI and ID

Photoshop requires additional steps, rather than just making a Startup Scripts folder. Choose Edit>Scripts>Scripts Events Manager… to open the Events Manager. You’ll need to activate Events, so click on the box to Enable Events to Run Scripts/Actions.

Script Events Manager

Script Events Manager

Once activated, you can browse to your script to attach it to the Start Application event. Make sure that Start Application is selected in the Photoshop Event menu, then click on the Script dropdown menu and choose Browse… Browse to your script, which could be one of the versions stored in one of the Startup Scripts folders from AI and ID. Select it, Click Done, then click Add to register the event. Click Done to finish setting up the startup event.

Script Events Manager

Script Events Manager

Under the hood, Photoshop has created files called Script Events Manager.xml and tw0001.dat that are stored in the Photoshop Settings folder in the user’s Preferences folder. You can create these files by hand, too. The xml file is just a list of registered events and additional scripts that will appear in the menu. The .dat file is the specific scripts that will run based on the event having fired.

Once you have the scripts installed, each time you start Photoshop, Illustrator or InDesign, they will automatically set their Color Settings to North America Prepress 2.

AEM 6.4 and InDesign Server workflows demystified

For many versions, Adobe Experience Manager has included support for parsing InDesign documents via InDesign Server. AEM admins could use pre-built workflow steps to send an InDesign document or InDesign Snippet to InDesign Server along with a set of scripts that InDesign Server would execute against the payload. It was possible to execute multiple scripts in sequence on the same payload, which was handy but not particularly efficient as it would invoke InDesign Server as many times as you had scripts in the workflow. In AEM 6.3, the workflow component matured to make the workflows more efficient, and to include a set of functions that help InDesign Server access content in AEM and to post output documents back to AEM for further processing. In AEM 6.4, the workflow component added a configuration to permit any MIME-type as the payload for InDesign Server, opening up a whole new set of use cases for AEM and InDesign Server.

Scripts Deconstructed

The InDesign Server workflow component is called Media Extraction. It began life as a way to extract the text, images and metadata from InDesign documents, and it’s a core part of the built-in DAM Update Asset workflow today. Media Extraction has a lot of power as a workflow ingredient, however, if you know how to use it. Let’s explore how the Media Extraction workflow component works in AEM 6.4.

Media Extraction works by sending a payload to InDesign Server, consisting of a document and a script that InDesign Server executes on the document. As stated above, earlier incarnations only allowed the payload to include an InDesign Document (.indd) or InDesign Snippet (.idms), but 6.4 lets us send any document, as long as it passes our MIME-type filter. You can specify the MIME-type in the Process Arguments section of the workflow step. It helps to know the MIME-type of your content. You can use one of the many resources online to help identify common MIMI-types, but you may want to upload a file of the desired type to AEM and then examine its /jcr:content/metadata/dam:MIMEtype node to see what AEM thinks it is.

MIME Types

Specify the allowed MIME types for your scripts. The default is InDesign and InDesign Snippet.

You will also need to send a script that can process the payload and return the resulting file back to AEM. The Media Extraction workflow component reads and sends .jsx files, which contain the actual script code, to your InDesign Server. The built-in scripts are located at /libs/settings/dam/indesign/scripts/ and you should not move or change them. You can copy them to /apps/settings/dam/indesign/scripts/, or leave them in place and put your own scripts in /apps/settings/dam/indesign/scripts/. The critical thing to know is that the .jsx files are actually script fragments, and that they are designed to be concatenated into one script at runtime.

Scripts are concatenated from top to bottom in the list of scripts specified in Process Arguments

There are four sections in Process Arguments: ExtendScript Library, Init Script, Extend Scripts, and Cleanup Script. It is not recommended to modify the ExtendScript Library, located at /libs/settings/dam/indesign/scripts/cq-lib.jsx, as it provides important functions related to processing the inbound payload and to returning the resulting file back to AEM. Read and understand the helper functions provided by the ExtendScript library; you will be glad you did.

If you look at the default Init Script, located at /libs/settings/dam/indesign/scripts/Init.jsx, you’ll see that it contains an unclosed try {. This try { encloses the scripts indicated in the Extend Scripts section, and it closes in the Cleanup Script, located at /libs/settings/dam/indesign/scripts/Cleanup.jsx It continues with a catch{}, as expected, for error handling. This means that each of the Extend Scripts can leverage the work done and functions defined by the preceding scripts, including the ExtendScript Library and the Init Script, as the workflow component will combine the jsx files into one before sending the single, combined script to InDesign Server.

If you do not specify an Init Script and a Cleanup Script, the Media Extraction component will use the default scripts. Study these two scripts to see how to prepare to handle the inbound payload, how to process errors, and how to clean up the temporary files mess left during your processing. It is a good idea to use the existing Init.jsx and Cleanup.jsx files as the starting and ending points for your solution, so make copies (and name them something that stands out!) in /apps/settings/dam/indesign/scripts/ and modify those for production.

Example, please

Let’s look at an example called IDSBasedThumbnails, that you can download and install from github. The package contains the scripts and a workflow model, which performs the following actions on PDF, AI, PS or EPS files:

  • Sends the file to InDesign Server as a payload
  • Places, scales and centers the document on a new InDesign document
  • Exports the new document as thumbnails (PNG and JPEG)
  • Puts the exported files back in the repository at /jcr:content/renditions/
  • Wipes out the debris and closes InDesign Server

You might be asking why would anyone want to do this? Well, it turns out that AEM doesn’t have native rendering for EPS files, and the default DAM Update Asset workflow uses ImageMagick to generate previews from EPS files. I thought that it would be better to use InDesign Server, as it can handle not only EPS files, but also PDF, AI, PS and a whole set of other asset types. In addition, InDesign can simulate overprints and flatten complex transparency during the export, which makes it a very accurate way to deliver color-managed previews for assets used in printing processes. Think of packaging, where there’s a lot of use of overprinting varnishes and spot colors. Also, InDesign Server is super fast at making these renditions, operates as a dedicated image processing server, and can scale to meet demand without impacting the AEM Server. Let’s dig in to the workflow and see some example output.

MIME-type and ExtendScripts for making thumbnails with InDesign Server

MIME-type and ExtendScripts for making thumbnails with InDesign Server

As you can see above, we have many allowed MIME-types to cover the various assets we want to preview. If you try to run the workflow on a Word document, it will not work, as it won’t pass the initial MIME test. We’ve left the ExtendScript Library alone, but we’ve made new Init.jsx and Cleanup.jsx files that focused specifically on non-InDesign documents as payloads. The bulk of the work happens in EPSThumbnailExport.jsx, and we’ll highlight some of that script here.

The function called exportThumbnail() does the most of the work, and there’s a helper function called myGetBounds() at the end that returns the dimensions of the rectangle contained within the margins of the page. I’ve not included that below. Also, I’ve included comments to help explain what each of the sections of code is doing. Know that many of the inputs of the exportThumbnails() function are defined by the ExtendScript Library and the Init Script, which is why those are so important to read and understand.

function exportThumbnail(document, folderName, fileName, resourcePath, host, credentials) {
    var myDocument = app.documents.add();
    //set the margins to 0
    myDocument.marginPreferences.top = 0;
    myDocument.marginPreferences.left = 0;
    myDocument.marginPreferences.bottom = 0;
    myDocument.marginPreferences.right = 0;

    //The following assumes that your default master spread contains two facing pages.
    //We set the margins on the master spread to 0 as well, on the left and right pages
    myDocument.masterSpreads.item(0).pages.item(0).marginPreferences.top = 0;
    myDocument.masterSpreads.item(0).pages.item(0).marginPreferences.left = 0;
    myDocument.masterSpreads.item(0).pages.item(0).marginPreferences.bottom = 0;
    myDocument.masterSpreads.item(0).pages.item(0).marginPreferences.right = 0;
    myDocument.masterSpreads.item(0).pages.item(1).marginPreferences.top = 0;
    myDocument.masterSpreads.item(0).pages.item(1).marginPreferences.left = 0;
    myDocument.masterSpreads.item(0).pages.item(1).marginPreferences.bottom = 0;
    myDocument.masterSpreads.item(0).pages.item(1).marginPreferences.right = 0;

    //We set the page width and height to 319px, with portrait orientation
    myDocument.documentPreferences.pageHeight = "319px";
    myDocument.documentPreferences.pageWidth = "319px";
    myDocument.documentPreferences.pageOrientation = PageOrientation.portrait;

    //One page only
    myDocument.documentPreferences.pagesPerDocument = 1;

    //These settings control how InDesign Server handles black ink.
    //False means that InDesign will attempt to display how the black ink 
    //will interact with the substrate and the other inks in the job.
    //True will use a faster but less accurate model. The faster, less accurate model 
    //is the default behavior in InDesign, which is why we need to change the setting here.
    app.colorSettings.idealizedBlackToExport = false;
    app.colorSettings.idealizedBlackToScreen = false;

    //PNG export options here. 
    //Disable anti-alias to hide boundaries between atomic regions
    //created by transparency flattening
    app.pngExportPreferences.antiAlias = false;

    //All pages must be exported for PNG. We only have 1 page, 
    //but we need to specify the range
    app.pngExportPreferences.pngExportRange = PNGExportRangeEnum.EXPORT_ALL;

    //We want to simutate overprinting. This works 
    //in conjunction with the black setting above.
    app.pngExportPreferences.simulateOverprint = true;

    //We want the color space to be RGB.
    app.pngExportPreferences.pngColorSpace = PNGColorSpaceEnum.RGB;

    //We want a high quality PNG
    app.pngExportPreferences.pngQuality = PNGQualityEnum.HIGH;

    //Resolution set to 72 to generate 319 x 319 preview. 
    //We will adjust for each preview size.
    app.pngExportPreferences.exportResolution = 72;

    //Enable PNG transparency
    app.pngExportPreferences.transparentBackground = true;

    //JPEG export options here. The same settings apply for JPEG as for PNG
    app.jpegExportPreferences.antiAlias = false;
    app.jpegExportPreferences.simulateOverprint = true;
    app.jpegExportPreferences.jpegQuality = JPEGOptionsQuality.MAXIMUM;

    //Resolution set to 300 for high quality JPEG for zooming.
    app.jpegExportPreferences.exportResolution = 300;

    //Prepare for the thumbnail files
    var jpegRendition=new File(exportFolderThumbnail+"/"+"cq5dam.rendition.jpg");
    var thumbnail319=new File(exportFolderThumbnail+"/"+"cq5dam.thumbnail.319.319.png");
    var thumbnail140=new File(exportFolderThumbnail+"/"+"cq5dam.thumbnail.140.140.png");
    var thumbnail48=new File(exportFolderThumbnail+"/"+"cq5dam.thumbnail.48.48.png");
    var thumbnail1280=new File(exportFolderThumbnail+"/"+"cq5dam.web.1280.1280.png");

    //Create a new page in the document
    var myPage = myDocument.pages.item(0);

    //Get the page size as an array
    var myBounds = myGetBounds(myDocument, myPage);

    //Create a new text frame
    var myImageFrame = myDocument.pages.item(0).rectangles.add();

    //Make the image frame fill the page
    myImageFrame.geometricBounds = myBounds;

    //Ensure that the placed file will center in the frame and fit proportiionally

    //Remove the black stroke on the frame
    myImageFrame.strokeWeight = 0;  

    //Place the payload into the frame

    //Fit the payload in the frame proportionally and centered

    //Export the JPEG Rendition
    myImageFrame.exportFile(ExportFormat.JPG, jpegRendition);

    //Export the 319 thumbnail
    myImageFrame.exportFile(ExportFormat.PNG_FORMAT, thumbnail319);

    //adjust the resolution and export the 140 thumbnail
    app.pngExportPreferences.exportResolution = 32;
    myImageFrame.exportFile(ExportFormat.PNG_FORMAT, thumbnail140);

    //adjust the resolution and export the 48 thumbnail
    app.pngExportPreferences.exportResolution = 11;
    myImageFrame.exportFile(ExportFormat.PNG_FORMAT, thumbnail48);

    //adjust the resolution and export the 1280 thumbnail
    app.pngExportPreferences.exportResolution = 289;
    myImageFrame.exportFile(ExportFormat.PNG_FORMAT, thumbnail1280);

    //Close the temporary document without saving

    //==== send files to AEM ====
    app.consoleout('Posting this file to AEM: ' + "cq5dam.rendition.jpg");
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, jpegRendition, "cq5dam.rendition.jpg", 'image/jpeg', target);

    app.consoleout('Posting this file to AEM: ' + "cq5dam.thumbnail.140.140.png");
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, thumbnail140, "cq5dam.thumbnail.140.140.png", 'image/png', target);

    app.consoleout('Posting this file to AEM: ' + "cq5dam.thumbnail.48.48.png");
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, thumbnail48, "cq5dam.thumbnail.48.48.png", 'image/png', target);

    app.consoleout('Posting this file to AEM: ' + "cq5dam.web.1280.1280.png");
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, thumbnail1280, "cq5dam.web.1280.1280.png", 'image/png', target);

    app.consoleout('Posting this file to AEM: ' + "cq5dam.thumbnail.319.319.png");
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, thumbnail319, "cq5dam.thumbnail.319.319.png", 'image/png', target);


Once this script completes and all of the images have been written back to AEM via the putResource() calls, the Cleanup Script runs.

The result of this script is that all of the thumbnails for the specified Asset in DAM have been replaced with new thumbnails generated by InDesign Server. Here are some before and after images to give you an idea of the difference and why this model could be useful.

Previews without new workflow

Here are two EPS files and one PDF uploaded to DAM. ImageMagick preview has failed to generate a preview of the EPS files, and the PDF file shows no overprinting.

In order to run the workflow, you need to have InDesign Server installed, running, and your AEM instance needs to be configured to use InDesign Server. You can either open the workflow called DAM Update Asset with IDS Previews and run it on an asset from the Workflows panel, or you can open an asset and choose Run Workflow from the bottom of the Timeline panel for a specific asset. As configured, the workflow can’t run on a folder, since the MIME-Type filter doesn’t pass folders, so you need to run it one at a time on each asset. When you do, you will see the following result, and pay close attention to the difference in the PDF thumbnail:

Once the workflow generates previews, the new thumbnails replace the existing thumbnails with color accurate, overprint-simulated previews.

The PDF thumbnail now properly respects the overprint settings in the PDF, as well as in the EPS file. This is critical in managing assets that are designed to support print workflows that make use of overprinting and multi-ink composite colors, such as packaging and book covers. You might be wondering about why the previews for the CMYK Overprints.pdf and CMYK Overprints.eps are cropped differently. This is due to the way that InDesign interprets artwork boundaries when it imports assets. InDesign uses the page boundaries as defined in the EPS file when placing onto the page. PDF files can and often do have a number of boundaries available. InDesign, by default, will select the Bounding Box (Visible Layers Only) if it is available. This box is defined by the authoring application and typically exactly bounds the edges of any visible objects on the page as determined by layer visibility. You can learn more about PDF Bounding Boxes at this InDesign Secrets article.

InDesign defaults to the Bounding Box (Visible Layers Only) when importing PDF. You need to adjust the import preferences in your script if you want to change the default PDF import behavior.

InDesign defaults to the Bounding Box (Visible Layers Only) when importing PDF. You need to adjust the import preferences in your script if you want to change the default PDF import behavior.

The bounding boxes constants are: PDFCrop.cropPDF, PDFCrop.cropArt, PDFCrop.cropTrim, PDFCrop.cropBleed, PDFCrop.cropMedia, PDFCrop.cropContentAllLayers, PDFCrop.cropContentVisibleLayers. You can add a line before myImageFrame.place(sourceFile) to change the behavior to match how InDesign imports EPS files:

app.pdfPlacePreferences.pdfCrop = PDFCrop.cropMedia;

If you make the change, you will need to save the JSX, then reimport the JSX to your workflow, then re-sync your workflow in order for it to become available. Importing the JSX can be a confusing step, so let’s discuss that briefly. The built-in asset browser for JSX files doesn’t let you select a JSX from the file tree. It’s a known issue and it will be fixed in a later version of AEM, but for now, the Search bar is your best friend. Just enter the name of the JSX you want to import, and it’ll appear in the search results. Select it, and you’re all set.

Use the Search bar to reimport your modified JSX to the workflow step.

Use the Search bar to reimport your modified JSX to the workflow step.

Once you re-import the JSX, the change is automatically saved to the workflow, but the workflow needs to be synced to become active. Once you tap the Sync button, you’re ready to go.

Be sure to tap Sync after updating the workflow step.

Be sure to tap Sync after updating the workflow step.

After you update the JSX and re-sync the workflow, the PDF and EPS thumbnails will be similar.

After you update the JSX and re-sync the workflow, the PDF and EPS thumbnails will be similar.

You could also modify the DAM Update Asset workflow to remove ImageMagick and/or the built-in PDF renderers and replace them with a new step. You would likely want to expand the script to handle multi-page PDF and AI files, however. If you’d like to explore this option, here’s a great starting point from Mike Edel for importing multi-page PDF and AI into InDesign via scripting.


Being able to use InDesign Server to generate better previews for EPS and PDF and AI files is a nice new benefit of the new MIME-type options in the Media Extraction workflow. This is a relatively trivial example of what a developer can do with this new capability, however. You could create a workflow that sends a whole package of items to InDesign Server, which would do some action on those items, and then return a new file or other data to AEM. Integrators can develop new editorial and creative tools based on this new capability to enhance existing inDesign documents or create entirely new ones from scratch. We hope you will be inspired to add more InDesign Server to your AEM Assets workflows.