Skip to main content
Inspiring
April 15, 2023
Question

Scripting tools to get the color of a particular dot placed placed on an image layer?

  • April 15, 2023
  • 2 replies
  • 2274 views

Hi all.
Does Illustrator have scripting tools to get the color of a particular dot or 3x3 dot patch placed on an image layer?

 

There is an image in the layer, you need to find the color of a certain point of this image...

This topic has been closed for replies.

2 replies

Inventsable
Legend
April 18, 2023

You really should add some more details to this otherwise it forces us to assume a lot of information, like:

  • How the BMP and path are each located or targeted. You say they're in separate layers, I don't know the names or order of these layers or how you intend to use them
  • The color profile and bit depth of the BMP, which I assumed was RGB and 32 instead of BMP, 16 or 24
  • Whether there are any other paths in this file that aren't the same as the one used for pixel analysis
  • Whether your dot will ever be outside the bounds of the image layer
  • Whether there will ever be multiple colors found in the path bounds or only a single one
  • What the script will actually do with this color once found

 

When you don't include details like this it means it takes a lot more work to help you, and if you want to get others to volunteer time and effort on your behalf then you'll find that not making it harder (intentionally or otherwise) for them to help will go a long way in determining whether or not you'll get many responses if not just questions prodding you to add more detail in the first place.

 

Anyway, there is no vanilla scripting API method to do this, but it's still possible given that BMP files are uncompressed pixel data. You have to manually parse the bytes of the BMP to recreate it's pixel data then you can narrow down the pixels to what was inside the bounds of the path relative to item, then narrow it further to the colors within:

 

(function () {
  if (!app.selection.length) {
    alert("Must select the path used for pixel analysis");
    return null;
  }
  Array.prototype.filter = function (callback) {
    var filtered = [];
    for (var i = 0; i < this.length; i++)
      if (callback(this[i], i, this)) filtered.push(this[i]);
    return filtered;
  };
  RGBColor.prototype.create = function (red, green, blue) {
    this.red = red;
    this.green = green;
    this.blue = blue;
    return this;
  };
  function parseBitmap(binaryData) {
    if (binaryData[0] !== 0x42 || binaryData[1] !== 0x4d) {
      alert("Invalid BMP format.");
      return null;
    }
    var pixelOffset =
        binaryData[10] +
        (binaryData[11] << 😎 +
        (binaryData[12] << 16) +
        (binaryData[13] << 24),
      width =
        binaryData[18] +
        (binaryData[19] << 😎 +
        (binaryData[20] << 16) +
        (binaryData[21] << 24),
      height =
        binaryData[22] +
        (binaryData[23] << 😎 +
        (binaryData[24] << 16) +
        (binaryData[25] << 24),
      bitDepth = binaryData[28] + (binaryData[29] << 8),
      bytesPerPixel = bitDepth / 8,
      pixelData = new Array(width * height);
    for (var i = 0; i < pixelData.length; i++) {
      var offset = pixelOffset + i * bytesPerPixel;
      pixelData[i] = {
        r: binaryData[offset + 2],
        g: binaryData[offset + 1],
        b: binaryData[offset],
        a: binaryData[offset + 3],
        x: i % width,
        y: Math.floor(i / width),
      };
    }
    return pixelData;
  }

  function getBinaryFromFile(item) {
    var file = item.file;
    file.open("r");
    file.encoding = "BINARY";
    var data = [];
    while (!file.eof) data.push(file.readch().charCodeAt(0));
    file.close();
    return data;
  }

  function getCoordinateOffsetFromPlacedItem() {
    var haystack = app.activeDocument.placedItems[0].geometricBounds,
      needle = app.selection[0].geometricBounds;
    return {
      x: Math.abs(haystack[0] - needle[0]),
      y: Math.abs(haystack[1] - needle[1]),
      w: Math.abs(needle[2] - needle[0]),
      h: Math.abs(needle[3] - needle[1]),
    };
  }
  function retrieveRGBValuesFromBitmap() {
    var target = app.activeDocument.placedItems[0],
      bounds = getCoordinateOffsetFromPlacedItem();
    var binaryData = getBinaryFromFile(target);
    var parsed = parseBitmap(binaryData);
    var result = parsed.filter(function (pixel) {
      return (
        pixel.x >= bounds.x &&
        pixel.x <= bounds.x + bounds.w &&
        pixel.y >= bounds.y &&
        pixel.y <= bounds.y + bounds.h
      );
    });
    if (!result) {
      alert("Faulty result");
      return null;
    } else {
      // Not really sure what you want to do with this since it isn't stated, so make first result the active app color
      app.activeDocument.defaultFillColor = new RGBColor().create(
        result[0].r,
        result[0].g,
        result[0].b
      );
      var msg =
        "Script found RGB(" +
        result[0].r +
        "," +
        result[0].g +
        "," +
        result[0].b +
        ")";
      alert(msg);
      return null;
    }
  }
  try {
    retrieveRGBValuesFromBitmap();
  } catch (err) {
    alert(err);
  }
})();

 In the test file I'm using, the below square is a BMP image that contains 3 colors: black, red, and blue. The white stroke square is the pathItem in Illustrator I'm using to analyze the pixels of the BMP image and it accurately reads RGB(19,100,216) which is the color of the blue inside the BMP image and contained nowhere else in the active document:

AnyONAuthor
Inspiring
April 18, 2023

Hi @Inventsable

Thank you for your response.


I'm not very familiar with Abobe JavaScript, and English is not my native language, so I have difficulty communicating, especially on such complex topics.
When working with Abobe JavaScrip, comes the understanding that besides it, you still need to know about some JavaScrip language constructs. So please forgive me for the incomplete description of the question of interest to me.


The purpose of such a script is to paint the overlying path with the color of the bitmap below it. The target is the center of the bounding path frames, as indicated in your example.

 

By bitmap, I mean a picture in JPG format. Will your code work with JPG format?

AnyONAuthor
Inspiring
April 19, 2023

I did work on this and mostly finished, though I haven't applied it to your exact file yet. It'd be as easy as using #include with the script then targeting your bottom right pixel of the pathItem though, if you're keen to try yourself.


Github.com.... has a question...

femkeblanco
Legend
April 15, 2023

Is it a raster image?  How is the dot/patch to be targeted? 

AnyONAuthor
Inspiring
April 16, 2023

in the document there are two layers in the first layer is a bitmap, in the second is a path element. You need to get the color value of the rasterized image, according to the location coordinates of the path element