Finding pixels using applescript.

Hello everybody,

i just registered here after checking the website so every now and often. Let me start by telling you i am by no means a programmer or scripter, but i do have a passion for it. I am working with Apples for about 15 years now and just recently i noticed what big leap applescript took (since classic enviroment).

Anyway to keep it short as no one is waiting for a big story about me :smiley:

I want to build a script which can check an Illustrator or Photoshop file and give me the coordinates of each pixel. The files i am using are all black & white so the script should only look for the black pixel and give me the X and Y coordinates of that pixel, meaning if we have a drawing it should be able to save all coordinates found into a text file (which will make a huge list i am aware of that)

Why would someone need this you ask! Well itā€™s easy i am building a small lathe device which will be controlled using my G5

Hopefully there is somebody out there that can tell me if applescript is capable of finding pixels in a black and white drawing and if so can help me out on how to achieve the desired result.

*in the mean time i am banging my head against a brick wall :slight_smile:

Kind regards

Bastiaan

Model: 1.8 Ghz PowerPC G5
Browser: Safari 417.8
Operating System: Mac OS X (10.4)

Hm, interesting problem. Iā€™m not ā€˜expertā€™ but hereā€™s my idea. You could script Photoshop CS or CS2, to count the pixel dimensions, select 1 pixel by 1 pixel starting at the top or wherever, and perhaps you can get whether the pixel is black or white, and then write that out to the text file.
An Illustrator file will need to be rasterized in greyscale, then changed to bitmap (1-bit) mode, and then the above process done again. You could manually script that process as well or use a photoshop action to make that a little more simple.

Hi there,

Iā€™m just responding because I find your problem interesting. I donā€™t think that you can use Applescript to get the color value of a single pixel, but I could be wrong. As I understand it though, you would have to have Applescript check every single pixel in the image and then write the coordinates of those that are black. You could potentially be checking millions of pixels in one image, which could take a very long time.

If you think about it though, an image file is essentially a list of coordinates and color values. If you open your image file in a text editor I suspect you could extract the information you need from that, using Applescript of course. That would take a bit of study into how image formats are written; .bmp is probably the most basic but it still looks rather cryptic.

Iā€™m interested to see what other responses you get and what solution you finally arrive at.

Good luck!
WF

Hi Bzzz,

if you said you want to try this on colored tiffs I would have seen no chance with AS. But you said itā€™s black and white (= bitmap?).

then Iā€™d try something like this:

  1. convert the tiff to an uncompressed tiff using ā€˜tiffutilā€™ ( a shell command - you can use it in AS with ā€˜do shell scriptā€™)

  2. Open the file for reading

  3. try to find out the x and y pixel dimension of the file. This info must be contained somewhere in the data but itā€™s probably better to use some third party tool. I tried with tiffutil -info - but the results didnā€™t seem to be reliable to me ā€¦

  4. Read until you find the start of the image date
    For this youā€™ll probably have to do some research on the tiff format, headers, marker for the start of data/end of header etc.

  5. Read the file byte wise - every byte represents 8 pixels - every set bit is a black pixel
    (0 = 8 white Pixels, 255 = 8 Black Pixel etc.)

EDIT: just realized: can applescript read byte wise? Iā€™m not sure ā€¦ maybe youā€™d better use an other way - an included perl script for example?

  1. Convert this information to the coordiantes you need :wink:

For a first test you could do this:
Make a new small (only a few pixels - preferably 8 pixels wide) bitmap file
convert it in the shell using:

tiffutil -none path/to/my/file.tif - out path/to/the/new/file.tif

now you can watch the result using hexdump:
hexdump -C path/to/the/new/file.tif

youā€™ll get something like this (my test - an 8x8 Pixel file - iā€™ve marked the Image data in bold letters):

