Copy link to clipboard
Copied
Hi,
I have more than a hundred old black and white photos that was scanned in jpg. They have all an white border that I want to cut out. Is there a way to computerize these photos in batch with Photoshop CC (2017 version on Windows 10) to cut out their border, which are all different widths. You can see two examples I have included here.
Thank you!
Let us be clear :
CS versions were sold with perpetual licenses. The last CS version was CS6
CC versions are all subscription only. Be that CC, CC 2014, 2015 .....etc ALL CC versions are subscription only and the subscription gives you access to the current versions. If you are using a "perpetual version" of CC then it is a hacked, pirated copy and as such illegal.
Dave
Copy link to clipboard
Copied
go to the image / trim menu
Copy link to clipboard
Copied
This will work on some of the images, but not all of them. Your second example, for instance, has darker tones in the top right corner which will stop this from working. It might save you some time time though.
Open one of the images and start a new Action. For argument sake, call it 'Remove Border'.
Record the following steps and stop the Action.
1) Add a Levels adjustment layer with theses values
2) Image Trim > top left corner
3) Delete the Levels Adjustment layer
Stop the Action.
COPY all of the images to a new folder.
Go File > Image Processor
Select the folder with the copied images
Decide where to save the processed images, or use the same location (only because you are using copies)
Decide on a format to save the processed images and the quality (if JPG)
Check Run Action and chose the action you made (Remove Border)
Run the action. Job done
Copy link to clipboard
Copied
Thank you for your answers Geppetto Luis and Trevor.Dennis!
I opened one of these images in Photoshop and used the Trim command. That opened the Trim windows where I choiced the "Top left pixel color" option, selected "Top", "Left", "Right" and "Bottum" and cliked OK, but nothing is trimmed on the image. What's wrong acording you?
Copy link to clipboard
Copied
In your photo, you will find black lines and gray stains in the margins instead of simple white.
These interfere with the menu action "trim".
I think that only the image processor shown by Trevor has the potential to be processed automatically.
Copy link to clipboard
Copied
I opened one of these images in Photoshop and used the Trim command. That opened the Trim windows where I choiced the "Top left pixel color" option, selected "Top", "Left", "Right" and "Bottum" and cliked OK, but nothing is trimmed on the image. What's wrong acording you?
By @Michel6755
Try using Trim again, but only fater using the Levels Adjustment layer with the settings I suggested. That would hopefully lif the border colours to full white. Your first example image has a darker stripe within the border on the right side (red arrow). I have used the Levels layer mask to hide its effect in the lower half of the image so you can see before and after.
The thing to note is that Adjustment layer does not change the image layer. Only how it appears. So Trim becomes mre effective, and you can delete the Adjustment layer right after using Trim.
Copy link to clipboard
Copied
Thank you ajabon grinsmith and Trevor.Dennis for highlighting the trimming issue with these photos. I had no idea.
I tried to use the Levels Adjustment layer like you suggested Trevor.Dennis, and now the Trim tool works. But there are always narrow white borders on one or more sides of the photos. I am including here an example with another photo. So, I need to make a manual cropping anyway. Then it's not faster.
Copy link to clipboard
Copied
Trim automation requires uniform fill around the edges of the frame - this is difficult to achieve on scanned images.
If all images are relatively even, then motion blur can be used to define the boundaries of the image. Blur in one direction, blur in the other, overlay layers to get a mask. For example like this:
The only drawback is that the dark edges of the photos caught in the frame interfere. They either need to be overwritten manually, or you need to select cropping (or fill) parameters to remove them during batch processing.
In principle, this problem can be solved using a script (sequentially create a selection on each side of the frame, ignoring all coordinates except the inner part). But there will remain a problem with frames that were located with rotation (you cannot process them with blur).
I do not pretend to be a perfect solution, but maybe it will help.
Copy link to clipboard
Copied
How do you 'set selection to current channel with inverse'?
Copy link to clipboard
Copied
🙂 bad screenshot. these are 2 different steps - creating a selection and inverting it
Copy link to clipboard
Copied
Loll yes, now I see it 😉
Copy link to clipboard
Copied
d.putBoolean(stringIDToTypeID("invert"), true);
....
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
Copy link to clipboard
Copied
That I know, but I was surprised that can be done also manually, but it can't I guess.
Copy link to clipboard
Copied
???
Copy link to clipboard
Copied
Yes, that I know too 😉 But I expcted that exact naming with invert from action panel 😉
Copy link to clipboard
Copied
I did not understand what you were saying.
Copy link to clipboard
Copied
I mean that's possible for Alpha channel, but not component, then you have 'transpareny channel' in the name of action item, not 'current channel', doesn't it is the same for you?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
d.putBoolean(stringIDToTypeID("invert"), true);
....
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
By @r-bin
*facepalm*
Copy link to clipboard
Copied
You can try using this script. Essentially the same as the action I suggested above, but it itself ignores out-of-frame garbage and, in theory, no additional photo processing is required. However, it still does not take into account the possible rotation of the photo
#target photoshop
var lr = new AM('layer'),
doc = new AM('document');
lr.copyToLayer(2)
lr.motionBlur(90, 2000)
lr.threshold(230)
var layerBounds = lr.descToObject(lr.getProperty('bounds')),
objectBounds = {};
lr.selectOrdinalChannel()
lr.substractSelection(layerBounds.top, layerBounds.right / 2, layerBounds.bottom, layerBounds.right)
objectBounds.left = doc.hasProperty('selection') ? lr.descToObject(doc.getProperty('selection')).right : layerBounds.left
lr.selectOrdinalChannel()
lr.substractSelection(layerBounds.top, layerBounds.left, layerBounds.bottom, layerBounds.right / 2)
objectBounds.right = doc.hasProperty('selection') ? lr.descToObject(doc.getProperty('selection')).left : layerBounds.right
lr.deselect()
lr.deleteOrdinalLayer()
lr.motionBlur(0, 2000)
lr.threshold(230)
lr.selectOrdinalChannel()
lr.substractSelection(layerBounds.bottom / 2, layerBounds.left, layerBounds.bottom, layerBounds.right)
objectBounds.top = doc.hasProperty('selection') ? lr.descToObject(doc.getProperty('selection')).bottom : layerBounds.top
lr.selectOrdinalChannel()
lr.substractSelection(layerBounds.top, layerBounds.left, layerBounds.bottom / 2, layerBounds.right)
objectBounds.bottom = doc.hasProperty('selection') ? lr.descToObject(doc.getProperty('selection')).top : layerBounds.bottom
lr.deleteOrdinalLayer()
lr.makeSelection(objectBounds)
lr.crop()
lr.deselect()
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = s2t(target)
this.getProperty = function (property, descMode, 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'), order ? s2t(order) : s2t('targetEnum'));
return descMode ? executeActionGet(r) : 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'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.copyToLayer = function (copies) {
var i = copies ? copies : 1
for (i = 0; i < copies; i++) executeAction(s2t('copyToLayer'), undefined, 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.deselect = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('to'), s2t('ordinal'), s2t('none'));
executeAction(s2t('set'), d, DialogModes.NO);
}
this.threshold = function (level) {
(d = new ActionDescriptor()).putInteger(s2t('level'), level);
executeAction(s2t('thresholdClassEvent'), d, DialogModes.NO);
}
this.selectOrdinalChannel = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putEnumerated(s2t('channel'), s2t('ordinal'), s2t('targetEnum'));
d.putReference(s2t('to'), r1);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.substractSelection = function (top, left, bottom, right) {
(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('subtractFrom'), d, DialogModes.NO);
}
this.makeSelection = function (bounds) {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t('top'), s2t('pixelsUnit'), bounds.top);
d1.putUnitDouble(s2t('left'), s2t('pixelsUnit'), bounds.left);
d1.putUnitDouble(s2t('bottom'), s2t('pixelsUnit'), bounds.bottom);
d1.putUnitDouble(s2t('right'), s2t('pixelsUnit'), bounds.right);
d.putObject(s2t('to'), s2t('rectangle'), d1);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.deleteOrdinalLayer = function () {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
this.crop = function () {
(d = new ActionDescriptor()).putBoolean(s2t('delete'), true);
executeAction(s2t('crop'), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return (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 [t2s(d.getEnumerationType(p)), t2s(d.getEnumerationValue(p))];
default: break;
};
}
}
Copy link to clipboard
Copied
Hi jazz-y,
Since I am a novice with Photoshop, but happy to learn it, your solution seems promising to me. But for me, it's high flying. I don't know how to use it. Can you help me with that?
Copy link to clipboard
Copied
Save it as Script.jsx to your 'Presets / Scripts' folder of your Photoshop. Then relaunch Ps and choose 'Script' item from 'File / Scripts' menu when your document is already open.
Copy link to clipboard
Copied
To save the script of jazz-y, I copied it without "#target photoshop" (should I include it?) and pasted it in Notepad. I saved the file in txt in 'Presets / Scripts' folder of Photoshop and then changed the extension in jsx. After, I launched Photoshop, opened a photo, but can't choose "Script" item from 'File / Scripts' menu because I don't have it in the Scripts menu. Is it same than "Image Processor"?
Copy link to clipboard
Copied
try this: Crop photo.jsx
you may not have changed the file extension, but simply added .jsx to its name.
If there are problems - discard a screenshot of your Presets\Scripts folder
Copy link to clipboard
Copied
When you save text pasted to notepad you should use the double quatation marks around file name: "Script.jsx". Or else you have more Photoshops installed than only CS6 you launched?