%ffp Category :"RC Filters" Title :"Hue/Saturation Channels" Filename :"HueSaturationChannels.8bf" Description:"Extracts a hue or saturation channel from an RGB image." Copyright :"© 2018 by Russell Cottrell." Author :"Russell Cottrell" Version :"1.2" URL :"http://www.russellcottrell.com/RCFilters" About :"Thank you for using !C!\n!t v!V by !A.\n!D\nPlease visit russellcottrell.com/RCFilters." // 3/14/2018 Dialog: Size=(590,406), MaxBox, MinBox, Theme=on, Initevent SupportedModes: RGBMode, RGB48Mode Embed: Bitmap="logo.bmp" ctl(1): RadioButton(Group), pos=(380,22), size=(60,*), Action=Preview, "Hue", val=1 ctl(2): RadioButton, pos=(380,34), size=(60,*), Action=Preview, "Hue difference" ctl(3): RadioButton, pos=(380,68), size=(60,*), Action=Preview, "HCY" ctl(4): RadioButton, pos=(380,80), size=(60,*), Action=Preview, "HSL" ctl(5): RadioButton, pos=(380,92), size=(60,*), Action=Preview, "HSV/HSB" ctl(6): RadioButton, pos=(380,104), size=(60,*), Action=Preview, "HSI" ctl(9): GroupBox(Group), pos=(0,0), size=(0,0), "", Invisible ctl(20): GroupBox, pos=(370,11), size=(92,36), "Hue" ctl(21): GroupBox, pos=(370,56), size=(92,62), "Saturation" ctl(10): Standard, "Rotate", pos=(396,130), size=(115,*), range=(0,360), val=0, Action=Preview ctl(11): checkbox(Lefttext, Right), text="Auto levels ", Pos=(355,148), Size=(50,*), val=1 ctl(12): checkbox(Lefttext, Right), text="Invert ", Pos=(355,164), Size=(50,*), val=0 ctl(41): Rect(Modalframe, White), pos=(0,0), size=(292, 149), Anchor=ANCHOR_LEFT|ANCHOR_TOP, Invisible ctl(42): Rect(Gray), pos=(3, 3), size=(286,87), Anchor=ANCHOR_LEFT|ANCHOR_TOP, Invisible ctl(43): StaticText(CENTER), pos=(3,94), size=(286, 8), Anchor=ANCHOR_LEFT|ANCHOR_TOP, Invisible, "Thank you for using RC Filters!" ctl(44): StaticText(CENTER), pos=(3,102), size=(286, 16), Anchor=ANCHOR_LEFT|ANCHOR_TOP, Invisible, "" ctl(45): StaticText(CENTER,NOTIFY), pos=(3,124), size=(286, 10), Anchor=ANCHOR_LEFT|ANCHOR_TOP, FontColor=blue, Invisible, "Please visit russellcottrell.com/RCFilters for more information." ctl(46): StaticText(CENTER,NOTIFY), pos=(3,134), size=(286, 10), Anchor=ANCHOR_LEFT|ANCHOR_TOP, FontColor=blue, Invisible, "Click here to open the plugin folder." ctl[CTL_PREVIEW]: Modify, Size=(333,383) ctl[CTL_PROGRESS]: Modify, Pos=(4,394) ctl[CTL_ZOOM]: Modify, Pos=(91,394) ctl(50): Pushbutton, "100%", Pos=(160,391), Anchor=ANCHOR_LEFT|ANCHOR_BOTTOM, Size=(30,14), Action=Preview ctl(51): Pushbutton, "Fit", Pos=(195,391), Anchor=ANCHOR_LEFT|ANCHOR_BOTTOM, Size=(30,14), Action=Preview // HueSaturationChannelsHelp.htm ctl(53): checkbox(Pushlike), text="About", Pos=(431,389), Size=(34,14), val=0, Anchor=ANCHOR_RIGHT|ANCHOR_BOTTOM ctl(54): Pushbutton, text="Reset", Pos=(474,389), Size=(34,14), val=0, Anchor=ANCHOR_RIGHT|ANCHOR_BOTTOM, Action=Preview ctl[CTL_OK]: Pushbutton, text="Apply", Pos=(517,389), Size=(34,14), Anchor=ANCHOR_RIGHT|ANCHOR_BOTTOM ctl[CTL_CANCEL]: Pushbutton, text="Cancel", Pos=(552,389), Size=(34,14), Anchor=ANCHOR_RIGHT|ANCHOR_BOTTOM OnFilterStart: { switch(imageMode) { case RGBMode: sprintf(str0, "8-bit RGB Color"); break; case RGB48Mode: sprintf(str0, "16-bit RGB Color"); break; } sprintf(str1, formatString("!t (%s, !f)"), str0); setDialogText(str1); setCtlText(44, formatString("!t v!V by !A.\n!D")); isTileable = false; // need to process the entire image for min and max levels refreshWindow(); return false; } OnCtl(n): { int logoL, logoT; void *TXT_FILE; if (e==FME_CLICKED) { if (ctl(53)) // About { logoL = (getDialogWidth() - getCtlPos(41, 2))/2; logoT = (getDialogHeight() - getCtlPos(41, 3))/2 - 10; setCtlPos(41, logoL, logoT, -1, -1); setCtlPos(42, logoL+3, logoT+3, -1, -1); setCtlPos(43, logoL+3, logoT+94, -1, -1); setCtlPos(44, logoL+3, logoT+102, -1, -1); setCtlPos(45, logoL+3, logoT+124, -1, -1); setCtlPos(46, logoL+3, logoT+134, -1, -1); for (i=41; i<=46; i++) { enableCtl(i, 3); setCtlOrder(i, 1); } } else // close About { for (i=41; i<=46; i++) enableCtl(i, 0); } if ((n==45) && (ctlEnabled(45)!=0)) shellExec("open", "http://www.russellcottrell.com/RCFilters", NULL, filterInstallDir); if ((n==46) && (ctlEnabled(46)!=0)) shellExec("open", filterInstallDir, NULL, NULL); if (ctl(54)) // Reset { setCtlVal(1,1); setCtlVal(2,0); setCtlVal(3,0); setCtlVal(4,0); setCtlVal(5,0); setCtlVal(6,0); setCtlVal(10,0); setCtlVal(11,1); setCtlVal(12,0); setCtlVal(53,0); setCtlVal(54,0); triggerEvent(54, FME_CLICKED, 0); triggerEvent(53, FME_CLICKED, 0); // ***AFTER*** 54 } } if (e==FME_INIT) setZoom(-888); if (e==FME_SIZE) setZoom(-888); if (n==50) setZoom(1); else if (n==51) setZoom(-888); return false; } ForEveryTile: { double dC = imageMode= Gv) && (Gv >= Bv)) { H = Rv; M = Gv; L = Bv; nn = 0.0; sig = 1.0; } else if ((Gv > Rv) && (Rv >= Bv)) { H = Gv; M = Rv; L = Bv; nn = 2.0; sig = -1.0; } else if ((Gv >= Bv) && (Bv > Rv)) { H = Gv; M = Bv; L = Rv; nn = 2.0; sig = 1.0; } else if ((Bv > Gv) && (Gv > Rv)) { H = Bv; M = Gv; L = Rv; nn = 4.0; sig = -1.0; } else if ((Bv > Rv) && (Rv >= Gv)) { H = Bv; M = Rv; L = Gv; nn = 4.0; sig = 1.0; } else if ((Rv >= Bv) && (Bv > Gv)) { H = Rv; M = Bv; L = Gv; nn = 6.0; sig = -1.0; } if (H != L) Hue = 60.0 * (nn + sig*((M-L)/(H-L))); else Hue = 0.0; if (ctl(1)) Hue = fmod(Hue + ro, 360.0); else { hd = fabs(Hue - ro); hd = fmin(hd, 360.0-hd); Hue = hd * 2.0; } Hue *= dC/360.0; vMin = fmin(Hue, vMin); // hue min vMax = fmax(Hue, vMax); // hue max fputArray(1,x,y,0,Hue); // save to buffer } } } // hue ////////// saturation ////////// else { // saturation for (y=y_start;y dC) sat = dC + dC - sat; sat = ((H==0.0) || (H==L)) ? 0.0 : ((H-L)*dC) / sat; } else if (ctl(5)) // HSV/HSB sat = (H > 0.0) ? dC - (L*dC)/H : 0.0; else if (ctl(6)) // HSI sat = (H==L) ? 0.0 : dC - (L*dC)/M; sat = fabs(ro/to8bit - sat); vMin = fmin(sat, vMin); // sat min vMax = fmax(sat, vMax); // sat max fputArray(1,x,y,0,sat); // save to buffer } } } // saturation ////////// auto levels ////////// for (y=y_start; y