What's new
Photoshop Gurus Forum

Welcome to Photoshop Gurus forum. Register a free account today to become a member! It's completely free. Once signed in, you'll enjoy an ad-free experience and be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Scripting Measurement Scale script


revnart

Power User
Messages
362
Likes
327
Hi I have a question :)
Maybe some great minds of PSG will be able to help :)

On a daily basis I deal mainly with car wrapping, and part of it is calculating square meters of print vinyl needed.
I use measurement scale for that because I can select multiple parts of car with simple selection, change measurement scale and record measurements to show me each element square meters and sum of all elements.

Using Script Listener I created this script which change measurement scale to one I want and record measurements:
Code:
// =======================================================var idsetd = charIDToTypeID( "setd" );
    var desc8 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
        var ref4 = new ActionReference();
        var idPrpr = charIDToTypeID( "Prpr" );
        var idmeasurementScale = stringIDToTypeID( "measurementScale" );
        ref4.putProperty( idPrpr, idmeasurementScale );
        var idDcmn = charIDToTypeID( "Dcmn" );
        var idOrdn = charIDToTypeID( "Ordn" );
        var idTrgt = charIDToTypeID( "Trgt" );
        ref4.putEnumerated( idDcmn, idOrdn, idTrgt );
    desc8.putReference( idnull, ref4 );
    var idT = charIDToTypeID( "T   " );
        var desc9 = new ActionDescriptor();
        var idNm = charIDToTypeID( "Nm  " );
        desc9.putString( idNm, "85px_to_3cm" );
        var idpixelLength = stringIDToTypeID( "pixelLength" );
        desc9.putInteger( idpixelLength, 85 );
        var idlogicalLength = stringIDToTypeID( "logicalLength" );
        desc9.putDouble( idlogicalLength, 3.000000 );
        var idlogicalUnits = stringIDToTypeID( "logicalUnits" );
        desc9.putString( idlogicalUnits, "cm" );
    var idmeasurementScale = stringIDToTypeID( "measurementScale" );
    desc8.putObject( idT, idmeasurementScale, desc9 );
executeAction( idsetd, desc8, DialogModes.NO );


// =======================================================
var idrecordMeasurements = stringIDToTypeID( "recordMeasurements" );
    var desc10 = new ActionDescriptor();
    var idSrce = charIDToTypeID( "Srce" );
    var idmeasurementSource = stringIDToTypeID( "measurementSource" );
    var idfsel = charIDToTypeID( "fsel" );
    desc10.putEnumerated( idSrce, idmeasurementSource, idfsel );
    var iddataPoints = stringIDToTypeID( "dataPoints" );
        var list1 = new ActionList();
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idAngle = stringIDToTypeID( "Angle" );
        list1.putEnumerated( idmeasurementDataPoint, idAngle );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idArea = stringIDToTypeID( "Area" );
        list1.putEnumerated( idmeasurementDataPoint, idArea );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idCircularity = stringIDToTypeID( "Circularity" );
        list1.putEnumerated( idmeasurementDataPoint, idCircularity );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idCount = stringIDToTypeID( "Count" );
        list1.putEnumerated( idmeasurementDataPoint, idCount );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idDateTime = stringIDToTypeID( "DateTime" );
        list1.putEnumerated( idmeasurementDataPoint, idDateTime );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idDocument = stringIDToTypeID( "Document" );
        list1.putEnumerated( idmeasurementDataPoint, idDocument );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idGrayValueMaximum = stringIDToTypeID( "GrayValueMaximum" );
        list1.putEnumerated( idmeasurementDataPoint, idGrayValueMaximum );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idGrayValueMean = stringIDToTypeID( "GrayValueMean" );
        list1.putEnumerated( idmeasurementDataPoint, idGrayValueMean );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idGrayValueMedian = stringIDToTypeID( "GrayValueMedian" );
        list1.putEnumerated( idmeasurementDataPoint, idGrayValueMedian );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idGrayValueMinimum = stringIDToTypeID( "GrayValueMinimum" );
        list1.putEnumerated( idmeasurementDataPoint, idGrayValueMinimum );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idHeight = stringIDToTypeID( "Height" );
        list1.putEnumerated( idmeasurementDataPoint, idHeight );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idHistogram = stringIDToTypeID( "Histogram" );
        list1.putEnumerated( idmeasurementDataPoint, idHistogram );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idIntegratedDensity = stringIDToTypeID( "IntegratedDensity" );
        list1.putEnumerated( idmeasurementDataPoint, idIntegratedDensity );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idLabel = stringIDToTypeID( "Label" );
        list1.putEnumerated( idmeasurementDataPoint, idLabel );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idLength = stringIDToTypeID( "Length" );
        list1.putEnumerated( idmeasurementDataPoint, idLength );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idPerimeter = stringIDToTypeID( "Perimeter" );
        list1.putEnumerated( idmeasurementDataPoint, idPerimeter );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idScale = stringIDToTypeID( "Scale" );
        list1.putEnumerated( idmeasurementDataPoint, idScale );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idScaleFactor = stringIDToTypeID( "ScaleFactor" );
        list1.putEnumerated( idmeasurementDataPoint, idScaleFactor );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idScaleUnits = stringIDToTypeID( "ScaleUnits" );
        list1.putEnumerated( idmeasurementDataPoint, idScaleUnits );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idSource = stringIDToTypeID( "Source" );
        list1.putEnumerated( idmeasurementDataPoint, idSource );
        var idmeasurementDataPoint = stringIDToTypeID( "measurementDataPoint" );
        var idWidth = stringIDToTypeID( "Width" );
        list1.putEnumerated( idmeasurementDataPoint, idWidth );
    desc10.putList( iddataPoints, list1 );
executeAction( idrecordMeasurements, desc10, DialogModes.NO );

the part when it fails is when document is not in 72PPI.

Is there a way to add prompt on the beginning of script which will alert me if file is not in 72 PPI and eventually change it to 72PPI?
 
Code:
#target photoshop;
var doc = activeDocument;
var res = doc.resolution;
//change to 72 PPI
if(doc.resolution != 72) doc.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);

//Your code here

//restore resolution to original
if(res != 72) doc.resizeImage(undefined, undefined, res, ResampleMethod.NONE);
 
Thank you Paul, big "thank you" for help :)
I guess I did everything ok, but somehow it doesn't work.
tested on document with 100PPI, no info popup about bad PPI (I guess there are no line for that in your code :) ) It measures with PPI of 100, which generates incorrect results.
But it doesn't change PPI.

btw. changing PPI while selection is active will work? If yes I guess the selection will be lost?
 
Hmmmm.....I'm not convinced you want the image resampling....you just want to change the resolution value for the document...this is going for printing....right?

When you say:

...and eventually change it to 72PPI?...

...what would you do at this point to manually correct this?

Change it via IMAGE > IMAGE SIZE...?

Regards.
MrToM.
 
We print car vinyls in 72 PPI, but sometimes client sends his project, and I need to calculate square meters needed, I know I can do it manually. I do it if I notice that the file is in different PPI. and I can still do it manually. All I need is mainly a prompt/popup that will stop script from measuring a will tell me "Hey you, your file is not 72PPI" and version even better "Hey you, your file is not 72PPI, would you like to correct this now? [ yes ] [no ]".
 
Well the resolution of the image has no bearing on Measurement calculations, its all based on the pixels in the image, which is why I wouldn't think you'd want the image resampling but may want the resolution changing so it prints at the correct size.

You didn't answer my question so I'll assume this is the case.... just add this to the bottom of your script....it will change the resolution to 72ppi regardless.

Code:
function cTID(s) { return app.charIDToTypeID(s); };
function sTID(s) { return app.stringIDToTypeID(s); };

var desc1 = new ActionDescriptor();
desc1.putUnitDouble( cTID('Rslt'), cTID('#Rsl'), 72.000000 );
executeAction( cTID('ImgS'), desc1, DialogModes.NO );

Regards.
MrToM.
 
If you use custom measurement scale PPI makes a huge difference.
Example is file 100x100cm, selection is 50x100cm.

1. Standard measurement scale with 100PPI
1.png
result = 7751953

2. Standard measurement scale with 72PPI
2.png
result = 4020030

3. Custom measurement scale ( 85px=3cm)
3.png
result = 5007 which I know is 0,5007m2
 
There are times when only documents of 72PPI will work.
But this seems as part of analysis.
The code I provided will change the document to 72PPI if was anything else then change it back to what it was originaly.
In your case, I think you just need.

Code:
#target photoshop;
var doc = activeDocument;
var res = doc.resolution;
//change to 72 PPI
if(doc.resolution != 72) doc.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);

You are setting the size then trying to record the measurments without making any?

Here is the first bit of your code..
Code:
function setMeasurementScale() {
var desc8 = new ActionDescriptor();
var ref4 = new ActionReference();
ref4.putProperty( charIDToTypeID('Prpr'), stringIDToTypeID('measurementScale') );
ref4.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
desc8.putReference( charIDToTypeID('null'), ref4 );
var desc9 = new ActionDescriptor();
desc9.putString( charIDToTypeID('Nm  '), '85px_to_3cm' );
desc9.putInteger( stringIDToTypeID('pixelLength'), 85 );
desc9.putDouble( stringIDToTypeID('logicalLength'), 3.000000 );
desc9.putString( stringIDToTypeID('logicalUnits'), 'cm' );
desc8.putObject( charIDToTypeID('T   '), stringIDToTypeID('measurementScale'), desc9 );
executeAction( charIDToTypeID('setd'), desc8, DialogModes.NO );
};
And the second bit.

