tchart

TeeChart 图像滤镜介绍
  1. {**********************************************}
  2. {   TeeChart and TeeTree Image Filters         }
  3. {                                              }
  4. {   Copyright (c) 2006-2007 by David Berneda   }
  5. {        All Rights Reserved                   }
  6. {**********************************************}
  7. unit TeeFilters;
  8. {$I TeeDefs.inc}
  9.  
  10. {$R-}
  11.  
  12. interface
  13.  
  14. uses
  15.   {$IFNDEF LINUX}
  16.   Windows,
  17.   {$ENDIF}
  18.   Classes,
  19.   {$IFDEF D6}
  20.   Types,
  21.   {$ENDIF}
  22.   {$IFDEF CLX}
  23.   Qt, QControls, QGraphics, QStdCtrls, QExtCtrls,
  24.   {$ELSE}
  25.   Controls, Graphics, StdCtrls, ExtCtrls,
  26.   {$ENDIF}
  27.   TeCanvas;
  28.  
  29. {$IFDEF CLR}
  30. {$UNSAFECODE ON}
  31. {$ENDIF}
  32.  
  33. type
  34.   TResizeFilter=class(TTeeFilter)
  35.   private
  36.     FWidth  : Integer;
  37.     FHeight : Integer;
  38.   public
  39.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  40.  
  41.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  42.     class function Description: String; override;
  43.   published
  44.     property Width:Integer read FWidth write FWidth default 0;
  45.     property Height:Integer read FHeight write FHeight default 0;
  46.   end;
  47.  
  48.   TCropFilter=class(TResizeFilter)
  49.   private
  50.     FLeft   : Integer;
  51.     FSmooth : Boolean;
  52.     FTop    : Integer;
  53.   public
  54.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  55.  
  56.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  57.     class function Description: String; override;
  58.   published
  59.     property Left:Integer read FLeft write FLeft default 0;
  60.     property Smooth:Boolean read FSmooth write FSmooth default False;
  61.     property Top:Integer read FTop write FTop default 0;
  62.   end;
  63.  
  64.   TInvertFilter=class(TTeeFilter)
  65.   public
  66.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  67.     class function Description: String; override;
  68.   end;
  69.  
  70.   TGrayMethod=(gmSimple, gmEye, gmEye2);
  71.  
  72.   TGrayScaleFilter=class(TTeeFilter)
  73.   private
  74.     FMethod : TGrayMethod;
  75.   public
  76.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  77.  
  78.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  79.     class function Description: String; override;
  80.   published
  81.     property Method:TGrayMethod read FMethod write FMethod default gmSimple;
  82.   end;
  83.  
  84.   TFlipFilter=class(TTeeFilter)
  85.   public
  86.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  87.     class function Description: String; override;
  88.   end;
  89.  
  90.   TReverseFilter=class(TTeeFilter)
  91.   public
  92.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  93.     class function Description: String; override;
  94.   end;
  95.  
  96.   TAmountFilter=class(TTeeFilter)
  97.   private
  98.     FAmount  : Integer;
  99.     FPercent : Boolean;
  100.     FScrollBar : TScrollBar;
  101.  
  102.     IOnlyPositive : Boolean;
  103.     procedure ResetScroll(Sender:TObject);
  104.     function ScrollMin:Integer;
  105.     function ScrollMax:Integer;
  106.   public
  107.     Constructor Create(Collection:TCollection); override;
  108.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  109.   published
  110.     property Percent:Boolean read FPercent write FPercent default True;
  111.     property Amount:Integer read FAmount write FAmount default 5;
  112.   end;
  113.  
  114.   TMosaicFilter=class(TAmountFilter)
  115.   public
  116.     Constructor Create(Collection:TCollection); override;
  117.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  118.     class function Description: String; override;
  119.   end;
  120.  
  121.   TBrightnessFilter=class(TAmountFilter)
  122.   public
  123.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  124.     class function Description: String; override;
  125.   end;
  126.  
  127.   TContrastFilter=class(TAmountFilter)
  128.   public
  129.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  130.     class function Description: String; override;
  131.   end;
  132.  
  133.   TColorFilter=class(TTeeFilter)
  134.   private
  135.     FBlue  : Integer;
  136.     FGreen : Integer;
  137.     FRed   : Integer;
  138.   public
  139.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  140.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  141.     class function Description: String; override;
  142.   published
  143.     property Red:Integer read FRed write FRed default 0;
  144.     property Green:Integer read FGreen write FGreen default 0;
  145.     property Blue:Integer read FBlue write FBlue default 0;
  146.   end;
  147.  
  148.   THueLumSatFilter=class(TTeeFilter)
  149.   private
  150.     FHue : Integer;
  151.     FLum : Integer;
  152.     FSat : Integer;
  153.   public
  154.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  155.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  156.     class function Description: String; override;
  157.   published
  158.     property Hue:Integer read FHue write FHue default 0;
  159.     property Luminance:Integer read FLum write FLum default 0;
  160.     property Saturation:Integer read FSat write FSat default 0;
  161.   end;
  162.  
  163.   TSharpenFilter=class(TConvolveFilter)
  164.   public
  165.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  166.     class function Description: String; override;
  167.   end;
  168.  
  169.   TEmbossFilter=class(TConvolveFilter)
  170.   public
  171.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  172.     class function Description: String; override;
  173.   end;
  174.  
  175.   TSoftenFilter=class(TConvolveFilter)
  176.   public
  177.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  178.     class function Description: String; override;
  179.   end;
  180.  
  181.   TGammaCorrectionFilter=class(TAmountFilter)
  182.   public
  183.     Constructor Create(Collection:TCollection); override;
  184.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  185.     class function Description: String; override;
  186.   published
  187.     property Amount default 70;
  188.   end;
  189.  
  190.   TRotateFilter=class(TTeeFilter)
  191.   private
  192.     FAngle     : Double;
  193.     FAutoSize  : Boolean;
  194.     FBackColor : TColor;
  195.     procedure SetAngle(const Value: Double);
  196.   public
  197.     Constructor Create(Collection:TCollection); override;
  198.  
  199.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  200.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  201.     class function Description: String; override;
  202.   published
  203.     property Angle:Double read FAngle write SetAngle;
  204.     property AutoSize:Boolean read FAutoSize write FAutoSize default True;
  205.     property BackColor:TColor read FBackColor write FBackColor default clWhite;
  206.   end;
  207.  
  208.   TMirrorDirection=(mdDown, mdUp, mdRight, mdLeft);
  209.  
  210.   TMirrorFilter=class(TTeeFilter)
  211.   private
  212.     FDirection : TMirrorDirection;
  213.   public
  214.     Constructor Create(Collection:TCollection); override;
  215.  
  216.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  217.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  218.     class function Description: String; override;
  219.   published
  220.     property Direction:TMirrorDirection read FDirection write FDirection
  221.                                 default mdDown;
  222.   end;
  223.  
  224.   TTileFilter=class(TTeeFilter)
  225.   private
  226.     FNumCols : Integer;
  227.     FNumRows : Integer;
  228.   public
  229.     Constructor Create(Collection:TCollection); override;
  230.  
  231.     procedure Apply(Bitmap:TBitmap; const R:TRect); override;
  232.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  233.     class function Description: String; override;
  234.   published
  235.     property NumCols:Integer read FNumCols write FNumCols default 3;
  236.     property NumRows:Integer read FNumRows write FNumRows default 3;
  237.   end;
  238.  
  239.   TBevelFilter=class(TTeeFilter)
  240.   private
  241.     FBright : Integer;
  242.     FSize   : Integer;
  243.   public
  244.     Constructor Create(Collection:TCollection); override;
  245.  
  246.     procedure Apply(Bitmap: TBitmap; const R:TRect); override;
  247.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  248.     class function Description: String; override;
  249.   published
  250.     property Bright:Integer read FBright write FBright default 64;
  251.     property Size:Integer read FSize write FSize default 15;
  252.   end;
  253.  
  254.   TZoomFilter=class(TTeeFilter)
  255.   private
  256.     FPercent : Double;
  257.     FSmooth  : Boolean;
  258.   public
  259.     Constructor Create(Collection:TCollection); override;
  260.  
  261.     procedure Apply(Bitmap: TBitmap; const R:TRect); override;
  262.     procedure CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent); override;
  263.     class function Description: String; override;
  264.   published
  265.     property Percent:Double read FPercent write FPercent;
  266.     property Smooth:Boolean read FSmooth write FSmooth default False;
  267.   end;
  268.  
  269.   TImageFiltered=class(TImage)
  270.   private
  271.     FFilters : TFilterItems;
  272.  
  273.     function FiltersStored:Boolean;
  274.     procedure ReadFilters(Reader: TReader);
  275.     procedure SetFilters(const Value: TFilterItems);
  276.     procedure WriteFilters(Writer: TWriter);
  277.   protected
  278.     procedure DefineProperties(Filer:TFiler); override;
  279.     procedure Paint; override;
  280.   public
  281.     Constructor Create(AOwner:TComponent); override;
  282.     Destructor Destroy; override;
  283.  
  284.     function Filtered:TBitmap;
  285.   published
  286.     property Filters:TFilterItems read FFilters write SetFilters stored False;
  287.   end;
  288.  
  289. var
  290.   FilterClasses : TList;
  291.  
  292. procedure TeeRegisterFilters(const FilterList:Array of TFilterClass);
  293. procedure TeeUnRegisterFilters(const FilterList:Array of TFilterClass);
  294.  
  295. procedure ColorToHLS(Color: TColor; out Hue, Luminance, Saturation: Word);
  296. procedure RGBToHLS(const Color: TRGB; out Hue, Luminance, Saturation: Word);
  297.  
  298. procedure HLSToRGB(Hue, Luminance, Saturation: Word; out rgb: TRGB);
  299. function HLSToColor(Hue, Luminance, Saturation: Word):TColor;
  300.  
  301. // Converts ABitmap pixels into Gray Scale (levels of gray) v5.02 (v8 moved from TeCanvas.pas)
  302. Procedure TeeGrayScale(ABitmap:TBitmap; Inverted:Boolean; AMethod:Integer);
  303.  
  304. implementation
  305.  
  306. uses
  307.   Math, SysUtils, TypInfo, TeeConst;
  308.  
  309. procedure TeeRegisterFilters(const FilterList:Array of TFilterClass);
  310. var t : Integer;
  311. begin
  312.   if not Assigned(FilterClasses) then
  313.      FilterClasses:=TList.Create;
  314.  
  315.   for t:=Low(FilterList) to High(FilterList) do
  316.   if FilterClasses.IndexOf({$IFDEF CLR}TObject{$ENDIF}(FilterList[t]))=-1 then
  317.   begin
  318.     FilterClasses.Add({$IFDEF CLR}TObject{$ENDIF}(FilterList[t]));
  319.     RegisterClass(FilterList[t]);
  320.   end;
  321. end;
  322.  
  323. procedure TeeUnRegisterFilters(const FilterList:Array of TFilterClass);
  324. var t : Integer;
  325. begin
  326.   if Assigned(FilterClasses) then
  327.   for t:=Low(FilterList) to High(FilterList) do
  328.       FilterClasses.Remove({$IFDEF CLR}TObject{$ENDIF}(FilterList[t]));
  329. end;
  330.  
  331. { TResizeFilter }
  332.  
  333. function SmoothBitmap(Bitmap:TBitmap; Width,Height:Integer):TBitmap;
  334. begin
  335.   result:=TBitmap.Create;
  336.   TeeSetBitmapSize(result,Width,Height);
  337.   SmoothStretch(Bitmap,result);
  338. end;
  339.  
  340. procedure TResizeFilter.Apply(Bitmap:TBitmap; const R:TRect);
  341. var tmp : TBitmap;
  342. begin
  343.   if (Width>0) and (Height>0) then
  344.   begin
  345.     tmp:=SmoothBitmap(Bitmap,Width,Height);
  346.     try
  347.       TeeSetBitmapSize(Bitmap,Width,Height);
  348.       Bitmap.Canvas.Draw(0,0,tmp);
  349.     finally
  350.       tmp.Free;
  351.     end;
  352.   end;
  353. // Do not call inherited;
  354. end;
  355.  
  356. procedure TResizeFilter.CreateEditor(Creator: IFormCreator;
  357.   AChanged: TNotifyEvent);
  358. begin
  359.   inherited;
  360.   Creator.AddInteger('Width',TeeMsg_Width,0,10000); // Do not localize
  361.   Creator.AddInteger('Height',TeeMsg_Height,0,10000); // Do not localize
  362. end;
  363.  
  364. class function TResizeFilter.Description: String;
  365. begin
  366.   result:=TeeMsg_Resize;
  367. end;
  368.  
  369. { TCropFilter }
  370.  
  371. procedure TCropFilter.Apply(Bitmap: TBitmap; const R: TRect);
  372. var tmp : TBitmap;
  373. begin
  374.   if (Width>0) and (Height>0) then
  375.   begin
  376.     tmp:=TBitmap.Create;
  377.     try
  378.       tmp.PixelFormat:=Bitmap.PixelFormat;
  379.       TeeSetBitmapSize(tmp,Width,Height);
  380.  
  381.       tmp.Canvas.CopyRect(TeeRect(0,0,tmp.Width,tmp.Height),
  382.          Bitmap.Canvas,TeeRect(Left,Top,Left+Width-1,Top+Height-1));
  383.  
  384.       if FSmooth then
  385.          SmoothStretch(tmp,Bitmap)
  386.       else
  387.          Bitmap.Canvas.StretchDraw(TeeRect(0,0,Bitmap.Width-1,Bitmap.Height-1),tmp);
  388.     finally
  389.       tmp.Free;
  390.     end;
  391.   end;
  392.  
  393. // Do not call inherited;
  394. end;
  395.  
  396. procedure TCropFilter.CreateEditor(Creator: IFormCreator;
  397.   AChanged: TNotifyEvent);
  398. begin
  399.   inherited;
  400.   Creator.AddInteger('Left',TeeMsg_Left,0,10000); // Do not localize
  401.   Creator.AddInteger('Top',TeeMsg_Top,0,10000); // Do not localize
  402.   Creator.AddCheckBox('Smooth',TeeMsg_Smooth); // Do not localize
  403. end;
  404.  
  405. class function TCropFilter.Description: String;
  406. begin
  407.   result:=TeeMsg_Crop;
  408. end;
  409.  
  410. { TInvertFilter }
  411. procedure TInvertFilter.Apply(Bitmap:TBitmap; const R:TRect);
  412. var x,: Integer;
  413. begin
  414.   inherited;
  415.  
  416.   if Length(Lines)=0 then
  417.      Exit;
  418.      
  419.   for y:=R.Top to R.Bottom do
  420.     for x:=R.Left to R.Right do
  421.     with Lines[y,x] do
  422.     begin
  423.       Blue:=255-Blue;
  424.       Green:=255-Green;
  425.       Red:=255-Red;
  426.     end;
  427. end;
  428.  
  429. class function TInvertFilter.Description: String;
  430. begin
  431.   result:=TeeMsg_Invert;
  432. end;
  433.  
  434. { TGrayScaleFilter }
  435. procedure TGrayScaleFilter.Apply(Bitmap:TBitmap; const R:TRect);
  436. var x,:  Integer;
  437.     tmp : Byte;
  438. begin
  439.   inherited;
  440.  
  441.   if Length(Lines)=0 then
  442.      Exit;
  443.      
  444.   case Method of
  445.     gmSimple: for y:=R.Top to R.Bottom do
  446.                   for x:=R.Left to R.Right do
  447.                   with Lines[y,x] do
  448.                   begin
  449.                     tmp:=(Blue+Green+Red) div 3;
  450.                     Blue:=tmp;
  451.                     Green:=tmp;
  452.                     Red:=tmp;
  453.                   end;
  454.        gmEye: for y:=R.Top to R.Bottom do
  455.                   for x:=R.Left to R.Right do
  456.                   with Lines[y,x] do
  457.                   begin
  458.                     tmp:=Round( (0.30*Red) +
  459.                                 (0.59*Green) +
  460.                                 (0.11*Blue));
  461.  
  462.                     Blue:=tmp;
  463.                     Green:=tmp;
  464.                     Red:=tmp;
  465.                   end;
  466.       gmEye2: for y:=R.Top to R.Bottom do
  467.                   for x:=R.Left to R.Right do
  468.                   with Lines[y,x] do
  469.                   begin
  470.                     tmp:=(11*Red+16*Green+5*Blue) div 32;
  471.                     Blue:=tmp;
  472.                     Green:=tmp;
  473.                     Red:=tmp;
  474.                   end;
  475.     end;
  476. end;
  477.  
  478. procedure TGrayScaleFilter.CreateEditor(Creator: IFormCreator;
  479.   AChanged: TNotifyEvent);
  480. begin
  481.   inherited;
  482.   Creator.AddCombo('Method'); // Do not localize
  483. end;
  484.  
  485. class function TGrayScaleFilter.Description: String;
  486. begin
  487.   result:=TeeMsg_GrayScale;
  488. end;
  489.  
  490. { TMosaicFilter }
  491. constructor TMosaicFilter.Create(Collection:TCollection);
  492. begin
  493.   inherited;
  494.   FAmount:=8;
  495.   IOnlyPositive:=True;
  496. end;
  497.  
  498. procedure TMosaicFilter.Apply(Bitmap:TBitmap; const R:TRect); {$IFDEF CLR}unsafe;{$ENDIF}
  499. var
  500.   tmpAmountX : Integer;
  501.   tmpAmountY : Integer;
  502.   tmpDims    : Single;
  503.  
  504.   procedure DoMosaic(const tmpX,tmpY:Integer); {$IFDEF CLR}unsafe;{$ENDIF}
  505.   var ar,
  506.       ag,
  507.       ab : Integer;
  508.       xx,
  509.       yy : Integer;
  510.       a    : TRGB;
  511.       Line : PRGBs;
  512.   begin
  513.     ar:=0;
  514.     ag:=0;
  515.     ab:=0;
  516.  
  517.     for yy:=0 to tmpAmountY do
  518.     begin
  519.       Line:=Lines[tmpY+yy];
  520.  
  521.       for xx:=0 to tmpAmountX do
  522.       with Line[tmpX+xx] do
  523.       begin
  524.         Inc(ar,Red);
  525.         Inc(ag,Green);
  526.         Inc(ab,Blue);
  527.       end;
  528.     end;
  529.  
  530.     a.Red:=Round(ar*tmpDims);
  531.     a.Green:=Round(ag*tmpDims);
  532.     a.Blue:=Round(ab*tmpDims);
  533.  
  534.     for yy:=0 to tmpAmountY do
  535.     begin
  536.       Line:=Lines[tmpY+yy];
  537.       for xx:=0 to tmpAmountX do
  538.           Line[tmpX+xx]:=a;
  539.     end;
  540.   end;
  541.  
  542.   procedure DoMosaicRow(const tmpY:Integer);
  543.   var tmpX : Integer;
  544.   begin
  545.     tmpX:=R.Left;
  546.     while tmpX<R.Right-Amount do
  547.     begin
  548.       DoMosaic(tmpX,tmpY);
  549.       Inc(tmpX,Amount);
  550.     end;
  551.  
  552.     // Remainder horizontal mosaic cell
  553.     if tmpX<R.Right then
  554.     begin
  555.       tmpAmountX:=R.Right-tmpX;
  556.       tmpDims:=1.0/(Succ(tmpAmountX)*Succ(tmpAmountY));
  557.  
  558.       DoMosaic(tmpX,tmpY);
  559.  
  560.       tmpAmountX:=tmpAmountY;
  561.       tmpDims:=1.0/Sqr(Amount);
  562.     end;
  563.   end;
  564.  
  565. var tmpY : Integer;
  566. begin
  567.   inherited;
  568.  
  569.   if Length(Lines)=0 then
  570.      Exit;
  571.  
  572.   if Amount>0 then
  573.   begin
  574.     tmpDims:=1.0/Sqr(Amount);
  575.     tmpAmountX:=Amount-1;
  576.     tmpAmountY:=tmpAmountX;
  577.  
  578.     tmpY:=R.Top;
  579.     while tmpY<R.Bottom-Amount do
  580.     begin
  581.       DoMosaicRow(tmpY);
  582.       Inc(tmpY,Amount);
  583.     end;
  584.  
  585.     // Remainder vertical mosaic row cells
  586.     if tmpY<R.Bottom then
  587.     begin
  588.       tmpAmountY:=R.Bottom-tmpY-1;
  589.       tmpDims:=1.0/(Succ(tmpAmountX)*Succ(tmpAmountY));
  590.       DoMosaicRow(tmpY);
  591.     end;
  592.   end;
  593. end;
  594.  
  595. class function TMosaicFilter.Description: String;
  596. begin
  597.   result:=TeeMsg_Mosaic;
  598. end;
  599.  
  600. { TFlipFilter }
  601. procedure TFlipFilter.Apply(Bitmap:TBitmap; const R:TRect); {$IFDEF CLR}unsafe;{$ENDIF}
  602. var tmp : TRGB;
  603.     tmpH,
  604.     tmpY,
  605.     x,: Integer;
  606. begin
  607.   inherited;
  608.  
  609.   if Length(Lines)=0 then
  610.      Exit;
  611.  
  612.   tmpH:=R.Bottom-R.Top;
  613.  
  614.   for y:=R.Top to R.Top+(tmpH div 2)-1 do
  615.       for x:=R.Left to R.Right do
  616.       begin
  617.         tmp:=Lines[y,x];
  618.         tmpY:=tmpH-y;
  619.         Lines[y,x]:=Lines[tmpY,x];
  620.         Lines[tmpY,x]:=tmp;
  621.       end;
  622. end;
  623.  
  624. class function TFlipFilter.Description: String;
  625. begin
  626.   result:=TeeMsg_Flip;
  627. end;
  628.  
  629. { TReverseFilter }
  630. procedure TReverseFilter.Apply(Bitmap:TBitmap; const R:TRect);
  631. var tmp : TRGB;
  632.     tmpW,
  633.     tmpX,
  634.     x,: Integer;
  635. begin
  636.   inherited;
  637.  
  638.   if Length(Lines)=0 then
  639.      Exit;
  640.      
  641.   tmpW:=R.Right-R.Left;
  642.  
  643.   for x:=R.Left to R.Left+(tmpW div 2)-1 do
  644.       for y:=R.Top to R.Bottom do
  645.       begin
  646.         tmp:=Lines[y,x];
  647.         tmpX:=tmpW-x;
  648.         Lines[y,x]:=Lines[y,tmpX];
  649.         Lines[y,tmpX]:=tmp;
  650.       end;
  651. end;
  652.  
  653. class function TReverseFilter.Description: String;
  654. begin
  655.   result:=TeeMsg_Reverse;
  656. end;
  657.  
  658. { TAmountFilter }
  659. Constructor TAmountFilter.Create(Collection:TCollection);
  660. begin
  661.   inherited;
  662.   FPercent:=True;
  663.   FAmount:=5; // %
  664. end;
  665.  
  666. function TAmountFilter.ScrollMin:Integer;
  667. begin
  668.   if FPercent then
  669.      if IOnlyPositive then result:=0 else result:=-100
  670.   else
  671.      if IOnlyPositive then result:=0 else result:=-255;
  672. end;
  673.  
  674. function TAmountFilter.ScrollMax:Integer;
  675. begin
  676.   if FPercent then result:=100
  677.               else result:=255;
  678. end;
  679.  
  680. procedure TAmountFilter.ResetScroll(Sender:TObject);
  681. begin
  682.   FScrollBar.Min:=ScrollMin;
  683.   FScrollBar.Max:=ScrollMax;
  684. end;
  685.  
  686. procedure TAmountFilter.CreateEditor(Creator:IFormCreator; AChanged:TNotifyEvent);
  687. begin
  688.   inherited;
  689.   FScrollBar:=Creator.AddScroll('Amount',ScrollMin,ScrollMax); // Do not localize
  690.   Creator.AddCheckBox('Percent',TeeMsg_Percent,ResetScroll); // Do not localize
  691. end;
  692.  
  693. { TBrightnessFilter }
  694. procedure TBrightnessFilter.Apply(Bitmap:TBitmap; const R: TRect);
  695. var x,y,:  Integer;
  696.     IPercent : Single;
  697. begin
  698.   if Amount=0 then
  699.      Exit;
  700.  
  701.   inherited;
  702.  
  703.   if Length(Lines)=0 then
  704.      Exit;
  705.  
  706.   if Percent then
  707.   begin
  708.     IPercent:=FAmount*0.01;
  709.  
  710.     for y:=R.Top to R.Bottom do
  711.         for x:=R.Left to R.Right do
  712.         with Lines[y,x] do
  713.         begin
  714.           l:=Red+Round(255*IPercent);
  715.           if l<0 then Red:=0 else if l>255 then Red:=255 else Red:=l;
  716.  
  717.           l:=Green+Round(255*IPercent);
  718.           if l<0 then Green:=0 else if l>255 then Green:=255 else Green:=l;
  719.  
  720.           l:=Blue+Round(255*IPercent);
  721.           if l<0 then Blue:=0 else if l>255 then Blue:=255 else Blue:=l;
  722.         end;
  723.   end
  724.   else
  725.   for y:=R.Top to R.Bottom do
  726.       for x:=R.Left to R.Right do
  727.       with Lines[y,x] do
  728.       begin
  729.         l:=Red+Amount;
  730.         if l<0 then Red:=0 else if l>255 then Red:=255 else Red:=l;
  731.  
  732.         l:=Green+Amount;
  733.         if l<0 then Green:=0 else if l>255 then Green:=255 else Green:=l;
  734.  
  735.         l:=Blue+Amount;
  736.         if l<0 then Blue:=0 else if l>255 then Blue:=255 else Blue:=l;
  737.       end;
  738. end;
  739.  
  740. class function TBrightnessFilter.Description: String;
  741. begin
  742.   result:=TeeMsg_Brightness;
  743. end;
  744.  
  745. procedure ColorToHLS(Color: TColor; out Hue, Luminance, Saturation: Word);
  746. var tmp : TRGB;
  747. begin
  748.   Color:=ColorToRGB(Color);
  749.   tmp.Red:=GetRValue(Color);
  750.   tmp.Green:=GetGValue(Color);
  751.   tmp.Blue:=GetBValue(Color);
  752.   RGBToHLS(tmp,Hue,Luminance,Saturation);
  753. end;
  754.  
  755. type
  756.   Float=Single;
  757.  
  758. const
  759.   // HLSMAX BEST IF DIVISIBLE BY 6.  RGBMAX, HLSMAX must each fit in a byte.
  760.   HLSMAX = 240;  // H,L, and S vary over 0-HLSMAX
  761.   RGBMAX = 255;  // R,G, and B vary over 0-RGBMAX
  762.  
  763.   RGBMAX2 = 2.0*RGBMAX;
  764.   InvRGBMAX2 = 1.0/RGBMAX2;
  765.  
  766.   HLSMAXDiv2=HLSMAX/2;
  767.   HLSMAXDiv3=HLSMAX/3;
  768.   HLSMAXDiv6=HLSMAX/6;
  769.   HLSMAXDiv12=HLSMAX/12;
  770.   HLSMAX2=HLSMAX*2;
  771.   HLSMAX3=HLSMAX*3;
  772.   HLSMAX2Div3=HLSMAX2/3;
  773.  
  774.   { Hue is undefined if Saturation is 0 (grey-scale)
  775.     This value determines where the Hue scrollbar is
  776.     initially set for achromatic colors }
  777.   HLSUndefined = 160; // HLSMAX2Div3;
  778.  
  779. procedure RGBToHLS(const Color: TRGB; out Hue, Luminance, Saturation: Word);
  780. var
  781.   H, L, S: Float;
  782.   R, G, B: Word;
  783.   dif : Integer;
  784.   sum, cMax, cMin: Word;
  785.   Rdelta, Gdelta, Bdelta: Extended; { intermediate value: % of spread from max }
  786. begin
  787.   R:=Color.Red;
  788.   G:=Color.Green;
  789.   B:=Color.Blue;
  790.  
  791.   { calculate lightness }
  792.   if R>G then
  793.      if R>B then cMax:=else cMax:=B
  794.   else
  795.      if G>B then cMax:=else cMax:=B;
  796.  
  797.   if R<G then
  798.      if R<B then cMin:=else cMin:=B
  799.   else
  800.      if G<B then cMin:=else cMin:=B;
  801.  
  802.   sum:=(cMax + cMin);
  803.  
  804.   L := ( (sum * HLSMAX) + RGBMAX ) / ( 2 * RGBMAX);
  805.  
  806.   if cMax = cMin then  { r=g=b --> achromatic case }
  807.   begin                { saturation }
  808.     Hue := Round(HLSUndefined);
  809. //    pwHue := 160;      { MS ColoroHLS always defaults to 160 in this case }
  810.     Luminance := Round(L);
  811.     Saturation := 0;
  812.   end
  813.   else                 { chromatic case }
  814.   begin
  815.     dif:=cMax-cMin;
  816.  
  817.     { saturation }
  818.     if L <= HLSMAXDiv2 then
  819.        S := ( (dif*HLSMAX) + (sum*0.5) ) / sum
  820.     else
  821.        S := ( (dif*HLSMAX) + ( RGBMAX-(sum*0.5) )) / (2*RGBMAX-sum);
  822.  
  823.     { hue }
  824.     Rdelta := ( ((cMax-R)*HLSMAXDiv6) + (dif*0.5) ) / dif;
  825.     Gdelta := ( ((cMax-G)*HLSMAXDiv6) + (dif*0.5) ) / dif;
  826.     Bdelta := ( ((cMax-B)*HLSMAXDiv6) + (dif*0.5) ) / dif;
  827.  
  828.     if R = cMax then
  829.        H := Bdelta - Gdelta
  830.     else
  831.     if G = cMax then
  832.        H := HLSMAX3 + Rdelta - Bdelta
  833.     else // B == cMax
  834.        H := HLSUndefined + Gdelta - Rdelta;
  835.  
  836.     if H < 0 then H := H + HLSMAX
  837.     else
  838.     if H > HLSMAX then H := H - HLSMAX;
  839.  
  840.     Hue := Round(H);
  841.     Luminance := Round(L);
  842.     Saturation := Round(S);
  843.   end;
  844. end;
  845.  
  846. function HLSToColor(Hue, Luminance, Saturation: Word):TColor;
  847. var tmp : TRGB;
  848. begin
  849.   HLSToRGB(Hue,Luminance,Saturation,tmp);
  850.   result:=RGB(tmp.Red,tmp.Green,tmp.Blue);
  851. end;
  852.  
  853. procedure HLSToRGB(Hue, Luminance, Saturation: Word; out rgb: TRGB);
  854.  
  855.   function HueToRGB(const Lum, Sat:Float; Hue: Float): Integer;
  856.   begin
  857.     { range check: note values passed add/subtract thirds of range }
  858.     if hue < 0 then hue:=hue+HLSMAX;
  859.     if hue > HLSMAX then hue:=hue-HLSMAX;
  860.  
  861.     { return r,g, or b value from this tridrant }
  862.     if hue < HLSMAXDiv6 then
  863.         Result := Round( Lum + (((Sat-Lum)*hue+HLSMAXDiv12)/HLSMAXDiv6))
  864.     else
  865.     if hue < HLSMAXDiv2 then
  866.         Result := Round( Sat)
  867.     else
  868.     if hue < HLSMAX2Div3 then
  869.         Result := Round( Lum + (((Sat-Lum)*(HLSMAX2Div3-hue)+HLSMAXDiv12)/HLSMAXDiv6) )
  870.     else
  871.         Result := Round( Lum );
  872.   end;
  873.  
  874.   function RoundColor(const Value: Integer): Integer;
  875.   begin
  876.     if Value > 255 then Result := 255 else Result := Round(Value);
  877.   end;
  878.  
  879. var
  880.   Magic1, Magic2: Float;       { calculated magic numbers (really!) }
  881.  
  882.   function RoundColor2(const Hue: Float): Integer;
  883.   begin
  884.     result:=RoundColor(Round((HueToRGB(Magic1,Magic2,Hue)*RGBMAX + HLSMAXDiv2)/HLSMAX));
  885.   end;
  886.  
  887. begin
  888.   if Saturation = 0 then
  889.   with rgb do
  890.   begin            { achromatic case }
  891.     Red := RoundColor(Round((Luminance * RGBMAX)/HLSMAX) );
  892.     Green:=Red;
  893.     Blue:=Green;
  894.     if Hue <> HLSUndefined then ;{ ERROR }
  895.   end
  896.   else
  897.   begin            { chromatic case }
  898.     { set up magic numbers }
  899.     if Luminance <= HLSMAXDiv2 then
  900.        Magic2 := (Luminance * (HLSMAX + Saturation) + HLSMAXDiv2) / HLSMAX
  901.     else
  902.        Magic2 := Luminance + Saturation - ((Luminance * Saturation) + HLSMAXDiv2) / HLSMAX;
  903.  
  904.     Magic1 := 2 * Luminance - Magic2;
  905.  
  906.     { get RGB, change units from HLSMAX to RGBMAX }
  907.     rgb.Red:=RoundColor2(Hue+HLSMAXDiv3);
  908.     rgb.Green:=RoundColor2(Hue);
  909.     rgb.Blue:=RoundColor2(Hue-HLSMAXDiv3);
  910.   end;
  911. end;
  912.  
  913. { TColorFilter }
  914.  
  915. procedure TColorFilter.Apply(Bitmap:TBitmap; const R: TRect); {$IFDEF CLR}unsafe;{$ENDIF}
  916. var x,y    : Integer;
  917.     tmpInt : Integer;
  918.     Line   : PRGBs;
  919. begin
  920.   inherited;
  921.  
  922.   if Length(Lines)=0 then
  923.      Exit;
  924.  
  925.   if (Red<>0) or (Green<>0) or (Blue<>0) then
  926.   for y:=R.Top to R.Bottom do
  927.   begin
  928.     Line:=Lines[y];
  929.  
  930.     for x:=R.Left to R.Right do
  931.     with Line[x] do
  932.     begin
  933.       if Self.FRed<>0 then
  934.       begin
  935.         tmpInt:=Red+Self.FRed;
  936.         if tmpInt<0 then Red:=0 else
  937.         if tmpInt>255 then Red:=255 else
  938.                            Red:=tmpInt;
  939.       end;
  940.  
  941.       if Self.FGreen<>0 then
  942.       begin
  943.         tmpInt:=Green+Self.FGreen;
  944.         if tmpInt<0 then Green:=0 else
  945.         if tmpInt>255 then Green:=255 else
  946.                            Green:=tmpInt;
  947.       end;
  948.  
  949.       if Self.FBlue<>0 then
  950.       begin
  951.         tmpInt:=Blue+Self.FBlue;
  952.         if tmpInt<0 then Blue:=0 else
  953.         if tmpInt>255 then Blue:=255 else
  954.                            Blue:=tmpInt;
  955.       end;
  956.     end;
  957.   end;
  958. end;
  959.  
  960. procedure TColorFilter.CreateEditor(Creator: IFormCreator;
  961.   AChanged: TNotifyEvent);
  962. begin
  963.   inherited;
  964.   Creator.AddScroll('Red',-255,255); // Do not localize
  965.   Creator.AddScroll('Green',-255,255); // Do not localize
  966.   Creator.AddScroll('Blue',-255,255); // Do not localize
  967. end;
  968.  
  969. class function TColorFilter.Description: String;
  970. begin
  971.   result:=TeeMsg_Color;
  972. end;
  973.  
  974. { THueLumSatFilter }
  975.  
  976. procedure THueLumSatFilter.Apply(Bitmap:TBitmap; const R: TRect); {$IFDEF CLR}unsafe;{$ENDIF}
  977. var x,y    : Integer;
  978.     tmpInt : Integer;
  979.     tmpHue : Word;
  980.     tmpLum : Word;
  981.     tmpSat : Word;
  982.     Line   : PRGBs;
  983. begin
  984.   inherited;
  985.  
  986.   if Length(Lines)=0 then
  987.      Exit;
  988.  
  989.   if (FHue<>0) or (FLum<>0) or (FSat<>0) then
  990.   for y:=R.Top to R.Bottom do
  991.   begin
  992.     Line:=Lines[y];
  993.  
  994.     for x:=R.Left to R.Right do
  995.     begin
  996.       RGBToHLS(Line[x],tmpHue,tmpLum,tmpSat);
  997.  
  998.       if Self.FHue<>0 then
  999.       begin
  1000.         tmpInt:=tmpHue+Self.FHue;
  1001.         if tmpInt<0 then tmpHue:=0 else
  1002.         if tmpInt>255 then tmpHue:=255 else
  1003.                            tmpHue:=tmpInt;
  1004.       end;
  1005.  
  1006.       if Self.FLum<>0 then
  1007.       begin
  1008.         tmpInt:=tmpLum+Self.FLum;
  1009.         if tmpInt<0 then tmpLum:=0 else
  1010.         if tmpInt>255 then tmpLum:=255 else
  1011.                            tmpLum:=tmpInt;
  1012.       end;
  1013.  
  1014.       if Self.FSat<>0 then
  1015.       begin
  1016.         tmpInt:=tmpSat+Self.FSat;
  1017.         if tmpInt<0 then tmpSat:=0 else
  1018.         if tmpInt>255 then tmpSat:=255 else
  1019.                            tmpSat:=tmpInt;
  1020.       end;
  1021.  
  1022.       HLSToRGB(tmpHue,tmpLum,tmpSat,Line[x]);
  1023.     end;
  1024.   end;
  1025. end;
  1026.  
  1027. procedure THueLumSatFilter.CreateEditor(Creator: IFormCreator;
  1028.   AChanged: TNotifyEvent);
  1029. begin
  1030.   inherited;
  1031.   Creator.AddScroll('Hue',-255,255); // Do not localize
  1032.   Creator.AddScroll('Luminance',-255,255); // Do not localize
  1033.   Creator.AddScroll('Saturation',-255,255); // Do not localize
  1034. end;
  1035.  
  1036. class function THueLumSatFilter.Description: String;
  1037. begin
  1038.   result:=TeeMsg_HueLumSat;
  1039. end;
  1040.  
  1041. { TSharpenFilter }
  1042.  
  1043. procedure TSharpenFilter.Apply(Bitmap:TBitmap; const R: TRect);
  1044. const Center=2.0;
  1045.       Pix=-((Center-1)/8.0);
  1046. begin
  1047.   Weights[-1,-1]:=Pix;  Weights[-1,0]:=Pix;    Weights[-1,1]:=Pix;
  1048.   Weights[ 0,-1]:=Pix;  Weights[ 0,0]:=Center; Weights[ 0,1]:=Pix;
  1049.   Weights[ 1,-1]:=Pix;  Weights[ 1,0]:=Pix;    Weights[ 1,1]:=Pix;
  1050.  
  1051.   InvTotalWeight:=1.0/16.0;
  1052.  
  1053.   inherited;
  1054. end;
  1055.  
  1056. class function TSharpenFilter.Description: String;
  1057. begin
  1058.   result:=TeeMsg_Sharpen;
  1059. end;
  1060.  
  1061. { TGammaCorrectionFilter }
  1062. Constructor TGammaCorrectionFilter.Create(Collection:TCollection);
  1063. begin
  1064.   inherited;
  1065.   FAmount:=70;
  1066.   IOnlyPositive:=True;
  1067. end;
  1068.  
  1069. procedure TGammaCorrectionFilter.Apply(Bitmap:TBitmap; const R: TRect);
  1070. var t,
  1071.     x,y    : Integer;
  1072.     IGamma : Array[0..255] of Byte;
  1073.     tmp    : Single;
  1074. begin
  1075.   inherited;
  1076.  
  1077.   if Length(Lines)=0 then
  1078.      Exit;
  1079.  
  1080.   tmp:=Max(0.001,Abs(Amount)*0.01);
  1081.  
  1082.   IGamma[0]:=0;
  1083.   for t:=1 to 255 do
  1084.       IGamma[t]:=Round(Exp(Ln(t/255.0)/tmp)*255.0);
  1085.  
  1086.   for y:=R.Top to R.Bottom do
  1087.     for x:=R.Left to R.Right do
  1088.     with Lines[y,x] do
  1089.     begin
  1090.       Red:=IGamma[Red];
  1091.       Green:=IGamma[Green];
  1092.       Blue:=IGamma[Blue];
  1093.     end;
  1094. end;
  1095.  
  1096. class function TGammaCorrectionFilter.Description: String;
  1097. begin
  1098.   result:=TeeMsg_GammaCorrection;
  1099. end;
  1100.  
  1101. { TEmbossFilter }
  1102.  
  1103. procedure TEmbossFilter.Apply(Bitmap:TBitmap; const R: TRect);
  1104. begin
  1105.   Weights[-1,-1]:= 0;  Weights[-1,0]:=-1;    Weights[-1,1]:=0;
  1106.   Weights[ 0,-1]:=-1;  Weights[ 0,0]:=1;     Weights[ 0,1]:=1;
  1107.   Weights[ 1,-1]:= 0;  Weights[ 1,0]:=-1;    Weights[ 1,1]:=0;
  1108.  
  1109.   InvTotalWeight:=1.0/1.0;
  1110.  
  1111.   inherited;
  1112. end;
  1113.  
  1114. class function TEmbossFilter.Description: String;
  1115. begin
  1116.   result:=TeeMsg_Emboss;
  1117. end;
  1118.  
  1119. { TContrastFilter }
  1120.  
  1121. procedure TContrastFilter.Apply(Bitmap:TBitmap; const R: TRect);
  1122. var x,y,:  Integer;
  1123.     IPercent : Single;
  1124. begin
  1125.   inherited;
  1126.  
  1127.   if Length(Lines)=0 then
  1128.      Exit;
  1129.  
  1130.   if Percent then
  1131.      IPercent:=FAmount*0.01
  1132.   else
  1133.      IPercent:=1;
  1134.  
  1135.   for y:=R.Top to R.Bottom do
  1136.       for x:=R.Left to R.Right do
  1137.       with Lines[y,x] do
  1138.       begin
  1139.         if Percent then l:=Red+(Round(Red*IPercent)*(Red-128) div 256)
  1140.                    else l:=Red+(Amount*(Red-128) div 256);
  1141.  
  1142.         if l<0 then Red:=0 else if l>255 then Red:=255 else Red:=l;
  1143.  
  1144.         if Percent then l:=Green+(Round(Green*IPercent)*(Green-128) div 256)
  1145.                    else l:=Green+(Amount*(Green-128) div 256);
  1146.  
  1147.         if l<0 then Green:=0 else if l>255 then Green:=255 else Green:=l;
  1148.  
  1149.         if Percent then l:=Blue+(Round(Blue*IPercent)*(Blue-128) div 256)
  1150.                    else l:=Blue+(Amount*(Blue-128) div 256);
  1151.  
  1152.         if l<0 then Blue:=0 else if l>255 then Blue:=255 else Blue:=l;
  1153.       end;
  1154. end;
  1155.  
  1156. class function TContrastFilter.Description: String;
  1157. begin
  1158.   result:=TeeMsg_Contrast;
  1159. end;
  1160.  
  1161. { TSoftenFilter }
  1162.  
  1163. procedure TSoftenFilter.Apply(Bitmap:TBitmap; const R: TRect);
  1164. begin
  1165.   Weights[-1,-1]:=0;  Weights[-1,0]:=0;    Weights[-1,1]:=0;
  1166.   Weights[ 0,-1]:=0;  Weights[ 0,0]:=1;    Weights[ 0,1]:=1;
  1167.   Weights[ 1,-1]:=0;  Weights[ 1,0]:=1;    Weights[ 1,1]:=1;
  1168.  
  1169.   InvTotalWeight:=1.0/4.0;
  1170.  
  1171.   inherited;
  1172. end;
  1173.  
  1174. class function TSoftenFilter.Description: String;
  1175. begin
  1176.   result:=TeeMsg_AntiAlias;
  1177. end;
  1178.  
  1179. { TImageFiltered }
  1180.  
  1181. Constructor TImageFiltered.Create(AOwner: TComponent);
  1182. begin
  1183.   inherited;
  1184.   FFilters:=TFilterItems.Create(Self,TTeeFilter);
  1185. end;
  1186.  
  1187. Destructor TImageFiltered.Destroy;
  1188. begin
  1189.   FFilters.Free;
  1190.   inherited;
  1191. end;
  1192.  
  1193. function TImageFiltered.Filtered:TBitmap;
  1194. var tmpDest : TBitmap;
  1195.     tmpR    : TRect;
  1196.     tmpW    : Integer;
  1197.     tmpH    : Integer;
  1198. begin
  1199.   result:=TBitmap.Create;
  1200.   result.Assign(Picture.Graphic);
  1201.  
  1202.   tmpR:=DestRect;
  1203.   tmpW:=tmpR.Right-tmpR.Left;
  1204.   tmpH:=tmpR.Bottom-tmpR.Top;
  1205.  
  1206.   if (tmpW<>result.Width) or (tmpH<>result.Height) then
  1207.   begin
  1208.     tmpDest:=SmoothBitmap(result,tmpW,tmpH);
  1209.     result.Free;
  1210.     result:=tmpDest;
  1211.   end;
  1212.  
  1213.   FFilters.ApplyTo(result);
  1214. end;
  1215.  
  1216. procedure TImageFiltered.SetFilters(const Value: TFilterItems);
  1217. begin
  1218.   FFilters.Assign(Value);
  1219. end;
  1220.  
  1221. procedure TImageFiltered.Paint;
  1222. var tmpCanvas : TCanvas;
  1223.     tmp       : TGraphic;
  1224. begin
  1225.   tmp:=Filtered;
  1226.   try
  1227.     tmpCanvas:=TControlCanvas.Create;
  1228.     try
  1229.       TControlCanvas(tmpCanvas).Control:=Self;
  1230.       tmpCanvas.Draw(0,0,tmp);
  1231.  
  1232.       if csDesigning in ComponentState then
  1233.       with tmpCanvas do
  1234.       begin
  1235.         Pen.Style:=psDash;
  1236.         Brush.Style:=bsClear;
  1237.  
  1238.         {$IFDEF CLX}
  1239.         Start;
  1240.         QPainter_setBackgroundMode(Handle,BGMode_TransparentMode);
  1241.         Stop;
  1242.         {$ELSE}
  1243.         SetBkMode(Handle,Windows.TRANSPARENT);
  1244.         {$ENDIF}
  1245.  
  1246.         with ClientRect do
  1247.              Rectangle(Left,Top,Right,Bottom);
  1248.       end;
  1249.     finally
  1250.       tmpCanvas.Free;
  1251.     end;
  1252.   finally
  1253.     tmp.Free;
  1254.   end;
  1255. end;
  1256.  
  1257. procedure TImageFiltered.ReadFilters(Reader: TReader);
  1258. begin
  1259.   TTeePicture.ReadFilters(Reader,Filters);
  1260. end;
  1261.  
  1262. procedure TImageFiltered.WriteFilters(Writer: TWriter);
  1263. begin
  1264.   TTeePicture.WriteFilters(Writer,Filters);
  1265. end;
  1266.  
  1267. function TImageFiltered.FiltersStored:Boolean;
  1268. begin
  1269.   result:=Assigned(FFilters) and (FFilters.Count>0);
  1270. end;
  1271.  
  1272. procedure TImageFiltered.DefineProperties(Filer: TFiler);
  1273. begin
  1274.   inherited;
  1275.   Filer.DefineProperty('FilterItems',ReadFilters,WriteFilters,FiltersStored);  // Do not localize
  1276. end;
  1277.  
  1278. { TRotateFilter }
  1279.  
  1280. Constructor TRotateFilter.Create(Collection:TCollection);
  1281. begin
  1282.   inherited;
  1283.   FBackColor:=clWhite;
  1284.   FAutoSize:=True;
  1285. end;
  1286.  
  1287. procedure TRotateFilter.Apply(Bitmap: TBitmap; const R: TRect); {$IFDEF CLR}unsafe;{$ENDIF}
  1288. const
  1289.   TeePiStep:Single=Pi/180.0;
  1290.  
  1291. var tmp : TBitmap;
  1292.     x,
  1293.     y,
  1294.     xc,
  1295.     yc,
  1296.     xxc,
  1297.     yyc,
  1298.     tmpY,
  1299.     tmpX,
  1300.     h,
  1301.     w   : Integer;
  1302.  
  1303.     f2 : TTeeFilter;
  1304.  
  1305.     f2Lines : PRGBs;
  1306.  
  1307.     xx,
  1308.     yy : Integer;
  1309.  
  1310.     tmpSin,
  1311.     tmpCos,
  1312.     tmpYSin,
  1313.     tmpYCos  : Single;
  1314.  
  1315.     Sin,
  1316.     Cos : Extended;
  1317. begin
  1318.   inherited;
  1319.  
  1320.   if Length(Lines)=0 then
  1321.      Exit;
  1322.  
  1323.   while Angle>360 do
  1324.         FAngle:=Angle-360;
  1325.  
  1326.   if Angle=180 then
  1327.   begin
  1328.     TFlipFilter.ApplyTo(Bitmap);
  1329.     TReverseFilter.ApplyTo(Bitmap);
  1330.   end
  1331.   else
  1332.   if Angle<>0 then
  1333.   begin
  1334.     tmp:=TBitmap.Create;
  1335.     try
  1336.       h:=Bitmap.Height;
  1337.       w:=Bitmap.Width;
  1338.  
  1339.       if (Angle=90) or (Angle=270) then
  1340.          TeeSetBitmapSize(tmp,h,w)
  1341.       else
  1342.       begin
  1343.         SinCos((360-Angle)*TeePiStep,Sin,Cos);
  1344.  
  1345.         if AutoSize then
  1346.         begin
  1347.           if Sin*Cos>0 then
  1348.              TeeSetBitmapSize(tmp,Abs(Round(w*Cos+h*Sin)),
  1349.                                   Abs(Round(w*Sin+h*Cos)))
  1350.           else
  1351.              TeeSetBitmapSize(tmp,Abs(Round(w*Cos-h*Sin)),
  1352.                                   Abs(Round(w*Sin-h*Cos)));
  1353.         end
  1354.         else
  1355.           TeeSetBitmapSize(tmp,w,h);
  1356.       end;
  1357.  
  1358.       if (w>1) and (h>1) then
  1359.       begin
  1360.         if BackColor=clNone then
  1361.            tmp.Transparent:=True
  1362.         else
  1363.         if BackColor<>clWhite then
  1364.         with tmp.Canvas do
  1365.         begin
  1366.           Brush.Style:=bsSolid;
  1367.           Brush.Color:=FBackColor;
  1368.           FillRect(TeeRect(0,0,tmp.Width,tmp.Height));
  1369.         end;
  1370.  
  1371.         f2:=TTeeFilter.Create(nil);
  1372.         try
  1373.           f2.Apply(tmp);
  1374.  
  1375.           if Angle=90 then
  1376.           begin
  1377.             for y:=0 to h-1 do
  1378.                 for x:=0 to w-1 do
  1379.                     f2.Lines[x,h-y-1]:=Lines[y,x];
  1380.           end
  1381.           else
  1382.           if Angle=270 then
  1383.           begin
  1384.             for y:=0 to h-1 do
  1385.                 for x:=0 to w-1 do
  1386.                     f2.Lines[w-x-1,y]:=Lines[y,x];
  1387.           end
  1388.           else
  1389.           begin
  1390.             xxc:=tmp.Width div 2;
  1391.             yyc:=tmp.Height div 2;
  1392.  
  1393.             xc:=div 2;
  1394.             yc:=div 2;
  1395.  
  1396.             tmpSin:=Sin;
  1397.             tmpCos:=Cos;
  1398.  
  1399.             tmpY:=-yyc-1;
  1400.  
  1401.             for y:=0 to tmp.Height-1 do
  1402.             begin
  1403.               Inc(tmpY);
  1404.               tmpYSin:=(tmpY*tmpSin)-xc;
  1405.               tmpYCos:=(tmpY*tmpCos)+yc;
  1406.  
  1407.               f2Lines:=f2.Lines[y];
  1408.  
  1409.               tmpX:=-xxc-1;
  1410.  
  1411.               for x:=0 to tmp.Width-1 do
  1412.               begin
  1413.                 Inc(tmpX);
  1414.  
  1415.                 xx:=Round(tmpX*tmpCos-tmpYSin);
  1416.  
  1417.                 if (xx>=0) and (xx<w) then
  1418.                 begin
  1419.                   yy:=Round(tmpX*tmpSin+tmpYCos);
  1420.  
  1421.                   if (yy>=0) and (yy<h) then
  1422.                      f2Lines[x]:=Lines[yy,xx];
  1423.                 end;
  1424.               end;
  1425.             end;
  1426.           end;
  1427.  
  1428.           Bitmap.FreeImage;
  1429.           Bitmap.Assign(tmp);
  1430.         finally
  1431.           f2.Free;
  1432.         end;
  1433.       end;
  1434.     finally
  1435.       tmp.Free;
  1436.     end;
  1437.   end;
  1438. end;
  1439.  
  1440. class function TRotateFilter.Description: String;
  1441. begin
  1442.   result:=TeeMsg_Rotate;
  1443. end;
  1444.  
  1445. procedure TRotateFilter.SetAngle(const Value: Double);
  1446. begin
  1447.   if FAngle<>Value then
  1448.   begin
  1449.     FAngle:=Value;
  1450.     // Repaint;
  1451.   end;
  1452. end;
  1453.  
  1454. procedure TRotateFilter.CreateEditor(Creator:IFormCreator; AChanged: TNotifyEvent);
  1455. begin
  1456.   inherited;
  1457.   Creator.AddScroll('Angle',0,360); // Do not localize
  1458.   Creator.AddColor('BackColor',TeeMsg_Back); // Do not localize
  1459.   Creator.AddCheckBox('AutoSize',TeeMsg_Autosize); // Do not localize
  1460. end;
  1461.  
  1462. { TMirrorFilter }
  1463.  
  1464. Constructor TMirrorFilter.Create(Collection: TCollection);
  1465. begin
  1466.   inherited;
  1467.   AllowRegion:=False;
  1468. end;
  1469.  
  1470. procedure TMirrorFilter.Apply(Bitmap: TBitmap; const R: TRect);
  1471. var tmp : TBitmap;
  1472. begin
  1473.   inherited;
  1474.  
  1475.   if Length(Lines)=0 then
  1476.      Exit;
  1477.  
  1478.   tmp:=TBitmap.Create;
  1479.   try
  1480.     if (Direction=mdDown) or (Direction=mdUp) then
  1481.     begin
  1482.       TeeSetBitmapSize(tmp,Bitmap.Width,Bitmap.Height*2);
  1483.  
  1484.       if Direction=mdDown then
  1485.          tmp.Canvas.Draw(0,0,Bitmap)
  1486.       else
  1487.          tmp.Canvas.Draw(0,Bitmap.Height,Bitmap);
  1488.  
  1489.       TFlipFilter.ApplyTo(Bitmap);
  1490.  
  1491.       if Direction=mdDown then
  1492.          tmp.Canvas.Draw(0,Bitmap.Height,Bitmap)
  1493.       else
  1494.          tmp.Canvas.Draw(0,0,Bitmap);
  1495.  
  1496.       Bitmap.Height:=Bitmap.Height*2;
  1497.     end
  1498.     else
  1499.     begin
  1500.       TeeSetBitmapSize(tmp,Bitmap.Width*2,Bitmap.Height);
  1501.  
  1502.       if Direction=mdRight then
  1503.          tmp.Canvas.Draw(0,0,Bitmap)
  1504.       else
  1505.          tmp.Canvas.Draw(Bitmap.Width,0,Bitmap);
  1506.  
  1507.       TReverseFilter.ApplyTo(Bitmap);
  1508.  
  1509.       if Direction=mdRight then
  1510.          tmp.Canvas.Draw(Bitmap.Width,0,Bitmap)
  1511.       else
  1512.          tmp.Canvas.Draw(0,0,Bitmap);
  1513.  
  1514.       Bitmap.Width:=Bitmap.Width*2;
  1515.     end;
  1516.  
  1517.     Bitmap.Canvas.Draw(0,0,tmp);
  1518.   finally
  1519.     tmp.Free;
  1520.   end;
  1521. end;
  1522.  
  1523. procedure TMirrorFilter.CreateEditor(Creator: IFormCreator;
  1524.   AChanged: TNotifyEvent);
  1525. begin
  1526.   inherited;
  1527.   Creator.AddCombo('Direction'); // Do not localize
  1528. end;
  1529.  
  1530. class function TMirrorFilter.Description: String;
  1531. begin
  1532.   result:=TeeMsg_Mirror;
  1533. end;
  1534.  
  1535. { TTileFilter }
  1536.  
  1537. Constructor TTileFilter.Create(Collection: TCollection);
  1538. begin
  1539.   inherited;
  1540.   FNumCols:=3;
  1541.   FNumRows:=3;
  1542. end;
  1543.  
  1544. procedure TTileFilter.Apply(Bitmap: TBitmap; const R: TRect);
  1545. var tmpCol,
  1546.     tmpRow,
  1547.     tmpW,
  1548.     tmpH : Integer;
  1549.     tmp  : TBitmap;
  1550. begin
  1551.   inherited;
  1552.  
  1553.   if Length(Lines)=0 then
  1554.      Exit;
  1555.  
  1556.   if FNumCols<1 then FNumCols:=1;
  1557.   if FNumRows<1 then FNumRows:=1;
  1558.  
  1559.   tmpW:=(R.Right-R.Left) div FNumCols;
  1560.   tmpH:=(R.Bottom-R.Top) div FNumRows;
  1561.  
  1562.   if (tmpW>0) and (tmpH>0) then
  1563.   begin
  1564.     tmp:=SmoothBitmap(Bitmap,tmpW,tmpH);
  1565.     try
  1566.       for tmpCol:=0 to FNumCols-1 do
  1567.           for tmpRow:=0 to FNumRows-1 do
  1568.               Bitmap.Canvas.Draw(tmpCol*tmpW,tmpRow*tmpH,tmp);
  1569.     finally
  1570.       tmp.Free;
  1571.     end;
  1572.   end;
  1573. end;
  1574.  
  1575. procedure TTileFilter.CreateEditor(Creator: IFormCreator;
  1576.   AChanged: TNotifyEvent);
  1577. begin
  1578.   inherited;
  1579.   Creator.AddInteger('NumCols',TeeMsg_Columns,1,1000); // Do not localize
  1580.   Creator.AddInteger('NumRows',TeeMsg_Rows,1,1000); // Do not localize
  1581. end;
  1582.  
  1583. class function TTileFilter.Description: String;
  1584. begin
  1585.   result:=TeeMsg_Tile;
  1586. end;
  1587.  
  1588. { TBevelFilter }
  1589.  
  1590. Constructor TBevelFilter.Create(Collection: TCollection);
  1591. begin
  1592.   inherited;
  1593.   FBright:=64;
  1594.   FSize:=15;
  1595. end;
  1596.  
  1597. procedure TBevelFilter.Apply(Bitmap: TBitmap; const R: TRect);
  1598. var t,
  1599.     x,y,
  1600.     h2,w2,
  1601.     x1,x2,
  1602.     y1,y2 : Integer;
  1603. begin
  1604.   inherited;
  1605.  
  1606.   if Length(Lines)=0 then
  1607.      Exit;
  1608.  
  1609.   x1:=R.Left;
  1610.   x2:=R.Right;
  1611.   y1:=R.Top;
  1612.   y2:=R.Bottom;
  1613.  
  1614.   w2:=(R.Right-R.Left) div 2;
  1615.   h2:=(R.Bottom-R.Top) div 2;
  1616.  
  1617.   for t:=0 to FSize-1 do
  1618.   begin
  1619.     if t<h2 then
  1620.     for x:=R.Left+to R.Right-do
  1621.     begin
  1622.       with Lines[y1,x] do
  1623.       begin
  1624.         if Red+Bright>255 then Red:=255
  1625.                           else Inc(Red,Bright);
  1626.         if Green+Bright>255 then Green:=255
  1627.                             else Inc(Green,Bright);
  1628.         if Blue+Bright>255 then Blue:=255
  1629.                            else Inc(Blue,Bright);
  1630.       end;
  1631.  
  1632.       with Lines[y2,x] do
  1633.       begin
  1634.         if Red-Bright<0 then Red:=0
  1635.                         else Dec(Red,Bright);
  1636.         if Green-Bright<0 then Green:=0
  1637.                           else Dec(Green,Bright);
  1638.         if Blue-Bright<0 then Blue:=0
  1639.                          else Dec(Blue,Bright);
  1640.       end;
  1641.  
  1642.     end;
  1643.  
  1644.     Inc(y1);
  1645.     Dec(y2);
  1646.  
  1647.     if t<w2 then
  1648.     for y:=R.Top+t+1 to R.Bottom-do
  1649.     begin
  1650.       with Lines[y,x1] do
  1651.       begin
  1652.         if Red+Bright>255 then Red:=255
  1653.                           else Inc(Red,Bright);
  1654.         if Green+Bright>255 then Green:=255
  1655.                             else Inc(Green,Bright);
  1656.         if Blue+Bright>255 then Blue:=255
  1657.                            else Inc(Blue,Bright);
  1658.       end;
  1659.  
  1660.       with Lines[y,x2] do
  1661.       begin
  1662.         if Red-Bright<0 then Red:=0
  1663.                         else Dec(Red,Bright);
  1664.         if Green-Bright<0 then Green:=0
  1665.                           else Dec(Green,Bright);
  1666.         if Blue-Bright<0 then Blue:=0
  1667.                          else Dec(Blue,Bright);
  1668.       end;
  1669.     end;
  1670.  
  1671.     Inc(x1);
  1672.     Dec(x2);
  1673.   end;
  1674. end;
  1675.  
  1676. procedure TBevelFilter.CreateEditor(Creator: IFormCreator;
  1677.   AChanged: TNotifyEvent);
  1678. begin
  1679.   inherited;
  1680.   Creator.AddScroll('Bright',1,255); // Do not localize
  1681.   Creator.AddScroll('Size',1,1000); // Do not localize
  1682. end;
  1683.  
  1684. class function TBevelFilter.Description: String;
  1685. begin
  1686.   result:=TeeMsg_Bevel;
  1687. end;
  1688.  
  1689. { TZoomFilter }
  1690.  
  1691. Constructor TZoomFilter.Create(Collection: TCollection);
  1692. begin
  1693.   inherited;
  1694.   FPercent:=10;
  1695. end;
  1696.  
  1697. procedure TZoomFilter.Apply(Bitmap: TBitmap; const R: TRect);
  1698. var w,h,
  1699.     wp,hp : Integer;
  1700.  
  1701.   procedure DoCrop(ALeft,ATop:Integer; ABitmap:TBitmap);
  1702.   begin
  1703.     with TCropFilter.Create(nil) do
  1704.     try
  1705.       Left:=ALeft+wp;
  1706.       Top:=ATop+hp;
  1707.       Width:=Max(1,w-2*wp);
  1708.       Height:=Max(1,h-2*hp);
  1709.       Smooth:=Self.Smooth;
  1710.       Apply(ABitmap,R);
  1711.     finally
  1712.       Free;
  1713.     end;
  1714.   end;
  1715.  
  1716. var tmp : TBitmap;
  1717. begin
  1718.   w:=R.Right-R.Left+1;
  1719.   h:=R.Bottom-R.Top+1;
  1720.   wp:=Round(FPercent*w*0.005);
  1721.   hp:=Round(FPercent*h*0.005);
  1722.  
  1723.   if (Bitmap.Width=w) and (Bitmap.Height=h) then
  1724.      DoCrop(R.Left,R.Top,Bitmap)
  1725.   else
  1726.   begin
  1727.     tmp:=TBitmap.Create;
  1728.     try
  1729.       TeeSetBitmapSize(tmp,w,h);
  1730.       tmp.Canvas.CopyRect(TeeRect(0,0,w,h),Bitmap.Canvas,R);
  1731.  
  1732.       DoCrop(0,0,tmp);
  1733.  
  1734.       Bitmap.Canvas.Draw(R.Left,R.Top,tmp);
  1735.     finally
  1736.       tmp.Free;
  1737.     end;
  1738.   end;
  1739. end;
  1740.  
  1741. procedure TZoomFilter.CreateEditor(Creator: IFormCreator;
  1742.   AChanged: TNotifyEvent);
  1743. begin
  1744.   inherited;
  1745.   Creator.AddScroll('Percent',0,100); // Do not localize
  1746.   Creator.AddCheckBox('Smooth',TeeMsg_Smooth); // Do not localize
  1747. end;
  1748.  
  1749. class function TZoomFilter.Description: String;
  1750. begin
  1751.   result:=TeeMsg_Zoom;
  1752. end;
  1753.  
  1754. procedure RotateGradient(Gradient:TCustomTeeGradient; ABitmap:TBitmap);
  1755. begin
  1756.   with TRotateFilter.Create(nil) do
  1757.   try
  1758.     Angle:=Gradient.Angle;
  1759.     Apply(ABitmap);
  1760.   finally
  1761.     Free;
  1762.   end;
  1763. end;
  1764.  
  1765. // This procedure will convert all pixels in ABitmap to levels of gray
  1766. Procedure TeeGrayScale(ABitmap:TBitmap; Inverted:Boolean; AMethod:Integer);
  1767. var tmp : TGrayScaleFilter;
  1768. begin
  1769.   tmp:=TGrayScaleFilter.Create(nil);
  1770.   try
  1771.     if AMethod<>0 then tmp.Method:=gmEye;
  1772.     tmp.Apply(ABitmap);
  1773.   finally
  1774.     tmp.Free;
  1775.   end;
  1776.  
  1777.   if Inverted then
  1778.      TInvertFilter.ApplyTo(ABitmap);
  1779. end;
  1780.  
  1781. initialization
  1782.   TeeRegisterFilters([ TInvertFilter,
  1783.                        TGrayScaleFilter,
  1784.                        TMosaicFilter,
  1785.                        TFlipFilter,
  1786.                        TReverseFilter,
  1787.                        TBrightnessFilter,
  1788.                        TContrastFilter,
  1789.                        TColorFilter,
  1790.                        THueLumSatFilter,
  1791.                        TBlurFilter,
  1792.                        TSharpenFilter,
  1793.                        TGammaCorrectionFilter,
  1794.                        TEmbossFilter,
  1795.                        TSoftenFilter,
  1796.                        TCropFilter,
  1797.                        TResizeFilter,
  1798.                        TRotateFilter,
  1799.                        TMirrorFilter,
  1800.                        TTileFilter,
  1801.                        TBevelFilter,
  1802.                        TZoomFilter ]);
  1803.  
  1804.   TeeGradientRotate:=RotateGradient;
  1805. finalization
  1806.   TeeGradientRotate:=nil;
  1807.   FreeAndNil(FilterClasses);
  1808. end.
  1809.  
  1810.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值