以下代码用ANSI编码保存到 C:\Program Files\Adobe\Adobe Photoshop 2025\Presets\Scripts\AddEXIFFrame.jsx
打开Photoshop,会看到

效果图:
大的文件会自动缩放到小边2000像素。
javascript
#target photoshop
// covert "2025:02:20 13:11:21" to 2025-02-20 13:11:21
function convertToStandardTime(input) {
if(input.length != 19){
return input;
}
/*var parts = input.split(' ');
var datePart = parts[0];
var timePart = parts[1];
var formattedDate = datePart.replace(/:/g, '-').replace(/-([^-]*)$/, ':$1');
return formattedDate + ' ' + timePart;*/
var arr = input.split('');
arr[4] = '-';
arr[7] = '-';
return arr.join('');
}
// ********** DATA FUNCTIONS START ***************
// Common Data Functions used to gather EXIF data
// Sets image data to a string that will later be used to set into the image
function getExifData(doc) {
const exifInfos = {
"Producer":"",
"Model": "",
"FocalLength": "",
"FocalLength35mm": "",
"ExposureTime" : "",
"ISO" : "",
"Aperture": "",
"ExposureBiasValue": "",
"Lens" : "",
"DateTimeDigitized": "",
"DateTime": ""
};
// Get exif data from file
var exifString = doc.info.exif.toString();
const parts = exifString.split(',');
// check the data
for (i = 0; i < parts.length; i = i + 3) {
var key = parts[i];
var value = parts[i + 1];
switch(key){
case "制造":
case "Make":
exifInfos.Producer = value;
break;
case "机型":
case "Model":
exifInfos.Model = value;
break;
case "焦距":
case "Focal Length":
exifInfos.FocalLength = value.replace(" mm", "mm");
break;
case "Focal Length in 35mm Film":
exifInfos.FocalLength35mm = value.replace(" mm", "mm");
break;
case "曝光时间":
case "Exposure Time":
exifInfos.ExposureTime = value.replace(" sec", "s");
break;
case "ISO 感光度":
case "ISO Speed Ratings":
exifInfos.ISO = value;
break;
case "光圈值":
case "Aperture Value":
exifInfos.Aperture = value;
break;
case "曝光补偿值":
case "Exposure Bias Value":
exifInfos.ExposureBiasValue = value;
break;
case "EXIF tag 42036":
exifInfos.Lens = value;
break;
case "数字化日期时间":
case "Date Time Digitized":
exifInfos.DateTimeDigitized = convertToStandardTime(value);
break;
case "日期时间":
case "Date Time":
exifInfos.DateTime = convertToStandardTime(value);
break;
default:
break;
}
}
return exifInfos;
}
function addText(doc, x, y, layer_name, text, color, justification, vertical_degree, anchor_position){
var textLayer = doc.artLayers.add();
textLayer.kind = LayerKind.TEXT;
textLayer.name = layer_name;
var textItem = textLayer.textItem;
textItem.position = [x, y];
textItem.size = 11;
textItem.font = "Arial";
textItem.tracking = 100;
textItem.color = color;
textItem.justification = justification;
if(vertical_degree != 0){
textItem.contents = "TEXT";
textLayer.rotate(vertical_degree, anchor_position);
}
textItem.contents = text;
return textLayer;
}
// Define Colors
var black = new SolidColor();
black.rgb.red = black.rgb.green = black.rgb.blue = 0;
var white = new SolidColor();
white.rgb.red = white.rgb.green = white.rgb.blue = 255;
var gray = new SolidColor();
gray.rgb.red = gray.rgb.green = gray.rgb.blue = 127;
var textColor = new SolidColor();
textColor.rgb.red = textColor.rgb.green = textColor.rgb.blue = 230;
// check image opened.
if (app.documents.length > 0) {
var originalRuleUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var doc = app.activeDocument;
var whRatio = doc.width/ doc.height;
var resizing = false;
var newWidth = doc.width;
var newHeight = doc.height;
if( whRatio > 1){
if(doc.height > 2000) {
// resize
newHeight = 2000;
newWidth = newHeight * doc.width / doc.height;
resizing = true;
}
}
else {
if(doc.width > 2000) {
// resize
newWidth = 2000;
newHeight = newWidth * doc.height / doc.width;
resizing = true;
}
}
if(resizing){
try {
doc.resizeImage(newWidth, newHeight, null, ResampleMethod.BICUBIC);
// alert("Image resized to " + newWidth + "x" + newHeight + " px.");
} catch (e) {
alert("Failed to resize image:" + e.message);
}
}
var originalWidth = doc.width;
var originalHeight = doc.height;
var bgLayer = undefined;
if (doc.artLayers.length > 0) {
bgLayer = doc.artLayers[doc.artLayers.length - 1];
bgLayer.isBackgroundLayer = false;
}
// set margins
var borderSize = Math.min(originalWidth, originalHeight) * 0.04;
if( borderSize < 20) {
borderSize = 20;
}
newWidth = originalWidth + borderSize * 2 + 10;
newHeight = originalHeight + borderSize * 2 + 10;
// resize cavas
doc.resizeCanvas(newWidth, newHeight, AnchorPosition.MIDDLECENTER);
// create frame layer
var borderLayer = doc.artLayers.add();
borderLayer.name = "Frame";
var selection = doc.selection;
selection.selectAll();
selection.fill(white);
selection.stroke(black, borderSize, StrokeLocation.INSIDE, ColorBlendMode.NORMAL, 100, false);
selection.selectAll();
selection.stroke(gray, 2, StrokeLocation.INSIDE, ColorBlendMode.NORMAL, 100, false);
selection.deselect();
if(bgLayer != undefined) {
borderLayer.move(bgLayer, ElementPlacement.PLACEAFTER);
}
else {
borderLayer.move(doc, ElementPlacement.PLACEATBEGINNING);
}
exifInfos = getExifData(doc);
var text1 = exifInfos.FocalLength + ' ' + exifInfos.Aperture + ' ' +exifInfos.ExposureTime + ' ISO' + exifInfos.ISO ;
if(exifInfos.ExposureBiasValue == 0){
text1 = text1 + ' EV+0.0';
}
else {
text1 = text1 + ' EV' + exifInfos.ExposureBiasValue;
}
var text3 = exifInfos.Producer + ' ' + exifInfos.Model + ' / ' + exifInfos.Lens;
var text2 = exifInfos.DateTimeDigitized;
if(text3 == ""){
exifInfos.DateTime;
}
var x = newWidth - borderSize;
var y = newHeight - borderSize * 0.5 + 10;
addText(doc, x, y , "EXIF Text 1", text1 , textColor, Justification.RIGHT, 0, AnchorPosition.BOTTOMLEFT);
x = newWidth - borderSize;
y = borderSize * 0.5 + 10;
if(text2 != ""){
addText(doc, x, y, "EXIF Text 2", text2, textColor, Justification.RIGHT, 0, AnchorPosition.TOPLEFT);
}
x = borderSize - 10;
y = newHeight - borderSize - 20;
addText(doc,x , y, "EXIF Text 3", text3, textColor, Justification.LEFT, -90, AnchorPosition.BOTTOMLEFT);
app.preferences.rulerUnits = originalRuleUnits;
} else {
alert("Open image first");
}
Enjoy!