%ffp Category :"RC Filters" Title :"Very High Radius Unsharp Mask" Filename :"VHRUnsharpMask.8bf" Description:"High-radius low-amount contrast enhancement for images of any size." Copyright :"© 2019 by Russell Cottrell; released under the Gnu General Public License." Author :"Russell Cottrell" Version :"1.202" 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." // 6/28/2019 /* Acknowledgements: Recursive gaussian demo code implemented by Tom Fiddaman from the article: Title: Recursive implementation of the Gaussian filter Authors: I.T. Young, L.J. van Vliet in: Signal Processing, vol. 44, no. 2, 1995, 139-151. Interpolation by Harald Heim The Plugin Site, http://thepluginsite.com Copyright 2002 by Harald Heim */ Dialog: Size=(590,406), MaxBox, MinBox, Theme=on, Initevent SupportedModes: RGBMode, RGB48Mode, GrayScaleMode, Gray16Mode Embed: Bitmap="logo.bmp" ctl(0): Standard, "Radius", Range=(0,200), Divisor=10, pos=(400,20), Val=100 ctl(1): StaticText, "0px", pos=(525,20), size=(60,10) ctl(2): Standard, "Amount", Range=(-50,100), pos=(400,32), Val=30 ctl(7): Scrollbar, "", pos=(525,31), size=(20,10), range=(0,400), val=0, line=400, invisible ctl(3): checkbox, text="Show the Gaussian Blur", Pos=(400,52), val=0, Action=Preview ctl(6): Standard, "Color", Range=(0,200), pos=(400,72), Val=0 ctl(10): checkbox(Pushlike, 3State), text="Normal", Pos=(525,69), Size=(56,12), val=1, Action=Preview ctl(4): Standard, "Dark/Light Mixer", Range=(-100,100), pos=(425,92), Val=0 ctl(30): StaticText, "Shadows/Highlights:", pos=(365,112), size=(70,10) ctl(31): Standard, "Tonal Width", Range=(0,255), pos=(400,128), size=(115,*), Val=0, Color=Black ctl(32): Standard, "Radius", Range=(0,1000), Divisor=100, pos=(400,140), size=(115,*), Val=100, Color=Black ctl(33): Standard, "Lighten", Range=(0,100), pos=(400,152), size=(115,*), Val=0, Color=Black ctl(34): Standard, "Tonal Width", Range=(0,255), pos=(400,168), size=(115,*), Val=0, Color=White ctl(35): Standard, "Radius", Range=(0,1000), Divisor=100, pos=(400,180), size=(115,*), Val=100, Color=White ctl(36): Standard, "Darken", Range=(0,100), pos=(400,192), size=(115,*), Val=0, Color=White ctl(37): checkbox(Pushlike), text="Enabled", Pos=(398,205), Size=(34,12), val=1 ctl(39): checkbox(Pushlike), text="Show", Pos=(434,205), Size=(34,12), val=0 ctl(70): StaticText, "Blend Ranges:", pos=(365,228), size=(160,10) ctl(71): GroupBox, pos=(363,235), size=(204,28) ctl(72): Trackbar(Noticks,Bottom,Toptip), Pos=(365,240), Size=(200,11), Range=(0,255), Val=0, Color=Black ctl(73): Trackbar(Noticks,Top,Toptip), Pos=(365,250), Size=(200,11), Range=(0,255), Val=127, Color=Black ctl(74): Trackbar(Noticks,Bottom,Toptip), Pos=(365,265), Size=(200,11), Range=(0,255), Val=127, Color=White ctl(75): Trackbar(Noticks,Top,Toptip), Pos=(365,275), Size=(200,11), Range=(0,255), Val=255, Color=White ctl(76): GroupBox, pos=(363,260), size=(204,28) ctl(77): checkbox(Pushlike), text="Midtones", Pos=(484,226), Size=(40,12), val=1 ctl(78): checkbox(Pushlike), text="Enabled", Pos=(526,226), Size=(40,12), val=1 ctl(40): OwnerDraw(drawitem), pos=(378,300), size=(256,100) // histogram 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), Invisible // VHRUnsharpMaskHelp.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; case GrayScaleMode: sprintf(str0, "8-bit Grayscale"); break; case Gray16Mode: sprintf(str0, "16-bit Grayscale"); break; } sprintf(str1, formatString("!t (%s, !f)"), str0); setDialogText(str1); if (e==FME_INIT) { if ((imageMode == RGBMode) || (imageMode == RGB48Mode)) { if (!ctl(3)) { enableCtl(6, 3); enableCtl(10, 3); } } else { enableCtl(6, 1); enableCtl(10, 1); } j0 = getCtlRange(6, 1); } setCtlPos(40, -1, -1, PixelsToHDBUs(259), PixelsToVDBUs(103)); setCtlText(44, formatString("!t v!V by !A.\n!D")); isTileable=false; refreshWindow(); return false; } OnCtl(n): { int jTemp; int logoL, logoT; void *TXT_FILE; int bctl0 = 72; // the blend range sliders int bctl1 = 73; int wctl0 = 74; int wctl1 = 75; if ((n==bctl0 || n==bctl1 || n==wctl0 || n==wctl1) && (e==FME_CHANGED)) { switch(n) { case 72: // can't use variables here if (ctl(bctl1) < ctl(bctl0)) setCtlVal(bctl1,ctl(bctl0)); if (ctl(wctl0) < ctl(bctl0)) setCtlVal(wctl0,ctl(bctl0)); if (ctl(wctl1) < ctl(bctl0)) setCtlVal(wctl1,ctl(bctl0)); break; case 73: if (ctl(bctl0) > ctl(bctl1)) setCtlVal(bctl0,ctl(bctl1)); if (ctl(wctl0) < ctl(bctl1)) setCtlVal(wctl0,ctl(bctl1)); if (ctl(wctl1) < ctl(bctl1)) setCtlVal(wctl1,ctl(bctl1)); break; case 74: if (ctl(bctl0) > ctl(wctl0)) setCtlVal(bctl0,ctl(wctl0)); if (ctl(bctl1) > ctl(wctl0)) setCtlVal(bctl1,ctl(wctl0)); if (ctl(wctl1) < ctl(wctl0)) setCtlVal(wctl1,ctl(wctl0)); break; case 75: if (ctl(bctl0) > ctl(wctl1)) setCtlVal(bctl0,ctl(wctl1)); if (ctl(bctl1) > ctl(wctl1)) setCtlVal(bctl1,ctl(wctl1)); if (ctl(wctl0) > ctl(wctl1)) setCtlVal(wctl0,ctl(wctl1)); break; } } if (n==77) { if (ctl(77)==0) { setCtlVal(bctl0,0); setCtlVal(bctl1,0); setCtlVal(wctl0,255); setCtlVal(wctl1,255); setCtlText(77, "All"); } else { setCtlVal(bctl0,0); setCtlVal(bctl1,127); setCtlVal(wctl0,127); setCtlVal(wctl1,255); setCtlText(77, "Midtones"); } } if (n==78) setCtlText(78, ctl(78) ? "Enabled" : "Off"); if (n==2 && ctl(2)==100) enableCtl(7,3); if (n==7 && e==FME_VALUECHANGED) setCtlRange(2, -40, 100 + ctl(7)); if (n==10) { switch(ctl(10)) { case 1: setCtlText(10, "Normal"); if ((imageMode == RGBMode) || (imageMode == RGB48Mode)) enableCtl(6, 3); jTemp = ctl(6); setCtlVal(6,j0); j0 = jTemp; break; case 2: setCtlText(10, "Grayscale Only"); enableCtl(6, 1); break; case 0: setCtlText(10, "Color Only"); enableCtl(6, 3); jTemp = ctl(6); setCtlVal(6,j0); j0 = jTemp; break; } } if (n==37) setCtlText(37, ctl(37) ? "Enabled" : "Off"); else if (n==39) setCtlText(39, ctl(39) ? "Hide" : "Show"); if (ctl(3)) { // gaussian blur enableCtl(2, 1); enableCtl(6, 1); enableCtl(4, 1); enableCtl(31, 1); enableCtl(32, 1); enableCtl(33, 1); enableCtl(34, 1); enableCtl(35, 1); enableCtl(36, 1); enableCtl(37, 1); enableCtl(39, 1); enableCtl(72, 1); enableCtl(73, 1); enableCtl(74, 1); enableCtl(75, 1); enableCtl(77, 1); enableCtl(78, 1); } else { enableCtl(2, 3); if (((imageMode == RGBMode) || (imageMode == RGB48Mode)) && (ctl(10) < 2)) enableCtl(6, 3); enableCtl(4, 3); enableCtl(31, 3); enableCtl(32, 3); enableCtl(33, 3); enableCtl(34, 3); enableCtl(35, 3); enableCtl(36, 3); enableCtl(37, 3); enableCtl(39, 3); enableCtl(72, 3); enableCtl(73, 3); enableCtl(74, 3); enableCtl(75, 3); enableCtl(77, 3); enableCtl(78, 3); } 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) || (n==54 && (e==FME_CUSTOMEVENT))) // Reset { setCtlVal(0,100); setCtlVal(2,30); setCtlRange(2, -40, 100); setCtlVal(3,0); setCtlVal(4,0); setCtlVal(5,0); if ((imageMode == RGBMode) || (imageMode == RGB48Mode)) setCtlVal(6,0); setCtlVal(7,0); setCtlVal(10,1); setCtlVal(31,0); setCtlVal(32,100); setCtlVal(33,0); setCtlVal(34,0); setCtlVal(35,100); setCtlVal(36,0); setCtlVal(37,1); setCtlVal(39,0); setCtlVal(72,0); setCtlVal(73,127); setCtlVal(74,127); setCtlVal(75,255); setCtlVal(77,1); setCtlVal(78,1); setCtlVal(53,0); setCtlVal(54,0); triggerEvent(54, FME_CLICKED, 0); j0 = ctl(6); if (ctlEnabled(10) != 1) triggerEvent(10, FME_CLICKED, 0); // ***AFTER*** 54 j0 = getCtlRange(6, 1); triggerEvent(37, FME_CLICKED, 0); triggerEvent(39, FME_CLICKED, 0); triggerEvent(77, FME_CLICKED, 0); triggerEvent(78, FME_CLICKED, 0); triggerEvent(53, FME_CLICKED, 0); } } if (e==FME_INIT) // only works on the full-size image setZoom(-888); if (e==FME_SIZE) setZoom(-888); return false; } ForEveryTile: { int C=imageMode (double)minD) radius = (double)minD; //rc = (int)ceil(radius); if (radiusS > (double)minD) radiusS = (double)minD; //rcS = (int)ceil(radiusS); if (radiusH > (double)minD) radiusH = (double)minD; //rcH = (int)ceil(radiusH); if (doingProxy) { // save the preview dimensions k0 = X; k1 = Y; x0 = radius; y0 = radiusS; y1 = radiusH; } else if ((radius == 0) && (hasMask == 0)) // no blur, no mask abort(); if (radius*(double)scaleFactor < 10) snprintf(str2, 3, "%f", radius*(double)scaleFactor); else sprintf(str2, "%d", (int)(radius*(double)scaleFactor)); if (radius < 10) snprintf(str3, 3, "%f", radius); else sprintf(str3, "%d", (int)radius); strcat(str4, str2); strcat(str4, " / "); strcat(str4, str3); strcat(str4, " px"); setCtlText(1, str4); strcpy(str4, ""); sprintf(str1, "Blend Ranges: %d-%d %d-%d", ctl(72), ctl(73), ctl(74), ctl(75)); setCtlText(70, str1); // mode: 0 = grayscale, 1 = RGB “Grayscale Only,” 2 = RGB “Normal,” 3 = RGB “Color Only.” // Array(2) is the new src, modified by Lighten/Darken. // Array(2,x,y,0) is a virtual Y channel when mode = 1 (same as grayscale when mode = 0). // In “Grayscale Only” mode, all changes target the virtual Y channel to minimize runtime calculations, // and the color components of src (Cb and Cr) are added back at the very end. // Array(2,x,y,3) is an unmodified Y channel used by the dark/light mixer and histogram (beyond zmax). if ((imageMode==GrayScaleMode) || (imageMode==Gray16Mode)) mode = 0; else if (ctl(10)==2) // “Grayscale Only” mode = 1; else if (ctl(10)==1) // “Normal” mode = 2; else // “Color Only” mode = 3; zmax = ((mode < 2) ? 0 : 2); allocArray(2, X, Y, 4, 2); // the new src plus unmodified Y channel for (y=y_start; y 0)) { // begin masks ////////// masks ////////// for (y=y_start; y twH) putArray(0,x,y,1, 0); } } if (radiusS + radiusH > 0) { // can blur ////////// reduce masks ////////// if (!doingProxy) { Xnew = k0; // scale to the preview dimensions Ynew = k1; for (y=y_start; y 0.0) { // can blur qr = (z==zz0 ? radiusS : radiusH); b0 = 1.57825 + 2.44413*qr + 1.4281*qr*qr + 0.422205*qr*qr*qr; b1 = 2.44413*qr + 2.85619*qr*qr + 1.26661*qr*qr*qr; b2 = -(1.4281*qr*qr + 1.26661*qr*qr*qr ); b3 = 0.422205*qr*qr*qr; b1_b0 = b1/b0; b2_b0 = b2/b0; b3_b0 = b3/b0; BB = 1.0 - (b1_b0+b2_b0+b3_b0); for (y=y_start; yx_start; x--) { wn = BB*((double)getArray(0,x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); wn3=wn2; wn2=wn1; wn1=wn; } // for x for (x=x_start; xx_end_new-2-2*rcN; x--) // chill down forward { wn = BB*((double)getArray(0,x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); t2set(x,y,0, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for x // warmup backward - no write for (x=x_end_new-1-2*rcN; x=x_start; x--) // backward pass { wn = BB*(double)(tget(x,y,0)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); putArray(0,x,y,z, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for x } // for y // NOW DO COLUMNS for (x=x_start; xy_start; y--) { wn = BB*((double)getArray(0,x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); wn3=wn2; wn2=wn1; wn1=wn; } // for y for (y=y_start; yy_end_new-2-2*rcN; y--) // chill down forward { wn = BB*((double)getArray(0,x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); t2set(x,y,0, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for y // warmup backward - no write for (y=y_end_new-1-2*rcN; y=y_start; y--) // backward pass { wn = BB*(double)(tget(x,y,0)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); if (!doingProxy) t3set(x,y,z-2, (int)wn); // enlargement else putArray(0,x,y,z, (int)wn); // no enlargement wn3=wn2; wn2=wn1; wn1=wn; } // for y } // for x } // can blur } // for z ////////// enlarge masks ////////// if (!doingProxy) { Xold = Xnew; Yold = Ynew; Xnew = (X*X)/(Xnew); // enlarge to original size Ynew = (Y*Y)/(Ynew); for (y=y_start; y 0) && (mode < 3)) { for (z=0; z<=zmax; z++) { // apply curve before generating the unsharp mask bg = (double)getArray(2,x,y,z); fg = pow((bg/dC), curveS) * dC; fg = alpha4*bg + (1.0-alpha4)*fg; putArray(2,x,y,z, (int)fg); } } alpha4 = fmin(fmax((double)getArray(0,x,y,1)/dC, 0.0), 1.0); if (ctl(37) && (ctl(36) > 0) && (mode < 3)) { for (z=0; z<=zmax; z++) { // apply curve before generating the unsharp mask bg = (double)getArray(2,x,y,z); fg = (1.0 - pow(1.0 - (bg/dC), curveH)) * dC; // inverted fg = alpha4*bg + (1.0-alpha4)*fg; putArray(2,x,y,z, (int)fg); } } for (z=0; z<=zmax; z++) pset(x,y,z, getArray(2,x,y,z)); } } } // end masks //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // the unsharp mask process if (!ctl(39)) { // begin USM ////////// reduce ////////// if (!doingProxy) { Xnew = k0; // scale to the preview dimensions Ynew = k1; for (y=y_start; yx_start; x--) { wn = BB*(double)(pget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); // src wn3=wn2; wn2=wn1; wn1=wn; } // for x for (x=x_start; xx_end_new-2-2*rc; x--) // chill down forward { wn = BB*(double)(pget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); // src t2set(x,y,z, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for x // warmup backward - no write for (x=x_end_new-1-2*rc; x=x_start; x--) // backward pass { wn = BB*(double)(tget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); pset(x,y,z, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for x } // for y // NOW DO COLUMNS for (x=x_start; xy_start; y--) { wn = BB*(double)(pget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); wn3=wn2; wn2=wn1; wn1=wn; } // for y for (y=y_start; yy_end_new-2-2*rc; y--) // chill down forward { wn = BB*(double)(pget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); t2set(x,y,z, (int)wn); wn3=wn2; wn2=wn1; wn1=wn; } // for y // warmup backward - no write for (y=y_end_new-1-2*rc; y=y_start; y--) // backward pass { wn = BB*(double)(tget(x,y,z)) + (b1_b0*wn1 + b2_b0*wn2 + b3_b0*wn3); if (!doingProxy) t3set(x,y,z, (int)wn); // enlargement else pset(x,y,z, (int)wn); // no enlargement wn3=wn2; wn2=wn1; wn1=wn; } // for y } // for x } // for z ////////// enlarge ////////// if (!doingProxy) { Xold = Xnew; Yold = Ynew; Xnew = (X*X)/(Xnew); // enlarge to original size Ynew = (Y*Y)/(Ynew); for (y=y_start; y0) || (ctl(73)>0) || (ctl(74)<255) || (ctl(75)<255)) ) { for (y=y_start; y wc1)) alpha = 0.0; else if ((bg >= bc0) && (bg < bc1)) alpha = (bg - bc0)/(bc1 - bc0); else if ((bg > wc0) && (bg <= wc1)) alpha = (wc1 - bg)/(wc1 - wc0); for (z=0; z<=zmax; z++) { bg2 = (double)src(x,y,z); fg2 = (double)pget(x,y,z); fg2 = alpha*fg2 + (1-alpha)*bg2; // blend range pset(x,y,z, (int)fg2); } } } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// ////////// darken/lighten mixer ////////// if ((ctl(4) != 0) && !ctl(3)) { for (y=y_start; y 0) && (bg > fg))) { if (mode < 2) bg2 = (double)getArray(2,x,y,3)/dC; else bg2 = (double)src(x,y,z)/dC; // the real src fg2 = (double)pget(x,y,z)/dC; fg2 = alpha2*bg2 + (1-alpha2)*fg2; pset(x,y,z, (int)(fg2*dC)); } } } } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// ////////// show masks ////////// if (!ctl(3)) { // begin masks for (y=y_start; y 0) { if (gg < t3get(x,y,0)) { // blend the highlight and shadow masks rr = C; bb = C - abs(t3get(x,y,0) - gg); } else if (t3get(x,y,0) < gg) { rr = C - abs(t3get(x,y,0) - gg); bb = C; } else { rr = C; bb = C; } gg = min(t3get(x,y,0), gg); pset(x,y,0,rr); pset(x,y,1,gg); pset(x,y,2,bb); } else pset(x,y,0, min(t3get(x,y,0), gg)); } } } } // end masks //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// ////////// histograms ////////// allocArray(10, 2, 256, 0, 4); fillArray(10, 0); cWhite = RGB(255,255,255); cLGray = RGB(200,200,200); cGray = RGB(180,180,180); cDGray = RGB(80,80,80); cBlack = RGB(0,0,0); for (y=y_start; y nMax) nMax = n; if (!ctl(39)) { // show mask if (mode < 2) Yv = (double)pget(x,y,0); else Yv = (double)pget(x,y,0)*0.299 + (double)pget(x,y,1)*0.587 + (double)pget(x,y,2)*0.114; Yv *= to8bit; xx = (int)Yv; n = getArray(10,1,xx,0) + 1; putArray(10,1,xx,0, n); if (n > nMax) nMax = n; } } } if (ctlEnabled(41)==0) { if (nMax > (X*Y*4)/256) nMax = (X*Y*4)/256; startSetPixel(40); setRectFrame(0, 0, 258, 102, cGray); setRectFill(1, 1, 257, 101, cLGray); if (nMax > 0) { for (i=0; i<256; i++) { xx0 = i+1; xx1 = i+1+1; hh0 = 100-min((int)((double)getArray(10,0,i,0)*(100.0/(double)nMax)),100)+1; hh1 = 100-min((int)((double)getArray(10,1,i,0)*(100.0/(double)nMax)),100)+1; hh2 = 100+1; if (hh0 < hh1) { setRectFill(xx0, hh0, xx1, hh1, cWhite); setRectFill(xx0, hh1, xx1, hh2, cDGray); } else { setRectFill(xx0, hh1, xx1, hh0, cBlack); setRectFill(xx0, hh0, xx1, hh2, cDGray); } } } endSetPixel(40); } ////////// color ////////// if ((mode > 0) && !ctl(3) && !ctl(39)) { for (y=y_start; y