jazz-y
Guide
jazz-y
Guide
Activity
Aug 28, 2024
08:08 AM
1 Upvote
The script works if you use the video timeline mode. I admit that it may not handle all possible cases, since I only considered the situation described by the author of the topic. Show a screenshot of your timeline, perhaps this will help to understand what the problem is. Normally, it is enough to change this line of code and set the desired number of seconds for the selected frames: (d = new ActionDescriptor()).putInteger(s2t("seconds"), 8);
... View more
Jan 25, 2024
11:13 AM
are you able to read the file binaries via JSX or do you need external tech here, like PHP or python? By @thomas_bredenfeld jsx has tools for reading binary data. Yes, there are some limitations that affect the speed of obtaining the necessary data, however, when writing scripts, I prefer to stay within the extendScript to ensure maximum compatibility with Photoshop and the operating system.
... View more
Jan 25, 2024
01:45 AM
2 Upvotes
Hi! If we are talking about linked layers in smart objects, then starting with version Photoshop 24.5, Adobe added a new warning dialog box when trying to open or convert to layers. It ruins the script and then it works incorrectly. I found a workaround and made some code sketches (read the binary image file directly from disk, look for all links inside, create temporary files in the directory with the main file), but I don't have the ability to adapt the script yet. If you install an earlier version of Photoshop (for example, 24.0), then the script should work correctly.
... View more
Nov 23, 2023
12:42 AM
Ingenious!
... View more
Nov 22, 2023
12:59 PM
1 Upvote
Nov 22, 2023
12:55 PM
1 Upvote
You are using variables newWidth
newHeight in layer.resize(newWidth, newHeight, AnchorPosition.MIDDLECENTER); but I don't see their definition in the code 🤷
... View more
Nov 22, 2023
12:43 PM
1 Upvote
Nov 22, 2023
12:17 PM
Downloading and Installing Adobe Scripts by @Stephen Marsh
... View more
Nov 22, 2023
10:24 AM
You can try my old script Batch for layers The script sequentially switches the selected layers and saves the document. Options can be adjusted to suit your needs.
... View more
Nov 22, 2023
07:07 AM
2 Upvotes
try this: #target photoshop
const s2t = stringIDToTypeID;
var activeHistoryState = activeDocument.activeHistoryState;
// convert document to RGB
(d = new ActionDescriptor()).putClass(s2t('to'), s2t('RGBColorMode'));
executeAction(s2t('convertMode'), d, DialogModes.NO);
var RGB = [];
// calculating background fill color (based on histogram)
for (var i = 1; i <= 3; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('histogram'));
r.putIndex(s2t('channel'), i);
var histogram = executeActionGet(r).getList(p),
max = 0, value = 0;
for (var n = 0; n < histogram.count; n++) {
var cur = histogram.getInteger(n);
if (cur > max) {
max = cur;
value = n;
}
}
RGB.push(value);
}
// fill document with found color in difference mode
(d = new ActionDescriptor()).putEnumerated(s2t('using'), s2t('fillContents'), s2t('color'));
(d1 = new ActionDescriptor()).putDouble(s2t('red'), RGB[0]);
d1.putDouble(s2t('green'), RGB[1]);
d1.putDouble(s2t('blue'), RGB[2]);
d.putObject(s2t('color'), s2t('RGBColor'), d1);
d.putUnitDouble(s2t('opacity'), s2t('percentUnit'), 100);
d.putEnumerated(s2t('mode'), s2t('blendMode'), s2t('difference'));
executeAction(s2t('fill'), d, DialogModes.NO);
// make selection to RGB channel
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('target'), r);
(r1 = new ActionReference()).putEnumerated(s2t('channel'), s2t('channel'), s2t('RGB'));
d.putReference(s2t('to'), r1);
executeAction(s2t('set'), d, DialogModes.NO);
//save selection to variable
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('selection'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var selection = executeActionGet(r).getObjectValue(p);
// return initial state of document
activeDocument.activeHistoryState = activeHistoryState;
// crop to saved selection
(d = new ActionDescriptor()).putObject(s2t('to'), s2t('rectangle'), selection);
d.putUnitDouble(s2t('angle'), s2t('angle'), 0);
d.putBoolean(s2t('delete'), false);
executeAction(s2t('crop'), d, DialogModes.NO); We can also simplify the code and use the select subject function, but the accuracy of determining the boundaries of the object may vary: #target photoshop
const s2t = stringIDToTypeID;
var activeHistoryState = activeDocument.activeHistoryState;
// convert document to RGB
(d = new ActionDescriptor()).putClass(s2t('to'), s2t('RGBColorMode'));
executeAction(s2t('convertMode'), d, DialogModes.NO);
//call select subject function
(d = new ActionDescriptor()).putBoolean(s2t('sampleAllLayers'), true);
executeAction(s2t('autoCutout'), d, DialogModes.NO);
//save selection to variable
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('selection'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var selection = executeActionGet(r).getObjectValue(p);
// return initial state of document
activeDocument.activeHistoryState = activeHistoryState;
// crop to saved selection
(d = new ActionDescriptor()).putObject(s2t('to'), s2t('rectangle'), selection);
d.putUnitDouble(s2t('angle'), s2t('angle'), 0);
d.putBoolean(s2t('delete'), false);
executeAction(s2t('crop'), d, DialogModes.NO);
... View more
Nov 22, 2023
12:26 AM
1 Upvote
app.system("cd /d %temp% & echo hi > tests.txt; & pause") The console process is launched from the app folder 'C:\Program Files\Adobe\Adobe Photoshop 2024' If you do not have administrator rights, then it is not surprising that you receive an error message 🤷
... View more
Nov 20, 2023
11:49 AM
1 Upvote
var d=new ActionDescriptor();
d.putClass( stringIDToTypeID( "as" ), stringIDToTypeID( "path" ));
executeAction( stringIDToTypeID( "paste" ), d, DialogModes.NO );
... View more
Oct 09, 2023
10:48 PM
1 Upvote
Can you automatically give every subsequent letter a different color for a batch of text designs?
... View more
Sep 09, 2023
07:07 AM
1 Upvote
Use frequency separation. You can find many tutorials about this processing method. With it, you can separate image details from noise and process them separately.
... View more
Sep 08, 2023
10:00 PM
1 Upvote
Why is the + sign needed here? var newTextContents = textContents.replace(new RegExp(searchWord, 'gi'),+ searchWord );
... View more
Sep 06, 2023
10:25 PM
2 Upvotes
Make sure the path of the file object is correct. Post the code of makedirs() function.
... View more
Sep 04, 2023
10:15 AM
2 Upvotes
Tiff is a rather old format that has a number of security problems due to the peculiarities of the internal data structure. I do not know the exact reason, but I suspect that Adobe is trying to protect your system from possible problems as much as possible, as a result, it performs a lot of additional checks on the file structure, leading to a noticeable decrease in performance. I use TIFF only as a format for data exchange (in cases where it is necessary for the receiving party). I recommend that you use PSD for storing files (if you do not have the file compression option disabled in Photoshop settings, then you will get a good balance between speed and final file size).
... View more
Sep 02, 2023
12:55 PM
1 Upvote
The code is written to work with RGB images. After the update, your PDF import options have lost and you open them as CMYK. This can be fixed in the script code, but the easiest way is to find the color mode settings when importing PDF and change CMYK to RGB.
... View more
Sep 02, 2023
04:25 AM
2 Upvotes
The question does not apply to Photoshop. Attach files as documents, in this case the original name and extension will be preserved.
... View more
Sep 01, 2023
03:10 PM
2 Upvotes
This is quite a creative task that does not have an unambiguous solution unless a mathematically precise definition of what "most prominent color" means is given ¯\_(ツ)_/¯ The first thing that came to my mind was to reduce the image and use the color difference formula to calculate how much each color differs from the other. If the color difference between two pixels is less than a user-specified threshold (in this case DE_THRESHOLD = 15), then add 1 point to the pixel. Thus, the color with the highest score will be more prominent in the image. var apl = new AM('application'),
doc = new AM('document');
const DE_THRESHOLD = 15,
RESIZE_TO = 35;
if (apl.getProperty('numberOfDocuments')) {
var docRes = doc.getProperty('resolution'),
docW = doc.getProperty('width') * docRes / 72,
docH = doc.getProperty('height') * docRes / 72;
doc.duplicate();
doc.resize(docW > docH ? 'width' : 'height', RESIZE_TO)
var f = new File(Folder.temp + '/colors.raw');
doc.flatten();
doc.saveToRAW(f);
doc.close('no');
var colors = findColors(f);
f.remove();
for (var i = 0; i < colors.length; i++) {
colors[i][3] = 0;
for (var x = 0; x < colors.length; x++) {
if (x != i && dE(colors[i], colors[x]) <= DE_THRESHOLD) colors[i][3]++
}
}
var result = 0,
idx = null;
for (var i = 0; i < colors.length; i++) {
if (colors[i][3] >= result) { result = colors[i][3]; idx = i; }
}
var c = new SolidColor;
c.rgb.red = colors[idx][0],
c.rgb.green = colors[idx][1],
c.rgb.blue = colors[idx][2];
foregroundColor = c;
}
function findColors(f) {
var content = '';
if (f.exists) {
f.open('r');
f.encoding = "BINARY";
content = f.read();
f.close();
f.remove();
return colors = function (s) {
var m = [],
offset = 0;
do {
var c = [];
for (i = 0; i < 3; i++) {
var k = s.charCodeAt(offset + i);
c.push(k)
};
m.push(c)
offset += 3;
} while (offset < s.length)
return m;
}(content);
}
}
function dE(a, b) {
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2));
}
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID,
c2t = charIDToTypeID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.resize = function (dimension, value) {
(d = new ActionDescriptor()).putUnitDouble(s2t(dimension), s2t("pixelsUnit"), value);
d.putBoolean(s2t("constrainProportions"), true);
d.putEnumerated(c2t("Intr"), s2t("interpolationType"), s2t("automaticInterpolation"));
executeAction(s2t("imageSize"), d, DialogModes.NO);
}
this.flatten = function () {
executeAction(s2t("flattenImage"), new ActionDescriptor(), DialogModes.NO);
}
this.saveToRAW = function (f) {
(d = new ActionDescriptor()).putBoolean(s2t('copy'), true);
(d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("rawFormat"), d);
d1.putPath(s2t("in"), f);
executeAction(s2t("save"), d1, DialogModes.NO);
}
this.duplicate = function () {
(r = new ActionReference()).putEnumerated(target, s2t("ordinal"), s2t("targetEnum"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
executeAction(s2t("duplicate"), d, DialogModes.NO);
}
this.close = function (yesNo) {
(d = new ActionDescriptor()).putEnumerated(s2t("saving"), s2t("yesNo"), s2t(yesNo));
executeAction(s2t("close"), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
} You can go further and compare groups of colors with maximum scores among themselves, finding the difference already among them (that is, find any desired number of color clusters). You can use other color models (for example, HSB to eliminate (or reduce) the influence of individual color components) and so on.
... View more
Aug 30, 2023
02:04 AM
2 Upvotes
It looks like you are working with an untagged rgb image on a monitor with a wide color gamut. Uncheck "convert to srgb" in the export window.
... View more
Aug 29, 2023
02:24 PM
1 Upvote
I have updated the code in the post above, try it. MAXIMUM_RADIUS specifies the radius with which the Filters -> Other -> Maximum filter is applied. The goal I'm aiming for is to clear the image of garbage and frames. Source frame: frame after Maximum filter with radius 22 Next, on this cleaned image, the script executes the command Select -> Select Subject: Then the script tries to align the image, for this it increases the selection box by the number of GLOBAL_OFFSET pixels in each direction. After that, the image is transformed by the Crop and Straighten filter: Then I re-execute the Select -> Select Subject command and increase the selection by HEAD_OFFSET pixels up to provide free space above the head and finally crop the image within these boundaries: That is, you can change these three constants yourself to achieve optimal results (however, it is difficult to guarantee that in 100% of cases the script will perform its task correctly).
... View more
Aug 29, 2023
12:22 PM
1 Upvote
Pay attention to how I arranged the guides (you need to divide whole cards with them, not portraits) The script constants depend on the resolution of the image. If you are using a larger image, then they need to be adjusted (larger MAXIMUM_RADIUS and larger GLOBAL_OFFSET and HEAD_OFFSET paddings). The screenshot in this case is useless - I can not adjust the parameters myself. If possible, post the original image.
... View more
Aug 29, 2023
10:41 AM
1 Upvote
Unfortunately, fully automatic image segmentation using scripts is not possible. I implemented the method about which I wrote above. It doesn't work perfectly, but it's better than nothing. Perhaps this will serve as a starting point for you. Parameters that depend on the resolution of the image are displayed in the constants block, you can change them if necessary. * for better results you need to enable the cloud processing option (for the automatic selection of objects function) in Photoshop settings. var apl = new AM('application'),
doc = new AM('document'),
lr = new AM('layer'),
tiles = [];
const MAXIMUM_RADIUS = 22, //adjust filters -> other -> maximum filter to remove fine black lines
GLOBAL_OFFSET = 80, //offset initial object selection to clarify the position of an object
HEAD_OFFSET = 30; //offset selection from the top line of the head
try {
if (apl.getProperty('numberOfDocuments')) {
activeDocument.suspendHistory('Tile Splitting', 'function () {}');
var docRes = doc.getProperty('resolution'),
docW = doc.getProperty('width') * docRes / 72,
docH = doc.getProperty('height') * docRes / 72;
activeDocument.suspendHistory('Find tiles', 'findTiles()');
activeDocument.suspendHistory('Save tile', 'saveTile()');
}
} catch (e) { alert('Many things can be wrong in this script. :(\n\n' + e) }
function findTiles() {
var guides = activeDocument.guides;
if (guides && guides.length) {
var startRulerUnits = preferences.rulerUnits,
startTypeUnits = preferences.typeUnits,
v = [],
h = [];
preferences.rulerUnits = Units.PIXELS;
preferences.typeUnits = TypeUnits.PIXELS;
for (var i = 0; i < guides.length; i++) {
var cur = guides[i];
if (cur.direction == Direction.VERTICAL)
v.push(Math.round(guides[i].coordinate.value)) else
h.push(Math.round(guides[i].coordinate.value))
}
h.sort();
v.sort();
var top = 0;
do {
var len = h.length,
cur = h.length ? h.shift() : docH,
left = 0;
for (var i = 0; i < v.length; i++) {
tiles.push([top, left, cur, v[i]]);
left += v[0];
}
tiles.push([top, v[i - 1], cur, docW]);
top = cur;
} while (len)
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
}
}
function saveTile() {
var title = doc.getProperty('title').replace(/\.[0-9a-z]+$/i, '') + '-',
pth = doc.getProperty('fileReference').parent;
for (var i = 0; i < tiles.length; i++) {
doc.duplicate(i + 1);
doc.makeSelection(tiles[i][0], tiles[i][1], tiles[i][2], tiles[i][3])
doc.crop();
lr.copyToLayer();
lr.filterMaximum(MAXIMUM_RADIUS, 'squareness')
lr.selectSubject();
lr.deleteLayer();
var sel = doc.getProperty('selection').value;
doc.makeSelection(
sel.getDouble(stringIDToTypeID('top')) - GLOBAL_OFFSET,
sel.getDouble(stringIDToTypeID('left')) - GLOBAL_OFFSET,
sel.getDouble(stringIDToTypeID('bottom')) + GLOBAL_OFFSET,
sel.getDouble(stringIDToTypeID('right')) + GLOBAL_OFFSET
)
doc.crop();
lr.straightenLayer();
doc.flatten();
lr.selectSubject();
var sel = doc.getProperty('selection').value;
doc.makeSelection(
sel.getDouble(stringIDToTypeID('top')) - HEAD_OFFSET,
sel.getDouble(stringIDToTypeID('left')),
sel.getDouble(stringIDToTypeID('bottom')),
sel.getDouble(stringIDToTypeID('right'))
)
doc.crop();
doc.saveToJPG(title + (i + 1), pth);
doc.close('no')
}
}
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID,
c2t = charIDToTypeID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.copyToLayer = function () {
executeAction(s2t("copyToLayer"), undefined, DialogModes.NO);
}
this.filterMaximum = function (radius, mode) {
(d = new ActionDescriptor()).putUnitDouble(c2t("Rds "), s2t("pixelsUnit"), radius);
d.putEnumerated(s2t("preserveShape"), s2t("preserveShape"), s2t(mode));
executeAction(s2t("maximum"), d, DialogModes.NO);
}
this.makeSelection = function (top, left, bottom, right) {
(r = new ActionReference()).putProperty(s2t("channel"), s2t("selection"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t("top"), s2t("pixelsUnit"), top);
d1.putUnitDouble(s2t("left"), s2t("pixelsUnit"), left);
d1.putUnitDouble(s2t("bottom"), s2t("pixelsUnit"), bottom);
d1.putUnitDouble(s2t("right"), s2t("pixelsUnit"), right);
d.putObject(s2t("to"), s2t("rectangle"), d1);
executeAction(s2t("set"), d, DialogModes.NO);
}
this.crop = function () {
(d = new ActionDescriptor()).putBoolean(s2t("delete"), true);
executeAction(s2t("crop"), d, DialogModes.NO);
}
this.saveToJPG = function (title, pth) {
(d = new ActionDescriptor()).putObject(s2t("as"), s2t("JPEG"), new ActionDescriptor());
d.putPath(s2t("in"), new File(pth + '/' + title));
d.putBoolean(s2t("copy"), true);
executeAction(s2t("save"), d, DialogModes.NO);
}
this.duplicate = function (title) {
(r = new ActionReference()).putEnumerated(target, s2t("ordinal"), s2t("targetEnum"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
d.putString(s2t("name"), title);
executeAction(s2t("duplicate"), d, DialogModes.NO);
}
this.selectionFromChannel = function (channel) {
(r = new ActionReference()).putProperty(s2t("channel"), s2t("selection"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
(r1 = new ActionReference()).putEnumerated(s2t("channel"), s2t("channel"), s2t(channel));
d.putReference(s2t("to"), r1);
executeAction(s2t("set"), d, DialogModes.NO);
}
this.inverseSelection = function () {
executeAction(s2t("inverse"), undefined, DialogModes.NO);
}
this.close = function (yesNo) {
(d = new ActionDescriptor()).putEnumerated(s2t("saving"), s2t("yesNo"), s2t(yesNo));
executeAction(s2t("close"), d, DialogModes.NO);
}
this.deleteLayer = function () {
(r = new ActionReference()).putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
executeAction(s2t("delete"), d, DialogModes.NO);
}
this.selectSubject = function () {
(d = new ActionDescriptor()).putBoolean(s2t("sampleAllLayers"), false);
executeAction(s2t("autoCutout"), d, DialogModes.NO);
}
this.straightenLayer = function () {
/** by r-bin
* https://community.adobe.com/t5/photoshop-ecosystem/use-the-crop-amp-straighten-but-don-t-crop/m-p/12225478
*/
var d = executeAction(stringIDToTypeID('CropPhotos0001'), undefined, DialogModes.NO);
var l = d.getList(stringIDToTypeID('value'));
var p = new Array();
for (var i = 0; i < 8; i += 2) p.push([l.getDouble(i), l.getDouble(i + 1)]);
var angle = - Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]) * 180 / Math.PI
if (angle != 0) {
if (activeDocument.activeLayer.isBackgroundLayer) executeAction(s2t('copyToLayer'), undefined, DialogModes.NO);
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putUnitDouble(s2t('angle'), s2t('angleUnit'), angle);
executeAction(s2t('transform'), d, DialogModes.NO);
}
}
this.flatten = function () {
executeAction(s2t("flattenImage"), new ActionDescriptor(), DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
} * code updated.
... View more
Aug 29, 2023
06:33 AM
1 Upvote
@r28071715i111, are you ready to manually mark up all your photos using guides? In this case, we can write a script that will retrieve each image based on this markup. After that, you scipt run the crop and straighten filter, which will try to align each image separately (this is unlikely to guarantee 100% success, but I think 80% of the work will be done automatically)
... View more
Aug 29, 2023
05:05 AM
1 Upvote
find line executeAction(s2t('cutToLayer'), undefined, DialogModes.NO); and replace cutToLayer by copyToLayer: executeAction(s2t('copyToLayer'), undefined, DialogModes.NO)
... View more
Aug 29, 2023
05:02 AM
1 Upvote
Yes, sure. I intentionally made them into constants to make it easier to edit. Above, I explained what they do and what result you should strive for.
... View more
Aug 29, 2023
03:25 AM
1 Upvote
Post the files with questions 6 and 7. I see 1-4 and 16-20. If you change the script parameters to MINIMUM_RADIUS = 60,
BLUR_DISTANCE = 500; then they are processed quite correctly (not counting the footer, but as I understand it, it is not needed) Unfortunately, Photoshop does not allow scripts to access the content of images. I have to use indirect methods to segment the image, keeping the balance between script execution time and the result obtained. It takes some patience to find the optimal parameters, or a fundamentally different approach. Perhaps someone else will come up with a better solution.
... View more
Aug 28, 2023
11:36 PM
1 Upvote
@erol5ECF, please reply in the thread, not in private messages. It doesn't matter to you, but a public dialogue can help other users. In the topic, you were asked several times to provide the original image with which you will work. Like @c.pfaffenbichler, i waited several hours for clarifications from you, but they did not follow, so I decided that all the remaining images look the same as your screenshots. If the script does not work on other images, then most likely its parameters need to be adjusted. Initially, I used the following values, which you can see in the code: MINIMUM_RADIUS = 30
BLUR_DISTANCE = 200; The script initially trims the black edges. If your original image does not contain them, then remove or comment out the line: lr.trim('topLeftPixelColor', 1, 1, 1, 1); (it is better not to delete the parent function, since it affects the number of history rollbacks performed by the script) Then I execute the command filters -> other -> minimum. My goal is to get evenly black blocks of text. In your example, a radius of 30 was enough for me, but perhaps a larger value should be set. Try to execute the minimum function on other images and find the optimal constant value. Next, I do motion blur. The purpose of this action is to get black continuous stripes from the left side of the image that separate each block of text. The right side of the image does not interest me at the moment. I used a radius of 200, but you can also try changing this setting. After applying levels with a black point of 195 and a white point of 220, I get this image: lr.levels([195, 220]) From it, I only need the left column 1 pixel wide and image height (I expanded it for an example) Further, the script simply looks for the boundaries of the black blocks and splits the original image based on them. If you see that a column of pixels contains artifacts or gaps, you can move the selection position closer to the center of the image, as long as it is 1 pixel wide doc.makeSelection(0, 0, docH, 1); //(top, left, bottom, right) I think you have received enough information to independently correct the script on the original images.
... View more
Aug 28, 2023
09:26 AM
2 Upvotes
On the two files you posted, this script works perfectly. How it will work with others - I do not know ¯\_(ツ)_/¯ var apl = new AM('application'),
doc = new AM('document'),
lr = new AM('layer'),
tiles = [];
const THRESHOLD_LEVEL = 80,
MINIMUM_RADIUS = 30,
BLUR_DISTANCE = 200;
try {
if (apl.getProperty('numberOfDocuments')) {
activeDocument.suspendHistory('Tile Splitting', 'function () {}');
activeDocument.suspendHistory('Trim', 'trim()');
var docRes = doc.getProperty('resolution'),
docW = doc.getProperty('width') * docRes / 72,
docH = doc.getProperty('height') * docRes / 72;
activeDocument.suspendHistory('Save strip', 'getPixelStrip()');
doc.stepBack();
if (tiles.length) {
var title = doc.getProperty('title').replace(/\.[0-9a-z]+$/i, '') + '-',
pth = doc.getProperty('fileReference').parent;
for (var i = 0; i < tiles.length; i++) {
doc.duplicate(i + 1);
doc.makeSelection(tiles[i][0], 0, tiles[i][1], docW);
doc.crop();
lr.copyToLayer();
doc.levels([128, 220]);
doc.selectionFromChannel('RGB');
doc.inverseSelection();
var bounds = doc.getProperty('selection').value;
lr.deleteLayer();
doc.makeSelection(bounds.getDouble(stringIDToTypeID('top')) - 2, 0, bounds.getDouble(stringIDToTypeID('bottom')) + 2, docW);
doc.crop();
doc.saveToPNG(title + (i + 1), pth);
doc.close('no');
}
}
doc.stepBack();
}
} catch (e) { alert('A lot of things can go wrong in this script. :(\n\n' + e) }
function trim() {
lr.copyToLayer();
lr.invert();
lr.threshold(THRESHOLD_LEVEL);
lr.trim('topLeftPixelColor', 1, 1, 1, 1);
lr.deleteLayer();
}
function getPixelStrip() {
lr.copyToLayer();
lr.filterMinimum(MINIMUM_RADIUS, 'squareness');
lr.motionBlur(0, BLUR_DISTANCE)
lr.levels([195, 220])
doc.makeSelection(0, 0, docH, 1);
doc.flatten();
doc.crop();
doc.convertToGrayscale();
var f = new File(Folder.temp + '/colors.raw');
doc.saveToRAW(f)
tiles = findTiles(f);
}
function findTiles(f) {
var content = '';
if (f.exists) {
f.open('r');
f.encoding = "BINARY";
content = f.read();
f.close();
f.remove();
var colors = function (s) {
var m = 0, c = [];
for (var i = 0; i < s.length; i++) {
var k = s.charCodeAt(i); m += k; c.push(k)
};
return c
}(content);
var tiles = [],
cur = 0;
do {
var tile = [];
for (cur; cur < colors.length; cur++) {
if (cur == colors.length - 1) {
c = 0
}
if (colors[cur] < 16) {
if (!tile.length || cur == colors.length - 1) {
tile.push(cur)
if (cur == colors.length - 1) tiles.push(tile);
} else continue;
}
if (colors[cur] > 128) {
if (tile.length == 1) {
tile.push(cur - 1);
tiles.push(tile);
break;
} else continue;
}
}
if (cur == colors.length) break;
} while (true);
return tiles;
}
}
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID,
c2t = charIDToTypeID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.copyToLayer = function () {
executeAction(s2t("copyToLayer"), undefined, DialogModes.NO);
}
this.invert = function () {
executeAction(s2t("invert"), new ActionDescriptor(), DialogModes.NO);
}
this.threshold = function (level) {
(d = new ActionDescriptor()).putInteger(s2t("level"), level);
executeAction(s2t("thresholdClassEvent"), d, DialogModes.NO);
}
this.trim = function (mode, top, bottom, left, right) {
(d = new ActionDescriptor()).putEnumerated(s2t("trimBasedOn"), s2t("trimBasedOn"), s2t(mode));
d.putBoolean(s2t("top"), top);
d.putBoolean(s2t("bottom"), bottom);
d.putBoolean(s2t("left"), left);
d.putBoolean(s2t("right"), right);
executeAction(s2t("trim"), d, DialogModes.NO);
}
this.filterMinimum = function (radius, mode) {
(d = new ActionDescriptor()).putUnitDouble(c2t("Rds "), s2t("pixelsUnit"), radius);
d.putEnumerated(s2t("preserveShape"), s2t("preserveShape"), s2t(mode));
executeAction(s2t("minimum"), d, DialogModes.NO);
}
this.motionBlur = function (angle, distance) {
(d = new ActionDescriptor()).putInteger(s2t("angle"), angle);
d.putUnitDouble(s2t("distance"), s2t("pixelsUnit"), distance);
executeAction(s2t("motionBlur"), d, DialogModes.NO);
}
this.levels = function (levels) {
(d = new ActionDescriptor()).putEnumerated(s2t("presetKind"), s2t("presetKindType"), s2t("presetKindCustom"));
(r = new ActionReference()).putEnumerated(s2t("channel"), s2t("channel"), s2t("composite"));
(d1 = new ActionDescriptor()).putReference(s2t("channel"), r);
var l1 = new ActionList();
for (var i = 0; i < levels.length; i++) l1.putInteger(levels[i]);
d1.putList(s2t("input"), l1);
(l = new ActionList()).putObject(s2t("levelsAdjustment"), d1);
d.putList(s2t("adjustment"), l);
executeAction(s2t("levels"), d, DialogModes.NO);
}
this.convertToGrayscale = function () {
(d = new ActionDescriptor()).putClass(s2t("to"), s2t("grayscaleMode"));
executeAction(s2t("convertMode"), d, DialogModes.NO);
}
this.flatten = function () {
executeAction(s2t("flattenImage"), new ActionDescriptor(), DialogModes.NO);
}
this.stepBack = function () {
(r = new ActionReference()).putProperty(c2t("HstS"), s2t("currentHistoryState"));
(d = new ActionDescriptor()).putReference(s2t("target"), r);
executeAction(s2t("delete"), d, DialogModes.NO);
}
this.makeSelection = function (top, left, bottom, right) {
(r = new ActionReference()).putProperty(s2t("channel"), s2t("selection"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t("top"), s2t("pixelsUnit"), top);
d1.putUnitDouble(s2t("left"), s2t("pixelsUnit"), left);
d1.putUnitDouble(s2t("bottom"), s2t("pixelsUnit"), bottom);
d1.putUnitDouble(s2t("right"), s2t("pixelsUnit"), right);
d.putObject(s2t("to"), s2t("rectangle"), d1);
executeAction(s2t("set"), d, DialogModes.NO);
}
this.crop = function () {
(d = new ActionDescriptor()).putBoolean(s2t("delete"), true);
executeAction(s2t("crop"), d, DialogModes.NO);
}
this.saveToRAW = function (f) {
(d = new ActionDescriptor()).putBoolean(s2t('copy'), true);
(d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("rawFormat"), d);
d1.putPath(s2t("in"), f);
executeAction(s2t("save"), d1, DialogModes.NO);
}
this.saveToPNG = function (title, pth) {
(d = new ActionDescriptor()).putObject(s2t("as"), s2t("PNGFormat"), new ActionDescriptor());
d.putPath(s2t("in"), new File(pth + '/' + title + '.png'));
d.putBoolean(s2t("copy"), true);
executeAction(s2t("save"), d, DialogModes.NO);
}
this.duplicate = function (title) {
(r = new ActionReference()).putEnumerated(target, s2t("ordinal"), s2t("targetEnum"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
d.putString(s2t("name"), title);
executeAction(s2t("duplicate"), d, DialogModes.NO);
}
this.selectionFromChannel = function (channel) {
(r = new ActionReference()).putProperty(s2t("channel"), s2t("selection"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
(r1 = new ActionReference()).putEnumerated(s2t("channel"), s2t("channel"), s2t(channel));
d.putReference(s2t("to"), r1);
executeAction(s2t("set"), d, DialogModes.NO);
}
this.inverseSelection = function () {
executeAction(s2t("inverse"), undefined, DialogModes.NO);
}
this.close = function (yesNo) {
(d = new ActionDescriptor()).putEnumerated(s2t("saving"), s2t("yesNo"), s2t(yesNo));
executeAction(s2t("close"), d, DialogModes.NO);
}
this.deleteLayer = function () {
(r = new ActionReference()).putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
executeAction(s2t("delete"), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
... View more