00000000 4d 4d 00 2a 00 00 00 10 aa ff ff f0 f0 aa 55 55 |MM.*ā€¦???UU|
00000010 00 0c 01 00 00 03 00 00 00 01 00 08 00 00 01 01 |ā€¦|
00000020 00 03 00 00 00 01 00 08 00 00 01 02 00 03 00 00 |ā€¦|
00000030 00 01 00 01 00 00 01 03 00 03 00 00 00 01 00 01 |ā€¦|
00000040 00 00 01 06 00 03 00 00 00 01 00 00 00 00 01 11 |ā€¦|
00000050 00 04 00 00 00 01 00 00 00 08 01 15 00 03 00 00 |ā€¦|
00000060 00 01 00 01 00 00 01 17 00 04 00 00 00 01 00 00 |ā€¦|
00000070 00 08 01 1a 00 05 00 00 00 01 00 00 00 a6 01 1b |ā€¦?..|
00000080 00 05 00 00 00 01 00 00 00 ae 01 1c 00 03 00 00 |ā€¦?..|
00000090 00 01 00 01 00 00 01 28 00 03 00 00 00 01 00 02 |ā€¦(ā€¦|
000000a0 00 00 00 00 00 00 00 1b 77 3f 00 00 27 10 00 1b |ā€¦w?..ā€˜ā€¦|
000000b0 77 3f 00 00 27 10 |w?..ā€™.|
000000b6

Good luck :slight_smile:

D.

iMagine Photo can read pixel values from an image. The following script reads the top horitontal line in the image you have chosen, and spits out the points and the pixel values.

The pixel values returned are {red, green, blue}, where each color component can have a value between 0 (completely unsaturated) and 65535 (completely saturated). Black is {0,0,0} and white {65535, 65535, 65535}.

Make sure you have the results tab selected in Script Editor because that is where you will see the output displayed.

Kevin

set thisFile to choose file with prompt "Choose an image file: "
tell application "iMagine Photo"
	set thisImporter to import graphic thisFile
	if the component error of thisImporter is not equal to 0 then
		close thisImporter
		display dialog "Not an image file that quicktime recognizes."
		return
	end if
	set {x, y, xDim, yDim} to the natural bounds of thisImporter
	set thisDocument to make new window document with properties {dimensions:{xDim, yDim}}
	set the drawing destination of thisImporter to thisDocument
	draw thisImporter
	close thisImporter
	set pixelValues to get pixel values of thisDocument with properties {pixel value class:pixels on line, start point:{0, 0}, end point:{xDim, 0}}
	close thisDocument
end tell
pixelValues

I forgot to mention the reason why I only returned one line of data, is because the ā€œget pixel valuesā€ routine returns huge amounts of data, and is usually unmanageable for any decent size graphic if you ask for all the data at once.
Further info can be found here:

http://www.yvs.eu.com/documentation/graphicwindowdoc.html

Kevin

By the way iMagine Photo is free and can be downloaded here:

http://www.yvs.eu.com/downloads/iMaginePhoto.dmg

Kevin

Bzzz,

Just a question. If this is going to be for a lathe, do you really need every pixel or just the ones bordering the outline of the object? Perhaps some inner pixels in the case of something like a donut.

PreTech

Wow guys, thanks for all the responses!!!

It sure gives me alot to think about and do research for. Somehow i have a feeling that i am thinking way to complex about this all, itā€™s good to see that people find this question intresting and really putting effort in it to finding a proper solution for this problem.
Another idea that pops into my mind could Applescript help with bezier curves like in Illustrator files??, they are build out of mathematical calculations and maybe Applescript can translate that information into something readable that i can use to control the lathe. Its just a thought maybe somebody has an idea about it???

If we will find a solution then i think it should be eventually in the script exchange section of this forum as i think it can be pretty valuable for people working on similair ideas.

KTAM
IMagine Photo sounds wonderfull and your script so far looks promising, but i am really looking for a way that i donā€™t really have to rely on third party or extra software so to speak. The programm i am writing is a little bit of Cocao objective-c (mainly for controlling the hardware) and i hope to use Applescript (if possible) for finding the pixels. With a bit of calculating i can then use those coordinates to control the stepper motors for the lathe device and in the end i will have a touchable replica of what is on my screen.

PRETECH
To answer your question, i only need the outer pixel, sorry that i forgot to mention that and thank you for noticing. Anyway since i will create my own drawings i had planned to use 1px line weight so in that case an outer pixel look up isnā€™t really necessary.

Well like i said lost of stuff to dive into and the problem is getting more intresting by the second if you ask me. I really hope that we can find a solution.

regards Bastiaan

Anyone had luck on this topic? I am still banging my head against the wall here :slight_smile:

regards Bastiaan

Bastian,

If you do consider using iMagine Photo it shouldnā€™t be too hard to write some scripts that do what you need. I could help you with the iMagine Photo side of things.

iMagine Photo is a small application, very small compared to Illustrator etc. so it wouldnā€™t add anything to your system.

Just for my interest, what hardware do you use to control the lathe. Is it an X11 interface plugged into USB?

Kevin

I have to look into IMagine, will have some time in the following days (so iā€™ll get back to you in this thread)

What i use for driving the lathe is a USB board called K8055 (Velleman), someguy at Hexten.net wrote a test application for this board since it only comes with a windows driver off the shelf. He made his Cocoa programm under GPL and i am taking the parts out that are of intrest and use for my app. His programm is nothing more then just a testprogramm. Andy of Hexten.net is planning on making his application also Applescript(able) but he is a busy guy and this can take a while i guess. And i like to experiment so i took the job upon me to use parts of his software and parts of mine and hopefully it will all come together as one hell of a controller app, that can be easily converted to work with (homebuild) foamcutters, lathe or even cnc drills etc.

Itā€™s a shame that there isnā€™t really any (good/open-source/freeware/shareware) software outthere for Mac that can do this stuff. Windows has lots of those, but i am just a sucker for mac so you wonā€™t see me go out shopping for a PC.
Anyway i hope to be able to make this into a succes as i think among mac users there is alot of intrest and potential for this stuff, but since the majority of computer users are windows people it will take ages before someone comes with a freeware or at least an affordable way to get this stuff done. (thanks to andy of hexten for setting a starting point)

if i will be able to get it all working i am going to drop the software online including the plans and the howtooā€™s for making the device as open-source, youā€™ll never know maybe somebody will improve it with some extra features! (i am a strong believer of open-source)

GPL software for the K8055 Velleman (which is by the way a usb board of max 49 euroā€™s if you build it yourself ), i already solderd the board and it works just perfect with this software (and know i didnā€™t blow-up my mac heheheheh, although i have to admit that i tested it on my cheap imac first before sticking the wires in my G5)

Anyway here is the link for those who are intrested in the board and the OSX sofware http://www.hexten.net/2005/09/19/control-stuff-with-your-mac

regards Bastiaan

Did you write K8055 entirely from scratch (I mean the drivers themselves)?

I notice that the Linux version has a Java interface but uses the XP driver. Iā€™d love to build one of these units too, but Iā€™m not sure I could extract what I need from your code to run it.

I now have a Sophisticated Circuits PowerKey Pro 650 with an AppleScriptable USB interface - basically a powerbar with 6 AppleScript-switchable line-voltage relays between the line cord and the receptacles. I use it to run office lights, turn printers on and off, turn on a G3 that I use as a server, etc.

One of its most often used functions is for a script to turn on an external firewire drive, wait for it to mount, run SuperDuper to back up my main partition, dismount the drive, and turn it back off again. The K8055 opens the door to all kinds of other possibilities, particularly if it can eventually be scripted.

Hi Adam,

No i did not write the driver myself, somebody else wrote the test application, i am just taking out all parts that are of intrest and making the driver from that.

Itā€™s nice to see that people are intrested in trying to control stuff with there macs, in windows land it is most common but a couple of months ago i got intrested in doing this with a mac and just noticed that there isnā€™t much available (unless you do it all yourself)

Anyway, iā€™ll hope i will be able to keep this thread alive with new updates and stuff.

regards Bastiaan

It looks like you may have other options but just to be clear, you can get the value of individual pixels in Photoshop. However, you can only do this for RGB, CMYK or Indexed color documents. You select an individual pixel and get the histogram. The histogram gives you the number of pixels within the selection that have a particular value from 0 to 255 and it is returned as a list.
Looking for black or white pixels simplifies the process, since you donā€™t need to worry about different channels. The script below converts to indexed color space and steps through the image pixel by pixel if there are black pixels in the row.

tell application "Adobe Photoshop CS2"
	set ruler units of settings to pixel units
	tell current document
		set px_w to width as integer
		set px_h to height as integer
		
		(* This section is quick and dirty.  
		Its purpose is to ensure an indexed mode color space *)
		
		if mode is CMYK or mode is RGB then
			change mode to grayscale
		end if
		if mode is grayscale then
			set bmp_options to {class:Bitmap mode options, conversion method:middle threshold, resolution:300}
			change mode to bitmap with options bmp_options
		end if
		if mode is bitmap then
			change mode to grayscale
			set idx_options to {class:indexed mode options, dither:none, forced colors:black and white}
			change mode to indexed color with options idx_options
		end if
		(*****************************************************)
		
		
		if mode is indexed color then
			repeat with this_row from 1 to px_h -- Process row of pixels
				(* Check if a row has any black pixels *)
				select region {{0, this_row - 1}, {px_w, this_row - 1}, {px_w, this_row}, {0, this_row}}
				set x to histogram
				if (item 1 of x) > 0 then -- If this is true then there were black pixels to find
					repeat with this_col from 1 to px_w -- get a pixel in this row
						select region {{this_col - 1, this_row - 1}, {this_col, this_row - 1}, {this_col, this_row}, {this_col - 1, this_row}} -- {this_row, this_col, this_row, this_col}
						set x to histogram
						if item 1 of x is 1 then
							--  This pixel is black !!!!!!!
							-- Do whatever it is that you want to do by calling a handler here
							
						end if
						if item 256 is 1 then
							-- This Pixel is white  !!!!!!!!!!!
						end if
					end repeat
				end if
			end repeat
		else
			display dialog "File is not indexed color"
		end if
	end tell
end tell

hi Drossi,

that looks very nice, i just gave it a go but i have a problem!
The script works perfect untill it reaches a blackpixel i then get an error through scripteditor telling me it ā€œmisses an parameter for event coregetdā€

I am not sure why this is might be because i am working with Photoshop CS and not with CS2, any ideas on how i can solve this?

regards Bastiaan

Bzzz,
I have to get a copy of CS installed on my machine and take a look, but I donā€™t think that is the problem. Most of that chunk of script was something I wrote before CS (PS 6 I believe). I need to wait for someone from our IT dept. arrives to get a copy of CS to install.
In the meantime, can you email the image you were using. I may be over-looking something when I create a test file. Too often, I have found that as I try to idiot-proof my scripts, the idiot I need to proof for is me!

My address is : donald.rossi@rrd.com

hi Drossi

Itā€™s in your mailbox! thanks again for all your help

regards Bastiaan

Bzzz,
I did find an error (Please see my previous post).

                       if item 256 is 1 then
                           -- This Pixel is white !!!!!!!!!!!
                       end if

Should be

						if item 256 of x is 1 then
							-- This Pixel is white  !!!!!!!!!!!
						end if

I threw that ā€œifā€ statement in as an after-thought as I was postin to the forum. With that change, the script runs using your GIF file that you sent but that is still with CS2. Iā€™ll check CS when I have access to it.

Hi Drossi

No need to check compatibility with CS, it works like a charm you made my day!!!
When i run the script now, it nicely makes a full width selection does a scan vertical, on detection of a black pixel the selection changes to a 1x1px and does another run on that line horizontally. To do the quick test i put the beep command in to symbolize a handler and it beeps on detecting the black pixel!

so let me shout to you ā€œTHANKS YOUR BRILLIANTā€, now itā€™s just a matter of finding a way to get the coordinates and write them to a file.

kind regards
Bastiaan!

Your coordinates should just be {this_col, this_row} where this_col = X and this_row = Y. With the resolution of the image and a possible scale factor of the image to your actual work piece, you should be able to translate those values into real world coordinates, right?

Your praise is very nice but you are the one taking Applescript in a new direction. You are ā€œThinking differentā€. I tend to be more stubborn than brilliant. You just happened to ask a question that I managed to answered for myself over a year ago. After all the knowledge that is shared here, it becomes a privilege when I am able to help someone else. It doesnā€™t happen often.