home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / image144.sit / Lut.p < prev    next >
Encoding:
Text File  |  1992-03-30  |  42.6 KB  |  1,812 lines

  1. unit Lut;
  2. {This file contains routines that deal with the video Look-Up Table(LUT).}
  3.  
  4. interface
  5.  
  6.     uses
  7.         QuickDraw, Palettes, Picker, PrintTraps, globals, Utilities, Graphics;
  8.  
  9.     function GetPseudoColorIndex: integer;
  10.     function isGrayScaleLUT: boolean;
  11.     procedure DoMouseDownInLUT (event: EventRecord);
  12.     procedure DoCopyColor;
  13.     procedure PasteColor;
  14.     procedure ShowRGBValues (index: integer);
  15.     procedure InvertPalette;
  16.     procedure FindPoints (var x1, y1, x2, y2: integer);
  17.     procedure UpdateMap;
  18.     procedure ResetGraymap;
  19.     procedure DrawMap;
  20.     procedure DoMouseDownInMap;
  21.     procedure EnableThresholding (level: integer);
  22.     procedure DrawLUT;
  23.     procedure UpdateLUT;
  24.     function LoadCLUTResource (id: integer): boolean;
  25.     procedure GetLookupTable (var table: LookupTable);
  26.     procedure RedrawLUTWindow;
  27.     procedure DrawDensitySlice (OptionKey: boolean);
  28.     procedure SelectLutTool;
  29.     procedure EnableDensitySlice;
  30.     procedure SetupPseudocolor;
  31.     procedure SetNumberOfColors;
  32.     procedure SetNumberOfExtraColors;
  33.     procedure DoImportLut (fname: str255; vnum: integer);
  34.     procedure OpenOldPalette (fname: str255; RefNum: integer);
  35.     procedure OpenNewPalette (fname: str255; RefNum: integer);
  36.     procedure OpenColorTable (fname: str255; RefNum: integer);
  37.     procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
  38.     procedure GetColorTable (id: integer);
  39.     procedure GetLutResource (id: integer);
  40.     procedure DrawScale;
  41.     procedure MakeSpectrum;
  42.     function GetColorTableItem (ctab: ColorTableType): integer;
  43.     procedure SwitchColorTables (item: integer; update: boolean);
  44.     procedure InitPaletteHeader (var hdr: PaletteHeader);
  45.  
  46.  
  47.  
  48.  
  49. implementation
  50.  
  51.  
  52.     function GetPseudoColorIndex: integer;
  53.         var
  54.             index: integer;
  55.     begin
  56.         with info^ do begin
  57.                 index := trunc((nColors) * (ForegroundIndex - ColorStart) / (ColorEnd - ColorStart + 1));
  58.                 if index < 0 then
  59.                     index := 0;
  60.                 if index > (nColors - 1) then
  61.                     index := nColors - 1;
  62.                 GetPseudoColorIndex := index;
  63.             end;
  64.     end;
  65.  
  66.  
  67.     procedure UpdateLUT;
  68.         var
  69.             MaxStart, i, v, index, last: integer;
  70.             inc, sIndex: LongInt;
  71.     begin
  72.         with info^ do begin
  73.                 sIndex := 0;
  74.                 if ColorEnd > ColorStart then
  75.                     inc := LongInt(nColors) * 10000 div (ColorEnd - ColorStart)
  76.                 else
  77.                     inc := 2560000;
  78.                 if ColorStart < 0 then
  79.                     sIndex := -ColorStart * Inc
  80.                 else
  81.                     sIndex := 0;
  82.                 last := nColors - 1;
  83.                 for i := 0 to 255 do
  84.                     with cTable[i].rgb do begin
  85.                             if (i < ColorStart) or (i > ColorEnd) then begin
  86.                                     if i < ColorStart then
  87.                                         cTable[i].rgb := FillColor1
  88.                                     else
  89.                                         cTable[i].rgb := FillColor2;
  90.                                 end
  91.                             else begin
  92.                                     index := sIndex div 10000;
  93.                                     if index > last then
  94.                                         index := last;
  95.                                     Red := bsl(RedLUT[index], 8);
  96.                                     Green := bsl(GreenLUT[index], 8);
  97.                                     Blue := bsl(BlueLUT[index], 8);
  98.                                     sIndex := sIndex + inc;
  99.                                 end;
  100.                         end; {for}
  101.                 LoadLUT(cTable);
  102.                 IdentityFunction := false;
  103.             end;
  104.     end;
  105.  
  106.  
  107.     function GetVLoc: integer;
  108.         var
  109.             loc: point;
  110.             vloc: integer;
  111.     begin
  112.         GetMouse(loc);
  113.         vloc := loc.v;
  114.         if vloc > 255 then
  115.             vloc := 255;
  116.         if vloc <= 0 then
  117.             vloc := 0;
  118.         GetVLoc := vloc;
  119.     end;
  120.  
  121.  
  122.     procedure GetNewColor (var color: RGBColor);
  123.         var
  124.             where: point;
  125.             inRGBColor, OutRGBColor: RGBColor;
  126.     begin
  127.         inRGBColor := color;
  128.         outRGBColor := color;
  129.         where.h := 0;
  130.         where.v := 0;
  131.         InitCursor;
  132.         if GetColor(where, 'Pick a new color...', inRGBColor, outRGBColor) then
  133.             color := outRGBColor;
  134.     end;
  135.  
  136.  
  137.     procedure EditPseudoColors;
  138.         var
  139.             where: point;
  140.             inRGBColor, OutRGBColor: RGBColor;
  141.             index, mloc: integer;
  142.     begin
  143.         with info^ do begin
  144.                 SetPort(LUTWindow);
  145.                 mloc := getvloc;
  146.                 if mloc < ColorStart then begin
  147.                         GetNewColor(FillColor1);
  148.                         UpdateLUT;
  149.                         exit(EditPseudoColors);
  150.                     end;
  151.                 if mloc > ColorEnd then begin
  152.                         GetNewColor(FillColor2);
  153.                         UpdateLUT;
  154.                         exit(EditPseudoColors);
  155.                     end;
  156.                 index := GetPseudoColorIndex;
  157.                 with inRGBColor do begin
  158.                         red := bsl(RedLUT[index], 8);
  159.                         green := bsl(GreenLUT[index], 8);
  160.                         blue := bsl(BlueLUT[index], 8);
  161.                     end;
  162.                 outRGBColor := inRGBColor;
  163.                 where.h := 0;
  164.                 where.v := 0;
  165.                 InitCursor;
  166.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then begin
  167.                         with outRGBColor do begin
  168.                                 RedLUT[index] := bsr(red, 8);
  169.                                 GreenLUT[index] := bsr(green, 8);
  170.                                 BlueLUT[index] := bsr(blue, 8);
  171.                             end;
  172.                         changes := true;
  173.                     end;
  174.                 ColorTable := CustomTable;
  175.                 UpdateLUT;
  176.             end; {with}
  177.     end;
  178.  
  179.  
  180.     function EditSliceColor: boolean;
  181.         var
  182.             where: point;
  183.             inRGBColor, OutRGBColor: RGBColor;
  184.             vloc: integer;
  185.     begin
  186.         SetPort(LUTWindow);
  187.         vloc := getvloc;
  188.         if (vloc >= SliceStart) and (vloc <= SliceEnd) then begin
  189.                 GetNewColor(SliceColor);
  190.                 DrawDensitySlice(false);
  191.                 EditSliceColor := true
  192.             end
  193.         else
  194.             EditSliceColor := false;
  195.     end;
  196.  
  197.  
  198.     procedure ShowLUTValues (tStart, tEnd: integer);
  199.         var
  200.             tPort: GrafPtr;
  201.     begin
  202.         with info^ do begin
  203.                 GetPort(tPort);
  204.                 SetPort(ValuesWindow);
  205.                 TextSize(9);
  206.                 TextFont(Monaco);
  207.                 TextMode(SrcCopy);
  208.                 MoveTo(xValueLoc, ValuesVStart);
  209.                 if DensityCalibrated then begin
  210.                         DrawReal(cvalue[tStart], 5, 2);
  211.                         DrawString(' (');
  212.                         DrawReal(tStart, 3, 0);
  213.                         DrawString(')');
  214.                     end
  215.                 else
  216.                     DrawReal(tStart, 3, 0);
  217.                 DrawString('    ');
  218.                 MoveTo(xValueLoc, ValuesVStart + 10);
  219.                 if DensityCalibrated then begin
  220.                         DrawReal(cvalue[tEnd], 5, 2);
  221.                         DrawString(' (');
  222.                         DrawReal(tEnd, 3, 0);
  223.                         DrawString(')');
  224.                     end
  225.                 else
  226.                     DrawReal(tEnd, 3, 0);
  227.                 DrawString('    ');
  228.                 SetPort(tPort);
  229.             end;
  230.     end;
  231.  
  232.  
  233.     procedure ShowRGBValues (index: integer);
  234.         var
  235.             tPort: GrafPtr;
  236.             vloc: integer;
  237.     begin
  238.         with info^ do begin
  239.                 GetPort(tPort);
  240.                 SetPort(ValuesWindow);
  241.                 TextSize(9);
  242.                 TextFont(Monaco);
  243.                 TextMode(SrcCopy);
  244.                 vloc := ValuesVStart;
  245.                 MoveTo(xValueLoc, vloc);
  246.                 DrawLong(index);
  247.                 DrawString('    ');
  248.                 if Info^.DensityCalibrated then begin
  249.                         vloc := vloc + 10;
  250.                         MoveTo(xValueLoc, vloc);
  251.                         DrawReal(cvalue[index], 1, precision);
  252.                         DrawString('    ');
  253.                     end;
  254.                 vloc := vloc + 10;
  255.                 MoveTo(xValueLoc, vloc);
  256.                 DrawRGB(index);
  257.                 DrawString('    ');
  258.                 SetPort(tPort);
  259.             end;
  260.     end;
  261.  
  262.  
  263.     procedure FindPoints (var x1, y1, x2, y2: integer);
  264.     begin
  265.         with info^ do begin
  266.                 if ColorStart >= 0 then begin
  267.                         x1 := ColorStart;
  268.                         y1 := 0;
  269.                     end
  270.                 else begin
  271.                         x1 := 0;
  272.                         if ColorEnd > ColorStart then
  273.                             y1 := -ColorStart * 255 div (ColorEnd - ColorStart)
  274.                         else
  275.                             y1 := 0;
  276.                     end;
  277.                 if ColorEnd <= 255 then begin
  278.                         x2 := ColorEnd;
  279.                         y2 := 255;
  280.                     end
  281.                 else begin
  282.                         x2 := 255;
  283.                         if ColorEnd > ColorStart then
  284.                             y2 := 255 * (255 - ColorStart) div (ColorEnd - ColorStart)
  285.                         else
  286.                             y2 := 255;
  287.                     end;
  288.             end;
  289.     end;
  290.  
  291.  
  292.     procedure UpdateMap;
  293.         var
  294.             r: rect;
  295.             x, y, i, h1, h2, h3, v1, v2, v3, dx, dy: integer;
  296.             xcenter, ycenter, brightness, islope, thumb: integer;
  297.             width, max: integer;
  298.             table: LookupTable;
  299.             hrect: rect;
  300.             slope: extended;
  301.             area, value, sum: LongInt;
  302.             p1x, p1y, p2x, p2y: integer;
  303.     begin
  304.         with info^ do begin
  305.                 FindPoints(p1x, p1y, p2x, p2y);
  306.                 SetPort(MapWindow);
  307.                 PenNormal;
  308.                 EraseRect(MapRect2);
  309.                 FrameRect(MapRect);
  310.                 if LutMode = CustomGrayscale then begin
  311.                         GetLookupTable(table);
  312.                         MoveTo(gmRectLeft, gmRectBottom - 1);
  313.                         for i := 0 to 63 do begin
  314.                                 x := gmRectLeft + i;
  315.                                 y := gmRectBottom - table[i * 4] div 4 - 1;
  316.                                 LineTo(x, y);
  317.                             end;
  318.                         EraseRect(gmSlide1i);
  319.                         EraseRect(gmSlide2i);
  320.                         exit(UpdateMap);
  321.                     end;
  322.                 h1 := gmRectLeft + p1x div 4;
  323.                 v1 := gmRectBottom - 1 - (p1y div 4);
  324.                 h2 := gmRectLeft + p2x div 4;
  325.                 v2 := gmRectBottom - 1 - (p2y div 4);
  326.                 MoveTo(gmRectLeft, gmRectBottom - 1);
  327.                 LineTo(h1, v1);
  328.                 LineTo(h2, v2);
  329.                 LineTo(gmRectRight - 1, gmRectTop);
  330.                 SetRect(hrect, h1 - 1, v1 - 1, h1 + 2, v1 + 2);
  331.                 PaintRect(hrect); {First handle}
  332.                 SetRect(hrect, h2 - 1, v2 - 1, h2 + 2, v2 + 2);
  333.                 PaintRect(hrect); {Last handle}
  334.                 dx := p2x - p1x;
  335.                 dy := p2y - p1y;
  336.                 xcenter := p1x + dx div 2;
  337.                 ycenter := p1y + dy div 2;
  338.                 h3 := gmRectLeft + xcenter div 4;
  339.                 v3 := gmRectBottom - 1 - (ycenter div 4);
  340.                 SetRect(hrect, h3 - 1, v3 - 1, h3 + 2, v3 + 2);
  341.                 PaintRect(hrect); {Center handle}
  342.                 thumb := gmSlideHeight - 2;
  343.                 max := gmSlideWidth - thumb - 2;
  344.                 width := ColorEnd - ColorStart;
  345.                 brightness := trunc(max * ((ColorStart + width) / (width + 255)));
  346.                 with gmSlide1 do
  347.                     SetRect(hrect, left + brightness + 1, top + 1, left + brightness + thumb + 1, top + thumb + 1);
  348.                 EraseRect(gmSlide1i);
  349.                 PaintRect(hrect);  {Thumb for contrast control}
  350.                 if dx <> 0 then
  351.                     slope := dy / dx
  352.                 else
  353.                     slope := 1000.0;
  354.                 if slope > 1.0 then begin
  355.                         if dy <> 0 then
  356.                             slope := 2.0 - dx / dy
  357.                         else
  358.                             slope := 2.0;
  359.                     end;
  360.                 islope := trunc(slope * 0.5 * (gmSlideWidth - thumb - 2.0));
  361.                 with gmSlide2 do
  362.                     SetRect(hrect, left + islope + 1, top + 1, left + islope + thumb + 1, top + thumb + 1);
  363.                 EraseRect(gmSlide2i);
  364.                 PaintRect(hrect);  {Thumb for contrast control}
  365.             end;
  366.     end;
  367.  
  368.  
  369.     procedure UpdateThreshold;
  370.         var
  371.             level: integer;
  372.     begin
  373.         DrawLabels('Thresh:', '', '');
  374.         with info^ do
  375.             repeat
  376.                 SetPort(LUTWindow);
  377.                 level := GetVLoc;
  378.                 if level <= 255 then begin
  379.                         ColorStart := level;
  380.                         ColorEnd := level;
  381.                         UpdateMap;
  382.                         UpdateLUT;
  383.                     end;
  384.                 Show1Value(level, NoValue);
  385.             until not Button;
  386.     end;
  387.  
  388.  
  389.     procedure UpdateDensitySlice;
  390.         var
  391.             mloc, saveloc, width, delta: integer;
  392.             adjust: (lower, upper, both);
  393.     begin
  394.         DrawLabels('Lower:', 'Upper:', '');
  395.         SetPort(LUTWindow);
  396.         mloc := getvloc;
  397.         saveloc := mloc;
  398.         width := SliceEnd - SliceStart + 1;
  399.         adjust := lower;
  400.         if mloc > (SliceStart + width div 4) then
  401.             adjust := both;
  402.         if mloc > (SliceEnd - width div 4) then
  403.             adjust := upper;
  404.         while button do begin
  405.                 width := SliceEnd - SliceStart + 1;
  406.                 mloc := getvloc;
  407.                 delta := mloc - saveloc;
  408.                 saveloc := mloc;
  409.                 case adjust of
  410.                     lower:  begin
  411.                             SliceStart := mloc;
  412.                             if SliceStart < 1 then
  413.                                 SliceStart := 1;
  414.                             if SliceStart > SliceEnd then
  415.                                 SliceStart := SliceEnd;
  416.                         end;
  417.                     upper:  begin
  418.                             SliceEnd := mloc;
  419.                             if SliceEnd > 254 then
  420.                                 SliceEnd := 254;
  421.                             if SliceEnd < SliceStart then
  422.                                 SliceEnd := SliceStart;
  423.                         end;
  424.                     both:  begin
  425.                             if mloc <= 1 then begin
  426.                                     SliceStart := 1;
  427.                                     SliceEnd := width;
  428.                                 end
  429.                             else if mloc >= 254 then begin
  430.                                     SliceEnd := 254;
  431.                                     SliceStart := 254 - width + 1;
  432.                                 end
  433.                             else if ((SliceStart + delta) >= 1) and ((SliceEnd + delta) <= 254) then begin
  434.                                     SliceStart := SliceStart + delta;
  435.                                     SliceEnd := SliceEnd + delta;
  436.                                 end;
  437.                         end;
  438.                 end; {case}
  439.                 DrawDensitySlice(OptionKeyDown);
  440.                 ShowLUTValues(SliceStart, SliceEnd);
  441.             end; {while}
  442.         DrawDensitySlice(false)
  443.     end;
  444.  
  445.  
  446.     procedure EditExtraColors (entry: integer);
  447.         var
  448.             where: point;
  449.             inRGBColor, OutRGBColor: RGBColor;
  450.     begin
  451.         if (entry <> WhiteIndex) and (entry <> BlackIndex) then begin
  452.                 inRGBColor := ExtraColors[entry];
  453.                 outRGBColor := inRGBColor;
  454.                 where.h := 0;
  455.                 where.v := 0;
  456.                 InitCursor;
  457.                 if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then
  458.                     with info^ do begin
  459.                             ExtraColors[entry] := OutRGBColor;
  460.                             changes := true;
  461.                             LoadLUT(cTable);
  462.                         end
  463.             end
  464.         else
  465.             PutMessage('Sorry, but you can not edit white or black.');
  466.     end;
  467.  
  468.  
  469.     function GetColorFromLUT (DoubleClick: boolean): integer;
  470.         var
  471.             mloc, color, i: integer;
  472.             loc: point;
  473.     begin
  474.         SetPort(LUTWindow);
  475.         GetMouse(loc);
  476.         if loc.v > 255 then begin
  477.                 color := 0;
  478.                 for i := 1 to nExtraColors + 2 do
  479.                     if PtInRect(loc, ExtraColorsRect[i]) then
  480.                         Color := ExtraColorsEntry[i];
  481.                 if DoubleClick then
  482.                     EditExtraColors(color);
  483.                 GetColorFromLUT := color;
  484.             end
  485.         else
  486.             GetColorFromLUT := loc.v;
  487.     end;
  488.  
  489.  
  490.     function isGrayScaleLUT: boolean;
  491.         var
  492.             i: integer;
  493.             GrayScaleLUT: boolean;
  494.     begin
  495.         with info^ do begin
  496.                 GrayscaleLUT := true;
  497.                 i := 0;
  498.                 repeat
  499.                     with cTable[i].rgb do
  500.                         GrayscaleLUT := GrayscaleLUT and (red = green) and (green = blue);
  501.                     i := i + 1;
  502.                 until (i = 256) or not GrayscaleLUT;
  503.                 isGrayScaleLUT := GrayScaleLUT;
  504.             end;
  505.     end;
  506.  
  507.  
  508.     procedure SetupPseudocolor;
  509.         var
  510.             i: integer;
  511.     begin
  512.         with info^ do begin
  513.                 DisableDensitySlice;
  514.                 for i := 1 to 254 do
  515.                     with cTable[i].rgb do begin
  516.                             RedLUT[i] := band(bsr(red, 8), 255);
  517.                             GreenLUT[i] := band(bsr(green, 8), 255);
  518.                             BlueLUT[i] := band(bsr(blue, 8), 255);
  519.                         end;
  520.                 RedLUT[0] := RedLUT[1];
  521.                 GreenLUT[0] := GreenLUT[1];
  522.                 BlueLUT[0] := BlueLUT[1];
  523.                 RedLUT[255] := RedLUT[254];
  524.                 GreenLUT[255] := GreenLUT[254];
  525.                 BlueLUT[255] := BlueLUT[254];
  526.                 nColors := 256;
  527.                 ColorStart := 0;
  528.                 ColorEnd := 255;
  529.                 FillColor1 := ctable[1].rgb;
  530.                 FillColor2 := ctable[254].rgb;
  531.                 InvertedColorTable := false;
  532.             end;
  533.     end;
  534.  
  535.  
  536.     procedure AdjustLUT;
  537.         const
  538.             MinWidth = 8;
  539.         var
  540.             mloc, saveloc, width, delta, cstart, cend: integer;
  541.             adjust: (lower, upper, both);
  542.             loc: point;
  543.     begin
  544.         with info^ do begin
  545.                 SetPort(LUTWindow);
  546.                 SetupLutUndo;
  547.                 DrawLabels('Lower:', 'Upper:', '');
  548.                 mloc := getvloc;
  549.                 saveloc := mloc;
  550.                 cstart := ColorStart;
  551.                 if cstart < 0 then
  552.                     cstart := 0;
  553.                 cend := ColorEnd;
  554.                 if cend > 255 then
  555.                     cend := 255;
  556.                 width := cend - cstart + 1;
  557.                 adjust := lower;
  558.                 if mloc > (cstart + width div 4) then
  559.                     adjust := both;
  560.                 if mloc > (cend - width div 4) then
  561.                     adjust := upper;
  562.                 while button do begin
  563.                         SetPort(LUTWindow);
  564.                         GetMouse(loc);
  565.                         mloc := loc.v;
  566.                         delta := mloc - saveloc;
  567.                         saveloc := mloc;
  568.                         case adjust of
  569.                             lower:  begin
  570.                                     ColorStart := mloc;
  571.                                     cend := ColorEnd;
  572.                                     if cend > 255 then
  573.                                         cend := 255;
  574.                                     if ColorStart > (cend - MinWidth) then
  575.                                         ColorStart := cend - MinWidth;
  576.                                 end;
  577.                             upper:  begin
  578.                                     ColorEnd := mloc;
  579.                                     cstart := ColorStart;
  580.                                     if cstart < 0 then
  581.                                         cstart := 0;
  582.                                     if ColorEnd < (cstart + MinWidth) then
  583.                                         ColorEnd := cstart + MinWidth;
  584.                                 end;
  585.                             both: 
  586.                                 if (mloc >= 0) and (mloc <= 255) then begin
  587.                                         ColorStart := ColorStart + delta;
  588.                                         ColorEnd := ColorEnd + delta;
  589.                                     end;
  590.                         end;
  591.                         UpdateLUT;
  592.                         UpdateMap;
  593.                         ShowLUTValues(ColorStart, ColorEnd);
  594.                     end;
  595.             end; {with info}
  596.     end;
  597.  
  598.  
  599.     procedure RotateLUT;
  600.         var
  601.             vstart, i, j, delta: integer;
  602.             loc: point;
  603.             TempTable: MyCSpecArray;
  604.     begin
  605.         with info^ do begin
  606.                 SetPort(LUTWindow);
  607.                 GetMouse(loc);
  608.                 vstart := loc.v;
  609.                 repeat
  610.                     GetMouse(loc);
  611.                     delta := vstart - loc.v;
  612.                     for i := 1 to 254 do begin {0 is resevred for white and 255 for black}
  613.                             j := i + delta;
  614.                             if j > 254 then
  615.                                 j := j - 254;
  616.                             if j > 254 then
  617.                                 j := 254;
  618.                             if j < 1 then
  619.                                 j := j + 254;
  620.                             if j < 1 then
  621.                                 j := 1;
  622.                             TempTable[i] := cTable[j]
  623.                         end;
  624.                     cTable := TempTable;
  625.                     LoadLUT(cTable);
  626.                     vstart := loc.v;
  627.                 until not button;
  628.                 SetupPseudocolor;
  629.                 ColorTable := CustomTable;
  630.             end;
  631.     end;
  632.  
  633.  
  634.     procedure DoMouseDownInLUT (event: EventRecord);
  635.         var
  636.             color: integer;
  637.             DoubleClick: boolean;
  638.     begin
  639.         with info^ do begin
  640.                 if CurrentTool = PickerTool then
  641.                     DoubleClick := (TickCount - LutTime) < GetDblTime
  642.                 else
  643.                     DoubleClick := false;
  644.                 LutTime := TickCount;
  645.                 if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  646.                         color := GetColorFromLUT(DoubleClick);
  647.                         if (CurrentTool = eraser) or OptionKeyDown then
  648.                             SetBackgroundColor(color)
  649.                         else
  650.                             SetForegroundColor(color);
  651.                         if not DoubleClick then
  652.                             exit(DoMouseDownInLUT);
  653.                     end;
  654.                 if Thresholding then begin
  655.                         UpdateThreshold;
  656.                         exit(DoMouseDownInLUT)
  657.                     end;
  658.                 if DoubleClick then begin
  659.                         if DensitySlicing and (CurrentTool = PickerTool) then begin
  660.                                 if EditSliceColor then
  661.                                     exit(DoMouseDownInLUT);
  662.                             end;
  663.                         if (CurrentTool = PickerTool) and (LutMode = Pseudocolor) then begin
  664.                                 EditPseudoColors;
  665.                                 exit(DoMouseDownInLUT)
  666.                             end;
  667.                     end; {if DoubleClick}
  668.                 if ((CurrentTool = LutTool) or (CurrentTool = Wand)) and DensitySlicing then begin
  669.                         UpdateDensitySlice;
  670.                         exit(DoMouseDownInLUT);
  671.                     end;
  672.                 if OptionKeyDown then
  673.                     RotateLUT
  674.                 else
  675.                     AdjustLUT;
  676.             end; {with}
  677.     end;
  678.  
  679.  
  680.     procedure DoCopyColor;
  681.     begin
  682.         with info^ do begin
  683.                 if ForegroundIndex = WhiteIndex then begin
  684.                         ClipboardColor := WhiteRGB;
  685.                         exit(DoCopyColor);
  686.                     end;
  687.                 if ForegroundIndex = BlackIndex then begin
  688.                         ClipboardColor := BlackRGB;
  689.                         exit(DoCopyColor);
  690.                     end;
  691.                 with cTable[ForegroundIndex].rgb do begin
  692.                         ClipboardColor.red := red;
  693.                         ClipboardColor.green := green;
  694.                         ClipboardColor.blue := blue;
  695.                     end;
  696.                 WhatsOnClip := AColor;
  697.                 ClipTextInBuffer := false;
  698.             end;
  699.     end;
  700.  
  701.  
  702.     procedure PasteColor;
  703.         var
  704.             CurrentColorIndex: integer;
  705.     begin
  706.         with info^ do begin
  707.                 if CurrentTool = PickerTool then begin
  708.                         if ForegroundIndex < ColorStart then begin
  709.                                 FillColor1 := ClipboardColor;
  710.                                 UpdateLUT;
  711.                                 exit(PasteColor);
  712.                             end;
  713.                         if ForegroundIndex > ColorEnd then begin
  714.                                 FillColor2 := ClipboardColor;
  715.                                 UpdateLUT;
  716.                                 exit(PasteColor);
  717.                             end;
  718.                         CurrentColorIndex := GetPseudoColorIndex;
  719.                         with ClipboardColor do begin
  720.                                 RedLUT[CurrentColorIndex] := bsr(red, 8);
  721.                                 GreenLUT[CurrentColorIndex] := bsr(green, 8);
  722.                                 BlueLUT[CurrentColorIndex] := bsr(blue, 8);
  723.                             end;
  724.                         ColorTable := CustomTable;
  725.                         UpdateLUT;
  726.                     end
  727.                 else
  728.                     beep;
  729.             end;
  730.     end;
  731.  
  732.  
  733.     procedure InvertPalette;
  734.         var
  735.             TempRed, TempGreen, TempBlue: LutArray;
  736.             i, LastColor: integer;
  737.             TempTable: MyCSpecArray;
  738.             TempFill: rgbColor;
  739.     begin
  740.         with info^ do begin
  741.                 TempRed := RedLUT;
  742.                 TempGreen := GreenLUT;
  743.                 TempBlue := BlueLUT;
  744.                 LastColor := ncolors - 1;
  745.                 for i := 0 to LastColor do begin
  746.                         RedLUT[i] := TempRed[LastColor - i];
  747.                         GreenLUT[i] := TempGreen[LastColor - i];
  748.                         BlueLUT[i] := TempBlue[LastColor - i];
  749.                     end;
  750.                 TempFill := FillColor1;
  751.                 FillColor1 := FillColor2;
  752.                 FillColor2 := TempFill;
  753.                 InvertedColorTable := not InvertedColorTable;
  754.                 IdentityFunction := false;
  755.             end;
  756.     end;
  757.  
  758.  
  759.     procedure DrawMap;
  760.         var
  761.             x, y, i: integer;
  762.             table: LookupTable;
  763.     begin
  764.         SetPort(MapWindow);
  765.         PenNormal;
  766.         TextFont(ApplFont);
  767.         TextSize(9);
  768.         with gmSlide1 do
  769.             MoveTo(left - 6, bottom);
  770.         DrawChar('B');
  771.         with gmSlide2 do
  772.             MoveTo(left - 6, bottom);
  773.         DrawChar('C');
  774.         FrameRect(gmSlide1);
  775.         FrameRect(gmSlide2);
  776.         FrameRect(gmIcon1);
  777.         FrameRect(gmIcon2);
  778.         with gmIcon1 do begin
  779.                 MoveTo(left, top + 10);
  780.                 LineTo(left + 5, top + 10);
  781.                 LineTo(left + 12, top + 3);
  782.                 LineTo(left + gmIconWidth - 1, top + 3);
  783.             end;
  784.         with gmIcon2 do begin
  785.                 MoveTo(left, top + 10);
  786.                 LineTo(left + gmIconWidth div 2, top + 10);
  787.                 LineTo(left + gmIconWidth div 2, top + 3);
  788.                 LineTo(left + gmIconWidth - 1, top + 3);
  789.             end;
  790.         UpdateMap;
  791.         GrayMapReady := true;
  792.     end;
  793.  
  794.  
  795.     procedure ResetGrayMap;
  796.         var
  797.             i: integer;
  798.     begin
  799.         with info^ do begin
  800.                 DisableDensitySlice;
  801.                 for i := 0 to 255 do begin
  802.                         RedLut[i] := 255 - i;
  803.                         GreenLut[i] := 255 - i;
  804.                         BlueLut[i] := 255 - i;
  805.                     end;
  806.                 FillColor1 := WhiteRGB;
  807.                 FillColor2 := BlackRGB;
  808.                 ColorStart := 0;
  809.                 ColorEnd := 255;
  810.                 nColors := 256;
  811.                 ColorTable := CustomTable;
  812.                 LUTMode := Grayscale;
  813.                 UpdateLUT;
  814.                 if GrayMapReady then
  815.                     UpdateMap;
  816.                 IdentityFunction := true;
  817.                 InvertedColorTable := false;
  818.             end;
  819.     end;
  820.  
  821.  
  822.     procedure AdjustBrightness;
  823.         var
  824.             loc, max, thumb, xcenter, ycenter, width: integer;
  825.             p: point;
  826.     begin
  827.         with info^ do begin
  828.                 thumb := gmSlideHeight - 2;
  829.                 max := gmSlideWidth - thumb - 2;
  830.                 width := ColorEnd - ColorStart;
  831.                 repeat
  832.                     GetMouse(p);
  833.                     loc := p.h - gmSlide1.left - 2;
  834.                     if loc < 0 then
  835.                         loc := 0;
  836.                     if loc > max then
  837.                         loc := max;
  838.                     ColorStart := -width + round((width + 255) * (loc / max));
  839.                     ColorEnd := ColorStart + width;
  840.                     UpdateMap;
  841.                     UpdateLUT;
  842.                 until not button;
  843.                 IdentityFunction := false;
  844.             end; {with}
  845.     end;
  846.  
  847.  
  848.     procedure AdjustContrast;
  849.         var
  850.             p: point;
  851.             loc, max, HalfMax, thumb: integer;
  852.             slope, center: extended;
  853.     begin
  854.         with info^ do begin
  855.                 thumb := gmSlideHeight - 2;
  856.                 max := gmSlideWidth - thumb - 2;
  857.                 HalfMax := max div 2;
  858.                 center := ColorStart + (ColorEnd - ColorStart) / 2.0;
  859.                 repeat
  860.                     GetMouse(p);
  861.                     loc := p.h - gmSlide2.left - 2;
  862.                     if loc < 0 then
  863.                         loc := 0;
  864.                     if loc > max then
  865.                         loc := max;
  866.                     if loc <= HalfMax then
  867.                         slope := loc / HalfMax
  868.                     else if loc < max then
  869.                         slope := HalfMax / (max - loc)
  870.                     else
  871.                         slope := 1000.0;
  872.                     if slope > 0.0 then begin
  873.                             ColorStart := round(center - 127.5 / slope);
  874.                             ColorEnd := round(center + 127.5 / slope);
  875.                         end
  876.                     else begin
  877.                             ColorStart := round(center - MaxColor);
  878.                             ColorEnd := round(center + MaxColor);
  879.                         end;
  880.                     UpdateMap;
  881.                     UpdateLUT;
  882.                 until not button;
  883.                 IdentityFunction := false;
  884.             end; {with}
  885.     end;
  886.  
  887.  
  888.     procedure ConvertMouseToXY (p: point; var x, y: integer);
  889.     begin
  890.         x := (p.h - gmRectLeft) * 4;
  891.         if x < 0 then
  892.             x := 0;
  893.         if x > 255 then
  894.             x := 255;
  895.         y := (gmRectBottom - p.v) * 4;
  896.         if y < 0 then
  897.             y := 0;
  898.         if y > 255 then
  899.             y := 255;
  900.     end;
  901.  
  902.  
  903.     procedure DoFreehandEditing;
  904.         var
  905.             p: point;
  906.             x1, x2, y, i: integer;
  907.             FirstTime: boolean;
  908.     begin
  909.         with info^ do begin
  910.                 LUTMode := CustomGrayscale;
  911.                 SetPort(MapWindow);
  912.                 FirstTime := true;
  913.                 while button do begin
  914.                         x1 := x2;
  915.                         GetMouse(p);
  916.                         ConvertMouseToXY(p, x2, y);
  917.                         if x2 > 252 then
  918.                             x2 := 252;
  919.                         if FirstTime then begin
  920.                                 x1 := x2;
  921.                                 FirstTime := false;
  922.                             end;
  923.                         if x2 >= x1 then
  924.                             for i := x1 to x2 + 3 do
  925.                                 with cTable[i].rgb do begin
  926.                                         red := bsl(255 - y, 8);
  927.                                         green := bsl(255 - y, 8);
  928.                                         blue := bsl(255 - y, 8);
  929.                                     end
  930.                         else
  931.                             for i := x1 + 3 downto x2 do
  932.                                 with cTable[i].rgb do begin
  933.                                         red := bsl(255 - y, 8);
  934.                                         green := bsl(255 - y, 8);
  935.                                         blue := bsl(255 - y, 8);
  936.                                     end;
  937.                         DrawMap;
  938.                         LoadLUT(cTable);
  939.                     end;
  940.                 if not isGrayscaleLut then
  941.                     LutMode := ColorLut;
  942.             end;
  943.     end;
  944.  
  945.  
  946.     procedure DoMouseDownInMap;
  947.         var
  948.             r: rect;
  949.             x, y, p1Dist, p2Dist: integer;
  950.             mode: (StartPoint, EndPoint, Brightness);
  951.             p: point;
  952.             pressed: boolean;
  953.             x1, y1, x2, y2: integer;
  954.             xintercept: integer;
  955.             deltax, deltay: LongInt;
  956.  
  957.         procedure DoFixup;
  958.         begin
  959.             with info^ do
  960.                 if ((x1 = 0) and (x2 = 0)) or ((x1 = 255) and (x2 = 255)) then begin
  961.                         y1 := 0;
  962.                         y2 := 255;
  963.                     end;
  964.         end;
  965.  
  966.     begin
  967.         with info^ do begin
  968.                 DisableDensitySlice;
  969.                 if OptionKeyDown then begin
  970.                         DoFreehandEditing;
  971.                         exit(DoMouseDownInMap);
  972.                     end;
  973.                 if LUTMode = CustomGrayscale then
  974.                     ResetGrayMap;
  975.                 FindPoints(x1, y1, x2, y2);
  976.                 SetPort(MapWindow);
  977.                 GetMouse(p);
  978.                 if PtInRect(p, gmIcon1) then begin
  979.                         InvertRect(gmIcon1);
  980.                         pressed := true;
  981.                         while Button and pressed do begin
  982.                                 GetMouse(p);
  983.                                 if not PtInRect(p, gmIcon1) then begin
  984.                                         InvertRect(gmIcon1);
  985.                                         pressed := false;
  986.                                     end;
  987.                             end;
  988.                         repeat
  989.                         until not button;
  990.                         if pressed then begin
  991.                                 InvertRect(gmIcon1);
  992.                                 ColorStart := 0;
  993.                                 ColorEnd := 255;
  994.                                 IdentityFunction := LutMode = Grayscale;
  995.                                 UpdateMap;
  996.                                 UpdateLUT;
  997.                                 exit(DoMouseDownInMap)
  998.                             end;
  999.                     end;
  1000.                 if PtInRect(p, gmIcon2) then begin
  1001.                         InvertRect(gmIcon2);
  1002.                         pressed := true;
  1003.                         while Button and pressed do begin
  1004.                                 GetMouse(p);
  1005.                                 if not PtInRect(p, gmIcon2) then begin
  1006.                                         InvertRect(gmIcon2);
  1007.                                         pressed := false;
  1008.                                     end;
  1009.                             end;
  1010.                         repeat
  1011.                         until not button;
  1012.                         if pressed then begin
  1013.                                 InvertRect(gmIcon2);
  1014.                                 EnableThresholding(128);
  1015.                                 exit(DoMouseDownInMap)
  1016.                             end;
  1017.                     end;
  1018.                 if PtInRect(p, gmSlide1) then
  1019.                     AdjustBrightness;
  1020.                 if PtInRect(p, gmSlide2) then
  1021.                     AdjustContrast;
  1022.                 if p.v > (gmRectBottom + 4) then begin
  1023.                         Thresholding := (x2 - x1) <= 1;
  1024.                         exit(DoMouseDownInMap);
  1025.                     end;
  1026.                 if LutMode = CustomGrayscale then
  1027.                     LutMode := Grayscale;
  1028.                 GetMouse(p);
  1029.                 ConvertMouseToXY(p, x, y);
  1030.                 if (x <= 24) or (y <= 32) then
  1031.                     mode := StartPoint
  1032.                 else if (x >= 224) or (y >= 232) then
  1033.                     mode := EndPoint
  1034.                 else
  1035.                     mode := brightness;
  1036.                 if (mode = brightness) and thresholding then
  1037.                     DrawLabels('Thresh:', '', '')
  1038.                 else
  1039.                     DrawLabels('X:', 'Y:', '');
  1040.                 repeat
  1041.                     case mode of
  1042.                         StartPoint:  begin
  1043.                                 if x > y then
  1044.                                     y := 0
  1045.                                 else
  1046.                                     x := 0;
  1047.                                 x1 := x;
  1048.                                 if x1 > x2 then
  1049.                                     x2 := x1;
  1050.                                 y1 := y;
  1051.                                 if y1 > y2 then
  1052.                                     y2 := y1;
  1053.                                 DoFixUp;
  1054.                                 Show2Values(x1, y1);
  1055.                             end;
  1056.                         EndPoint:  begin
  1057.                                 if x > y then
  1058.                                     x := 255
  1059.                                 else
  1060.                                     y := 255;
  1061.                                 x2 := x;
  1062.                                 if x2 < x1 then
  1063.                                     x1 := x2;
  1064.                                 y2 := y;
  1065.                                 if y2 < y1 then
  1066.                                     y1 := y2;
  1067.                                 DoFixUp;
  1068.                                 Show2Values(x2, y2);
  1069.                             end;
  1070.                         Brightness:  begin
  1071.                                 deltax := x2 - x1;
  1072.                                 deltay := y2 - y1;
  1073.                                 if deltax = 0 then begin
  1074.                                         x1 := x;
  1075.                                         y1 := 0;
  1076.                                         x2 := x;
  1077.                                         y2 := 255;
  1078.                                     end
  1079.                                 else if deltay = 0 then begin
  1080.                                         x1 := 0;
  1081.                                         y1 := y;
  1082.                                         x2 := 255;
  1083.                                         y2 := y;
  1084.                                     end
  1085.                                 else begin
  1086.                                         x1 := x - y * deltax div deltay;
  1087.                                         xIntercept := x1;
  1088.                                         y1 := 0;
  1089.                                         if x1 < 0 then begin
  1090.                                                 y1 := -deltay * x1 div deltaX;
  1091.                                                 x1 := 0;
  1092.                                             end;
  1093.                                         y2 := 255;
  1094.                                         x2 := 255 * deltax div deltay;
  1095.                                         if xIntercept < 0 then
  1096.                                             x2 := x2 + xIntercept
  1097.                                         else
  1098.                                             x2 := x2 + x1;
  1099.                                         if x2 > 255 then begin
  1100.                                                 y2 := 255 - (x2 - 255) * deltay div deltax;
  1101.                                                 x2 := 255;
  1102.                                             end;
  1103.                                     end;
  1104.                                 if x2 < 1 then
  1105.                                     x2 := 1;
  1106.                                 if y2 < 1 then
  1107.                                     y2 := 1;
  1108.                                 if x1 > 254 then
  1109.                                     x1 := 254;
  1110.                                 if y1 > 254 then
  1111.                                     y1 := 254;
  1112.                                 if thresholding then
  1113.                                     Show1Value(x1, NoValue);
  1114.                             end;
  1115.                     end; {case}
  1116. {showmessage(concat(long2str(x1), '  ', long2str(y1), '  ', long2str(x2), '  ', long2str(y2), cr, long2str(ColorStart), '  ', long2str(ColorEnd)));}
  1117.                     if y1 = 0 then
  1118.                         ColorStart := x1
  1119.                     else begin
  1120.                             if (y2 > y1) then
  1121.                                 ColorStart := -LongInt(x2 - x1) * y1 div (y2 - y1)
  1122.                             else
  1123.                                 ColorStart := -MaxColor;
  1124.                         end;
  1125.                     if y2 = 255 then
  1126.                         ColorEnd := x2
  1127.                     else begin
  1128.                             if (y2 > y1) then
  1129.                                 ColorEnd := 255 + LongInt(x2 - x1) * (255 - y2) div ((y2 - y1))
  1130.                             else
  1131.                                 ColorEnd := MaxColor;
  1132.                         end;
  1133.                     UpdateMap;
  1134.                     UpdateLUT;
  1135.                     GetMouse(p);
  1136.                     ConvertMouseToXY(p, x, y);
  1137.                 until not Button;
  1138.                 IdentityFunction := false;
  1139.                 Thresholding := (x2 - x1) <= 1;
  1140.             end; {with info}
  1141.     end;
  1142.  
  1143.  
  1144.     procedure EnableThresholding (level: integer);
  1145.     begin
  1146.         with info^ do begin
  1147.                 ColorStart := level;
  1148.                 ColorEnd := level;
  1149.                 UpdateMap;
  1150.                 UpdateLut;
  1151.                 Thresholding := true;
  1152.                 SelectLutTool;
  1153.             end;
  1154.     end;
  1155.  
  1156.  
  1157.     procedure DrawLUT;
  1158.         var
  1159.             tPort: GrafPtr;
  1160.             h, v, i: integer;
  1161.     begin
  1162.         GetPort(tPort);
  1163.         SetPort(LUTWindow);
  1164.         with LutWindow^ do begin
  1165.                 for v := 0 to 255 do begin
  1166.                         pmForeColor(v);
  1167.                         MoveTo(0, v);
  1168.                         LineTo(cwidth, v)
  1169.                     end;
  1170.                 for i := 1 to nExtraColors + 2 do begin
  1171.                         pmForeColor(ExtraColorsEntry[i]);
  1172.                         PaintRect(ExtraColorsRect[i]);
  1173.                     end;
  1174.                 TextFont(ApplFont);
  1175.                 TextSize(9);
  1176.                 with ExtraColorsRect[1] do
  1177.                     MoveTo(left + 3, bottom - 1);
  1178.                 pmForeColor(BlackIndex);
  1179.                 DrawString('white');
  1180.                 with ExtraColorsRect[2] do
  1181.                     MoveTo(left + 4, bottom - 1);
  1182.                 InvertRect(ExtraColorsRect[2]);
  1183.                 DrawString('black');
  1184.                 InvertRect(ExtraColorsRect[2]);
  1185.             end;
  1186.         SetPort(tPort);
  1187.     end;
  1188.  
  1189.  
  1190.     function LoadPP2Palette: boolean;
  1191. {Loads COLR resource from PixelPaint 2.0 palette file.}
  1192.         var
  1193.             i: integer;
  1194.             size: LongInt;
  1195.             h: Handle;
  1196.             PPColorTable: record
  1197.                     ctSize: INTEGER;
  1198.                     table: array[0..255] of RGBColor;
  1199.                 end;
  1200.     begin
  1201.         h := GetResource('COLR', 999);
  1202.         size := GetHandleSize(handle(h));
  1203.         if (ResError = NoErr) and (size = 1538) then
  1204.             with info^ do begin
  1205.                     BlockMove(handle(h)^, @PPColorTable, SizeOf(PPColorTable));
  1206.                     with PPColorTable do begin
  1207.                             for i := 0 to 255 do
  1208.                                 cTable[i].rgb := table[i];
  1209.                         end;
  1210.                     LoadLUT(cTable);
  1211.                     LutMode := ColorLut;
  1212.                     SetupPseudocolor;
  1213.                     IdentityFunction := false;
  1214.                     LoadPP2Palette := true;
  1215.                 end
  1216.         else
  1217.             LoadPP2Palette := false;
  1218.         if h <> nil then
  1219.             DisposHandle(h);
  1220.     end;
  1221.  
  1222.  
  1223.     function LoadCLUTResource;{(id:integer):boolean}
  1224.         const
  1225.             ExpectedSize = 2056;
  1226.         var
  1227.             Size: LongInt;
  1228.             h: cTabHandle;
  1229.             MyColorTable: record
  1230.                     ctSeed: LONGINT;
  1231.                     transIndex: INTEGER;
  1232.                     ctSize: INTEGER;
  1233.                     ctTable: MyCSpecArray;
  1234.                 end;
  1235.     begin
  1236.         DisableDensitySlice;
  1237.         h := GetCTable(id);
  1238.         size := GetHandleSize(handle(h));
  1239.         if (ResError <> NoErr) or (size < ExpectedSize) then begin
  1240.                 LoadCLUTResource := false;
  1241.                 if id = PixelpaintID then begin
  1242.                         if LoadPP2Palette then
  1243.                             LoadCLUTResource := true;
  1244.                     end;
  1245.                 if h <> nil then
  1246.                     DisposCTable(h);
  1247.                 exit(LoadCLUTResource)
  1248.             end;
  1249.         if size > ExpectedSize then
  1250.             size := ExpectedSize;
  1251.         BlockMove(handle(h)^, @MyColorTable, size);
  1252.         DisposCTable(h);
  1253.         LoadLUT(MyColorTable.ctTable);
  1254.         with info^ do begin
  1255.                 cTable := MyColorTable.ctTable;
  1256.                 LutMode := ColorLut;
  1257.                 IdentityFunction := false;
  1258.             end;
  1259.         SetupPseudocolor;
  1260.         LoadCLUTResource := true;
  1261.     end;
  1262.  
  1263.  
  1264.     procedure GetLookupTable;{(VAR table:LookupTable)}
  1265.         var
  1266.             i, r, g, b: integer;
  1267.             GrayscaleImage: boolean;
  1268.     begin
  1269.         with info^ do begin
  1270.                 if DensitySlicing then begin
  1271.                         for i := 0 to 255 do
  1272.                             if (i >= SliceStart) and (i <= SliceEnd) then begin
  1273.                                     if ThresholdToForeground then
  1274.                                         table[i] := ForegroundIndex
  1275.                                     else
  1276.                                         table[i] := i
  1277.                                 end
  1278.                             else begin
  1279.                                     if NonThresholdToBackground then
  1280.                                         table[i] := BackgroundIndex
  1281.                                     else
  1282.                                         table[i] := i
  1283.                                 end;
  1284.                         DisableDensitySlice;
  1285.                         exit(GetLookupTable);
  1286.                     end;
  1287.                 if (LutMode = GrayScale) or (LutMode = CustomGrayscale) then
  1288.                     for i := 0 to 255 do
  1289.                         table[i] := 255 - BSR(cTable[i].RGB.red, 8)
  1290.                 else begin
  1291.                         table[0] := 0;
  1292.                         for i := 1 to 254 do
  1293.                             with cTable[i].RGB do
  1294.                                 table[i] := 255 - trunc(band(bsr(red, 8), 255) * 0.3 + band(bsr(green, 8), 255) * 0.59 + band(bsr(blue, 8), 255) * 0.11);
  1295.                         table[255] := 255;
  1296.                     end;
  1297.             end; {with}
  1298.     end;
  1299.  
  1300.  
  1301.     procedure RedrawLUTWindow;
  1302.     begin
  1303.         LoadLUT(info^.cTable);
  1304.         cheight := 256 + (2 + nExtraColors) * ExtraColorsHeight;
  1305.         SizeWindow(LUTWindow, cwidth, cheight, true);
  1306.     end;
  1307.  
  1308.  
  1309.     procedure DrawDensitySlice (OptionKey: boolean);
  1310.         var
  1311.             i, tRed: integer;
  1312.     begin
  1313.         with info^ do begin
  1314.                 if OptionKey then begin
  1315.                         UndoLutChange;
  1316.                         exit(DrawDensitySlice);
  1317.                     end
  1318.                 else
  1319.                     for i := 0 to 255 do
  1320.                         if (i >= SliceStart) and (i <= SliceEnd) then
  1321.                             cTable[i].rgb := SliceColor
  1322.                         else
  1323.                             ctable[i].rgb := UndoInfo^.cTable[i].rgb;
  1324.                 LoadLUT(cTable);
  1325.             end;
  1326.     end;
  1327.  
  1328.  
  1329.     procedure SelectLutTool;
  1330.         var
  1331.             tPort: GrafPtr;
  1332.     begin
  1333.         if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  1334.                 GetPort(tPort);
  1335.                 SetPort(ToolWindow);
  1336.                 InvalRect(ToolRect[CurrentTool]);
  1337.                 InvalRect(ToolRect[LutTool]);
  1338.                 CurrentTool := LutTool;
  1339.                 isSelectionTool := false;
  1340.                 SetPort(tPort);
  1341.             end;
  1342.     end;
  1343.  
  1344.  
  1345.     procedure EnableDensitySlice;
  1346.     begin
  1347.         if not DensitySlicing then begin
  1348.                 SetupLutUndo;
  1349.                 DrawDensitySlice(false);
  1350.                 DensitySlicing := true;
  1351.                 SelectLUTTool;
  1352.             end;
  1353.     end;
  1354.  
  1355.  
  1356.     procedure SetNumberOfColors;
  1357.         var
  1358.             n, i, r, g, b, index: integer;
  1359.             Canceled: boolean;
  1360.             eIndex, inc, fraction: extended;
  1361.             SaveRed, SaveGreen, SaveBlue: LutArray;
  1362.     begin
  1363.         with info^ do begin
  1364.                 DisableDensitySlice;
  1365.                 SetupLutUndo;
  1366.                 n := GetInt('Number Of Colors(1..256):', ncolors, Canceled);
  1367.                 if (n <= 256) and (n > 0) and not Canceled then begin
  1368.                         SaveRed := RedLUT;
  1369.                         SaveGreen := GreenLUT;
  1370.                         SaveBlue := BlueLUT;
  1371.                         eIndex := 0.0;
  1372.                         inc := (nColors - 1) / (n - 1);
  1373.                         for i := 0 to n - 1 do begin
  1374.                                 index := trunc(eIndex);
  1375.                                 if index >= (nColors - 1) then begin
  1376.                                         RedLUT[i] := SaveRed[index];
  1377.                                         GreenLUT[i] := SaveGreen[index];
  1378.                                         BlueLUT[i] := SaveBlue[index]
  1379.                                     end
  1380.                                 else begin
  1381.                                         fraction := eIndex - index;
  1382.                                         RedLUT[i] := round(SaveRed[index] * (1.0 - fraction) + SaveRed[index + 1] * fraction);
  1383.                                         GreenLUT[i] := round(SaveGreen[index] * (1.0 - fraction) + SaveGreen[index + 1] * fraction);
  1384.                                         BlueLUT[i] := round(SaveBlue[index] * (1.0 - fraction) + SaveBlue[index + 1] * fraction);
  1385.                                     end;
  1386.                                 eIndex := eIndex + inc;
  1387.                             end;
  1388.                         nColors := n;
  1389.                         LutMode := PseudoColor;
  1390.                         ColorTable := CustomTable;
  1391.                         UpdateLUT;
  1392.                         UpdateMap;
  1393.                     end
  1394.                 else if not Canceled then
  1395.                     beep;
  1396.             end;
  1397.     end;
  1398.  
  1399.  
  1400.     procedure SetNumberOfExtraColors;
  1401.         var
  1402.             n: integer;
  1403.             Canceled: boolean;
  1404.     begin
  1405.         n := GetInt('Number of Extra Colors(0..6):', nExtraColors, Canceled);
  1406.         if (n <= 6) and (n >= 0) and not Canceled then begin
  1407.                 nExtraColors := n;
  1408.                 RedrawLUTWindow;
  1409.                 SelectWindow(LUTWindow);
  1410.                 if info <> NoInfo then
  1411.                     SelectWindow(info^.wptr);
  1412.             end
  1413.         else if not Canceled then
  1414.             beep;
  1415.     end;
  1416.  
  1417.  
  1418.     procedure DoImportLut (fname: str255; vnum: integer);
  1419.         var
  1420.             err: OSErr;
  1421.             f, i: integer;
  1422.             ByteCount: LongInt;
  1423.             ImportedLUT: array[1..3] of packed array[0..255] of byte;
  1424.     begin
  1425.         DisableDensitySlice;
  1426.         err := fsopen(fname, vNum, f);
  1427.         ByteCount := 768;
  1428.         err := fsRead(f, ByteCount, @ImportedLUT);
  1429.         if err = NoErr then
  1430.             with info^ do begin
  1431.                     for i := 0 to 255 do
  1432.                         with cTable[i], cTable[i].rgb do begin
  1433.                                 value := 0;
  1434.                                 red := bsl(ImportedLUT[1, i], 8);
  1435.                                 green := bsl(ImportedLUT[2, i], 8);
  1436.                                 blue := bsl(ImportedLUT[3, i], 8);
  1437.                             end;
  1438.                     LoadLUT(cTable);
  1439.                     SetupPseudocolor;
  1440.                     LutMode := PseudoColor;
  1441.                     IdentityFunction := false;
  1442.                     if isGrayScaleLUT then
  1443.                         info^.LutMode := CustomGrayScale;
  1444.                     UpdateMap;
  1445.                 end
  1446.         else
  1447.             beep;
  1448.         err := fsClose(f);
  1449.     end;
  1450.  
  1451.  
  1452.     procedure OpenOldPalette (fname: str255; RefNum: integer);
  1453. {Opens palette files created by versions Image earlier than 1.42.}
  1454.         var
  1455.             PaletteHeader: ColorArray;
  1456.             err, f, ColorWidth: integer;
  1457.             size: LongInt;
  1458.     begin
  1459.         DisableDensitySlice;
  1460.         err := fsopen(fname, RefNum, f);
  1461.         with info^ do begin
  1462.                 size := SizeOf(ColorArray);
  1463.                 err := fsread(f, size, @PaletteHeader);
  1464.                 nColors := PaletteHeader[0];
  1465.                 if nColors > MaxPseudocolors then
  1466.                     nColors := MaxPseudoColors;
  1467.                 ColorEnd := 255 - PaletteHeader[1];
  1468.                 ColorWidth := PaletteHeader[2];
  1469.                 ColorStart := ColorEnd - nColors * ColorWidth + 1;
  1470.                 if ColorStart < 0 then
  1471.                     ColorStart := 0;
  1472.                 FillColor1 := BlackRGB;
  1473.                 FillColor2 := BlackRGB;
  1474.                 err := fsread(f, size, @RedLut);
  1475.                 err := fsread(f, size, @GreenLut);
  1476.                 err := fsread(f, size, @BlueLut);
  1477.                 LutMode := PseudoColor;
  1478.                 InvertedColorTable := false;
  1479.             end;
  1480.         err := fsclose(f);
  1481.         UpdateLUT;
  1482.     end;
  1483.  
  1484.  
  1485.     procedure OpenNewPalette (fname: str255; RefNum: integer);
  1486. {Opens palette files created by versions of Image later than 1.41.}
  1487.         var
  1488.             err, f: integer;
  1489.             count: LongInt;
  1490.             hdr: PaletteHeader;
  1491.     begin
  1492.         DisableDensitySlice;
  1493.         err := fsopen(fname, RefNum, f);
  1494.         with info^ do begin
  1495.                 count := SizeOf(PaletteHeader);
  1496.                 err := fsread(f, count, @hdr);
  1497.                 with hdr do begin
  1498.                         nColors := pnColors;
  1499.                         if nColors > 256 then
  1500.                             nColors := 256;
  1501.                         ColorStart := pColorStart;
  1502.                         ColorEnd := pColorEnd;
  1503.                         FillColor1 := pFill1;
  1504.                         FillColor2 := pFill2;
  1505.                         InvertedColorTable := false;
  1506.                     end;
  1507.                 count := nColors;
  1508.                 err := fsread(f, count, @RedLut);
  1509.                 count := nColors;
  1510.                 err := fsread(f, count, @GreenLut);
  1511.                 count := nColors;
  1512.                 err := fsread(f, count, @BlueLut);
  1513.                 LutMode := PseudoColor;
  1514.             end;
  1515.         err := fsclose(f);
  1516.         UpdateLUT;
  1517.     end;
  1518.  
  1519.  
  1520.     procedure OpenColorTable (fname: str255; RefNum: integer);
  1521.         var
  1522.             err: OSErr;
  1523.             f: integer;
  1524.             FileSize, count: LongInt;
  1525.             id: packed array[1..4] of char;
  1526.     begin
  1527.         err := fsopen(fname, RefNum, f);
  1528.         err := GetEOF(f, FileSize);
  1529.         count := SizeOf(id);
  1530.         err := fsread(f, count, @id);
  1531.         err := fsclose(f);
  1532.         if FileSize = 768 then
  1533.             DoImportLut(fname, RefNum)
  1534.         else if id = 'ICOL' then
  1535.             OpenNewPalette(fname, RefNum)
  1536.         else
  1537.             OpenOldPalette(fname, RefNum);
  1538.     end;
  1539.  
  1540.  
  1541.     procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
  1542.         var
  1543.             RefNum: integer;
  1544.             ok: boolean;
  1545.             err: OSErr;
  1546.     begin
  1547.         err := SetVol(nil, vnum);
  1548.         refNum := OpenResFile(fname);
  1549.         if RefNum <> -1 then begin
  1550.                 if FileType = 'CLUT' then
  1551.                     ok := LoadClutResource(KlutzID)
  1552.                 else
  1553.                     ok := LoadClutResource(PixelPaintID); {Load PixelPaint or Canvas palette}
  1554.                 CloseResFile(RefNum);
  1555.                 if isGrayScaleLUT then begin
  1556.                         info^.LutMode := CustomGrayScale;
  1557.                         DrawMap;
  1558.                     end;
  1559.             end;
  1560.     end;
  1561.  
  1562.  
  1563.     procedure InitPaletteHeader (var hdr: PaletteHeader);
  1564.         var
  1565.             i: integer;
  1566.     begin
  1567.         with hdr, info^ do begin
  1568.                 pID := 'ICOL';
  1569.                 pVersion := version;
  1570.                 pnColors := nColors;
  1571.                 pColorStart := ColorStart;
  1572.                 pColorEnd := ColorEnd;
  1573.                 pFill1 := FillColor1;
  1574.                 pFill2 := FillColor2;
  1575.                 for i := 1 to 4 do
  1576.                     pUnused[i] := 0;
  1577.             end;
  1578.     end;
  1579.  
  1580.  
  1581.     procedure SaveLutResource;
  1582. {Saves the current color table as  a CPAL resource}
  1583.         var
  1584.             id: integer;
  1585.             canceled: boolean;
  1586.             PalH: handle;
  1587.             hdr: PaletteHeader;
  1588.             p: ptr;
  1589.     begin
  1590.         with info^ do begin
  1591.                 id := GetInt('Resource ID', 1000, canceled);
  1592.                 if canceled then
  1593.                     exit(SaveLutResource);
  1594.                 PalH := GetResource('CPAL', id);
  1595.                 if GetHandleSize(PalH) > 0 then begin
  1596.                         RmveResource(PalH);
  1597.                         DisposHandle(PalH);
  1598.                     end;
  1599.                 InitPaletteHeader(hdr);
  1600.                 PalH := NewHandle(SizeOF(PaletteHeader) + nColors * 3);
  1601.                 p := PalH^;
  1602.                 BlockMove(@hdr, p, SizeOf(PaletteHeader));
  1603.                 p := ptr(ord4(p) + SizeOf(PaletteHeader));
  1604.                 BlockMove(@RedLut, p, nColors);
  1605.                 p := ptr(ord4(p) + nColors);
  1606.                 BlockMove(@GreenLut, p, nColors);
  1607.                 p := ptr(ord4(p) + nColors);
  1608.                 BlockMove(@BlueLut, p, nColors);
  1609.                 AddResource(PalH, 'CPAL', id, '');
  1610.                 WriteResource(PalH);
  1611.                 if ResError <> NoErr then
  1612.                     SysBeep(1);
  1613.                 DisposHandle(PalH);
  1614.             end;
  1615.     end;
  1616.  
  1617.  
  1618.     procedure GetLutResource (id: integer);
  1619.         var
  1620.             LutH: handle;
  1621.             hdr: PaletteHEader;
  1622.             p: ptr;
  1623.     begin
  1624.         with info^ do begin
  1625.                 LutH := GetResource('CPAL', id);
  1626.                 if (ResError <> noErr) or (LutH = nil) then begin
  1627.                         beep;
  1628.                         if LutH <> nil then
  1629.                             ReleaseResource(LutH);
  1630.                         exit(GetLutResource)
  1631.                     end;
  1632.                 p := LutH^;
  1633.                 BlockMove(p, @hdr, SizeOf(PaletteHeader));
  1634.                 with hdr do begin
  1635.                         if pID <> 'ICOL' then begin
  1636.                                 beep;
  1637.                                 ReleaseResource(LutH);
  1638.                                 exit(GetLutResource);
  1639.                             end;
  1640.                         nColors := pnColors;
  1641.                         if nColors > 256 then
  1642.                             nColors := 256;
  1643.                         ColorStart := pColorStart;
  1644.                         ColorEnd := pColorEnd;
  1645.                         FillColor1 := pFill1;
  1646.                         FillColor2 := pFill2;
  1647.                         InvertedColorTable := false;
  1648.                     end;
  1649.                 p := ptr(ord4(p) + SizeOf(PaletteHeader));
  1650.                 BlockMove(p, @RedLut, nColors);
  1651.                 p := ptr(ord4(p) + nColors);
  1652.                 BlockMove(p, @GreenLut, nColors);
  1653.                 p := ptr(ord4(p) + nColors);
  1654.                 BlockMove(p, @BlueLut, nColors);
  1655.                 ReleaseResource(LutH);
  1656.             end;
  1657.     end;
  1658.  
  1659.  
  1660.     procedure DrawScale;
  1661.         var
  1662.             hloc, vloc, width, height, SaveForeground, LUTStart, LutEnd, LUTWidth: integer;
  1663.     begin
  1664.         if NoSelection or NotRectangular then
  1665.             exit(DrawScale);
  1666.         ShowWatch;
  1667.         with info^.RoiRect, info^ do begin
  1668.                 width := right - left;
  1669.                 height := bottom - top;
  1670.                 if (width = 0) or (height = 0) then
  1671.                     exit(DrawScale);
  1672.                 SetPort(GrafPtr(osPort));
  1673.                 PenNormal;
  1674.                 SetupUndoFromClip;
  1675.                 SetupUndo;
  1676.                 WhatToUndo := UndoEdit;
  1677.                 SaveForeground := ForegroundIndex;
  1678.                 LUTStart := ColorStart;
  1679.                 if LutStart <= 0 then
  1680.                     LutStart := 1;
  1681.                 LutEnd := ColorEnd;
  1682.                 if LutEnd >= 255 then
  1683.                     LutEnd := 254;
  1684.                 LUTWidth := LutEnd - LutStart + 1;
  1685.                 if width >= height then
  1686.                     for hloc := left to right - 1 do begin
  1687.                             SetForegroundColor(trunc(((hloc - left) / width) * LUTWidth) + LUTStart);
  1688.                             MoveTo(hloc, top);
  1689.                             LineTo(hloc, Bottom - 1);
  1690.                         end
  1691.                 else
  1692.                     for vloc := top to bottom - 1 do begin
  1693.                             SetForegroundColor(trunc(((vloc - top) / height) * LUTWidth) + LUTStart);
  1694.                             MoveTo(left, vloc);
  1695.                             LineTo(right - 1, vloc);
  1696.                         end;
  1697.                 SetForegroundColor(SaveForeground);
  1698.                 changes := true;
  1699.             end;
  1700.         SetupRoiRect;
  1701.     end;
  1702.  
  1703.  
  1704.     procedure MakeSpectrum;
  1705.         const
  1706.             Sat = -1;
  1707.             Val = -1;
  1708.         var
  1709.             i: integer;
  1710.             color: HSVColor;
  1711.     begin
  1712.         with info^ do begin
  1713.                 for i := 0 to 255 do begin
  1714.                         color.hue := i * 256;
  1715.                         color.saturation := sat;
  1716.                         color.value := val;
  1717.                         HSV2RGB(color, ctable[i].rgb);
  1718.                     end;
  1719.                 LutMode := ColorLut;
  1720.                 IdentityFunction := false;
  1721.                 SetupPseudocolor;
  1722.             end;
  1723.     end;
  1724.  
  1725.  
  1726.     function GetColorTableItem (ctab: ColorTableType): integer;
  1727.     begin
  1728.         case ctab of
  1729.             AppleDefault: 
  1730.                 GetColorTableItem := SystemPaletteItem;
  1731.             Pseudo20: 
  1732.                 GetColorTableItem := Pseudo20Item;
  1733.             Pseudo32: 
  1734.                 GetColorTableItem := Pseudo32Item;
  1735.             Rainbow: 
  1736.                 GetColorTableItem := RainbowItem;
  1737.             Fire1: 
  1738.                 GetColorTableItem := Fire1Item;
  1739.             Fire2: 
  1740.                 GetColorTableItem := Fire2Item;
  1741.             Ice: 
  1742.                 GetColorTableItem := IceItem;
  1743.             Grays: 
  1744.                 GetColorTableItem := GraysItem;
  1745.             Spectrum: 
  1746.                 GetColorTableItem := SpectrumItem;
  1747.             otherwise
  1748.                 GetColorTableItem := Pseudo20Item;
  1749.         end;
  1750.     end;
  1751.  
  1752.  
  1753.     procedure SwitchColorTables (item: integer; update: boolean);
  1754.         var
  1755.             ok: boolean;
  1756.     begin
  1757.         DisableDensitySlice;
  1758.         if update then
  1759.             SetupLutUndo;
  1760.         with info^ do begin
  1761.                 case item of
  1762.                     SystemPaletteItem:  begin
  1763.                             ok := LoadCLUTResource(AppleDefaultCLUT);
  1764.                             ColorTable := AppleDefault;
  1765.                         end;
  1766.                     Pseudo20Item:  begin
  1767.                             GetLutResource(Pseudo20ID);
  1768.                             ColorTable := Pseudo20;
  1769.                         end;
  1770.                     Pseudo32Item:  begin
  1771.                             GetLutResource(Pseudo32ID);
  1772.                             ColorTable := Pseudo32;
  1773.                         end;
  1774.                     RainbowItem:  begin
  1775.                             GetLutResource(RainbowID);
  1776.                             ColorTable := Rainbow;
  1777.                         end;
  1778.                     Fire1Item:  begin
  1779.                             GetLutResource(Fire1ID);
  1780.                             ColorTable := Fire1;
  1781.                         end;
  1782.                     Fire2Item:  begin
  1783.                             GetLutResource(Fire2ID);
  1784.                             ColorTable := Fire2;
  1785.                         end;
  1786.                     IceItem:  begin
  1787.                             GetLutResource(IceID);
  1788.                             ColorTable := Ice;
  1789.                         end;
  1790.                     GraysItem:  begin
  1791.                             GetLutResource(GraysID);
  1792.                             ColorTable := Grays;
  1793.                         end;
  1794.                     SpectrumItem: 
  1795.                         if ControlKeyDown and OptionKeyDown and ShiftKeyDown then
  1796.                             SaveLutResource
  1797.                         else begin
  1798.                                 MakeSpectrum;
  1799.                                 ColorTable := Spectrum;
  1800.                             end;
  1801.                 end; {case}
  1802.                 LutMode := Pseudocolor;
  1803.                 if update then begin
  1804.                         UpdateLUT;
  1805.                         UpdateMap;
  1806.                     end;
  1807.             end;
  1808.     end;
  1809.  
  1810.  
  1811.  
  1812. end.