## Scale Normalization

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Fahim, Distinct Sun, Víctor Paredes, erey, Belgarath, slowtiger

dkwroot
Posts: 659
Joined: Thu May 02, 2013 6:56 am
Location: USA
Contact:

### Scale Normalization

When using the layer function "SetScaleNormalization(f)", we're required to pass a parameter f. Does anyone know what this is? What value should we use for f if we want the scalenormalization() function to give the same result as edit>Normalize Layer Scale? Any help would be appreciated.
hayasidist
Posts: 2122
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

### Re: Scale Normalization

I've not actually used that function but …

a quick peep at the raw .mohoproj file shows "scale_normalization":1.0 -- so I'd try f = 1.0

No idea what other values might produce.

There's a f = MohoLayer:ScaleNormalization() function that you could use after messing with things in the UI that might change scale_normalization -- such as x/y layer scale???
dkwroot
Posts: 659
Joined: Thu May 02, 2013 6:56 am
Location: USA
Contact:

### Re: Scale Normalization

Thank you, I didn't think about checking the Json, but after some investigation I figured out how it works. For future references, it works like this:

You use the SetScaleNormalization(f) to set the normalize amount for a layer. This doesn't do anything but prep the layer for the amount that it's going to be normalized by. This amount should be equal to 1 divided by the amount of scaling done on a layer. I found the best way to get a good result is to average the scale x,y values and then divide 1 by them.

ex: SetScaleNormalization( 1/((scale.x+scale.y)/2) )

After you set the scale normalization, you apply it to the layer using the ScaleNormalization() function.

If you have a nested layer with transforms done on its parent layers, you can adjust for this by checking each parent layer and multiplying the averages of their scale values together. At the end, divide 1 by the product of the base layer scale average and all of its parent layer scale averages and you'll get the value you need to set the scale normalization to.

ex: If you have a group layer named "GLayer" and a child layer named "CLayer", where GLayer has scale (5,5,5) and CLayer has scale (2,2,2) then the norm would be...

SetScaleNormalization( 1/( ((5+5)/2)*((2+2)/2) ) )
hayasidist
Posts: 2122
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

### Re: Scale Normalization

good detective work there! so if I've understood properly -

layer:SetScaleNormalization(f) just writes the number into the file and f=layer:ScaleNormalization() actually applies it.

==

In your example you've set
CLayer:SetScaleNormalization( 1/( ((5+5)/2)*((2+2)/2) ))

but do you also do
GLayer:SetScaleNormalization(1/((5+5)/2))
or do you leave GLayer as 1?

In the latter case ( GLayer left as 1) - I'm just pondering if the ScaleNormalization() call would give you the ancestor chain value if you set each layer individually.

IOW following your example
GLayer:SetScaleNormalization(1/((5+5)/2))
CLayer:SetScaleNormalization(1/((2+2)/2))
f=CLayer:ScaleNormalization() returns f = 1/( ((5+5)/2)*((2+2)/2) )

??
dkwroot
Posts: 659
Joined: Thu May 02, 2013 6:56 am
Location: USA
Contact:

### Re: Scale Normalization

hayasidist wrote:good detective work there! so if I've understood properly -

layer:SetScaleNormalization(f) just writes the number into the file and f=layer:ScaleNormalization() actually applies it.
Yes, this appears to be how it works.
hayasidist wrote: In your example you've set
CLayer:SetScaleNormalization( 1/( ((5+5)/2)*((2+2)/2) ))

but do you also do
GLayer:SetScaleNormalization(1/((5+5)/2))
or do you leave GLayer as 1?
From what I can tell, normalization of a group layer does nothing. I tested this and found no results from group normalization. It seems that normalization doesn't get applied to the children layers, so I just leave the group layers alone.
hayasidist wrote: In the latter case ( GLayer left as 1) - I'm just pondering if the ScaleNormalization() call would give you the ancestor chain value if you set each layer individually.

IOW following your example
GLayer:SetScaleNormalization(1/((5+5)/2))
CLayer:SetScaleNormalization(1/((2+2)/2))
f=CLayer:ScaleNormalization() returns f = 1/( ((5+5)/2)*((2+2)/2) )

??
It doesn't. The SetScaleNormalization() function appears to be indifferent to whatever you do to the parent layers. In regards to the example you gave, it would look like this:

GLayer:SetScaleNormalization(1/((5+5)/2))
CLayer:SetScaleNormalization(1/((2+2)/2))
f=CLayer:ScaleNormalization() returns f = 1/((2+2)/2)

It's pretty much the coders responsibility to go through the document and add up values required to correctly normalize the layer.

What I did was make a function that cycles through all layers in a document. It first checks if a selected group layer is an ancestor to the current layer. If it returns true, then the code steps through all parent layers and takes the product of their scale averages. At the end, it returns the inverse of this value: 1/scale

I then apply the returned value to the scalenormalization.

This code allows me to normalize all layers in a group, but the code could easily be changed to apply to an entire document.
hayasidist
Posts: 2122
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

### Re: Scale Normalization

ok thanks ---- and a last (I hope!) question - if you've changed scale.x and .y but not setScaleNormalisation does f = scaleNormalisation() return 1?

… and I'll add a few words to the mohoscripting.com descriptions of these functions.

thanks again
synthsin75
Posts: 7103
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

### Re: Scale Normalization

hayasidist wrote:ok thanks ---- and a last (I hope!) question - if you've changed scale.x and .y but not setScaleNormalisation does f = scaleNormalisation() return 1?

… and I'll add a few words to the mohoscripting.com descriptions of these functions.

thanks again
Yeah, until you set SetScaleNormalization, ScaleNormalization returns 1.
And on the off chance it's not clear, there's no need to assign ScaleNormalization to a variable, other than printing its value.