• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Pixel Bounds if Image with Illustrator ExtendScript

Participant ,
Oct 22, 2024 Oct 22, 2024

Copy link to clipboard

Copied

I have a MacOS Illustrator ExtendScript that steps out images on a layout with a designated gap between each. It currently uses the image canvas size for the spacing. I'd like to use the pixel bounds instead (ignoring white or transparent backgrounds).

 

Is it possible to get this information from the images with Illustrator ExtendScript, without using something that would need to be installed (i.e., ImageMagic, etc.)?

 

I thought perhaps using Image Trace » Silhouette » Expand might work, then get those dimensions, but am having difficulty removing the bounding box that's created with .expandTracing():

 

var selectedItem = app.activeDocument.selection[0];

// Duplicate the selected item to preserve the original
var duplicateItem = selectedItem.duplicate();

// Rasterize the duplicate item
var rasterItem = app.activeDocument.rasterize(duplicateItem);

// Perform Image Trace
var tracedItem = rasterItem.trace();

// Set silhouette tracing options 
var tracingOptions = tracedItem.tracing.tracingOptions;
tracingOptions.tracingMode = TracingModeType.TRACINGMODEBLACKANDWHITE; 
tracingOptions.ignoreWhite = true; 
tracingOptions.threshold = 254;

// Expand 
tracedItem.tracing.expandTracing();

 


Thoughts?

TOPICS
Scripting

Views

250

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Oct 22, 2024 Oct 22, 2024

Hi @Chris.S, see if this helps. I've made your code into a function that returns a bounds, and tweaked the rasterization and image trace options to (hopefully!) improve the accuracy. It won't be super accurate though, and tends to be larger than the source art, so I've included a `chokeAmount` that moves it in a little (just leave empty or zero if not needed). The `drawRectangle` function is just for the demo and testing—you don't need it in your final script. Good luck!

- Mark

(function () {

 
...

Votes

Translate

Translate
Adobe
Community Expert ,
Oct 22, 2024 Oct 22, 2024

Copy link to clipboard

Copied

Hi @Chris.S, see if this helps. I've made your code into a function that returns a bounds, and tweaked the rasterization and image trace options to (hopefully!) improve the accuracy. It won't be super accurate though, and tends to be larger than the source art, so I've included a `chokeAmount` that moves it in a little (just leave empty or zero if not needed). The `drawRectangle` function is just for the demo and testing—you don't need it in your final script. Good luck!

- Mark

(function () {

    var doc = app.activeDocument;
    var selectedItem = doc.selection[0];

    var myBounds = getRasterizedBounds(doc, selectedItem, 0.25);

    // just for showing bounds, draw a rectangle around it
    var rectangle = drawRectangleIllustrator(selectedItem.parent, myBounds, {
        filled: false,
        stroked: true,
        strokeWidth: 0.3,
        strokeColor: doc.swatches[4].color, // just a guess!
    });

})();

/**
 * Returns bounds of non-transparent region of `item`.
 * @param {Dcument} doc
 * @param {RasterItem|PlacedItem} item - the target item.
 * @param {Number} chokeAmount - amount, in points, to contract the bounds by.
 * @returns {Array<Number>}
 */
function getRasterizedBounds(doc, item, chokeAmount) {

    chokeAmount = chokeAmount || 0;

    // Duplicate the selected item to preserve the original
    var duplicateItem = item.duplicate();

    // set up the raserization to maximize fidelity
    var rasterizeOptions = new RasterizeOptions();
    rasterizeOptions.antiAliasingMethod = AntiAliasingMethod.ARTOPTIMIZED;
    rasterizeOptions.clippingMask = false;
    rasterizeOptions.padding = 0;
    rasterizeOptions.convertSpotColors = true;
    rasterizeOptions.resolution = 1200; // set this according to your needs
    rasterizeOptions.convertTextToOutlines = true;
    rasterizeOptions.transparency = true;

    // Rasterize the duplicate item
    var rasterItem = doc.rasterize(duplicateItem, undefined, rasterizeOptions);

    // Perform Image Trace
    var tracedItem = rasterItem.trace();

    // Set silhouette tracing options 
    var tracingOptions = tracedItem.tracing.tracingOptions;
    tracingOptions.tracingMode = TracingModeType.TRACINGMODEBLACKANDWHITE;
    tracingOptions.ignoreWhite = true;
    tracingOptions.threshold = 254;
    tracingOptions.noiseFidelity = 0;
    tracingOptions.cornerFidelity = 100;
    tracingOptions.pathFidelity = 50;
    tracingOptions.padding = 0;

    // Expand 
    var group = tracedItem.tracing.expandTracing();

    // Remove outer frame
    group.pageItems[group.pageItems.length - 1].remove();

    // This is what we want
    var bounds = group.geometricBounds;

    // Clean up
    group.remove();

    return [
        bounds[0] + chokeAmount,
        bounds[1] - chokeAmount,
        bounds[2] - chokeAmount,
        bounds[3] + chokeAmount,
    ];

};

/**
 * Draws a rectangle to the document.
 * @param {Document|Layer|GroupItem} container - an Illustrator container.
 * @param {Array<Number>} bounds - [T, L, B, R]
 * @param {Object} props - properties to assign to the rectangle.
 * @return {PathItem}
 */
function drawRectangleIllustrator(container, bounds, properties) {

    properties = properties || {};

    var rectangle = container.pathItems.rectangle(bounds[1], bounds[0], bounds[2] - bounds[0], -(bounds[3] - bounds[1])); // TLWH

    // defaults
    rectangle.filled = true;
    rectangle.stroked = false;

    // apply properties
    for (var key in properties)
        if (properties.hasOwnProperty(key))
            rectangle[key] = properties[key];

    return rectangle;

};

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Oct 23, 2024 Oct 23, 2024

Copy link to clipboard

Copied

LATEST

Thank you @m1b !  The line below is what I was looking for

 group.pageItems[group.pageItems.length - 1].remove();

 Coincidentally, it appears going directly to .trace() and skipping the .rasterize() beforehand produces a result that is a bit accurate (raster produces a larger frame and larger offset), as shown in the attached screenshot. Not sure why both methods shift it down and to the right a bit, but with the trace alone method it's less than 0.25pt, so I can live with that... or shift the results with an offset.

Assuming this is probably the best/fastest method to figure out where the image bounds are, excluding white and transparent backgrounds with Illustrator ExtendScript, or any other ideas?
Screenshot 2024-10-23 at 9.30.18 AM.png

 




Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines