home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 1992 August / info-mac-1992.iso / Source / Pascal / Image / Color.p < prev    next >
Encoding:
Text File  |  1991-09-16  |  24.7 KB  |  1,092 lines  |  [TEXT/PJMM]

  1. unit Color;
  2.  
  3. interface
  4.  
  5.     uses
  6.         QuickDraw, Palettes, Picker, PrintTraps, globals, Utilities, Graphics;
  7.  
  8.     procedure DoMouseDownInLUT (event: EventRecord);
  9.     procedure PasteColor;
  10.     procedure ShowRGBValues (index: integer);
  11.     procedure InvertPalette;
  12.     procedure UpdateGrayMap;
  13.     procedure ResetGraymap;
  14.     procedure DrawGrayMap;
  15.     procedure DoMouseDownInGrayMap;
  16.     procedure EnableThresholding (level: integer);
  17.     procedure DrawLUT;
  18.     procedure UpdateColors;
  19.  
  20.  
  21.  
  22. implementation
  23.  
  24.  
  25.     function GetColorIndex: integer;
  26.  {*****This routine needs work***}
  27.         var
  28.             ColorWidth: integer;
  29.             CLUTIndex: LongInt;
  30.     begin
  31.         ColorWidth := 1;
  32.         CLUTIndex := 255 - ForegroundIndex;
  33.         with info^ do
  34.             if (CLUTIndex < ColorStart) or (CLUTIndex > (ColorStart + nColors * ColorWidth)) then begin
  35.                     GetColorIndex := NoColor
  36.                 end
  37.             else
  38.                 GetColorIndex := (CLUTIndex - ColorStart) div ColorWidth;
  39.     end;
  40.  
  41.  
  42.     procedure EditColor;
  43.         var
  44.             where: point;
  45.             inRGBColor, OutRGBColor: RGBColor;
  46.             index: integer;
  47.     begin
  48.         with info^ do begin
  49.                 index := GetColorIndex;
  50.                 if index = NoColor then
  51.                     exit(EditColor);
  52.                 with inRGBColor do begin
  53.                         red := RedLUT[index];
  54.                         green := GreenLUT[index];
  55.                         blue := BlueLUT[index];
  56.                     end;
  57.                 outRGBColor := inRGBColor;
  58.                 where.h := 0;
  59.                 where.v := 0;
  60.                 InitCursor;
  61.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then begin
  62.                         with outRGBColor do begin
  63.                                 RedLUT[index] := red;
  64.                                 GreenLUT[index] := green;
  65.                                 BlueLUT[index] := blue;
  66.                             end;
  67.                         info^.changes := true;
  68.                     end;
  69.                 UpdateColors;
  70.             end; {with}
  71.     end;
  72.  
  73.     procedure EditSliceColor;
  74.         var
  75.             where: point;
  76.             inRGBColor, OutRGBColor: RGBColor;
  77.     begin
  78.         inRGBColor := SliceColor;
  79.         outRGBColor := inRGBColor;
  80.         where.h := 0;
  81.         where.v := 0;
  82.         InitCursor;
  83.         if GetColor(where, 'Pick a new color...', inRGBColor, outRGBColor) then
  84.             SliceColor := outRGBColor;
  85.         DrawDensitySlice(false);
  86.     end;
  87.  
  88.  
  89.     procedure RotateColors;
  90.         var
  91.             vstart, i, j, delta: integer;
  92.             loc: point;
  93.             TempTable: MyCSpecArray;
  94.     begin
  95.         with info^ do begin
  96.                 SetPort(LUTWindow);
  97.                 GetMouse(loc);
  98.                 vstart := loc.v;
  99.                 repeat
  100.                     GetMouse(loc);
  101.                     delta := vstart - loc.v;
  102.                     for i := 1 to 254 do begin {0 is resevred for white and 255 for black}
  103.                             j := i + delta;
  104.                             if j > 254 then
  105.                                 j := j - 254;
  106.                             if j > 254 then
  107.                                 j := 254;
  108.                             if j < 1 then
  109.                                 j := j + 254;
  110.                             if j < 1 then
  111.                                 j := 1;
  112.                             TempTable[i] := cTable[j]
  113.                         end;
  114.                     cTable := TempTable;
  115.                     LoadLUT(cTable);
  116.                     vstart := loc.v;
  117.                 until not button;
  118.             end;
  119.     end;
  120.  
  121.  
  122.     procedure ShowLUTValues (tStart, tEnd: integer);
  123.         var
  124.             tPort: GrafPtr;
  125.     begin
  126.         with info^ do begin
  127.                 GetPort(tPort);
  128.                 SetPort(ResultsWindow);
  129.                 TextSize(9);
  130.                 TextFont(Monaco);
  131.                 TextMode(SrcCopy);
  132.                 MoveTo(xValueLoc, ValuesVStart);
  133.                 if DensityCalibrated then begin
  134.                         DrawReal(cvalue[tStart], 5, 2);
  135.                         DrawString(' (');
  136.                         DrawReal(tStart, 3, 0);
  137.                         DrawString(')');
  138.                     end
  139.                 else
  140.                     DrawReal(tStart, 3, 0);
  141.                 DrawString('    ');
  142.                 MoveTo(xValueLoc, ValuesVStart + 10);
  143.                 if DensityCalibrated then begin
  144.                         DrawReal(cvalue[tEnd], 5, 2);
  145.                         DrawString(' (');
  146.                         DrawReal(tEnd, 3, 0);
  147.                         DrawString(')');
  148.                     end
  149.                 else
  150.                     DrawReal(tEnd, 3, 0);
  151.                 DrawString('    ');
  152.                 SetPort(tPort);
  153.             end;
  154.     end;
  155.  
  156.  
  157.     procedure DrawRGB (index: integer);
  158.         var
  159.             rStr, gStr, bStr: str255;
  160.             TempRGB: rgbColor;
  161.             i, entry: integer;
  162.  
  163.         procedure Convert (n: integer; var str: str255);
  164.             var
  165.                 i: integer;
  166.         begin
  167.             RealToString(n, 3, 0, str);
  168.             for i := 1 to 3 do
  169.                 if str[i] = ' ' then
  170.                     str[i] := '0';
  171.         end;
  172.  
  173.     begin
  174.         TempRGB := cScreenPort^.portPixMap^^.pmTable^^.ctTable[index].rgb;
  175.         with TempRGB do begin
  176.                 Convert(band(bsr(red, 8), 255), rStr);
  177.                 Convert(band(bsr(green, 8), 255), gStr);
  178.                 Convert(band(bsr(blue, 8), 255), bStr);
  179.                 DrawString(concat(rStr, ' ', gStr, ' ', bStr));
  180.             end;
  181.     end;
  182.  
  183.  
  184.     procedure ShowRGBValues (index: integer);
  185.         var
  186.             tPort: GrafPtr;
  187.             vloc: integer;
  188.     begin
  189.         with info^ do begin
  190.                 GetPort(tPort);
  191.                 SetPort(ResultsWindow);
  192.                 TextSize(9);
  193.                 TextFont(Monaco);
  194.                 TextMode(SrcCopy);
  195.                 vloc := ValuesVStart;
  196.                 MoveTo(xValueLoc, vloc);
  197.                 DrawLong(index);
  198.                 DrawString('    ');
  199.                 if Info^.DensityCalibrated then begin
  200.                         vloc := vloc + 10;
  201.                         MoveTo(xValueLoc, vloc);
  202.                         DrawReal(cvalue[index], 1, precision);
  203.                         DrawString('    ');
  204.                     end;
  205.                 vloc := vloc + 10;
  206.                 MoveTo(xValueLoc, vloc);
  207.                 DrawRGB(index);
  208.                 DrawString('    ');
  209.                 SetPort(tPort);
  210.             end;
  211.     end;
  212.  
  213.  
  214.     function GetVLoc: integer;
  215.         var
  216.             loc: point;
  217.             vloc: integer;
  218.     begin
  219.         GetMouse(loc);
  220.         vloc := loc.v;
  221.         if vloc > 255 then
  222.             vloc := 255;
  223.         if vloc <= 0 then
  224.             vloc := 0;
  225.         GetVLoc := vloc;
  226.     end;
  227.  
  228.  
  229.     procedure UpdateThreshold;
  230.         var
  231.             level: integer;
  232.     begin
  233.         DrawLabels('Thresh:', '', '');
  234.         SetPort(LUTWindow);
  235.         with info^ do
  236.             repeat
  237.                 level := GetVLoc;
  238.                 if level <= 255 then begin
  239.                         p1x := level;
  240.                         p2x := level;
  241.                         UpdateGrayMap;
  242.                         SetGrayScaleLUT;
  243.                     end;
  244.                 Show1Value(p1x, NoValue);
  245.             until not Button;
  246.     end;
  247.  
  248.  
  249.     procedure UpdateDensitySlice;
  250.         var
  251.             mloc, saveloc, width, delta: integer;
  252.             adjust: (lower, upper, both);
  253.     begin
  254.         DrawLabels('Lower:', 'Upper:', '');
  255.         SetPort(LUTWindow);
  256.         mloc := getvloc;
  257.         saveloc := mloc;
  258.         width := SliceEnd - SliceStart + 1;
  259.         adjust := lower;
  260.         if mloc > (SliceStart + width div 3) then
  261.             adjust := both;
  262.         if mloc > (SliceEnd - width div 3) then
  263.             adjust := upper;
  264.         while button do begin
  265.                 width := SliceEnd - SliceStart + 1;
  266.                 mloc := getvloc;
  267.                 delta := mloc - saveloc;
  268.                 saveloc := mloc;
  269.                 case adjust of
  270.                     lower: 
  271.                         begin
  272.                             SliceStart := mloc;
  273.                             if SliceStart < 1 then
  274.                                 SliceStart := 1;
  275.                             if SliceStart > SliceEnd then
  276.                                 SliceStart := SliceEnd;
  277.                         end;
  278.                     upper: 
  279.                         begin
  280.                             SliceEnd := mloc;
  281.                             if SliceEnd > 254 then
  282.                                 SliceEnd := 254;
  283.                             if SliceEnd < SliceStart then
  284.                                 SliceEnd := SliceStart;
  285.                         end;
  286.                     both: 
  287.                         begin
  288.                             if mloc <= 1 then begin
  289.                                     SliceStart := 1;
  290.                                     SliceEnd := width;
  291.                                 end
  292.                             else if mloc >= 254 then begin
  293.                                     SliceEnd := 254;
  294.                                     SliceStart := 254 - width + 1;
  295.                                 end
  296.                             else if ((SliceStart + delta) >= 1) and ((SliceEnd + delta) <= 254) then begin
  297.                                     SliceStart := SliceStart + delta;
  298.                                     SliceEnd := SliceEnd + delta;
  299.                                 end;
  300.                         end;
  301.                 end; {case}
  302.                 DrawDensitySlice(OptionKeyDown);
  303.                 ShowLUTValues(SliceStart, SliceEnd);
  304.             end; {while}
  305.         DrawDensitySlice(false)
  306.     end;
  307.  
  308.  
  309.     procedure EditExtraColors (entry: integer);
  310.         var
  311.             where: point;
  312.             inRGBColor, OutRGBColor: RGBColor;
  313.     begin
  314.         if (entry <> WhiteIndex) and (entry <> BlackIndex) then begin
  315.                 inRGBColor := ExtraColors[entry];
  316.                 outRGBColor := inRGBColor;
  317.                 where.h := 0;
  318.                 where.v := 0;
  319.                 InitCursor;
  320.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then
  321.                     with info^ do begin
  322.                             ExtraColors[entry] := OutRGBColor;
  323.                             changes := true;
  324.                             LoadLUT(cTable);
  325.                         end
  326.             end
  327.         else
  328.             PutMessage('Sorry, but you can not edit white or black.');
  329.     end;
  330.  
  331.  
  332.     function GetColorFromPalette (DoubleClick: boolean): integer;
  333.         var
  334.             mloc, color, i: integer;
  335.             loc: point;
  336.     begin
  337.         SetPort(LUTWindow);
  338.         GetMouse(loc);
  339.         if loc.v > 255 then begin
  340.                 color := 0;
  341.                 for i := 1 to nExtraColors + 2 do
  342.                     if PtInRect(loc, ExtraColorsRect[i]) then
  343.                         Color := ExtraColorsEntry[i];
  344.                 if DoubleClick then
  345.                     EditExtraColors(color);
  346.                 GetColorFromPalette := color;
  347.             end
  348.         else
  349.             GetColorFromPalette := loc.v;
  350.     end;
  351.  
  352.  
  353.     procedure AdjustLUT;
  354.         const
  355.             MinWidth = 8;
  356.         var
  357.             mloc, saveloc, width, delta: integer;
  358.             adjust: (lower, upper, both);
  359.     begin
  360.         with info^ do begin
  361.                 DrawLabels('Lower:', 'Upper:', '');
  362.                 SetPort(LUTWindow);
  363.                 mloc := getvloc;
  364.                 saveloc := mloc;
  365.                 width := ColorEnd - ColorStart + 1;
  366.                 adjust := lower;
  367.                 if mloc > (ColorStart + width div 3) then
  368.                     adjust := both;
  369.                 if mloc > (ColorEnd - width div 3) then
  370.                     adjust := upper;
  371.                 while button do begin
  372.                         mloc := getvloc;
  373.                         delta := mloc - saveloc;
  374.                         saveloc := mloc;
  375.                         case adjust of
  376.                             lower: 
  377.                                 begin
  378.                                     ColorStart := mloc;
  379.                                     if ColorStart > (ColorEnd - MinWidth) then
  380.                                         ColorStart := ColorEnd - MinWidth;
  381.                                 end;
  382.                             upper: 
  383.                                 begin
  384.                                     ColorEnd := mloc;
  385.                                     if ColorEnd < (ColorStart + MinWidth) then
  386.                                         ColorEnd := ColorStart + MinWidth;
  387.                                 end;
  388.                             both: 
  389.                                 begin
  390.                                     width := ColorEnd - ColorStart + 1;
  391.                                     if mloc <= 0 then begin
  392.                                             ColorStart := 0;
  393.                                             ColorEnd := width - 1;
  394.                                         end
  395.                                     else if mloc >= 255 then begin
  396.                                             ColorEnd := 255;
  397.                                             ColorStart := 255 - width + 1;
  398.                                         end
  399.                                     else if ((ColorStart + delta) >= 0) and ((ColorEnd + delta) <= 255) then begin
  400.                                             ColorStart := ColorStart + delta;
  401.                                             ColorEnd := ColorEnd + delta;
  402.                                         end;
  403.                                 end;
  404.                         end;
  405.                         UpdateColors;
  406.                         ShowLUTValues(ColorStart, ColorEnd);
  407.                     end;
  408.             end;
  409.     end;
  410.  
  411.  
  412.     procedure DoMouseDownInLUT (event: EventRecord);
  413.         var
  414.             color: integer;
  415.             DoubleClick: boolean;
  416.     begin
  417.         with info^ do begin
  418.                 if CurrentTool = PickerTool then
  419.                     DoubleClick := (TickCount - LutTime) < GetDblTime
  420.                 else
  421.                     DoubleClick := false;
  422.                 LutTime := TickCount;
  423.                 if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  424.                         color := GetColorFromPalette(DoubleClick);
  425.                         if (CurrentTool = eraser) or OptionKeyDown then
  426.                             SetBackgroundColor(color)
  427.                         else
  428.                             SetForegroundColor(color);
  429.                         if not DoubleClick then
  430.                             exit(DoMouseDownInLUT);
  431.                     end;
  432.                 if Thresholding then begin
  433.                         UpdateThreshold;
  434.                         exit(DoMouseDownInLUT)
  435.                     end;
  436.                 if DoubleClick then begin
  437.                         EditSliceColor;
  438.                         exit(DoMouseDownInLUT)
  439.                     end;
  440.                 if DensitySlicing then begin
  441.                         if DoubleClick and (CurrentTool = PickerTool) then
  442.                             EditSliceColor
  443.                         else if (CurrentTool = LutTool) or (CurrentTool = Wand) then
  444.                             UpdateDensitySlice;
  445.                         exit(DoMouseDownInLUT)
  446.                     end;
  447.                 if nColors = 0 then
  448.                     exit(DoMouseDownInLUT);
  449.                 if (LUTMode <> PseudoColor) and not DoubleClick then begin
  450.                         if pDeltaX <> 0 then
  451.                             RotateColors;
  452.                         exit(DoMouseDownInLUT)
  453.                     end;
  454.                 if (CurrentTool = PickerTool) and DoubleClick then begin
  455.                         if LUTMode <> PseudoColor then
  456.                             exit(DoMouseDownInLUT);
  457.                         EditColor;
  458.                         exit(DoMouseDownInLUT)
  459.                     end;
  460.                 AdjustLUT;
  461.             end; {with}
  462.     end;
  463.  
  464.  
  465.     procedure PasteColor;
  466. {*******Needs Work*****}
  467.         var
  468.             CurrentColorIndex, ClipColorIndex: integer;
  469.     begin
  470.         exit(PasteColor);
  471.         with info^ do
  472.             if (CurrentTool = PickerTool) and (LUTMode = PseudoColor) then begin
  473.                     RedLUT[CurrentColorIndex] := RedLUT[ClipColorIndex];
  474.                     GreenLUT[CurrentColorIndex] := GreenLUT[ClipColorIndex];
  475.                     BlueLUT[CurrentColorIndex] := BlueLUT[ClipColorIndex];
  476.                     UpdateColors;
  477.                 end
  478.             else
  479.                 beep;
  480.     end;
  481.  
  482.  
  483.     procedure InvertPalette;
  484.         var
  485.             TempRed, TempGreen, TempBlue: LutArray;
  486.             i, LastColor: integer;
  487.             TempTable: MyCSpecArray;
  488.     begin
  489.         with info^ do begin
  490.                 if LutMode = PseudoColor then begin
  491.                         TempRed := RedLUT;
  492.                         TempGreen := GreenLUT;
  493.                         TempBlue := BlueLUT;
  494.                         LastColor := ncolors - 1;
  495.                         for i := 0 to LastColor do begin
  496.                                 RedLUT[i] := TempRed[LastColor - i];
  497.                                 GreenLUT[i] := TempGreen[LastColor - i];
  498.                                 BlueLUT[i] := TempBlue[LastColor - i];
  499.                             end;
  500.                         UpdateColors;
  501.                     end
  502.                 else begin
  503.                         TempTable := cTable;
  504.                         for i := 1 to 254 do
  505.                             cTable[i] := TempTable[255 - i];
  506.                         LoadLUT(cTable);
  507.                     end;
  508.             end; {with}
  509.     end;
  510.  
  511.  
  512.  
  513.     procedure UpdateGrayMap;
  514.         const
  515.             gmRectArea = 4096.0; {64x64}
  516.             max = 4177920;
  517.         var
  518.             tPort: GrafPtr;
  519.             r: rect;
  520.             x, y, i, h1, h2, h3, v1, v2, v3, dx, dy: integer;
  521.             xcenter, ycenter, brightness, islope, thumb: integer;
  522.             table: LookupTable;
  523.             hrect: rect;
  524.             slope: extended;
  525.             area, value, sum: LongInt;
  526.     begin
  527.         GetPort(tPort);
  528.         SetPort(GrayMapWindow);
  529.         PenNormal;
  530.         EraseRect(GrayMapRect2);
  531.         FrameRect(GrayMapRect);
  532.         with info^ do
  533.             if LutMode = CustomGrayscale then begin
  534.                     GetLookupTable(table);
  535.                     MoveTo(gmRectLeft, gmRectBottom - 1);
  536.                     for i := 0 to 63 do begin
  537.                             x := gmRectLeft + i;
  538.                             y := gmRectBottom - table[i * 4] div 4 - 1;
  539.                             LineTo(x, y);
  540.                         end;
  541.                     EraseRect(gmSlide1i);
  542.                     EraseRect(gmSlide2i);
  543.                 end
  544.             else begin
  545.                     h1 := gmRectLeft + p1x div 4;
  546.                     v1 := gmRectBottom - 1 - (p1y div 4);
  547.                     h2 := gmRectLeft + p2x div 4;
  548.                     v2 := gmRectBottom - 1 - (p2y div 4);
  549.                     MoveTo(gmRectLeft, gmRectBottom - 1);
  550.                     LineTo(h1, v1);
  551.                     LineTo(h2, v2);
  552.                     LineTo(gmRectRight - 1, gmRectTop);
  553.                     SetRect(hrect, h1 - 1, v1 - 1, h1 + 2, v1 + 2);
  554.                     PaintRect(hrect); {First handle}
  555.                     SetRect(hrect, h2 - 1, v2 - 1, h2 + 2, v2 + 2);
  556.                     PaintRect(hrect); {Last handle}
  557.                     dx := p2x - p1x;
  558.                     dy := p2y - p1y;
  559.                     xcenter := p1x + dx div 2;
  560.                     ycenter := p1y + dy div 2;
  561.                     h3 := gmRectLeft + xcenter div 4;
  562.                     v3 := gmRectBottom - 1 - (ycenter div 4);
  563.                     SetRect(hrect, h3 - 1, v3 - 1, h3 + 2, v3 + 2);
  564.                     PaintRect(hrect); {Center handle}
  565.                     thumb := gmSlideHeight - 2;
  566.                     i := 0;
  567.                     sum := 0;
  568.                     repeat
  569.                         value := ctable[i].rgb.red;
  570.                         value := band(value, 65535);
  571.                         sum := sum + value;
  572.                         i := i + 4;
  573.                     until i > 255;
  574.                     brightness := trunc((sum / max) * (gmSlideWidth - thumb - 2.0));
  575.                     gmSlide1Loc := brightness;
  576.                     with gmSlide1 do
  577.                         SetRect(hrect, left + brightness + 1, top + 1, left + brightness + thumb + 1, top + thumb + 1);
  578.                     EraseRect(gmSlide1i);
  579.                     PaintRect(hrect);  {Thumb for brightness control}
  580.                     if dx <> 0 then
  581.                         slope := dy / dx
  582.                     else
  583.                         slope := 1000.0;
  584.                     if slope > 1.0 then begin
  585.                             if dy <> 0 then
  586.                                 slope := 2.0 - dx / dy
  587.                             else
  588.                                 slope := 2.0;
  589.                         end;
  590.                     islope := trunc(slope * 0.5 * (gmSlideWidth - thumb - 2.0));
  591.                     with gmSlide2 do
  592.                         SetRect(hrect, left + islope + 1, top + 1, left + islope + thumb + 1, top + thumb + 1);
  593.                     EraseRect(gmSlide2i);
  594.                     PaintRect(hrect);  {Thumb for contrast control}
  595.                 end;
  596.         SetPort(tPort);
  597.     end;
  598.  
  599.  
  600.     procedure DrawGrayMap;
  601.         var
  602.             tPort: GrafPtr;
  603.             x, y, i: integer;
  604.             table: LookupTable;
  605.     begin
  606.         GetPort(tPort);
  607.         SetPort(GrayMapWindow);
  608.         PenNormal;
  609.         TextFont(ApplFont);
  610.         TextSize(9);
  611.         with gmSlide1 do
  612.             MoveTo(left - 6, bottom);
  613.         DrawChar('B');
  614.         with gmSlide2 do
  615.             MoveTo(left - 6, bottom);
  616.         DrawChar('C');
  617.         FrameRect(gmSlide1);
  618.         FrameRect(gmSlide2);
  619.         FrameRect(gmIcon1);
  620.         FrameRect(gmIcon2);
  621.         with gmIcon1 do begin
  622.                 MoveTo(left, top + 10);
  623.                 LineTo(left + 5, top + 10);
  624.                 LineTo(left + 12, top + 3);
  625.                 LineTo(left + gmIconWidth - 1, top + 3);
  626.             end;
  627.         with gmIcon2 do begin
  628.                 MoveTo(left, top + 10);
  629.                 LineTo(left + gmIconWidth div 2, top + 10);
  630.                 LineTo(left + gmIconWidth div 2, top + 3);
  631.                 LineTo(left + gmIconWidth - 1, top + 3);
  632.             end;
  633.         UpdateGrayMap;
  634.         GrayMapReady := true;
  635.         SetPort(tPort);
  636.     end;
  637.  
  638.  
  639.     procedure ResetGrayMap;
  640.     begin
  641.         with info^ do begin
  642.                 DisableDensitySlice;
  643.                 p1x := 0;
  644.                 p1y := 0;
  645.                 p2x := 255;
  646.                 p2y := 255;
  647.                 pDeltaX := 256;
  648.                 pDeltaY := 256;
  649.                 SetGrayScaleLUT;
  650.                 LUTMode := Grayscale;
  651.                 if GrayMapReady then
  652.                     UpdateGrayMap;
  653.                 IdentityFunction := true;
  654.                 Thresholding := false;
  655.             end;
  656.     end;
  657.  
  658.  
  659.     procedure FindEndPoints (x, y: integer);
  660.         var
  661.             xintercept: integer;
  662.     begin
  663.         with info^ do begin
  664.                 if pDeltaX = 0 then begin
  665.                         p1x := x;
  666.                         p1y := 0;
  667.                         p2x := x;
  668.                         p2y := 255;
  669.                         exit(FindEndPoints);
  670.                     end;
  671.                 if pDeltaY = 0 then begin
  672.                         p1x := 0;
  673.                         p1y := y;
  674.                         p2x := 255;
  675.                         p2y := y;
  676.                         exit(FindEndPoints);
  677.                     end;
  678.                 p1x := x - y * LongInt(pDeltaX) div pDeltaY;
  679.                 xIntercept := p1x;
  680.                 p1y := 0;
  681.                 if p1x < 0 then begin
  682.                         p1y := -(LongInt(pDeltaY) * p1x) div pDeltaX;
  683.                         p1x := 0;
  684.                     end;
  685.                 p2y := 255;
  686.                 p2x := 255 * LongInt(pDeltaX) div pDeltaY;
  687.                 if xIntercept < 0 then
  688.                     p2x := p2x + xIntercept
  689.                 else
  690.                     p2x := p2x + p1x;
  691.                 if p2x > 255 then begin
  692.                         p2y := 255 - (p2x - 255) * LongInt(pDeltaY) div pDeltaX;
  693.                         p2x := 255;
  694.                     end;
  695.                 if p2x < 0 then
  696.                     p2x := 0;
  697.             end; {with}
  698.     end;
  699.  
  700.  
  701.     procedure ChangeBrightness;
  702.         var
  703.             loc, oldloc, max, HalfMax, thumb, xcenter, ycenter, delta: integer;
  704.             hrect: rect;
  705.  
  706.         function FindLoc: integer;
  707.             var
  708.                 p: point;
  709.                 loc: integer;
  710.         begin
  711.             GetMouse(p);
  712.             loc := p.h - gmSlide1.left - 2;
  713.             if loc < 0 then
  714.                 loc := 0;
  715.             if loc > max + 5 then
  716.                 loc := max + 5;
  717.             FindLoc := loc;
  718.         end;
  719.  
  720.     begin
  721.         with info^ do begin
  722.                 thumb := gmSlideHeight - 2;
  723.                 max := gmSlideWidth - thumb - 2;
  724.                 HalfMax := max div 2;
  725.                 OldLoc := FindLoc;
  726.                 repeat
  727.                     xcenter := p1x + (p2x - p1x) div 2;
  728.                     ycenter := p1y + (p2y - p1y) div 2;
  729.                     loc := FindLoc;
  730.                     delta := gmSlide1Loc + 1 - loc;
  731.                     if pDeltaY <> 0 then begin
  732.                             xcenter := xcenter - delta;
  733.                             if xcenter < 0 then
  734.                                 xcenter := 0;
  735.                             if xcenter > 255 then
  736.                                 xcenter := 255;
  737.                         end;
  738.                     if pDeltaX <> 0 then begin
  739.                             ycenter := ycenter + delta;
  740.                             if ycenter < 0 then
  741.                                 ycenter := 0;
  742.                             if ycenter > 255 then
  743.                                 ycenter := 255;
  744.                         end;
  745.                     FindEndPoints(xcenter, ycenter);
  746.                     UpdateGrayMap;
  747.                     gmFixedSlope := true;
  748.                     SetGrayScaleLUT;
  749.                     gmFixedSlope := false;
  750.                     OldLoc := loc;
  751.                 until not button;
  752.                 IdentityFunction := false;
  753.             end; {with}
  754.     end;
  755.  
  756.  
  757.     procedure ChangeContrast;
  758.         var
  759.             p: point;
  760.             loc, max, HalfMax, thumb, xcenter, ycenter: integer;
  761.             hrect: rect;
  762.             slope: extended;
  763.             str: str255;
  764.     begin
  765.         with info^ do begin
  766.                 thumb := gmSlideHeight - 2;
  767.                 max := gmSlideWidth - thumb - 2;
  768.                 HalfMax := max div 2;
  769.                 xcenter := p1x + pDeltaX div 2;
  770.                 if xcenter > 255 then
  771.                     xcenter := 255;
  772.                 ycenter := p1y + pDeltaY div 2;
  773.                 repeat
  774.                     GetMouse(p);
  775.                     loc := p.h - gmSlide2.left - 2;
  776.                     if loc < 0 then
  777.                         loc := 0;
  778.                     if loc > max then
  779.                         loc := max;
  780.                     if loc <= HalfMax then
  781.                         slope := loc / HalfMax
  782.                     else if loc < max then
  783.                         slope := HalfMax / (max - loc)
  784.                     else
  785.                         slope := 1000.0;
  786.                     RealToString(slope, 1, 2, str);
  787. {ShowMessage(concat(str, cr, long2str(xcenter), cr, long2str(ycenter), cr, long2str(pdeltax), cr, long2str(deltay)));}
  788.                     if slope <= 1.0 then begin
  789.                             pDeltaX := 255;
  790.                             pDeltaY := round(slope * pDeltaX);
  791.                         end
  792.                     else begin
  793.                             pDeltaY := 255;
  794.                             pDeltaX := round(pDeltaY / slope);
  795.                         end;
  796.                     FindEndPoints(xcenter, ycenter);
  797.                     UpdateGrayMap;
  798.                     SetGrayScaleLUT;
  799.                 until not button;
  800.                 IdentityFunction := false;
  801.             end; {with}
  802.     end;
  803.  
  804.  
  805.     procedure ConvertMouseToXY (p: point; var x, y: integer);
  806.     begin
  807.         x := (p.h - gmRectLeft) * 4;
  808.         if x < 0 then
  809.             x := 0;
  810.         if x > 255 then
  811.             x := 255;
  812.         y := (gmRectBottom - p.v) * 4;
  813.         if y < 0 then
  814.             y := 0;
  815.         if y > 255 then
  816.             y := 255;
  817.     end;
  818.  
  819.  
  820.     procedure DoFreehandEditing;
  821.         var
  822.             p: point;
  823.             x1, x2, y, i: integer;
  824.             FirstTime, WasColor: boolean;
  825.     begin
  826.         with info^ do begin
  827.                 WasColor := (LUTMode = custom) or (LUTMode = PseudoColor) or (LUTMode = AppleDefault) or (LUTMode = Spectrum);
  828.                 LUTMode := CustomGrayscale;
  829.                 SetPort(GrayMapWindow);
  830.                 FirstTime := true;
  831.                 while button do begin
  832.                         x1 := x2;
  833.                         GetMouse(p);
  834.                         ConvertMouseToXY(p, x2, y);
  835.                         if x2 > 252 then
  836.                             x2 := 252;
  837.                         if FirstTime then begin
  838.                                 x1 := x2;
  839.                                 FirstTime := false;
  840.                             end;
  841.                         if x2 >= x1 then
  842.                             for i := x1 to x2 + 3 do
  843.                                 with cTable[i].rgb do begin
  844.                                         red := bsl(255 - y, 8);
  845.                                         green := bsl(255 - y, 8);
  846.                                         blue := bsl(255 - y, 8);
  847.                                     end
  848.                         else
  849.                             for i := x1 + 3 downto x2 do
  850.                                 with cTable[i].rgb do begin
  851.                                         red := bsl(255 - y, 8);
  852.                                         green := bsl(255 - y, 8);
  853.                                         blue := bsl(255 - y, 8);
  854.                                     end;
  855.                         DrawGrayMap;
  856.                         LoadLUT(cTable);
  857.                     end;
  858.                 if WasColor then
  859.                     LUTMode := custom;
  860.             end;
  861.     end;
  862.  
  863.  
  864.     procedure DoMouseDownInGrayMap;
  865.         var
  866.             r: rect;
  867.             x, y, p1Dist, p2Dist, x1, y1: integer;
  868.             mode: (StartPoint, EndPoint, Brightness);
  869.             p: point;
  870.             pressed: boolean;
  871.  
  872.         procedure DoFixup;
  873.         begin
  874.             with info^ do
  875.                 if ((p1x = 0) and (p2x = 0)) or ((p1x = 255) and (p2x = 255)) then begin
  876.                         p1y := 0;
  877.                         p2y := 255;
  878.                     end;
  879.         end;
  880.  
  881.     begin
  882.         DisableDensitySlice;
  883.         if OptionKeyDown then begin
  884.                 DoFreehandEditing;
  885.                 exit(DoMouseDownInGrayMap);
  886.             end;
  887.         if info^.LUTMode = CustomGrayscale then
  888.             ResetGrayMap;
  889.         SetPort(GrayMapWindow);
  890.         GetMouse(p);
  891.         if PtInRect(p, gmIcon1) then begin
  892.                 InvertRect(gmIcon1);
  893.                 pressed := true;
  894.                 while Button and pressed do begin
  895.                         GetMouse(p);
  896.                         if not PtInRect(p, gmIcon1) then begin
  897.                                 InvertRect(gmIcon1);
  898.                                 pressed := false;
  899.                             end;
  900.                     end;
  901.                 repeat
  902.                 until not button;
  903.                 if pressed then begin
  904.                         InvertRect(gmIcon1);
  905.                         ResetGrayMap;
  906.                         exit(DoMouseDownInGrayMap)
  907.                     end;
  908.             end;
  909.         if PtInRect(p, gmIcon2) then begin
  910.                 InvertRect(gmIcon2);
  911.                 pressed := true;
  912.                 while Button and pressed do begin
  913.                         GetMouse(p);
  914.                         if not PtInRect(p, gmIcon2) then begin
  915.                                 InvertRect(gmIcon2);
  916.                                 pressed := false;
  917.                             end;
  918.                     end;
  919.                 repeat
  920.                 until not button;
  921.                 if pressed then begin
  922.                         InvertRect(gmIcon2);
  923.                         EnableThresholding(128);
  924.                         exit(DoMouseDownInGrayMap)
  925.                     end;
  926.             end;
  927.         if PtInRect(p, gmSlide1) then
  928.             ChangeBrightness;
  929.         if PtInRect(p, gmSlide2) then
  930.             ChangeContrast;
  931.         if p.v > (gmRectBottom + 4) then begin
  932.                 Thresholding := info^.pDeltaX <= 1;
  933.                 exit(DoMouseDownInGrayMap);
  934.             end;
  935.         GetMouse(p);
  936.         ConvertMouseToXY(p, x, y);
  937.         if (x <= 24) or (y <= 32) then
  938.             mode := StartPoint
  939.         else if (x >= 224) or (y >= 232) then
  940.             mode := EndPoint
  941.         else
  942.             mode := brightness;
  943.         if (mode = brightness) and thresholding then
  944.             DrawLabels('Thresh:', '', '')
  945.         else
  946.             DrawLabels('X:', 'Y:', '');
  947.         repeat
  948.             with info^ do
  949.                 case mode of
  950.                     StartPoint: 
  951.                         begin
  952.                             if x > y then
  953.                                 y := 0
  954.                             else
  955.                                 x := 0;
  956.                             p1x := x;
  957.                             if p1x > p2x then
  958.                                 p2x := p1x;
  959.                             p1y := y;
  960.                             if p1y > p2y then
  961.                                 p2y := p1y;
  962.                             DoFixUp;
  963.                             Show2Values(p1x, p1y);
  964.                         end;
  965.                     EndPoint: 
  966.                         begin
  967.                             if x > y then
  968.                                 x := 255
  969.                             else
  970.                                 y := 255;
  971.                             p2x := x;
  972.                             if p2x < p1x then
  973.                                 p1x := p2x;
  974.                             p2y := y;
  975.                             if p2y < p1y then
  976.                                 p1y := p2y;
  977.                             DoFixUp;
  978.                             Show2Values(p2x, p2y);
  979.                         end;
  980.                     Brightness: 
  981.                         begin
  982.                             FindEndPoints(x, y);
  983.                             if thresholding then
  984.                                 Show1Value(p1x, NoValue);
  985.                         end;
  986.                 end; {case}
  987.             UpdateGrayMap;
  988.             gmFixedSlope := mode = brightness;
  989.             SetGrayScaleLUT;
  990.             gmFixedSlope := false;
  991.             GetMouse(p);
  992.             ConvertMouseToXY(p, x, y);
  993.         until not Button;
  994.         IdentityFunction := false;
  995.         Thresholding := info^.pDeltaX <= 1;
  996.     end;
  997.  
  998.  
  999.     procedure EnableThresholding (level: integer);
  1000.     begin
  1001.         with info^ do begin
  1002.                 pDeltaX := 1;
  1003.                 pDeltaY := 255;
  1004.                 p1x := level;
  1005.                 p1y := 0;
  1006.                 p2x := level;
  1007.                 p2y := 255;
  1008.                 SetGrayScaleLUT;
  1009.                 UpdateGrayMap;
  1010.                 Thresholding := true;
  1011.                 SelectLutTool;
  1012.             end;
  1013.     end;
  1014.  
  1015.  
  1016.     procedure DrawLUT;
  1017.         var
  1018.             tPort: GrafPtr;
  1019.             h, v, i: integer;
  1020.     begin
  1021.         GetPort(tPort);
  1022.         SetPort(LUTWindow);
  1023.         with LutWindow^ do begin
  1024.                 for v := 0 to 255 do begin
  1025.                         pmForeColor(v);
  1026.                         MoveTo(0, v);
  1027.                         LineTo(cwidth, v)
  1028.                     end;
  1029.                 for i := 1 to nExtraColors + 2 do begin
  1030.                         pmForeColor(ExtraColorsEntry[i]);
  1031.                         PaintRect(ExtraColorsRect[i]);
  1032.                     end;
  1033.                 TextFont(ApplFont);
  1034.                 TextSize(9);
  1035.                 with ExtraColorsRect[1] do
  1036.                     MoveTo(left + 3, bottom - 1);
  1037.                 pmForeColor(BlackIndex);
  1038.                 DrawString('white');
  1039.                 with ExtraColorsRect[2] do
  1040.                     MoveTo(left + 4, bottom - 1);
  1041.                 InvertRect(ExtraColorsRect[2]);
  1042.                 DrawString('black');
  1043.                 InvertRect(ExtraColorsRect[2]);
  1044.             end;
  1045.         SetPort(tPort);
  1046.     end;
  1047.  
  1048.  
  1049.     procedure UpdateColors;
  1050.         var
  1051.             MaxStart, i, v, index: integer;
  1052.             OptionKey: boolean;
  1053.             inc, sIndex: LongInt;
  1054.     begin
  1055.         OptionKey := OptionKeyDown;
  1056.         DisableDensitySlice;
  1057.         Thresholding := false;
  1058.         with info^ do begin
  1059.                 sIndex := 0;
  1060.                 inc := LongInt(nColors) * 10000 div (ColorEnd - ColorStart);
  1061.                 for i := 0 to 255 do
  1062.                     with cTable[i].rgb do begin
  1063.                             if (i < ColorStart) or (i > ColorEnd) then begin
  1064.                                     if OptionKey then begin
  1065.                                             v := bsl(i, 8);
  1066.                                             Red := v;
  1067.                                             Green := v;
  1068.                                             Blue := v;
  1069.                                         end
  1070.                                     else begin
  1071.                                             Red := 0;
  1072.                                             Green := 0;
  1073.                                             Blue := 0;
  1074.                                         end
  1075.                                 end
  1076.                             else begin
  1077.                                     index := sIndex div 10000;
  1078.                                     Red := bsl(RedLUT[index], 8);
  1079.                                     Green := bsl(GreenLUT[index], 8);
  1080.                                     Blue := bsl(BlueLUT[index], 8);
  1081.                                     sIndex := sIndex + inc;
  1082.                                 end;
  1083.                         end; {for}
  1084.                 LoadLUT(cTable);
  1085.                 LUTMode := PseudoColor;
  1086.             end;
  1087.         IdentityFunction := false;
  1088.     end;
  1089.  
  1090.  
  1091.  
  1092. end.