Copy link to clipboard
Copied
Hi,
I am working on a document with 500 images and all of them run beyond the text frame size (W: 5 in, H: 7.7 in). Hence, to fit them to the frame, I tried to use Transform->Scale and set the percentage value to less than 100% and the image got fit into the text frame. However, the problem is with a single selection. Selecting an image every time and setting the scale for 500 objects is a time consuming task. I tried using Object style but it does not incorporate "Scale" option in its palette. I tried using Find/Change option but it does not take anything other than an Object style, hence bringing me back to square one.
Then I started a discussion on InDesign for the problem: https://forums.adobe.com/thread/2502461
vinny38​ was a kind enough soul to provide two solutions:
Solution A
It worked wonders for the images with respect to the width. It rescaled (and not trimmed) the width of the over bound images to the width of the text frame however, it could not adjust the height of too large images.
Thus, Vinny took out the time from his busy schedule and provided the following solution.
Solution B
The solution worked for both width and height this time however, it trimmed down the top and bottom part of the over bound images (width got rescaled), instead of rescaling them to fit to the text frame size.
Vinny has been of great help but he would not be able to provide more time to the puzzle and I am already grateful to him for providing all the help.
I am searching for a solution which could search for all the over bound images and rescale (not trim down) them to fit to the size of the text frame. I urge all the scripting experts to provide guidance in the right direction.
Regards,
Aman Mittal
Hi Aman,
1. The sample document contains aboveLine anchors (not only pure inline.) I found that in such case rescaling to the height of the text frame is not sufficient to wake up the ghost object. An advanced product could surely work around this using smart calculations and so. But here I will consider the inline mode as a requirement, so the version below just converts any aboveLine anchor into inline. (Recall that custom anchored objects are ignored.)
2. Smart text reflow is not properly confi
...Copy link to clipboard
Copied
Hey Laubender,
Yes, all the pages have same text frame size: 5 inch x 7.7 inch with a single column setting.
Regards,
Aman Mittal
Copy link to clipboard
Copied
Hi there,
I'm "branching" this thread Scale all images at once in InDesign here... No need to have 2 similar threads...
So this message is the continuation of my previous attempts to handle this question.
Please note I'm learning scripting so be indulgent ^^ This interesting question is a good exercise for me.
So my suggested scenario was:
- change all inline objects to custom positioned ones. This trick, suggest by the OP, should prevent objects from over-flowing.
- then check width and height for each object and columns
- use a couple of conditions to scale (or not) objects vertically or horizontally in regard of OP's requirements.
- reassign INLINE positioning to all objects
Sounded pretty much straightforward, But, in the last episode, a JavaScript error was thrown.
After a lot of thinking, I couldn't reproduce it... And I couldn't open the shared file since I use CS6...
I was stuck until I read Marc's remark:
"The sample document contains aboveLine anchors (not only pure inline.)"
Then I realized aboveLine anchors were not handled in my latest attempt.
So, please find below version 7 of the script that starts by changing all aboveLine anchors to Inline anchors.
I don't know why but sometimes script does not work properly, just like if it would need a "break" between the 2 instructions "app.findObjectPreferences". For now, I just put an alert() but this is a very unsatisfactory tweak and I would appreciate javascript experts advice on this issue.
Now Aman, please try this one:
If still not working, can you please share an idml file? Thanks
//FitAnchorToColumn v7
//by Vinny
if (parseFloat(app.version) < 6)
main();
else
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "FitAnchorToColumn");
function main() {
if (app.documents.length > 0) {
var
myDoc = app.activeDocument,
myFound;
// Let's transform ABOVE_LINE to INLINE for all objects
app.findObjectPreferences.anchoredPosition = AnchorPosition.ABOVE_LINE;
app.findChangeObjectOptions.objectType = ObjectTypes.GRAPHIC_FRAMES_TYPE;
myFound = myDoc.findObject();
for (i = 0; i < myFound.length; i++) {
myFound.anchoredObjectSettings.anchoredPosition = AnchorPosition.INLINE_POSITION;
}
//reset query
myFound = [];
app.findObjectPreferences = null;
alert("let's go"); //need a pause here
// Let's now transform INLINE to CUSTOM for all objects
app.findObjectPreferences.anchoredPosition = AnchorPosition.INLINE_POSITION;
app.findChangeObjectOptions.objectType = ObjectTypes.GRAPHIC_FRAMES_TYPE;
myFound = myDoc.findObject();
for (i = 0; i < myFound.length; i++) {
myFound.anchoredObjectSettings.anchoredPosition = AnchorPosition.ANCHORED;
}
//then check and transform
for (i = 0; i < myFound.length; i++) {
var
columnWidth = myFound.parent.parentTextFrames[0].textFramePreferences.textColumnFixedWidth,
columnHeight = myFound.parent.parentTextFrames[0].geometricBounds[2] - myFound.parent.parentTextFrames[0].geometricBounds[0],
myObjectWidth = myFound.geometricBounds[3] - myFound.geometricBounds[1],
myObjectHeight = myFound.geometricBounds[2] - myFound.geometricBounds[0],
myScaleFactorH = columnWidth / myObjectWidth,
myScaleFactorV = columnHeight / myObjectHeight,
myScaleMatrixH = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorH,
verticalScaleFactor: myScaleFactorH
}),
myScaleMatrixV = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorV,
verticalScaleFactor: myScaleFactorV
});
if (myObjectWidth > columnWidth && myObjectHeight <= columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectWidth < columnWidth && myObjectHeight > columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
} else if (myObjectWidth / myObjectHeight > columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectWidth / myObjectHeight < columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
} else {
// nothing happens;
}
}
// change back to inline position
for (i = 0; i < myFound.length; i++) {
myFound.anchoredObjectSettings.anchoredPosition = AnchorPosition.INLINE_POSITION;
// and (delete line below if not wanted), reset Y position to 0
myFound.anchoredObjectSettings.anchorYoffset = 0;
}
} else {
alert("Open a document");
}
}
Copy link to clipboard
Copied
Hi Vinny,
Welcome to this subbranch of the original thread 😉
I'm sure your code does a great job—in particular, it deals with text columns, which mine purely ignores.
In fact, I think the main problem (= the interesting problem) is solved in both cases. But in addition we have to address refreshing time issues. Indeed, while smart reflow is processing, layout components are created (additional text frames for receiving the flow) but we don't know exactly when this new stuff is ready to operate.
So, for example, the code
myFound.parent.parentTextFrames…
in your script might go to nowhere if myFound.parent still is in overset zone.
Reminder: myFound is an object whose parent is a Character. This specific character, at a specific time, may have no parent text frame. A character instance always have a parentStory, but it doesn't necessarily have a host text frame. So I think you should check that before further processing. This may explain the undefined or invalid object errors you have observed.
Best,
Marc
Copy link to clipboard
Copied
Hey Marc,
Thank you for sending the IDML file. I tried the script n the sample document and it worked for all the frames and processed all the 7 items. However, when I followed the same properties for the master page and Text Reflow and tried to run the script in the original document, it gave the earlier results. It processed the first two images and turn the rest of the images to dots.
I tried the script with another document and it worked like a charm. It left all the in-bound images to the original state and rescaled the out-of-bound images to the size of the frame.
vinny38 An update regarding the script. It worked perfectly on other document as well. It rescaled out-of-bound images and gave them their anchor back. However, it rescaled all the in-bound images which was taken care of by Marc.
Both, versions (yours and Marc) complement each other. I guess the scripts could be considered as a generic one as
These scripts cater to such a problem which is experienced by every InDesign user one time or the other.
Therefore, Thank you for all the hard work and for being such an amazing help and bringing out the best in things.
Kudos to Marc, Uwe and Vinny for being such great sports.
Regards,
Aman Mittal
Copy link to clipboard
Copied
There are two Correct answers to the thread, now.
Post 22 and Post 25 are both correct answers to the query as provided by great people -
If you would like to scale only out-of-bound images with proportions (those which run out of text frame size), then, you may go for Marc's script.
If you would like to scale all the images to fit to the text frame column, even in-bound images (those which are already under the text frame size), then, you may go for Vinny's script.
Big thank you to both of you! Stay blessed! Stay awesome!
Regards,
Aman
Copy link to clipboard
Copied
Hi Aman,
I'm glad you finally solved your issue.
I think you should give credit to Marc for his script as correct answer (not yours).
Marc Autret​
I tried to analyze your script for learning purposes. It's quite hard to understand for a rookie like me^^ but obviously very interesting. I learnt a lot. Thanks for it!
I understood that the recompose() method was definitely missing in my script.
So I added it, as well as Uwe's snippet for safety purposes and it seems to make a real difference...
I have no idea why the provided IDML would require much more time to recompose than my test documents, but as a matter of fact, it does...
The latest version of my suggested script did throw the JS error, as mentioned by Aman.
But with the recompose() method, (and a few adjustments) it seems to work nicely.
So, dear Aman, please find below the version 8 - and final one - for your information purpose:
- make sure auto reflow is ON
- find all anchored objects and set anchor position as "custom"
- recompose
- check size of each found anchor and scale if necessary
- set objects' anchor position as "inline" and reset Y position to 0
//FitAnchorToColumn v8
//by Vinny
if (parseFloat(app.version) < 6)
main();
else
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "FitAnchorToColumn");
function main() {
if (app.documents.length > 0) {
var
myDoc = app.activeDocument,
myFound,
startTime = Date.now();
// make sure autoreflow is on
myDoc.textPreferences.properties = {
deleteEmptyPages: true,
limitToMasterTextFrames: true,
preserveFacingPageSpreads: true,
};
// Let's transform all anchored objects into custom positioned objects
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "~a"
var myFound = myDoc.findGrep();
for (i = 0; i < myFound.length; i++) {
myFound.pageItems[0].anchoredObjectSettings.anchoredPosition = AnchorPosition.ANCHORED;
}
//recompose document
myDoc.recompose();
app.menuActions.itemByName("$ID/Recompose all stories").invoke();
//then check size and transform
for (i = 0; i < myFound.length; i++) {
var
columnWidth = myFound.parentTextFrames[0].textFramePreferences.textColumnFixedWidth,
columnHeight = myFound.parentTextFrames[0].geometricBounds[2] - myFound.parentTextFrames[0].geometricBounds[0],
myObjectWidth = myFound.pageItems[0].geometricBounds[3] - myFound.pageItems[0].geometricBounds[1],
myObjectHeight = myFound.pageItems[0].geometricBounds[2] - myFound.pageItems[0].geometricBounds[0],
myScaleFactorH = columnWidth / myObjectWidth,
myScaleFactorV = columnHeight / myObjectHeight,
myScaleMatrixH = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorH,
verticalScaleFactor: myScaleFactorH
}),
myScaleMatrixV = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorV,
verticalScaleFactor: myScaleFactorV
});
if (myObjectWidth > columnWidth && myObjectHeight <= columnHeight) {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectWidth < columnWidth && myObjectHeight > columnHeight) {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
} else if (myObjectWidth > columnWidth && myObjectWidth / myObjectHeight > columnWidth / columnHeight) {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectHeight > columnHeight && myObjectWidth / myObjectHeight < columnWidth / columnHeight) {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
} else {
// nothing happens;
}
}
// change back every anchor to inline position
for (i = 0; i < myFound.length; i++) {
myFound.pageItems[0].anchoredObjectSettings.anchoredPosition = AnchorPosition.INLINE_POSITION;
// and (delete line below if not wanted), reset Y position to 0
myFound.pageItems[0].anchoredObjectSettings.anchorYoffset = 0;
}
alert("Script finished in "+ (Date.now() - startTime)+"ms. Now wait for autoreflow");
} else {
alert("Open a document");
}
}
Copy link to clipboard
Copied
Hey vinny38​,
I wanted to give credit to both - Marc as well as you for the answer. Unfortunately, forum does not allow two correct answers. Therefore, I created a post marking both answers (yours as well as Marc) correct. I could never take credit for the thing as I did not do anything. I was divided in giving credit one as it was a team effort led by Marc, Uwe and you so that is why, I marked another post as the right answer.
I am highly indebted to all of you for pitching with such enthusiasm and for going through lengths to solved the request. Big thank you!
Regards,
Aman
Copy link to clipboard
Copied
I know, I know, it's definitely a team work...
It's just some sort of Forum "rule" not to mark his own post as "correct" but to try to pick the best answer.
Not a big deal anyway, don't worry...
Just by curiosity, how is version 8 working for you?
Copy link to clipboard
Copied
Hey vinny38​,
I apologize for the late reply. I could not try the latest version, yesterday hence, I could not comment upon the same. I tried your version 8 and it worked perfectly.
It scaled out-of-bound images to text frame size and left the already in-bound images unattended.
You did it with perfection! Thanks a lot for being such a great sport, for all the help and trouble you went through. Its been a pleasure knowing you! Stay blessed!
Regards,
Aman Mittal
Copy link to clipboard
Copied
Salut Marc!
Thanks a million for the valuable lesson.
It was very clear and I definitely see what you mean, although I am really not sure how to tackle the issue.
Maybe some sort of timeout function that would check whether or not there is still overflowing text after changing all anchors as AnchorPosition.ANCHORED... wait a little, check again, wait a little, check again... then ends the script after an arbitrary amount of time...
But I'm not sure about it, and I am now reaching my scripting limits.
Copy link to clipboard
Copied
Hi vinny38​,
Welcome back! Thank you, once again for showing interest in the question. I tried your version 7 of the script in the original document and found:
1. The script rescaled even the in-bound images, again (which were needed to be left alone)
2. When I ran the script, it gave me the following error and left the very large image frame in their original size and did not change back the custom positioning to inline:
3. I tried it one more time, then the script worked. Upon the next trial, it gave the same error.
However, when I ran the same script in the sample document that I had shared, it worked wonders. Everything, you has written in the script worked but the script rescaled the in-bound images, as well. So, I am not able to figure out the anomaly in the original document though the sample document had been derived from the original, itself.
Additionally, I tried to tweak with your version 4 in terms of scaling factor and the script worked like charm. Though it rescaled the size of all the images, but did not give any error and worked perfectly:
//FitAnchorToColumn v4
//by Vinny
if (parseFloat(app.version) < 6)
main();
else
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "FitAnchorToColumn");
function main() {
if (app.documents.length > 0) {
var
myDoc = app.activeDocument,
docUnits = myDoc.viewPreferences.horizontalMeasurementUnits,
myFound;
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "~a";
myFound = myDoc.findGrep();
// first rescale overflow objects to 45%
for (i = 0; i < myFound.length; i++) {
if (typeof myFound.parentTextFrames[0] == "undefined") {
// alert(myFound.pageItems[0].geometricBounds);
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
app.transformationMatrices.add({
horizontalScaleFactor: .45,
verticalScaleFactor: .45
})
)
}
}
// then fit everything to column width if possible, otherwise to column height
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "~a";
myFound = myDoc.findGrep();
for (i = 0; i < myFound.length; i++) {
if (typeof myFound.parentTextFrames[0] != "undefined") {
var
columnWidth = myFound.parentTextFrames[0].textFramePreferences.textColumnFixedWidth,
columnHeight = myFound.parentTextFrames[0].geometricBounds[2] - myFound.parentTextFrames[0].geometricBounds[0],
myObjectWidth = myFound.pageItems[0].geometricBounds[3] - myFound.pageItems[0].geometricBounds[1],
myObjectHeight = myFound.pageItems[0].geometricBounds[2] - myFound.pageItems[0].geometricBounds[0],
myScaleFactorH = (columnWidth / myObjectWidth) - 0.15,
myScaleFactorV = (columnHeight / myObjectHeight) - 0.15,
myScaleMatrixH = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorH,
verticalScaleFactor: myScaleFactorH
}),
myScaleMatrixV = app.transformationMatrices.add({
horizontalScaleFactor: myScaleFactorV,
verticalScaleFactor: myScaleFactorV
});
if (myObjectHeight * myScaleFactorH == columnHeight) {
return null;
} else if (myObjectHeight * myScaleFactorH < columnHeight) {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else {
myFound.pageItems[0].transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
}
}
}
app.findGrepPreferences = app.changeGrepPreferences = null;
} else {
alert("Open a document");
}
}
This one worked, perfectly when I changed the rescale overflow from 5% to 45% and changed the scale factor by 0.15. However, the rescale overflow seems to be a specific measure as for humongous image frames, this might not be an ideal solution for which, your version 7 of the script could work. However, the anomaly of the script to work one time and not the other time, seems to be interesting.
Regards,
Aman
Copy link to clipboard
Copied
Hi Aman,
just a comment about your observation where Vinny's script sometimes produced errors when testing on the original placed Word document vs your constructed sample document that did not include images, but only graphic frames:
1. If you are testing the original Word document the story that is placed has overset and ( that's important! ) InDesign never drew all frames necessary to expose the whole story to spreads in the layout window. I do not know how you did your made up sample for download, but it could be different with that.
I saw cases where a very long table done in one frame with overset would answer when asked about its contents that a lot of cells are empty. In fact that was not the case after new frames were threaded to the story so that all the table was exposed to the pages. Later I tried to recreate the problem, removed all the frames of the story, but the first one, asked again after contents and to my surprise back then all frames seemed to be occupied with contents. So it made a difference if the story was at least exposed one time fully to the layout window.
2. Complexness of your constructed sample is definitely lower than the original placed story from Word.
So be aware that it will be a big difference to construct a sample vs to work with an original case!
Best,
Uwe
Copy link to clipboard
Copied
Hey Laubender​,
Thank you for the insights. Once, I found that the scripts worked on other documents, I realized that the original document could definitely have certainly complexities which could not have been captured by the script. The two specific points, you mentioned:
"InDesign never drew all frames necessary to expose the whole story to spreads in the layout window".
"So it made a difference if the story was at least exposed one time fully to the layout window."
They are indeed the right observations and I shall bear them in mind, in future. Thank you for providing such an important insight.
Regards,
Aman
Copy link to clipboard
Copied
Hi Aman
Regarding the issue of rescaling inbound graphic frames, that was my mistake...
You can replace lines
} else if (myObjectWidth / myObjectHeight > columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectWidth / myObjectHeight < columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
by (just the "else if" lines)
} else if (myObjectWidth > columnWidth && myObjectWidth / myObjectHeight > columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixH);
} else if (myObjectHeight > columnHeight && myObjectWidth / myObjectHeight < columnWidth / columnHeight) {
myFound.transform(
CoordinateSpaces.INNER_COORDINATES,
AnchorPoint.TOP_LEFT_ANCHOR,
myScaleMatrixV);
However, the main problem still remain...
I have downloaded the IDML file, so I will have a look at it, and see if I can go deeper in the understanding of the issue.
Copy link to clipboard
Copied
There are two Correct answers to the thread, now.
Post 22 and Post 34 are both correct answers to the query as provided by great people -
Big thank you to both of you! Stay blessed! Stay awesome!
Regards,
Aman