I am a bit stuck. I have created a script for Photoshop that opens a PSD file containing a few layers plus a linked one, sort of a template.
So far, I got things working for me by creating a droplet that runs the following steps and scripts:
Opening the file/image that is dropped.
Opening the PSD file (opening template, scripted).
Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action).
Applying the template features to this linked layer which has been updated previously (scripted).
Saves a PNG file (scripted),
And finally, closing up opened image and template documents (recorded action).
All is good so far. But this has a limitation. It will only work on one file at a time, with a specific name, at a specific location. So, for example, for the update linked layer to work, the name of the image must be 1.png inside Downloads folder only, in this case.
So my question is: How can I script this to run an iteration of the update on the linked layer using as source(s) the images dropped onto the droplet, regardless of file types (png, jpg, etc.), name, location, and index the output saved PNG file(s)? (1.png, 2.png, 3.png, and so on.)
I started working on my approach, and the steps previously mentioned:
1 - Opening the file/image that is dropped onto the Photoshop droplet.
This would happen automatically with the file—Photoshop will open the file dropped onto the droplet, thus triggering the specific actions sequence set forth. Step one solved. Next!
2 - Opening the PSD file (opening template, scripted)
With this step, I wrote a script that opens the template file. The first step in the action sequence would be this!
var template = new File("/Users/name/Desktop/Folder/Template.psd"); // Of course, you can have your template file anywhere on your computer as long as the path to find it is correct. I have selected my desktop for testing purposes.
app.open(template);
That was another effortless one. Next!
3 - Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action)
I needed to ensure that the template would easily find its previously linked layer location for the update for this third step to work. I know there are ways to update this with a script, but I didn't want to tinker with that. It was too much of a hassle for me at this stage and with my limited knowledge. Therefore I've decided to accommodate the necessary so the template would find a familiar file name it would look for when the "Update all Modified Content" action is triggered.
At this stage, there are two files opened in Photoshop, one the initial image that serves as a new source for the template, and the second file the template.psd, which contains the linked layer that needs to be updated with the content of the first file.
First, I have saved a copy of the image using the name that the template would look for when searching for the linked layer's name. Next, I have saved a copy of the template using the location of the first image file to keep the initial template safe from all these actions. And third, I triggered the "Update all Modified Content" action. And voila, everything worked. The initial template had the linked file next to it. So the new template copy would search and find the file next to it, in the same place, folder/location, as it happened on the previews step that helped save it as such.
// The following script will retrieve the path of the opened image and will save a copy that matches the name of the linked layer in the template in the same location.
var image_doc = app.documents[0]; //If two or more documents are opened, this approach will help switch between them.
var image_name = image_doc.name;
var image_path = app.documents[0].path.fsName;
var temp_image = new File("" + image_path + "/" + image_name + "");
var opts, file;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
var image_temp_name = "link.png";
pngFile = new File("" + image_path + "/" + image_temp_name + "");
image_doc.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
// Save a copy of the template.psd in the same location as the image and the link.png file needed to update the linked layer.
var temp_template = new File("" + image_path + "/" + image_name + "");
app.open(template);
var opts, file;
opts = new PhotoshopSaveOptions();
opts.format = SaveDocumentType.PHOTOSHOP;
var template_temp_name = "template.psd";
psdFile = new File(image_path + "/" + template_temp_name);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
// After these Update all Modified Content action
Now, four, five, and six are straightforward:
4 - Applying the template features to this linked layer which has just been updated previously (scripted). Done!
5 - Saves the newly formed template as a PNG file (scripted). Done!
6 - And finally, closing up opened image and template documents (recorded action). Done!
Related
I have a file which I am updating using fs and then creating zip in other location. When I check, file update is working fine, but in zip updated contents are not there. Can you tell me what I am doing wrong here. Here is my code.
const content = "new content";
const outputFile = `${unzipDir}/output.docx`
const zip = new AdmZip(outputFile);
fs.writeFileSync(`${unzipDir}/word/document.xml`,content); //content updated successfully in this path.
zip.addLocalFolder(`${unzipDir}/_rels/`);
zip.addLocalFolder(`${unzipDir}/customXml/`);
zip.addLocalFolder(`${unzipDir}/docProps/`);
zip.addLocalFolder(`${unzipDir}/word/`);
zip.addLocalFile(`${unzipDir}/[Content_Types].xml`);
zip.writeZip(outputFile);//old content is showing when extracting zip
Finally I got the solution. When we try to add local folders like I have done in above code, it not add folders and instead add all files containing those folders to root. So in that case file from original location was not replaced and I got old contents. So instead of adding all folders one-by-one, I have added entire folder structure at once and it works for me.
//zip.addLocalFolder(`${unzipDir}/_rels/`);
//zip.addLocalFolder(`${unzipDir}/customXml/`);
//zip.addLocalFolder(`${unzipDir}/docProps/`);
//zip.addLocalFolder(`${unzipDir}/word/`);
//commented above lines and added below line
zip.addLocalFolder(`${unzipDir}/`);
Hope this will help others also.
I created a webserver using Python Flask. My "index.html" loads a table. I am planning to create a new field "view result" to each row of the table. On clicking view result, I should be able to visualize the data. I want the filename (corresponding to each entry of "view result"), to be the input file parameter to a javascript.
The filename should get passed here d3.csv("/static/<filename>.csv", function(data){...} which belongs to a file named view_data.js and data from corresponding file is visualized in another html page.
I have index.html page and view_data.js ready. How do I pass filename from index.html page to data.js for visualization?
For now I have hardcoded the filename in view_data.js.
Are you familiar with element selectors and events in javascript?
A simple implementation would be to set up event triggers that will fire when clicking each link, using the filename as that you store in a data attribute.
<a class="view-trigger" data-filename="filename_1.csv">view result</a>
<a class="view-trigger" data-filename="filename_2.csv">view result</a>
etc
You can set up the event using something like a specific class on each of the links (in the example view-trigger.
var resultLinks = document.getElementsByClassName(".view-trigger")
for(var i = 0; i < resultLinks.length; i++) {
(function(index) {
resultLinks[index].addEventListener("click", function(event) {
var filename = event.target.getAttribute('data-filename');
d3.csv("/static/" + filename + ".csv", function(data){...}
})
})(i);
}
I haven't tested this code so you may need to fix/adjust for your case. If you are not familiar with these concepts it's worth reading a bit more about them.
Also, d3.js also seems to come with utilities to do DOM selection and handling events, so you may want to use those instead.
I have a program where a camera is set up to constantly take pictures (about every 10 seconds or so) and the picture is sent to a folder on my server and then another program refreshes that folder constantly so that I always just have the most recent picture in that particular folder.
An HTML document exists that also constantly refreshes, and references that picture location to get and display the newest image.
What I'm trying to do is extract the EXIF data (that I've verified exists when I save the image from the active webpage and look at it's properties). I want to display the DateCreated (I believe this is DateTime) and the Latitude and Longitude (I believe is GPSLatitude and GPSLongitude).
I came across this library, exif-js, which seems like the go-to for most people trying to do this same thing in JavaScript. My code looks the same as the code at the bottom of the README.md file, except I changed out my img id="...." and variable names, (see below). It seems like it should work, but it's not producing any data. My empty span element just stays empty.
Is there an issue with the short time span that the page has before refreshing?
Thanks for any help!
Here's what my code currently looks like (just trying to get the DateTime info). I have also tried the GPSLatitude and GPSLongitude tags.
<!-- Library to extract EXIF data -->
<script src="vendors/exif-js/exif-js"></script>
<script type="text/javascript">
window.onload=getExif;
function getExif()
{
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var time = EXIF.getTag(this, "DateTime");
var img1Time = document.getElementById("img1Time");
img1Time.innerHTML = `${time}`;
});
var img2 = document.getElementById("img2");
EXIF.getData(img2, function() {
var allMetaData = EXIF.getALLTags(this);
var allMetaDataSpan = document.getElementById("Img2Time");
allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, "\t");
});
}
</script>
go into ur exif.js file and then go to line 930 and then change it to
EXIF.getData = function(img, callback) {
if ((self.Image && img instanceof self.Image
|| self.HTMLImageElement && img instanceof self.HTMLImageElement)
&& !img.complete)
return false;
I know this may be already solved but I'd like to offer an alternative solution, for the people stumbling upon this question.
I'm a developer of a new library exifr you might want to try. It's maintained, actively developed library with focus on performance and works in both nodejs and browser.
async function getExif() {
let output = await exifr.parse(imgBuffer)
console.log('latitude', output.latitude) // converted by the library
console.log('longitude', output.longitude) // converted by the library
console.log('GPSLatitude', output.GPSLatitude) // raw value
console.log('GPSLongitude', output.GPSLongitude) // raw value
console.log('GPSDateStamp', output.GPSDateStamp)
console.log('DateTimeOriginal', output.DateTimeOriginal)
console.log('DateTimeDigitized', output.DateTimeDigitized)
console.log('ModifyDate', output.ModifyDate)
}
You can also try out the library's playground and experiment with images and their output, or check out the repository and docs.
in extendscript - Photoshop, I would like my dialog-box check boxes to default to previously used choices ... anyone know if this is possible?
You have two choices.
First choice: Using a //#targetengine
Values can be made persistent over a session using a targetengine.
First script
//#targetengine myengine
var x = 100;
Second script
//#targetengine myengine
$.writeln(x);
If you close Photoshop all of the values will be lost
Second choice: Write to a file.
I wont write an example here. This can be done in so many ways. Plain .txt file. .json file. See this example on how to read and write files.
fabianmoronzirfas has got the right answer.
I will say it could with one script only. That script reads in the previous value stored in a text file in a hardcoded location like C:\temp. If the script cannot file the settings file it'll default to some predetermined value and then store this time around.
Just in case, here is the simple script that saves (and tries to load) your prefs in JSON format to the system temp folder:
// set default values
var prefs = {
file: File(Folder.temp.fsName + "/prefs.json"),
title: "",
length: 0
}
// try to load previous prefs
if (prefs.file.exists) prefs = $.evalFile(prefs.file);
// do something
prefs.title = prompt("Type the title:", prefs.title);
prefs.length = prefs.title.length;
// save the prefs to the file
prefs.file.open("w");
prefs.file.write(prefs.toSource());
prefs.file.close();
I am developing a browser game using MVC4 and have been able to deploy to my website for the first time tonight. I'm sloshing through the differences between running the site off of localhost and running it from the website.
Right now the first thing I do is load all of the static content on the page--navigation bars, icons, the world map, and some basic javascript to interact with it. Then, I call four AJAX functions that return information about various elements on my 2d map, such as cities and their x,y coordinate, name, and a small flag icon.
Upon completing the AJAX function I begin to parse the JSON returned. For each item in the JSON, I add a new 20x20 pixel class using code like this:
function loadSuccessCityTiles(data) {
var cityTiles = jQuery.parseJSON(data);
var cityTileCount = cityTiles.length;
$(".CityTile").remove();
for (var i = 0; i < cityTiles.length; i++) {
var imgName = "../Images/City_Tiles/Small/" + cityTiles[i].Type + "";
$("#scrollWindow").append("<div class = 'CityTile' style = 'left: " + Math.floor(cityTiles[i].X)*tileSize + "px; top: " + Math.floor(cityTiles[i].Y)*tileSize + "px; background-image: url(" + imgName + ");'></div>") ;
}
}
As you can see, I append a new class using that has its background-image set to the appropriate image url (that is what Type means). This works great on localhost, but when I run it on the website I discover that the images don't load.
I'm not quite sure how to proceed here. I have a lot of small image elements (each in separate files) and there is no guarantee that all will be used, so it is wasteful to load them all. What would be a good solution in this case? One thought I have had is to return JSON data on which image files will be used and then preload those images via javascript all before creating the classes that will use them.
Why does this happen on the server but not localhost? Clearing my cache before reloading on localhost does not recreate this problem. Is it because there is no need for a download as all the files are already on your hard drive?
Does anyone have a suggestion on a better way to do this all together?
A better option could be to use a single image sprite as a background image for each tile. Use the Type as a class name, and set the background x,y positioning in CSS. The single image will have a large file size, but it will be a single request that could easily be cached.
As for it not working, what errors are you getting? What do you see in the network tab in Chrome dev tools for the image request?