RetouchPRO

Go Back   RetouchPRO > Tools > Software
Register Blogs FAQ Site Nav Search Today's Posts Mark Forums Read


Software Photoshop, Lightroom, Paintshop Pro, Painter, etc., and all their various plugins. Of course, you can also discuss all other programs, as well.

Filter Meister: thinking about S/H

Reply
 
Thread Tools
  #1  
Old 05-21-2006, 01:01 PM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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;
}
Reply With Quote top
  #2  
Old 05-23-2006, 05:46 AM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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.
Reply With Quote top
  #3  
Old 05-23-2006, 10:39 AM
Cameraken's Avatar
Cameraken Cameraken is offline
Senior Member
 
Join Date: Feb 2005
Location: Lancashire (UK)
Posts: 1,158
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.
Reply With Quote top
  #4  
Old 05-23-2006, 04:03 PM
byRo's Avatar
byRo byRo is offline
Senior Member
 
Join Date: May 2004
Location: Goianésia, Brazil
Posts: 1,609
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.

Reply With Quote top
  #5  
Old 05-24-2006, 01:50 AM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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
Reply With Quote top
  #6  
Old 05-24-2006, 07:15 AM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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!
Reply With Quote top
  #7  
Old 05-25-2006, 01:34 PM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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.
Reply With Quote top
  #8  
Old 05-28-2006, 05:08 AM
Stroker's Avatar
Stroker Stroker is offline
Senior Member
 
Join Date: Jan 2005
Posts: 370
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;
}
Reply With Quote top
  #9  
Old 05-28-2006, 06:19 AM
Cameraken's Avatar
Cameraken Cameraken is offline
Senior Member
 
Join Date: Feb 2005
Location: Lancashire (UK)
Posts: 1,158
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.
Reply With Quote top
Reply

  RetouchPRO > Tools > Software


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Filter Forge has been officially released! Craig Walters Software 2 03-06-2007 11:09 AM
Filter Forge Doug Nelson Software 77 07-06-2006 03:05 PM
Sharpening T Paul Scratch Pad 34 08-16-2004 11:02 AM
Tutorial: Texturizer Filter tricks DannyRaphael Photo-Based Art 6 07-13-2002 03:13 PM
Colored Pencil filter: Stroke direction options DannyRaphael Photo-Based Art 14 06-11-2002 06:27 PM


All times are GMT -6. The time now is 04:29 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
Copyright © 2016 Doug Nelson. All Rights Reserved