Code:
function recordMeasurements() {
var desc10 = new ActionDescriptor();
desc10.putEnumerated( charIDToTypeID('Srce'), stringIDToTypeID('measurementSource'), charIDToTypeID('fsel') );
var list1 = new ActionList();
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Angle') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Area') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Circularity') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Count') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('DateTime') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Document') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('GrayValueMaximum') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('GrayValueMean') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('GrayValueMedian') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('GrayValueMinimum') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Height') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Histogram') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('IntegratedDensity') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Label') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Length') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Perimeter') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Scale') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('ScaleFactor') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('ScaleUnits') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Source') );
list1.putEnumerated( stringIDToTypeID('measurementDataPoint'), stringIDToTypeID('Width') );
desc10.putList( stringIDToTypeID('dataPoints'), list1 );
executeAction( stringIDToTypeID('recordMeasurements'), desc10, DialogModes.NO );
};

By the way a selection is not modal so yes you can make changes.
 
Normally I have a opened file, selects all parts of vinyl I need to know square meters and then run the script.

Which change the measurement scale and make measurements.

If I have selection active and change PPI selection dissappear, that's why I'm asking :-)
 
In your first two images your Measurement scale is 1:1.
In your third image your Measurement scale is YOUR scale set by YOUR script.

You cannot compare images using different scales.

revnart_01.png

revnart_02.png

revnart_03.png

Also, the first two images are completely different sizes!!! They EQUATE to the same document size in linear measurement but of course that means one must have many more pixels in it if the ppi is different....and hence the difference in measurement calculations.

If you set the first two documents to be of the SAME DIMENSIONS in PIXELS then you'll find that resolution has no impact on the calculations.

In essence you've used two different document sizes and two different measurement scales....hardly a fair, (nor accurate), comparison.

Change the scale in the first TWO examples to YOUR scale and THEN do a comparison.

Regards.
MrToM.
 
Last edited:
Tom, I know this
This is the point why I need 72PPI, because only with that PPI 85px will be equal to 3cm, and I don't want to create different measurement scales for 90PPI, 100PPI, 120PPI and so on :)
 
Tom, I know this
This is the point why I need 72PPI, because only with that PPI 85px will be equal to 3cm, and I don't want to create different measurement scales for 90PPI, 100PPI, 120PPI and so on :)

No.

This is the point I'm trying to make.

The RESOLUTION of an image has NO effect on the measurement calculations......they are done by the CUSTOM SCALE that YOU set in the Measurement window and are based on the PIXELS in the image.

Try changing the RESOLUTION of 'an' image using IMAGE > IMAGE Size... WITHOUT resampling......then do your calculation with a selection.

Then change the RESOLUTION back to its original and do the same measurement with the same selection.....there will be NO difference.

On the other hand if you have an image that isn't 72ppi then it will not PRINT at the correct size.....so you need to ensure that the ppi is correct.

If the document is just totally scaled wrong and it DOES need resampling then thats a whole different question.

Regards.
MrToM.
 
I get your point Tom but still we are talking about something different.

Files I'm working on are usually 3-5GB because they are 1:1 set in 72 PPI
with my custom measurements scale (85px=3cm) measurement will give me the results I need.
We print in 72 PPI and we work in 72PPI unless its a business card or some smaller print.

For example:
I have a car set 1:1 from client but the file is 100PPI, my measurement scale will not work because on a square meter of 100PPI file much more pixels are contained.
I know I can turn off "resample Image" in Image size window, and measurements will be equal even if I set the PPI of 400. File dimensions in centimeters will change but measurements will be ok.
The thing is I need to send files to print in 72PPI, because they will not accept anything else.

Sorry If I still don't get you point :) don't be angry, sometimes It's because english is not my native language, and I can misunderstood something :)
 
No worries.....not angry at all.....just trying to be clear on whats going on.

Lets back track a little and try to get on the same page.....bear with me...I'll make it as simple as I can.

For the time being forget all about resolution...

I see the problem you are having as being different images sizes....ie in PIXELS.

The same 'object', lets say for instance a car door, may occupy all of the available space on say a 1000px square image.....the door touches all four sides of the canvas.

Now lets say you get the same image from another client on a 3000px square image....the door still touches all four sides.

If you use your script on those images then you WILL get different results.....as you point out there will be many more pixels per 'door' in the larger image.....so your Measurement calculations will reflect that.

IDEALLY you want the 'object', (the car door), to occupy the SAME amount of PIXELS regardless of image size.....and preferably at a size that relates to your 'scale' (85px / cm).

