Copy link to clipboard
Copied
Hi All,
I am relatively new to this. I'm creating a script to get the PPI value for linked images in an illustrator file.
Please can any one help me to find this.
Thanks in advance!
Reference screenshot:
Copy link to clipboard
Copied
try this script by Moluapple
alert(72/app.selection[0].matrix.mValueA);
alert(72/app.selection[0].matrix.mValueD);
more info here
Copy link to clipboard
Copied
Hi, here is a functions I wrote that expands on this idea a bit.
/**
* Displays the resolution (ppi) of the selected item.
* @author m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/illustrator-script-how-to-find-linked-images-ppi-value/m-p/14034494
*/
(function () {
var doc = app.activeDocument,
item = doc.selection[0],
ppi = getPPI(item);
if (ppi)
alert(ppi);
})();
/**
* Returns resolution (ppi) of item.
* Note: see known limitation in getLinkScaleAndRotation.
* @Param {RasterItem|PlacedItem} item
* @Returns {Array<Number>} [X-ppi, Y-ppi]
*/
function getPPI(item) {
if (!(
item.constructor.name == 'RasterItem'
|| item.constructor.name == 'PlacedItem'
))
return;
// get current scale and rotation
var sr = getLinkScaleAndRotation(item),
rotation = sr[2];
// duplicate and "unrotate"
var workingImage = item.duplicate();
var tm = app.getRotationMatrix(-rotation);
workingImage.transform(tm, true, true, true, true, true);
// calculate ppi
var ppi = [Math.abs(round(72 / app.selection[0].matrix.mValueA, 0)), Math.abs(round(-72 / app.selection[0].matrix.mValueD, 0))];
// clean up
workingImage.remove();
return ppi;
};
/**
* Return the scale, rotation and size of
* a PlacedItem or RasterItem.
* IMPORTANT: this relies on Illustrator's
* 'BBAccumRotation' tag to determine rotation.
* Files converted to Illustrator format from
* other sources may not have this and will
* show 0 rotation, and the ppi will be
* incorrectly calculated.
* @author m1b
* @version 2023-03-09
* @Param {PlacedItem|RasterItem} item - an Illustrator item.
* @Param {Boolean} round - whether to round numbers to nearest integer.
* @Returns {Array} [scaleX%, scaleY%, rotation°, width, height]
*/
function getLinkScaleAndRotation(item, round) {
if (item == undefined)
return;
var m = item.matrix,
rotatedAmount,
unrotatedMatrix,
scaledAmount;
var flipPlacedItem = (item.typename == 'PlacedItem') ? 1 : -1;
try {
rotatedAmount = item.tags.getByName('BBAccumRotation').value * 180 / Math.PI;
} catch (error) {
rotatedAmount = 0;
}
unrotatedMatrix = app.concatenateRotationMatrix(m, rotatedAmount * flipPlacedItem);
if (
unrotatedMatrix.mValueA == 0
&& unrotatedMatrix.mValueB !== 0
&& unrotatedMatrix.mValueC !== 0
&& unrotatedMatrix.mValueD == 0
)
scaledAmount = [unrotatedMatrix.mValueB * 100, unrotatedMatrix.mValueC * -100 * flipPlacedItem];
else
scaledAmount = [unrotatedMatrix.mValueA * 100, unrotatedMatrix.mValueD * -100 * flipPlacedItem];
if (scaledAmount[0] == 0 || scaledAmount[1] == 0)
return;
if (round)
return [round(scaledAmount[0]), round(scaledAmount[1]), round(rotatedAmount)];
else
return [scaledAmount[0], scaledAmount[1], rotatedAmount];
};
/**
* Rounds `n` to `places` decimal places.
* @Param {Number} n - the number to round
* @Param {Number} places - number of decimal places, can be negative
* @Returns {Number}
*/
function round(n, places) {
var m = Math.pow(10, places != undefined ? places : 3);
return Math.round(n * m) / m;
};
Copy link to clipboard
Copied
Here's another version that does the same thing (mostly just for my learning), but it calculates the rotation of the placedItem or rasterItem differently, without relying on the "BBAccumRotation" tag value, which isn't always there (see the findRotationOfRectangularItem function to see how I did it).
- Mark
/**
* Displays the resolution (ppi) of the selected item.
* @author m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/illustrator-script-how-to-find-linked-images-ppi-value/m-p/14034494
*/
(function () {
var doc = app.activeDocument,
item = doc.selection[0],
ppi = getPPI(item);
if (ppi)
alert(ppi);
})();
/**
* Returns resolution (ppi) of item.
* @Param {RasterItem|PlacedItem} item
* @Returns {Array<Number>} [X-ppi, Y-ppi]
*/
function getPPI(item) {
if (!(
item.constructor.name == 'RasterItem'
|| item.constructor.name == 'PlacedItem'
))
return;
// get rotation to nearest factor of 90°
var rotation = findRotationOfRectangularItem(item);
var ppi_A = getResolutionOfRotatedItem(item, rotation),
ppi_B = getResolutionOfRotatedItem(item, rotation + 90);
// the ppi will be radically huge if the rotation
// is 90° off, so we return the sensible one:
if (ppi_A[0] < ppi_B[0])
return ppi_A;
return ppi_B;
/**
* Returns the resolution (ppi) of an item
* having a defined rotation.
* @Param {PlacedItem|RasterItem} item
* @Param {Number} rotation
* @Returns {Array<Number} - [X_ppi, Y_ppi]
*/
function getResolutionOfRotatedItem(item, rotation) {
// duplicate and "unrotate"
var workingImage = item.duplicate();
var tm = app.getRotationMatrix(-rotation);
workingImage.transform(tm, true, true, true, true, true);
var ppi = [Math.abs(round(72 / workingImage.matrix.mValueA, 0)), Math.abs(round(-72 / workingImage.matrix.mValueD, 0))];
// clean up
workingImage.remove();
// calculate ppi
return ppi;
};
};
/**
* Returns the rotation amount in degrees
* that the item needs to be rotated such
* that it has a minimal bounding box area.
* Assuming that `item` is a rectangular
* object, such as a PlacedItem, RasterItem
* or a rectangular path item, the resulting
* rotation will rotate it so that the sides
* of the rectangle align to a factor of 90°.
* In other words, it will return the value
* required to "unrotate" the item.
* @author m1b
* @version 2023-08-25
* @Param {PageItem} item - an Illustrator page item.
* @Returns {Number}
*/
function findRotationOfRectangularItem(item) {
// we will rotate a copy and leave the original
var workingItem = item.duplicate(),
convergenceThreshold = 0.001,
inc = 45, // the starting rotation increment
rotationAmount = 0,
prevArea = area(workingItem);
while (Math.abs(inc) >= convergenceThreshold) {
workingItem.rotate(inc);
var newArea = area(workingItem);
if (newArea < prevArea) {
prevArea = newArea;
rotationAmount -= inc;
inc *= 0.5;
}
else {
workingItem.rotate(-inc); // Undo the last rotation
inc *= -0.5;
}
}
// clean up
workingItem.remove();
return round(rotationAmount, 2);
/**
* Returns area of bounding box of `item`.
* @Param {PageItem} item
* @Returns {Number}
*/
function area(item) {
return item.width * item.height;
};
};
/**
* Rounds `n` to `places` decimal places.
* @Param {Number} n - the number to round
* @Param {Number} places - number of decimal places, can be negative
* @Returns {Number}
*/
function round(n, places) {
var m = Math.pow(10, places != undefined ? places : 3);
return Math.round(n * m) / m;
};
Copy link to clipboard
Copied
This script working fine in some images only.
Copy link to clipboard
Copied
How to get Dimensions Value for Linked images?
Copy link to clipboard
Copied
This script working fine in some images only.
Hi @New Beginner1 can you attach a sample document show a problem image, so I can test? (Note: you must save as pdf with Illustrator editing capabilities, because you can't attach .ai files directly here.)
- Mark
Copy link to clipboard
Copied
Copy link to clipboard
Copied
@m1b PDF is attached.
Copy link to clipboard
Copied
@m1b PDF is attached, please check
Copy link to clipboard
Copied
@m1b please check attached pdf and advice.
Copy link to clipboard
Copied
try this, it is essentially m1b script, I just returned dimensions (that the previous script already calculated) instead of ppi
/**
* Displays the Dimensions of the selected item.
* m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/illustrator-script-how-to-find-linked-images-ppi-value/m-p/14034494
*/
(function () {
var doc = app.activeDocument,
item = doc.selection[0],
ppi = getPPI(item);
if (ppi)
alert(ppi);
})();
/**
* Returns resolution (ppi) of item.
* Note: see known limitation in getLinkScaleAndRotation.
* {RasterItem|PlacedItem} item
* {Array<Number>} [X-ppi, Y-ppi]
*/
function getPPI(item) {
if (!(
item.constructor.name == 'RasterItem'
|| item.constructor.name == 'PlacedItem'
))
return;
// get current scale and rotation
var sr = getLinkScaleAndRotation(item),
rotation = sr[2];
// duplicate and "unrotate"
var workingImage = item.duplicate();
var tm = app.getRotationMatrix(-rotation);
workingImage.transform(tm, true, true, true, true, true);
// calculate ppi
var ppi = [Math.abs(round(72 / app.selection[0].matrix.mValueA, 0)), Math.abs(round(-72 / app.selection[0].matrix.mValueD, 0))];
var dims = [Math.abs(round(app.selection[0].width / sr[0]*100)), Math.abs(round(app.selection[0].height / sr[1]*100))];
// clean up
workingImage.remove();
//return ppi;
return dims;
};
/**
* Return the scale, rotation and size of
* a PlacedItem or RasterItem.
* IMPORTANT: this relies on Illustrator's
* 'BBAccumRotation' tag to determine rotation.
* Files converted to Illustrator format from
* other sources may not have this and will
* show 0 rotation, and the ppi will be
* incorrectly calculated.
* m1b
* 2023-03-09
* {PlacedItem|RasterItem} item - an Illustrator item.
* {Boolean} round - whether to round numbers to nearest integer.
* {Array} [scaleX%, scaleY%, rotation°, width, height]
*/
function getLinkScaleAndRotation(item, round) {
if (item == undefined)
return;
var m = item.matrix,
rotatedAmount,
unrotatedMatrix,
scaledAmount;
var flipPlacedItem = (item.typename == 'PlacedItem') ? 1 : -1;
/*
try {
rotatedAmount = item.tags.getByName('BBAccumRotation').value * 180 / Math.PI;
} catch (error) {
rotatedAmount = 0;
}
*/
rotatedAmount = 0;
unrotatedMatrix = app.concatenateRotationMatrix(m, rotatedAmount * flipPlacedItem);
if (
unrotatedMatrix.mValueA == 0
&& unrotatedMatrix.mValueB !== 0
&& unrotatedMatrix.mValueC !== 0
&& unrotatedMatrix.mValueD == 0
)
scaledAmount = [unrotatedMatrix.mValueB * 100, unrotatedMatrix.mValueC * -100 * flipPlacedItem];
else
scaledAmount = [unrotatedMatrix.mValueA * 100, unrotatedMatrix.mValueD * -100 * flipPlacedItem];
if (scaledAmount[0] == 0 || scaledAmount[1] == 0)
return;
if (round)
return [round(scaledAmount[0]), round(scaledAmount[1]), round(rotatedAmount)];
else
return [scaledAmount[0], scaledAmount[1], rotatedAmount];
};
/**
* Rounds `n` to `places` decimal places.
* {Number} n - the number to round
* {Number} places - number of decimal places, can be negative
* {Number}
*/
function round(n, places) {
var m = Math.pow(10, places != undefined ? places : 3);
return Math.round(n * m) / m;
};
Copy link to clipboard
Copied
Hi @New Beginner1, I looked at your pdf, but the linked image wasn't included so I couldn't use it. Please post linked image also. - Mark
Copy link to clipboard
Copied
@m1b please check attached pdf and advice.
Copy link to clipboard
Copied
Simliar to Carlos' modification, here is my other version, now with pixel dimensions of image.
/**
* Displays the pixel dimensions and ppi of the selected raster item.
* @author m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/illustrator-script-how-to-find-linked-images-ppi-value/m-p/14034494
*/
(function () {
var doc = app.activeDocument,
item = doc.selection[0],
dims = getDimensions(item);
if (dims)
alert('dimensions:\nppi: ' + dims.ppi + '\nrotation: ' + dims.rotation + '\nimageSize: ' + dims.imageSize.join(' x ') + ' pixels');
})();
/**
* Returns resolution (ppi) of item.
* @Param {RasterItem|PlacedItem} item
* @Returns {Array<Number>} [X-ppi, Y-ppi]
*/
function getDimensions(item) {
if (!(
item.constructor.name == 'RasterItem'
|| item.constructor.name == 'PlacedItem'
))
return;
var dims = {};
// get rotation to nearest factor of 90°
var rotation = findRotationOfRectangularItem(item);
var dimsA = getDimsOfRotatedItem(item, rotation),
dimsB = getDimsOfRotatedItem(item, rotation + 90);
// the ppi will be radically huge if the rotation
// is 90° off, so we return the sensible one:
var dims = (dimsA.ppi[0] < dimsB.ppi[0]) ? dimsA : dimsB;
return dims;
/**
* Returns the resolution (ppi) of an item
* having a defined rotation.
* @Param {PlacedItem|RasterItem} item
* @Param {Number} rotation
* @Returns {Array<Number>} - { ppi: , width: height: }
*/
function getDimsOfRotatedItem(item, rotation) {
// duplicate and "unrotate"
var workingImage = item.duplicate();
var tm = app.getRotationMatrix(-rotation);
workingImage.transform(tm, true, true, true, true, true);
var ppi = [Math.abs(round(72 / workingImage.matrix.mValueA, 0)), Math.abs(round(-72 / workingImage.matrix.mValueD, 0))],
width = round(ppi[0] * (workingImage.width / 72), 0),
height = round(ppi[1] * (workingImage.height / 72), 0);
// clean up
workingImage.remove();
// calculate ppi
return { ppi: ppi, rotation: rotation, imageSize: [width, height] };
};
};
/**
* Returns the rotation amount in degrees
* that the item needs to be rotated such
* that it has a minimal bounding box area.
* Assuming that `item` is a rectangular
* object, such as a PlacedItem, RasterItem
* or a rectangular path item, the resulting
* rotation will rotate it so that the sides
* of the rectangle align to a factor of 90°.
* In other words, it will return the value
* required to "unrotate" the item.
* @author m1b
* @version 2023-08-25
* @Param {PageItem} item - an Illustrator page item.
* @Returns {Number}
*/
function findRotationOfRectangularItem(item) {
// we will rotate a copy and leave the original
var workingItem = item.duplicate(),
convergenceThreshold = 0.001, // the precision
inc = 45, // the starting rotation increment
rotationAmount = 0,
prevArea = area(workingItem);
while (Math.abs(inc) >= convergenceThreshold) {
workingItem.rotate(inc);
var newArea = area(workingItem);
if (newArea < prevArea) {
prevArea = newArea;
rotationAmount -= inc;
inc *= 0.5;
}
else {
workingItem.rotate(-inc); // Undo the last rotation
inc *= -0.5;
}
}
// clean up
workingItem.remove();
return round(rotationAmount, 2);
/**
* Returns area of bounding box of `item`.
* @Param {PageItem} item
* @Returns {Number}
*/
function area(item) {
return item.width * item.height;
};
};
/**
* Rounds `n` to `places` decimal places.
* @Param {Number} n - the number to round
* @Param {Number} places - number of decimal places, can be negative
* @Returns {Number}
*/
function round(n, places) {
var m = Math.pow(10, places != undefined ? places : 3);
return Math.round(n * m) / m;
};