| Notices | Welcome to RetouchPRO . You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload images and access many other special features. Registration is fast, simple and absolutely free so please, join our community today! If you have any problems with the registration process or your account login, please contact contact us. | | Software Photoshop, Paintshop Pro, Painter, etc., and all their various plugins. Of course, you can also discuss all other programs, as well. | 
05-21-2006, 01:01 PM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | | Filter Meister: thinking about S/H Okay, finally getting around to this Shadow/Highlight thing. I've had more than a few requests, so maybe get this ball rolling, eh?
Now, I do understand how S/H works and the ChOps involved, but I don't entirely like it. A little too much reliance on High Pass for my tastes and no control over the masking. Well, there is some control over the masking, but not the kind that I like working with.
The first thing is to come up with a plan of attack. If you were to do it by hand, how would you do it?
The first thing for me is the base mask. Lots of tricks and variations that I use, so I had to boil it down to a few basic steps that I could do in FM. Basically extract Lum, Gauss it, and Levels. Right away that is 3 controls: blur, high point, and low point. Not terribly sophisticated, but I'm mostly happy with this masking process.
Once you have the mask, how to tweak the highs and low? For this, I chose something that I like to call Linear Gamma. It's mot really gamma, but the basic idea is the same. All you really do is take 128 and wiggle it. The scl() function will do for this. If these tweaks get more sophisticated, will move to a weight-based tweak and away from scl().
One thing I would like to point out right now is this: Code: final=blend(l1,l2,0,0,255-mask);
Notice that the mask value has been inverted right in the blend() function. This is because blend() didn't like the way I had set things up. It was either invert the blend() mask value or invert everything else. So, I took the easy way out.
Currently, this is proof of concept. This is the main reason why output is Lum only. However, this will eventually pose and interesting foible when doing this kind of work. After all, the name of the game is contrast. Code: %ffp
SupportedModes: RGBMode
//dialog: size=(240,250)
dialog: color=lightgrey
//ctl[CTL_OK]: MODIFY, pos=(160,230)
//ctl[CTL_CANCEL]: MODIFY, pos=(200,230)
ctl(0): "q",Range=(1,512),val=5
ctl(1): "High",range=(0,255),val=192
ctl(2): "Low",range=(0,255),val=64
ctl(3): "High Tweak",range=(10,245),val=128
ctl(4): "Low Tweak",range=(10,245),val=128
ctl(5): checkbox,"Show Mask",val=0
//------------------------------------------------------------------------------------------
// Here comes the filter code
OnFilterstart:{
isTileable=0;
// setZoom(1);
return false;
}
ForEveryTile:
{
int c;
int xw = x_end-x_start;
int yw = y_end-y_start;
int radius = min(ctl(0),xw/2,yw/2);
float q = (float)(radius)/scaleFactor;
float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q;
float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q;
float b2 = -(1.4281*q*q + 1.26661*q*q*q );
float b3 = 0.422205*q*q*q;
float b1_b0 = b1/b0;
float b2_b0 = b2/b0;
float b3_b0 = b3/b0;
float BB = 1.0 - (b1_b0+b2_b0+b3_b0);
float wn,wn1,wn2,wn3;
int r,g,b,lum,thediff;
int mask,l1,l2,final;
//const int startclock = clock();
// temporary constant
z=0;
// z = 0 = luminosity
// z = 1 = guass
// z = 2 = high pass
// will have to rearrange how these are written
allocArray(0,X,Y,0,1);
allocArray(1,X,Y,0,1);
allocArray(2,X,Y,0,1);
// put luminosity into arrray
for(x=x_start;x<x_end;x++){
for(y=y_start;y<y_end;y++){
r=src(x,y,0);
g=src(x,y,1);
b=src(x,y,2);
lum=r*0.30 + g*0.59 + b*0.11;
putArray(0,x,y,0,lum);
}} // end y and x
// copy lum to 1 for gaussing
copyArray(0,1);
// for (z=0; z<Z; z++){ // loop through all channels
//
// forward pass
//
// warmup forward - no write
for (y=y_start; y<y_end; y++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-1]
wn2 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-2]
wn3 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-3]
for (x=x_start+2*radius; x>x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
// real forward pass
for (x=x_start; x<x_end; x++){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+1,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (x=x_end-1; x>=x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
//hmm.. this seems to be working so far
//pset(x,y,z, (int)wn );
putArray(1,x,y,0,(int)wn);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+2,4*Z) ) break;
// NOW DO COLUMNS
//
// forward pass
//
// warmup forward pass
for (x=x_start; x<x_end; x++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-1]
wn2 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-2]
wn3 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-3]
for (y=y_start+2*radius; y>y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
// real forward pass
for (y=y_start; y<y_end; y++){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+3,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (y=y_end-1; y>=y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+4,4*Z) ) break;
// } // for z
//0=lum
//1=gauss, mask
// time to loop the tweaks
for(x=x_start;x<x_end;x++){
for(y=y_start;y<y_end;y++){
// grab values
mask=getArray(1,x,y,0);
l1=getArray(0,x,y,0);
l2=l1;
// tweak the mask
// notice that values are clipped
mask=scl(mask,ctl(2),ctl(1),0,255);
if(mask>255){mask=255;}
if(mask<0){mask=0;}
// scale high
if(l1<128){
l1=scl(l1,0,128,0,ctl(3));
}else{
l1=scl(l1,128,255,ctl(3),255);
}
// scale low
if(l2<128){
l2=scl(l2,0,128,0,ctl(4));
}else{
l2=scl(l2,128,255,ctl(4),255);
}
// final output
if(ctl(5)==0){ // output final luminosity with blending
final=blend(l1,l2,0,0,255-mask);
pset(x,y,0,final);
pset(x,y,1,final);
pset(x,y,2,final);
}else{ // output mask
pset(x,y,0,mask);
pset(x,y,1,mask);
pset(x,y,2,mask);
}
}} // end y and x
//Stop processing and apply the effect
return true;
}
| 
05-23-2006, 05:46 AM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | | Okay, let's talk about the Lum mask for a bit. The combination used is rather simple. As far as I know, Lum > Guass > Levels is fairly well known. Simple and it works.
Although, it feels to me like something is missing. The frequency work done with Gauss isn't enough for me. Needs more frequency ChOps.
Things like this always give me the giggles. It just tickles me pink.
Okay, let's do this using stock Photoshop tools. Once we understand the process using the stock tools, then move on to cobbling it together in FM.
- start with some photograph
- copy to new layer
- Edit > Fill
--- Use: Black, White, or 50% Grey
--- Mode: Saturation
There, just extracted Lum to work with.
- copy the Lum to another layer so you have 2 copies of Lum
- bottom Lum, Gauss @ 15
- top Lum
--- High Pass @ 15
--- Image > Adjust > Invert (ctrl + i)
--- Linear Light @ 50%
Now use your favorite method to get it into an alpha channel.
You know, looks kind of messy, doesn't it? Well, take it for a spin and see just how messy it is. Use it as a mask for your favorite adjustment layer. Invert it and use it as a mask for another adjustment layer. My guess is that you will be surprised.
I'm all giddy inside.
tee hee hee
Even without FM, that is a pretty neat trick to keep in your bag. | 
05-23-2006, 10:39 AM
|  | Senior Member | | Join Date: Feb 2005 Location: Lancashire (UK)
Posts: 1,112
| | | Hi Stroker.
I had a play with the code. It works very very well and being able to see the mask makes it even more useable. (I’m still working through the code)
Before I could reply the second post answered some questions.
I’ve worked through the alpha channel manually. I really need to get my head round applying a filter to a mask in FM. It’s a very important technique, so please go slowly.
Stupid question.
Is there any difference between putting the corrected layer above the original and setting blending mode to Luminocity and putting the original above the corrected and setting blending mode to colour?
I can’t see a difference. There shouldn’t be one should there? I knew it was a stupid question.
Ken. | 
05-23-2006, 04:03 PM
|  | Moderator | | Join Date: May 2004 Location: Goiânia, Brazil
Posts: 1,549
| | Quote: |
Originally Posted by Cameraken Stupid question.
Is there any difference between putting the corrected layer above the original and setting blending mode to Luminocity and putting the original above the corrected and setting blending mode to colour?
I can’t see a difference. There shouldn’t be one should there? I knew it was a stupid question. | No, that's not a stupid question. No, there is no difference. Stroker, I thought it was going to work like the Shadow / Highlight adjustment in CS2. That's probably why the controls got me all confused - until I looked at the code.
Nice start though - hope I get some time tomorrow to contribute something.
Rô | 
05-24-2006, 01:50 AM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | Yeah, controls are kind of a tricky subject. But that's one of the things that makes this kind of stuff so great. Once you get the pieces, put them together how you like them. I'm doing my version of S/H in a way that makes sense to me. I'm sure people out there would do it in a totally different way.
Generating a mask within FM and using it to fade between shouldn't be too hard to understand. Yes? No?
In my code, l1 is the low end of things, the darks. And l2 is the high end of things.
If the mask = 0, then full l1 and no l2.
If the mask = 255, then no l1 and full l2.
Then mask values inbetween are interpolated how ever you wish.
In my previous code, I used the blend() func to blend in a linear manner. Of course, you can use trig to blend. Or provide further controls for different kinds of blending. Maybe get exponetial or use logs. Whatever floats your boat. For me, linear is just fine for the majority of applications.
In my new code, blend() wasn't cutting it anymore. It gets weird on me when I get a little crazy. So I'm going to blend manually using a simple scale function.
Now, my code and tweaks aren't very specific. I have it set up rather open-ended. This will give it versatility, but also makes it a bit more complicated. Since it's mine and I understand it, I don't mind the extra complication.
However, the extra versatility and adding high pass to the mask don't always play nice. Depending, sometimes HP is good and sometimes it isn't. Because of this, I tossed in an extra control to tweak the high pass in the mask.
Now, the lum mask is blurred and scaled. However, I don't want the HP to scaled along with the lum. This means that I have to extract HP before blurring + scaling the lum, then add the HP in.
What I want:
- extract lum
- gauss lum
- extract hp
- scale lum
- add hp
What I don't want:
- extract lum
- gauss um
- extract hp
- add hp
- scale result
The new control that I added and the meat of the changes that I made: Code: ctl(6): "HP Mask",range=(-200,200),val=100
// time to loop the tweaks
for(x=x_start;x<x_end;x++){
for(y=y_start;y<y_end;y++){
int hp;
// grab values
mask=getArray(1,x,y,0);
l1=getArray(0,x,y,0);
l2=l1;
// tweak the mask
hp=(l1-mask)*ctl(6)/100;
mask=scl(mask,ctl(2),ctl(1),0,255);
if(mask>255){mask=255;}
if(mask<0){mask=0;}
mask-=hp;
// scale high
if(l1<128){
l1=scl(l1,0,128,0,ctl(3));
}else{
l1=scl(l1,128,255,ctl(3),255);
}
// scale low
if(l2<128){
l2=scl(l2,0,128,0,ctl(4));
}else{
l2=scl(l2,128,255,ctl(4),255);
}
// final output
if(ctl(5)==0){ // output final luminosity with blending
// final=blend(l1,l2,0,0,255-mask);
final=l2+(l1-l2)*mask/255;
pset(x,y,0,final);
pset(x,y,1,final);
pset(x,y,2,final);
}else{ // output mask
pset(x,y,0,mask);
pset(x,y,1,mask);
pset(x,y,2,mask);
}
}} // end y and x
| 
05-24-2006, 07:15 AM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | | If the mask = 0, then full l1 and no l2.
If the mask = 255, then no l1 and full l2.
reverse that
If the mask = 255, then full l1 and no l2.
If the mask = 0, then no l1 and full l2.
i think...
i don't know
i'm confusing myself again
add + dyslexia = rox0rz! | 
05-25-2006, 01:34 PM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | | So far just a simple mask and two simple tweaks. But there is another technique I use that I would like to incorporate.
I'm sure most of you folks are familiar with High Pass sharpening. I know a few of ya'll will sharpen to various radii and mask. Ah, but there is another tweak that I like to use with High Pass.
- Start with a photograph and make a luminosity mask
- Copy photo to new layer
- High Pass the new layer
--- Linear Light @ 50%.
- mask High Pass with your lum mask
There. You just sharpened a particular region of the photograph.
Time for a little extra magic. Clip a Levels adjustment layer to the HP layer and tweak away. Uber awesome.
Now, when it comes to coding in FM, Levels is a bit much. Let's see if we can reduce the technique.
Instead of clipping Levels, clip a Brightness/Contrast adjustment layer to the High Pass layer. When you wiggle the Brightness slider, you will brighten or darken as expected. However, when you wiggle the Contrast slider, you will sharpen more or less.
This is an excellant technique for culling even more detail. | 
05-28-2006, 05:08 AM
|  | Senior Member | | Join Date: Jan 2005
Posts: 314
| | Meh. Getting sucked into that other thing going on in this sub-forum.
Added B/C controls for High/Low shaprening, both use same radius. This requires another pass with rGauss.
At this point, I am pretty happy. I put it through some paces and it does what I want in a way that makes sense to me. This means extreme beta 1 and time to start thinking about cleaning up. Maybe change a little behavior here or there. Or maybe two different sharpening passes, one for high and one for low instead of using the same for both. Look for speed increases.
One thing that I really have to watch out for is loosing my eyeballs with this one. That versatility might still bite my buttocks.
blah blah blah Code: %ffp
SupportedModes: RGBMode
//dialog: size=(240,250)
dialog: color=lightgrey
//ctl[CTL_OK]: MODIFY, pos=(160,230)
//ctl[CTL_CANCEL]: MODIFY, pos=(200,230)
ctl(0): "Mask Radius",Range=(1,512),val=15
ctl(1): "High",range=(0,255),val=192
ctl(2): "Low",range=(0,255),val=64
ctl(3): "High Tweak",range=(10,245),val=128
ctl(4): "Low Tweak",range=(10,245),val=128
ctl(5): checkbox,"Show Mask",val=0
ctl(6): "HP Mask",range=(-200,200),val=100
ctl(7): "Sharpen Radius",Range=(1,512),val=5
ctl(8): "High Sharp B",range=(-50,50),val=0
ctl(9): "High Sharp C",range=(0,300),val=100
ctl(10): "Low Sharp B",range=(-50,50),val=0,pos=(350,105)
ctl(11): "Low Sharp C",range=(0,300),val=100,pos=(350,115)
//------------------------------------------------------------------------------------------
// Here comes the filter code
OnFilterstart:{
isTileable=0;
// setZoom(1);
return false;
}
ForEveryTile:
{
int c;
int xw = x_end-x_start;
int yw = y_end-y_start;
int radius = min(ctl(0),xw/2,yw/2);
float q = (float)(radius)/scaleFactor;
float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q;
float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q;
float b2 = -(1.4281*q*q + 1.26661*q*q*q );
float b3 = 0.422205*q*q*q;
float b1_b0 = b1/b0;
float b2_b0 = b2/b0;
float b3_b0 = b3/b0;
float BB = 1.0 - (b1_b0+b2_b0+b3_b0);
float wn,wn1,wn2,wn3;
int r,g,b,lum,thediff;
int mask,l1,l2,final;
//const int startclock = clock();
// temporary constant
z=0;
// z = 0 = luminosity
// z = 1 = guass
// z = 2 = high pass
// will have to rearrange how these are written
allocArray(0,X,Y,0,1);
allocArray(1,X,Y,0,1);
allocArray(2,X,Y,0,1);
// put luminosity into arrray
for(x=x_start;x<x_end;x++){
for(y=y_start;y<y_end;y++){
r=src(x,y,0);
g=src(x,y,1);
b=src(x,y,2);
lum=r*0.30 + g*0.59 + b*0.11;
putArray(0,x,y,0,lum);
}} // end y and x
// copy lum to 1 for gaussing
copyArray(0,1);
copyArray(0,2);
// for (z=0; z<Z; z++){ // loop through all channels
//
// forward pass
//
// warmup forward - no write
for (y=y_start; y<y_end; y++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-1]
wn2 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-2]
wn3 = (float)(getArray(1,x_start+2*radius,y,0)); // w[n-3]
for (x=x_start+2*radius; x>x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
// real forward pass
for (x=x_start; x<x_end; x++){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+1,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (x=x_end-1; x>=x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
//hmm.. this seems to be working so far
//pset(x,y,z, (int)wn );
putArray(1,x,y,0,(int)wn);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+2,4*Z) ) break;
// NOW DO COLUMNS
//
// forward pass
//
// warmup forward pass
for (x=x_start; x<x_end; x++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-1]
wn2 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-2]
wn3 = (float)(getArray(1,x,y_start+2*radius,0)); // w[n-3]
for (y=y_start+2*radius; y>y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
// real forward pass
for (y=y_start; y<y_end; y++){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+3,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (y=y_end-1; y>=y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(1,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(1,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+4,4*Z) ) break;
// } // for z
// ********* high pass *********
radius = min(ctl(7),xw/2,yw/2);
q = (float)(radius)/scaleFactor;
b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q;
b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q;
b2 = -(1.4281*q*q + 1.26661*q*q*q );
b3 = 0.422205*q*q*q;
b1_b0 = b1/b0;
b2_b0 = b2/b0;
b3_b0 = b3/b0;
BB = 1.0 - (b1_b0+b2_b0+b3_b0);
// for (z=0; z<Z; z++){ // loop through all channels
//
// forward pass
//
// warmup forward - no write
for (y=y_start; y<y_end; y++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(2,x_start+2*radius,y,0)); // w[n-1]
wn2 = (float)(getArray(2,x_start+2*radius,y,0)); // w[n-2]
wn3 = (float)(getArray(2,x_start+2*radius,y,0)); // w[n-3]
for (x=x_start+2*radius; x>x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
// real forward pass
for (x=x_start; x<x_end; x++){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(2,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+1,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (x=x_end-1; x>=x_start; x--){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
//hmm.. this seems to be working so far
//pset(x,y,z, (int)wn );
putArray(2,x,y,0,(int)wn);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for x
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+2,4*Z) ) break;
// NOW DO COLUMNS
//
// forward pass
//
// warmup forward pass
for (x=x_start; x<x_end; x++){ // loop through all rows
// initialize row
wn1 = (float)(getArray(2,x,y_start+2*radius,0)); // w[n-1]
wn2 = (float)(getArray(2,x,y_start+2*radius,0)); // w[n-2]
wn3 = (float)(getArray(2,x,y_start+2*radius,0)); // w[n-3]
for (y=y_start+2*radius; y>y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
// real forward pass
for (y=y_start; y<y_end; y++){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(2,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+3,4*Z) ) break;
//
// backward pass
//
// real backward pass
for (y=y_end-1; y>=y_start; y--){ // loop through all columns
wn = BB*(float)(getArray(2,x,y,0)) + (b1_b0*wn1+b2_b0*wn2+b3_b0*wn3);
putArray(2,x,y,0, (int)wn );
// update
wn3=wn2;
wn2=wn1;
wn1=wn;
} // for y
} // for x
//Update progress bar and cancel if ESC key was pressed
//if ( updateProgress(4*z+4,4*Z) ) break;
// } // for z
//0=lum
//1=gauss, mask
// 2 = sharpen highpass
// time to loop the tweaks
for(x=x_start;x<x_end;x++){
for(y=y_start;y<y_end;y++){
int hp,hp1,hp2;
// grab values
mask=getArray(1,x,y,0);
l1=getArray(0,x,y,0);
l2=l1;
// tweak the mask
hp=(l1-mask)*ctl(6)/100;
mask=scl(mask,ctl(2),ctl(1),0,255);
if(mask>255){mask=255;}
if(mask<0){mask=0;}
mask-=hp;
// scale high
if(l1<128){
l1=scl(l1,0,128,0,ctl(3));
}else{
l1=scl(l1,128,255,ctl(3),255);
}
// scale low
if(l2<128){
l2=scl(l2,0,128,0,ctl(4));
}else{
l2=scl(l2,128,255,ctl(4),255);
}
// high pass sharpen high
hp1=getArray(0,x,y,0)-getArray(2,x,y,0);
hp2=hp1;
hp1=hp1*ctl(9)/100 + ctl(8);
l1+=hp1;
// high pass sharpen low
hp2=hp2*ctl(11)/100+ctl(10);
l2+=hp2;
// final output
if(ctl(5)==0){ // output final luminosity with blending
// final=blend(l1,l2,0,0,255-mask);
final=l2+(l1-l2)*mask/255;
pset(x,y,0,final);
pset(x,y,1,final);
pset(x,y,2,final);
}else{ // output mask
pset(x,y,0,mask);
pset(x,y,1,mask);
pset(x,y,2,mask);
//pset(x,y,0,hp1+128);
//pset(x,y,1,hp1+128);
//pset(x,y,2,hp1+128);
//pset(x,y,0,128+getArray(0,x,y,0)-getArray(2,x,y,0));
//pset(x,y,1,128+getArray(0,x,y,0)-getArray(2,x,y,0));
//pset(x,y,2,128+getArray(0,x,y,0)-getArray(2,x,y,0));
}
}} // end y and x
//Stop processing and apply the effect
return true;
}
| 
05-28-2006, 06:19 AM
|  | Senior Member | | Join Date: Feb 2005 Location: Lancashire (UK)
Posts: 1,112
| | Hi Stroker.
Thank You.
That’s working fine. It’s a lot more complicated than I expected it to be, but it also seems a lot more versatile. I don’t have CS so I can’t compare but for PS7 users this is a great addition.
Thanks again.
(I’d be interested to hear your thoughts on Filter Forge?)
Ken. |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | All times are GMT -6. The time now is 11:30 AM. | |
|