Unfortunately this is something that only you can do manually.....if you know the dimensions of an 'object' then you have to scale, (using transform or other method), or resample the image so that the amount of pixels / object fit with your scale.

No script can do that for you as only you can interpret what you see in the image as an 'object'.....PS just sees a whole bunch of greyscale squares.

I see you having two options...

A: Resample or transform each image to 'fit' your scale of 85px / cm....OR....
B: Set a new scale based on the image you are working on....and SAVE it for future use.

I don't see how you can have "one scale fits all" when the image dimensions could be completely different from one another.....after all the whole idea of having a 'Custom' scale is precisely for this reason....that images come in different sizes and the 'objects' in those images could occupy any amount of pixels.

Either way I think your stuck with manually measuring each image and setting your custom 'scale' for each one....do you get dimensions on these images?

When it comes to printing the resolution only needs to be 72ppi to keep your printer people happy......but you'll have to be careful to get the scale correct for each 'object' you put in it....or whatever you do with your calculations.

I've probably just confused you even more now but the intention is good.....honest.

Regards.
MrToM.
 
Now I see where we were misunderstood :)
I manually set the dimension based on the measurements I take on a real car:
IMG_20160512_134259.jpg
and scaled in photoshop:
Screen Shot 2016-05-12 at 13.43.14.png

so I know its 1:1 :) I'm not dumb enough to think that photoshop will tell me dimensions of a door even If I don't have manually set their size correctly :)

All I wanted Is just prompt that the file is not in 72PPI before measurements :)
If I create file I set it on the beginning :) but If client sends me visualisation on his car also set 1:1 but with different PPI a just want to popup that information :)

Hope now everything is clear :)
 
I'm with you all the way and respect your workflow but just to satisfy my own curiosity:

You are scaling the image so that 1" of 'car' is 72 pixels......right?

(I have no idea what 1:1 means.....1 what to 1 what?)

You need to do this so that the 'print' is the correct size....right?

All you need then is to make sure the image has a resolution of 72ppi to match...to keep the print people happy....right?

That's what my code will do.....although its a bit overkill when Image > Image Size is just as easy.

You could run the code before making measurements but its your scaling of the image prior to taking measurements NOT the resolution that will make a difference.

Its for this reason that I'm confused as to why you need a warning......you should have the document already set up correctly...@72ppi.....(or 85px / 3cm if you prefer), otherwise how can any of your measurements make any sense?

All you need to do then is set the resolution of the image...either by IMAGE > IMAGE Size or my script on the end of yours, prior to saving for printing.

You see my point?....you shouldn't need a warning.

Regards.
MrToM.
 
I don't know if I'm doing it right, but before my code from script listener i put:

Code:
#target photoshop;var doc = activeDocument;
var res = doc.resolution;
//change to 72 PPI
if(doc.resolution != 72) 


var r = confirm("Document is not 72 PPI");
if (r == true) {
    x = doc.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
} else {
    x = "You pressed Cancel!";
}

but even If I click "yes" ppi is not changing, I know the ppi will return to previous state because of last line of code, but the measure results show me that they ere not taken in 72PPI :)

I hope that I've explained that correctly :)
 
Your code is trying to resample the image.....from what I can gather you are doing this manually...as stated in your last post....(And you have to do it manually as we've already established)

If you use my script at the end of yours it will change the resolution to 72ppi.

Regards.
MrToM.
 
There should be no difference between your code and mine.
I am using DOM and you are using AM.
The only difference is I am checking it is not 72PPI before changing it.
 
Paul's code works well, but it doesn't resample image which I want, so it changes do PPI but also cm dimensions.
example:
file 100x100 @ 100PPI
after script is:
138,89x138,89 @ 72PPI

I want it to still be 100x100cm but with 72PPI

this one does the job, but If i paste it on the beginning of my script I get error:
"Error 8800: General Photoshop error occurred. This functionality may not be available in this version of Photoshop.
- The parameters for command “Record Measurements” are not currently valid.
Line: 114
-> executeAction( idrecordMeasurements, desc10, DialogModes.NO );"
Code:
// =======================================================var idImgS = charIDToTypeID( "ImgS" );
    var desc4 = new ActionDescriptor();
    var idRslt = charIDToTypeID( "Rslt" );
    var idRsl = charIDToTypeID( "#Rsl" );
    desc4.putUnitDouble( idRslt, idRsl, 72.000000 );
    var idIntr = charIDToTypeID( "Intr" );
    var idIntp = charIDToTypeID( "Intp" );
    var idbicubicAutomatic = stringIDToTypeID( "bicubicAutomatic" );
    desc4.putEnumerated( idIntr, idIntp, idbicubicAutomatic );
executeAction( idImgS, desc4, DialogModes.NO );

sorry.. I just lame when it comes to scripting.. :/
 

Back
Top