
Software Photoshop, Lightroom, Paintshop Pro, Painter, etc., and all their various plugins. Of course, you can also discuss all other programs, as well. 
 Thread Tools 
#61
 
 
The last code does work as it should. It just doesn't work as most folks are used to. Hard to explain. If I think about it, I might be able to come with a way of explaining it. Here comes a subject I adore. Contrast is finding the difference and amplifying it. It can be anything you desire. Can be difference in saturation between subjects. Can be shades of red and shades of blue. A common use of contrast is Levels. Basically contrast between high/low in each seperate channel. Earlier I showed how to get 3d midtones in Lab. You know, the distance from the center thing. With vectors and normals, you can actually move values away from the midtone center in a 3d manner. This is a form of contrast. Very basic example for Lab: Code: %ffp ctl(0):standard,"Amount",range=(100,100),val=10,track ctl(1):checkbox,"Absolute Distance",val=0 supportedmodes: labmode ForEveryTile:{ int ll,aa,bb; float distance,nx,ny,nz; for(x=x_start;x<x_end;x++){ for(y=y_start;y<y_end;y++){ // grab values // bother with 128 to make things easier ll=src(x,y,0)128; aa=src(x,y,1)128; bb=src(x,y,2)128; // Pythagoras to get distance distance=sqrt( (float)ll*ll + aa*aa + bb*bb); //distance hack, move straight up if(distance==0){ nx=1; ny=0; nz=0; }else{ // normalize the vector nx=ll/distance; ny=aa/distance; nz=bb/distance; } // end distance hack // add with option if(ctl(1)==0){ // relative ll=ll+nx*ctl(0); aa=aa+ny*ctl(0); bb=bb+nz*ctl(0); }else{ // absolute distance ll=nx*ctl(0); aa=ny*ctl(0); bb=nz*ctl(0); } // output, don't forget 128 pset(x,y,0,ll+128); pset(x,y,1,aa+128); pset(x,y,2,bb+128); }} // y x return true; } // for every tile (If you want to, you don't have to push values away from the center. With some controls and offsetting, you can actually push values away from any given point. To tickle your brain, imagine using gravity instead of vectors. With gravity, you can pull towards and push away from several points. How would you like a magnet effect for contrast and colour balance?) As the code is, it works just like Levels  except you are doing all 3 channels at once in a simple manner. Since this can be done with Levels, it may seem a bit silly. Believe me, it's not. This is just a building block. 
#62
 
 
That works just fine Stroker, Thank you. It sounds like there is better to come. I found this great thread on HSB http://photoshoptechniques.com/forum...t=10495&page=2 Pity I didn’t find it sooner. I may have won more cookies. Ken. 
#63
 
 
Dude, I haven't seen that thread in awhile. Now that's an old school rampage. If I remember correctly, I made some gnarly mistakes in that thread and had to do some followups to ammend. Let's talk about gradients some more. With trigonometry you can do a lot of things with triangles, especially if they are right triangles. The Photoshop's Gradient tool is proof positive of this. How does the Gradient tool work? Vectors and trig. When you drag a the Gradient tool, you are defining a 2d vector in screen space. Basically a position vector in x and y. As you go through the x and y loops, you use one point on the defined vector to define a second vector. Then you make it a right triangle. Using a simple formula, you can get another angle in the right triangle. After that, it should be cake to finish it up. The forumula to get the angle is simply: p1 * p2 = p1 * p2 * cos(angle) cos(angle) = p1 * p2 / p1 * p2 angle = acos( p1 * p2 / p1 * p2 ) Well, maybe not simply. Maybe if you read Understanding the Dot Product enough times will click. Or maybe the attached graphic will help. The graphic attached shows distance along a vector. Just a simple percentage with the length of v1 = 100%. The length of p3 along v1 = 50%. And that's how the Linear Gradient tool in Photoshop works. Um, yeah. 
#64
 
 
I mentioned that Levels is a common method for increasing contrast. Once in a great while I take issue with this. Why? Because each channel is done seperately and you end up with a square. If you do this in 3d space, you end up with a box. While the two points and the line between maybe good and gradual, sometimes I don't like what happens to the rest of the space around the 'vector'. 
#65
 
 
Why not create a gradient based on colour values instead of pos x and y? Why not make it 3d? Why not in Lab which is good for our eyes instead of RGB which is good for monitors? Here is an early version of one of my personal filters that does just that. Code: %ffp Category:"Tech Slop Lab" Title:"3D Linear Grad" Author:"JLHalmich" Copyright: "2005 by JLHalmich" Organization:"Tech Slop" Version:"beta 1" Filename: "TS_3dlineargrad.8bf" Description: "Linear gradient in 3d Lab space" About: "!t Plugin !V\n!C\n!c\n!D" SupportedModes: LabMode dialog: size=(395,175) ctl[CTL_OK]: MODIFY, pos=(315,155) ctl[CTL_CANCEL]: MODIFY, pos=(355,155) ctl(0):standard,"L",pos=(260,15),range=(0,255),val=25,track ctl(1):standard,"a",pos=(260,25),range=(127,127),val=25,track ctl(2):standard,"b",pos=(260,35),range=(128,128),val=25,track ctl(3):standard,"L",pos=(260,65),range=(0,255),val=240,track ctl(4):standard,"a",pos=(260,75),range=(127,127),val=25,track ctl(5):standard,"b",pos=(260,85),range=(127,127),val=25,track ctl(6):checkbox,"LL against Lightness",pos=(260,105) ctl(7):groupbox,"Black", pos=(240,5),size=(150,45) ctl(8):groupbox,"White",pos=(240,55),size=(150,45) ctl(9):standard,"Blend",pos=(260,120),val=255,track OnFilterStart:{ setPreviewCursor (32515); return false; } OnCtl(n):{ if (e==FME_RIGHTCLICKED_DOWN && n==CTL_PREVIEW){ int x,y,ll,aa,bb; x = getPreviewCoordX();//*scaleFactor; y = getPreviewCoordY();//*scaleFactor; ll=src(x,y,0); aa=src(x,y,1)128; bb=src(x,y,2)128; if(getAsyncKeyState(VK_CONTROL)>=0){ // white setCtlVal(3,ll); setCtlVal(4,aa); setCtlVal(5,bb); } else { // black setCtlVal(0,ll); setCtlVal(1,aa); setCtlVal(2,bb); } doAction(CA_PREVIEW); } // end right click return false; } // on ctl ForEveryTile:{ int x,y,ll,aa,bb,c,a; int final; //float pi = 3.14159; // p1 with normalization int p1x,p1y,p1z; float p1dist; float p1nx,p1ny,p1nz; //p2 without normalization int p2x,p2y,p2z; float p2dist; // theta junk float pretheta,theta; float adj; // can precalculate some junk before the loop // do p1 with offset p1x=ctl(3)ctl(0); p1y=ctl(4)ctl(1); p1z=ctl(5)ctl(2); // get length of p1 p1dist = sqrt( (float)p1x*p1x + p1y*p1y + p1z*p1z); //normalize p1 p1nx=(float)p1x/p1dist; p1ny=(float)p1y/p1dist; p1nz=(float)p1z/p1dist; for (y=y_start; y<y_end; y++){ //if(updateProgress(y,y_end)) abort(); for (x=x_start; x<x_end; x++){ c = srcp (x,y); //Explode it into the color values ll = Rval(c); //c & 0xff; aa = Gval(c)128; //c >> 8 & 0xff; bb = Bval(c)128; //c >> 16 & 0xff; //if (Z>3) a = Aval(c); //c >> 24 & 0xff; // p2 p2x=llctl(0); p2y=aactl(1); p2z=bbctl(2); p2dist = sqrt( (float)p2x*p2x + p2y*p2y + p2z*p2z); // get angle, aka theta // don't forget: float and radians // p1 * p2 = p1 * p2 * cos(angle) // cos(angle)= p1 * p2 / p1 * p2 pretheta=(p1x*p2x + p1y*p2y + p1z*p2z) / (p1dist*p2dist); theta=acos(pretheta); if(theta==0){ // theta hack, seems around 99.99% final=(p2dist/p1dist)*255; }else{ // now solve to adj adj=fcos(theta)*p2dist; final=(adj/p1dist)*255; } // write the values back if(doingProxy==false){ if(ctl(6)==1){final=(finalll)/2+128;} pset(x,y,0,final); pset(x,y,1,128); pset(x,y,2,128); }else{ ll=blend(ll,final,0,0,ctl(9)); aa=blend(aa+128,128,0,0,ctl(9)); bb=blend(bb+128,128,0,0,ctl(9)); pset(x,y,0,ll); pset(x,y,1,aa); pset(x,y,2,bb); } }} // x y return true; } // for every pixel I originally wanted this for increasing contrast in fleshtones. As I got to playing with it, I was rather surprised at how well it works with a variety of photographs. For example, helping with desaturating photographs of sunsets with tricky hues. Oh, I almost forgot. That code has some rightclick functionality. Right click Preview to sample White. Ctrl + right click Preview to sample Black. Two other optional dohickies which aren't too hard to figure out. 
#66
 
 
Here's one to ponder.

#67
 
 
The Rabbit hole gets deeper Phew. You weren’t joking There is some good stuff at the Xzone. But I found this a little easier. Thanks to Philip Harrison http://www.netsoc.tcd.ie/~jgilbert/m...t_product.html When LW < LB the image goes negative (that’s understandable) When LW > 200(approx) the image starts to get darker??? Right Click on Preview to sample White Ctrl + right click Preview to sample Black Alt + right click Preview seems to give threshold?? Sorry I can’t find another, I was expecting Mid Tones. And I can’t read the code Oh dear. I’ve so much to learn. Re the HSB thread. I did read the follow up Addendums. It was good of you to add that. I don’t think many would have noticed Vectors made easy http://www.bbc.co.uk/schools/gcsebit...onshrev2.shtml http://www.euclideanspace.com/maths/algebra/vectors/ Ken. (AKA March Hare) 
#68
 
 
Vectors and things are cool, but can be hard to wrap around your head. I'm glad you found a link that makes more sense to you. Visualize what's going on? Imagine a sphere. This is the Lab sphere. In this sphere, pick two points. Between these two points in a vector and even a normal. If you can imagine it, visualize two planes in the sphere. Each of these planes are parallel to each other and will never touch each other. The two previously defined points are on these planes.  between the planes, points closer to one plane will darker  between the planes, points closer to the other plane will be brighter  points not between the planes will be either black or white It is a truly 3d gradient. In the last code,  right click sets the white point  ctrl + right click sets the black point However, alt + click will behave as right click and that probably explains the threshhold effect you are seeing. This is because the two points are rather close together. If you use Levels to set black and white really close together, what do you get? A threshhold effect. Another little thing that I truly adore is Linear Light. Over 128 goes in one direction and less than 128 goes in the opposite direction. We can actually use the 3d gradient to push values away from each other in a linear 3d fashion. Use the vector/normal as a direction and the gradient as a magnitude. Using this method, it becomes almost trivial to boost contrast in subtle shades and things. Need a little more contrast between slightly red cheeks and slightly yellow jowel? Not a problem. Early beta of just such a thing: Code: %ffp SupportedModes: LabMode dialog: size=(395,175) ctl[CTL_OK]: MODIFY, pos=(315,155) ctl[CTL_CANCEL]: MODIFY, pos=(355,155) ctl(0):standard,"L",pos=(260,15),range=(0,255),val=25,track ctl(1):standard,"a",pos=(260,25),range=(127,127),val=25,track ctl(2):standard,"b",pos=(260,35),range=(128,128),val=25,track ctl(3):standard,"L",pos=(260,65),range=(0,255),val=240,track ctl(4):standard,"a",pos=(260,75),range=(127,127),val=25,track ctl(5):standard,"b",pos=(260,85),range=(127,127),val=25,track //ctl(6):checkbox,"LL against Lightness",pos=(260,105) ctl(7):groupbox,"Black", pos=(240,5),size=(150,45) ctl(8):groupbox,"White",pos=(240,55),size=(150,45) //ctl(9):standard,"Offset",pos=(260,120),range=(100,100),val=0,track ctl(10):standard,"Expand",pos=(270,130),range=(200,200),val=50,track OnFilterStart:{ setPreviewCursor (32515); return false; } OnCtl(n):{ if (e==FME_RIGHTCLICKED_DOWN && n==CTL_PREVIEW){ int x,y,ll,aa,bb; x = getPreviewCoordX();//*scaleFactor; y = getPreviewCoordY();//*scaleFactor; ll=src(x,y,0); aa=src(x,y,1)128; bb=src(x,y,2)128; if(getAsyncKeyState(VK_CONTROL)>=0){ // white setCtlVal(3,ll); setCtlVal(4,aa); setCtlVal(5,bb); } else { // black setCtlVal(0,ll); setCtlVal(1,aa); setCtlVal(2,bb); } doAction(CA_PREVIEW); } // end right click return false; } // on ctl ForEveryTile:{ int x,y,ll,aa,bb,c,a; int final; //float pi = 3.14159; // p1 with normalization int p1x,p1y,p1z; float p1dist; float p1nx,p1ny,p1nz; //p2 without normalization int p2x,p2y,p2z; float p2dist; // theta junk float pretheta,theta; float adj; // can precalculate some junk before the loop // do p1 with offset p1x=ctl(3)ctl(0); p1y=ctl(4)ctl(1); p1z=ctl(5)ctl(2); // get length of p1 p1dist = sqrt( (float)p1x*p1x + p1y*p1y + p1z*p1z); //normalize p1 p1nx=(float)p1x/p1dist; p1ny=(float)p1y/p1dist; p1nz=(float)p1z/p1dist; for (y=y_start; y<y_end; y++){ //if(updateProgress(y,y_end)) abort(); for (x=x_start; x<x_end; x++){ c = srcp (x,y); //Explode it into the color values ll = Rval(c); //c & 0xff; aa = Gval(c)128; //c >> 8 & 0xff; bb = Bval(c)128; //c >> 16 & 0xff; //if (Z>3) a = Aval(c); //c >> 24 & 0xff; // p2 p2x=llctl(0); p2y=aactl(1); p2z=bbctl(2); p2dist = sqrt( (float)p2x*p2x + p2y*p2y + p2z*p2z); // get angle, aka theta pretheta=(p1x*p2x + p1y*p2y + p1z*p2z) / (p1dist*p2dist); // don't forget: float + radians theta=acos(pretheta); // solve for adj using theta // conert to linear light form using *10050 if(theta==0){ // theta hack, seems around 99.99% final=(p2dist/p1dist)*10050; }else{ // now solve to adj adj=fcos(theta)*p2dist; final=(adj/p1dist)*10050; } // add it all up ll=ll+p1nx*final*ctl(10)/100; aa=aa+p1ny*final*ctl(10)/100; bb=bb+p1nz*final*ctl(10)/100; pset(x,y,0,ll); pset(x,y,1,aa+128); pset(x,y,2,bb+128); }} // x y return true; } // for every pixel Now, masking using trig in the Lab sphere is a lot of fun  doesn't have to be a pointtopoint blacktowhite gradient. I'll touch on this later. (Roland, I got your message finally. I'll get back to you soon.) 
#69
 
 
Meh. Getting sucked into other things. Some quick touchies from Uncle Stroker.  Used Pythagoras to get distance from a point. Even did some pushing around.  Used vectors/normals to get distance along a vector. Again, some pushing around. To get the distance along the vector, used trig one way. However, you can get the distance from a vector using trig the other way. Instead of solving for adj, just solve for opp and go from there. Using this method, you can actually bore holes in the Lab sphere from one point to another. Instead of dichotomy, you are actually connecting. This is a good way of masking some vector operations. Another good way to push values around or mask is to use theta. Instead of solving for adj or opp, just stop at theta and use that. Once you start getting the hang of it, you can do some uber ChOps in 3d space. Do you want shades of orange that fade into magenta that are between the two? Not a problem. Harsh coloured lights causing extremely tinted highlights? Not a problem. That funky oversaturated event horizon? Not a problem. (The event horizon thing is something that I had been wrestling with for quite some time. It's this funny space that exists between light and dark where the change takes place. I call it event horizon, but terminator might be more appropriate. Using trig in Lab, I have finally found a way to isolate it. So far just an annoying curiosity.) Been getting sucked into several things. Of note, Hue and Sat in Lab space as Photoshop uses them. Been using theta and rho, but Photoshop cubes the sphere and things get funky. Haven't decided on a rampage yet. Another thing I've been messing with is manipulating Hue sort of like Levels. I've done this in RGB, but it is so much easier in Lab space with FM. It is very nice being able to manipulate tonal range in such a manner. I haven't forgotten about you, Roland. I'm getting there. 
#70
 
 
Thanks Stroker. The effect of the Linear Light code can be quite subtle. I am still having difficulty with this whole vector thing. I am slowly working my way through this. http://www.netcomuk.co.uk/~jenolive/vecfind.html Ken. 

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)  
Thread Tools  
 
Similar Threads  
Thread  Thread Starter  Forum  Replies  Last Post 
Color Space conversions  Reimar  Photoshop Elements Help  4  01162004 06:58 AM 
Batch Raw conversions in PS CS  okplayer  Software  0  12192003 01:03 PM 