Advertisement
Stella_209

STAF_Imp.pas

May 29th, 2018
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 158.38 KB | None | 0 0
  1. (*
  2.   STAF - BASIC IMEGE PROCESSES UNIT  Ver 1.0.0.1
  3.   ---------------------------------
  4.   By Agócs László 2008
  5. *)
  6.  
  7. (*
  8.   STAF - StarFactory Image Process Library for Astrophotographers
  9.   -----------------------------------------------------------------
  10.   by Agócs László Hungarian Amateur Astronomer in StellaObservatory
  11.      Email: lagocsstella@gmail.com
  12.      Website: http://stella_209.extra.hu/
  13.  
  14.   Licence: GPU licence;  'Do anything you wish!'
  15.  
  16.   This unit contains:
  17.   - BASIC IMAGE PROCESSES: Brightness, Darken, Threshold, Contrast, .....
  18.   - ADVENCE IMAGE PROCESSES:
  19.   - IMAGE EFFECTS:
  20.   - PUBLISHING IMAGES: Bordered image, labels, lists, hotmap, ....
  21.   - ASTROPHOTOGRAPHY RUTINF FOR PROCESSES AND ANALYSIS
  22.     - ASTROMETRY
  23.     - PHOTOMETRY
  24. *)
  25.  
  26. unit STAF_Imp;
  27.  
  28. interface
  29.  
  30. uses
  31.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  32.   ShellApi, ClipBrd, CommCtrl, ExtCtrls, Math, Jpeg, NewGeom, Szamok, Szoveg;
  33.  
  34.  
  35. Const PixelMax = 6000;
  36.  
  37. Type
  38.    pPixelArray = ^TPixelArray;
  39.    TPixelArray = Array[0..PixelMax-1] Of TRGBTriple;
  40.    PRGBTripleArray = ^TRGBTripleArray;
  41.    TRGBTripleArray = array[0..PixelMax] of TRGBTriple;
  42.    T3x3FloatArray = array[0..2] of array[0..2] of Extended;
  43.  
  44.    PRGB24 = ^TRGB24;
  45.    TRGB24 = record B, G, R: Byte; end;
  46.    PRGBArray = ^TRGBArray;
  47.    TRGBArray = array [Word] of TRGB24;
  48.  
  49.    TRGBColorsArray  = Array[0..2,0..255] of Cardinal; // RGB szinek tömbje for histogram
  50.  
  51.    TRGBStatisticArray = Array[0..2,0..255] of double; // RGB szinek tömbje for statistic (%)
  52.  
  53.    TStarPixelsArray = Array of TPoint;
  54.  
  55.    TBMPAction = (bacNone, bacFlipVertical, bacFlipHorizontal,
  56.                  bacGrayscale, bacNegative, bacFlaxen, bacEmboss
  57.                  );
  58.  
  59.   // Indicates which chanel is active in image
  60.   TRGBList = (rgbRGB,rgbR,rgbG,rgbB);
  61.   TRGBSet = set of TRGBList;
  62.  
  63.   pThreshold   = ^TThreshold;
  64.   TThreshold   = TRGB24;      // Record for average of threshold or measuring
  65.  
  66.   pStarRecord = ^TStarRecord;
  67.   TStarRecord = packed record         // Record for star detection
  68.      ID       : integer;
  69.      PixCount : integer;
  70.      x,y      : double;
  71.      Radius   : double;
  72.      R,G,B    : word;
  73.      HalfRad  : double;        // Wide of half intensity
  74.      Intensity: double;        // Average intenzity in the HalfRad
  75.      mg       : double;        // magnitude
  76.      Dist     : double;
  77.      Selected : boolean;
  78.      Deleted  : boolean;
  79.      Filtered : boolean;
  80.   end;
  81.  
  82.  
  83.   TStarIndexList  = array of integer;              // Index list for stars' IDs
  84.   TStarArray      = Array of TStarRecord;          // List for stars
  85.  
  86.   CSILLAG = Record
  87.     StarCount : integer;                           // Stars count
  88.     StarArray : Array of TStarRecord;              // Array of Star's datas
  89.   end;
  90.  
  91.   TDrawingTool = (dtNone, dtPoint, dtLine, dtInfo, dtRectangle,
  92.        dtRoundRect, dtEllipse, dtFillRect, dtFillRoundRect,
  93.        dtFillEllipse, dtPolyLine, dtPolygon, dtIv, dtText,
  94.        dtExtraText, dtBrush);
  95.  
  96.  
  97.   ProcessCommand = (
  98.                  pcRGBChanel,       // Select RGB chanel: par=1 : R,G,B,RGB
  99.                  pcMono,            // Monochrome image;  par=0;
  100.                  pcInvers,          // Invers image;      par=0;
  101.                  pcTurnLeft,        // Turn left 90 deg.  par=0;
  102.                  pcTurnRight,       // Turn right 90 deg. par=0;
  103.                  pcRotate,          // Rotate             par=1 : Deg
  104.                  pcBright,          // Brightness         par=1 : Amount
  105.                  pcContrast,        // Brightness         par=1 : Amount
  106.                  pcLevel,           // Brightness         par=1 : LevelStep
  107.                  pcBlur,            // Blur               par=1 : Amount
  108.                  pcSaturate,        // Saturate           par=1 : Amount
  109.                  pcHighPass,        // HighPass           par=1 : Amount(0..255)
  110.                  pcLowPass,         // LowPass            par=1 : Amount(0..255)
  111.                  pcHighPassEx,      // HighPass           par=1 : Amount(0..255)
  112.                  pcLowPassEx,       // LowPass            par=1 : Amount(0..255)
  113.                  pcThresElim,       // Threshold elimin.  par=1 : ThresHoldLevel
  114.                  pcCreateMasterDark,// Create a master dark     par=1 : DarkList
  115.                  pcCreateMasterFlat,// Create a median flat     par=1 : FlatList
  116.                  pcCreateMasterLight,// Create a median light   par=1 : FlatList
  117.                  pcHotPixelCorrect,
  118.                  pcReScale,
  119.                  pcMosaic,
  120.                  pcLoad,
  121.                  pcSave,
  122.                  pcCopyToClipboard,
  123.                  pcStarDetect,
  124.                  pcPrecisionStarDeave
  125.                  );
  126.  
  127.   TProcessAction = record
  128.      ProcessText : String[50];   // Process by text: e.x. 'Contrast 100'
  129.      ProcessIdx  : integer;
  130.      Params      : Array of Variant;
  131.   end;
  132.  
  133.   TProcessActionList = TStringList;
  134.  
  135.   TBMPFileHeaderStruct = record
  136.     BM           : word;           // 00h 'BM' Characters
  137.     BMPSize      : integer;        // 02h Size of the BMP file
  138.     AppSpec1     : word;           // 06h Application Specific - none used
  139.     AppSpec2     : word;           // 08h Application Specific - none used
  140.     DataOffset   : word;           // 0Ah The offset where the bitmap data (pixels) can be found.
  141.     NumberOfByte : integer;        // 0Eh The number of bytes in the header (from this point).
  142.     BMPWidth     : integer;        // 12h The width of the bitmap in pixels
  143.     BMPHeight    : integer;        // 16h The height of the bitmap in pixels
  144.     Planes       : word;           // 1Ah Number of color planes being used.
  145.     BitPerPixel  : word;           // 1Ch bits/pixel.
  146.     Compression  : integer;        // 1Eh BI_RGB, No compression used = 0;
  147.     RAWBMP       : integer;        // 22h The size of the raw BMP data (after this header)
  148.     HResolution  : integer;        // 26h The horizontal resolution of the image
  149.     VResolution  : integer;        // 2Ah The horizontal resolution of the image
  150.     ColorNumber  : integer;        // 2Eh Number of colors in the palette
  151.     iColor       : integer;        // 32h Means all colors are important
  152.   end;
  153.  
  154.  
  155.   TRefStarRecord = packed record
  156.     Id          : integer;         // Index of the reference star in the starlist
  157.     x,y         : double;          // Coordinates of the star
  158.     distance    : double;          // Distance from 0. ref. star
  159.     angle       : double;          // Angle from 0. ref. star
  160.     Radius      : double;          // Brightness of ref. star
  161.   end;
  162.  
  163.   TRefStarArray = array of TRefStarRecord;
  164.  
  165.  
  166. type
  167.   TPlaneType = (ptOrthogonal, ptStretched);
  168.  
  169.   TPlane = record
  170.     PlaneType: TPlaneType;
  171.     Origin,
  172.     X_Axis,
  173.     Y_Axis: TPoint;
  174.   end;
  175.  
  176.   TStretchHeader = record
  177.     SourcePlane,
  178.     TargetPlane: TPlane;
  179.   end;
  180.  
  181.   TRotateRec = record
  182.     x1, y1, x2, y2, w, h,           // Forrás téglalap két szemközti a,c csúcsa
  183.     x1s, y1s, x2s, y2s, x3s, y3s,   // cél paralelogramma 3 csúcsa: a,b,d
  184.     ww, hh, maxw, maxh,
  185.     ptr1, ptr2,
  186.     ptrscanline1, ptrscanline2: integer;
  187.   end;
  188.  
  189.   TArray = record
  190.     x, y, cor: integer;
  191.   end;
  192.  
  193.   TStretchBitmap = class
  194.   private
  195.     R: TRotateRec;
  196.     FBackgroundColor: TColor;
  197.     procedure MakeArray(X1S, X2S, Y1S, Y2S, W: integer; WW_ptr, ptr: Pointer);
  198.     procedure SetBackgroundColor(const Value: TColor);
  199.   public
  200.     SourceBitmap,      //the bitmap that is about to be transformed
  201.     TargetBitmap: TBitmap;    //the bitmap to save the transformed image
  202.     ResizeTargetBitmap: Boolean;  //set if you want to resize the target bitmap
  203.  
  204.     StretchHeader: TStretchHeader;  //transformation vectors
  205.     ErrorX, ErrorY: integer;    //shows point where an error occurred
  206.     constructor Create;
  207.     destructor Destroy;
  208.  
  209.     function StretchBitm(Bitmap, Target: TBitmap; R: TRotateRec): Boolean;
  210.     procedure StretchArea(R: TRotateRec; ErrX, ErrY: integer);
  211.     function CheckPlane(pl: TPlane): Boolean;
  212.     procedure AdjustTargetPlaneToBitmap;
  213.  
  214.     { Transfor the source rect to a dest paralelogram }
  215.     procedure TransBMP
  216.             ( src,dst  : TBitmap;      // Source, Destination bitmap,
  217.               srcRect  : TRect;        // Source rectangle in src bitmap
  218.               Cent     : TPoint2d;     // Centrum of the destination
  219.               Zoom     : double;       // Zoom
  220.               RotAngle : double);      // Rotate angle
  221.  
  222.     function StretchIt: Boolean;  //stretch the bitmap according to StretchHeader
  223.     function RotateIt(RotationAngle: Single): Boolean; overload; //rotate bitmsp
  224.     function RotateIt(RotationAngle,Magnify: double): Boolean; overload;
  225.     function SkewIt(Horizontally, Vertically: Single): Boolean;  //skew bitmap
  226.     property BackgroundColor: TColor read FBackgroundColor write SetBackgroundColor;
  227.   end;
  228.  
  229.  
  230. Var
  231.     // BMP's are created and destroyed by this unit: you need not to do!
  232.     OrigBMP : TBitmap; // Original bitmap
  233.     bmp     : TBitmap; // bitmap for else
  234.     wbmp    : TBitmap; // work bitmap copied from Origbmp
  235.  
  236.     AvgThreshold    : TThreshold;    // for average of threshold
  237.     ThresholdFactor : double = 1;    // Subjective factor for threshold
  238.  
  239.     StarCount : integer;                           // Stars count
  240.     StarArray : Array[0..80000] of TStarRecord;    // Array of Star's datas
  241.     stRec     : TStarRecord;                       // Star record for any usage
  242.  
  243.     ActivePhotometry : boolean;              // Photometry in active mode
  244.  
  245.     ProcessList : TStringList;               // For programming processes
  246.  
  247.  
  248. // NEEDED ROUTINS
  249.  
  250.   procedure SortArray(var A : array of integer);
  251.   function MedianAverage(var A : array of integer) : integer;
  252.   function InRange(Test,Min,Max: integer): Boolean; overload;
  253.   function InRange(Test,Min,Max: double): Boolean; overload;
  254.   function Range(Test,Min,Max: Integer): Integer;
  255.   function BoolToStr(bVal: boolean): string;
  256.   function IntToByte(i:Integer):Byte;
  257.   function FloatToByte(i:double):Byte;
  258.   function Set255(Clr : integer) : integer;
  259.   procedure quicksort(var a: array of integer);
  260.   function GetCoordStr(x,y: integer): string; overload;
  261.   function GetCoordStr(x,y: double): string; overload;
  262.   function PointToCoord(p: TPoint): string;
  263.   function GetRGBStr(co: TColor): string;
  264.  
  265.   function RectMagnify(R: TRect; n: double):TRect;
  266.   function RectInflate(R: TRect; dx,dy: integer):TRect;
  267.  
  268.   function BMPCopy( SourceBitmap : TBitmap; DestBitmap : TBitmap ):boolean;
  269.   procedure CopyMe(tobmp: TBitmap; frbmp : TGraphic);
  270.   function BMPResize( Bitmap:TBitmap ; const x,y: integer ):boolean;
  271.   function ScalePercentBmp(bitmp: TBitmap; iPercent: Integer): Boolean;
  272.   function Load_Bitmap(FName: string; BM: TBitmap): boolean;
  273.   function Save_Bitmap(FName: string; BM: TBitmap): boolean;
  274.   function Delete_file(FName: string): boolean;
  275.  
  276. // DIR and File rutines
  277.  
  278.   procedure GetSubDirs(const sRootDir: string; slt: TStrings);
  279.   procedure GetJPGSize(const sFile: string; var wWidth, wHeight: word);
  280.   procedure GetPNGSize(const sFile: string; var wWidth, wHeight: Word);
  281.   procedure GetGIFSize(const sGIFFile: string; var wWidth, wHeight: Word);
  282.   function WinExecAndWait32(FileName: string; Visibility: Integer): Longword;
  283.   procedure ShellExecute_AndWait(FileName: string; Params: string);
  284.  
  285. // CLIPBOARD rutins
  286.  
  287.   procedure CopyStreamFromClipboard(fmt: Cardinal; S: TStream);
  288.   procedure CopyStreamToClipboard(fmt: Cardinal; S: TStream);
  289.  
  290. // RGB Colors
  291.  
  292.   function ColorToTriple(Color:TColor):TRGBTriple;
  293.   function TripleToColor( RGB: TRGBTriple):TColor;
  294.   function ChangeRGBColor(var color:TRGBTriple;R,G,B:integer):TRGBTriple;
  295.   procedure ChangeRGB(var Bitmap:TBitmap;R,G,B: double);
  296.  
  297. // BASIC IMAGE PROCESSES
  298.  
  299.   procedure DoBMPAction( var Bitmap:TBitmap; BMPAction: TBMPAction;
  300.                        Par1, Par2, Par3: Variant);
  301. //  procedure DoBMPAction( var Bitmap:TBitmap; BMPAction: TBMPAction);
  302.   procedure DrawShape(Canv: TCanvas; DrawingTool:TDrawingTool; T,B: TPoint;
  303.            AMode: TPenMode);
  304.  
  305.   // Transformations
  306.   procedure TurnLeft(src,dst:tbitmap);
  307.   procedure TurnRight(src,dst:Tbitmap);
  308.  
  309.     procedure AntiAlias(clip:tbitmap);
  310.     procedure AntiAliasRect(clip:tbitmap;XOrigin, YOrigin, XFinal, YFinal: Integer);
  311.  
  312.   procedure Lightness( Bitmap:TBitmap; Amount: Integer);
  313.   procedure Brightness( Bitmap:TBitmap; Amount: integer);
  314.   procedure Darkness( Bitmap:TBitmap; Amount: integer);
  315.   procedure Contrast(var Bitmap:TBitmap; Amount: Integer);
  316.   procedure ContrastNess(var clip: tbitmap; Amount: Integer);
  317.   procedure Gamma(var Bitmap:TBitmap; Amount: double);
  318.   procedure KeepBlue(src:Tbitmap;factor:extended);
  319.   procedure KeepGreen(src:Tbitmap;factor:extended);
  320.   procedure KeepRed(src:Tbitmap;factor:extended);
  321.   procedure Saturation(var  Bitmap: TBitmap; Amount: Integer);
  322.   Procedure ColorAdjust(var Bitmap:TBitmap; AmountR, AmountG, AmountB: double);
  323.   Procedure ColorAdjustEx(var Bitmap:TBitmap; Threshold: byte);
  324.   Procedure ColorNoiseElimination(var Bitmap:TBitmap);
  325.  
  326.   procedure Threshold( Bitmap:TBitmap ; const Light:TRgbTriple;
  327.             const Dark:TRgbTriple; Amount:Integer = 128);
  328.  
  329.             // The fast rotation
  330.   function CreateRotatedBitmap(Bitmap: TBitmap; const Angle: Extended; bgColor: TColor): TBitmap;
  331.             // The slow rotation
  332.   Procedure RotateBitmap( SourceBitmap : TBitmap; out DestBitmap : TBitmap;
  333.             Center : TPoint; Angle : Double) ;
  334.  
  335.   procedure Negative(var Bitmap:TBitmap);
  336.   Procedure GrayScale(var Bitmap:TBitmap);
  337.   procedure BlackAndWhite(var Bitmap:TBitmap);
  338.  
  339.   procedure Crop(var Bitmap:TBitmap; Rec: TRect);
  340.   procedure FlipHorizontal(var Bitmap:TBitmap);
  341.   procedure FlipVertical(var Bitmap:TBitmap);
  342.  
  343.   procedure Flaxen( Bitmap:TBitmap);
  344.   procedure Emboss(Bitmap : TBitmap; AMount : Integer);
  345.   Procedure Blur( var Bitmap :TBitmap);
  346.   procedure SplitBlur(var clip:tbitmap;Amount:integer);
  347.   procedure GaussianBlur(var clip:tbitmap;Amount: integer);
  348.   procedure Posterize(Bitmap: TBitmap; amount: integer);
  349.   procedure Sepia ( Bitmap:TBitmap;depth:byte);
  350.  
  351.   procedure MonoNoise(var Bitmap: TBitmap; Amount: Integer);
  352.   procedure ColorNoise( Bitmap: TBitmap; Amount: Integer);
  353.   procedure Mosaic(var Bm: TBitmap; size: Integer);
  354.  
  355.   procedure FadeOut(const Bmp: TImage; Pause: Integer);
  356.   procedure ChangeRGBChanel(Bitmap : TBitmap; RCh,GCh,BCh: boolean); overload;
  357.   procedure ChangeRGBChanel(Bitmap : TBitmap; Mono,RCh,GCh,BCh: boolean); overload;
  358.   procedure ChangeRGBChanelToMonochrome(Bitmap : TBitmap; RCh,GCh,BCh: boolean);
  359.   procedure StepRGB(Bitmap: TBitmap; Step: byte);
  360.   procedure StepRGBContur(Bitmap: TBitmap; Step: byte;
  361.                                 ConturColor: TColor);
  362.  
  363.   procedure DrawCentralCross(Ca: TCanvas; cPen: Tpen);
  364.  
  365.   function ShowBaloonHint(Point: TPoint; Handle: THandle; Title: String;
  366.            Msg: String; Icon: Integer): Boolean;
  367.  
  368.     function AbovePass(var vol: byte; amount: byte):byte;
  369.     function BelowPass(var vol: byte; amount: byte):byte;
  370.     function EqualPass(var vol: byte; amount: byte):byte;
  371.  
  372.   procedure HighPass(Bitmap: TBitmap; R,G,B: byte);
  373.   procedure LowPass(Bitmap: TBitmap; R,G,B: byte);
  374.   procedure HighPassEx(Bitmap: TBitmap; amount:integer);
  375.   procedure LowPassEx(Bitmap: TBitmap; amount:integer);
  376.   procedure SlicePass(Bitmap: TBitmap; Low,High:integer);
  377.  
  378.   procedure EdgeDetect(Bitmap: TBitmap);
  379.   PROCEDURE Convolve(ABitmap : TBitmap ; AMask : T3x3FloatArray ; ABias : integer);
  380.   procedure ConvolveM(ray : array of integer; z : word; aBmp : TBitmap);
  381.   procedure ConvolveE(ray : array of integer; z : word; aBmp : TBitmap);
  382.   procedure ConvolveI(ray : array of integer; z : word; aBmp : TBitmap);
  383.   procedure ConvolveFilter(filternr,edgenr:integer;src:TBitmap);
  384.   procedure Median(src:TBitmap);
  385.  
  386.     (*  BAD PIXEL CORRECTIONS *)
  387.  
  388. function FixStuckPixels(Bitmap: TBitmap; Threshold: byte; difference: byte): integer;
  389. function GetStuckPixelsStatistic(Bitmap: TBitmap; VAR stpa: array of TPoint;
  390.                                  Threshold: byte; difference: byte): integer;
  391.  
  392.     (*  FRAMES CORRECTIONS *)
  393.  
  394. function SubtractDark(SrcBitmap, DarkBitmap: TBitmap): boolean;
  395. function FlatCorrection(SrcBitmap, FlatBitmap: TBitmap): boolean;
  396. function AddFrames(SrcBitmap1, SrcBitmap2: TBitmap; var DstkBitmap: TBitmap): boolean;
  397. function AddFramesLimited(SrcBitmap1, SrcBitmap2: TBitmap; var DstkBitmap: TBitmap;
  398.                           Limit: integer ): boolean;
  399. function AlignFrames(SrcBitmap1, SrcBitmap2: TBitmap):TPoint;
  400.  
  401.  
  402.     (*  ASTROPHOTOGRAPHY RUTINS *)
  403.  
  404. // Basic preparations on image
  405. procedure AutoNoiseReduction(Bitmap: TBitmap; factor: DOUBLE);
  406. procedure AutoNoiseReduction_1(Bitmap: TBitmap; factor: DOUBLE);
  407. procedure AutomaticThresholdElimination(Bitmap: TBitmap; factor: double);
  408. function GetBMPSum(Bitmap: TBitmap):Longint;
  409. function GetBMPAverage(Bitmap: TBitmap; HighLimit: byte): TThreshold;
  410. function  GetAverageThreshold(Bitmap: TBitmap): TThreshold;
  411. procedure ThresholdElimination(Bitmap: TBitmap; avgTres: TThreshold; factor: double);
  412. procedure To2Bit(Bitmap: TBitmap; Threshold: byte);
  413. procedure RGBMultiplication(Bitmap: TBitmap; Rm,Gm,Bm: double);
  414. // The Red chanel reduction to Green chanel's level
  415. procedure RedToGreen(Bitmap: TBitmap);
  416. // StarDetect methods
  417. Function  AutomaticStarDetection(Bitmap: TBitmap): integer;
  418. Function PrecisionStarDetection(Bitmap: TBitmap; ThresholdFactor: double;
  419.                                  HighPassLevel: byte): integer;
  420. function GetStarCentroid(Bitmap: TBitmap; x, y, Radius: double): TPoint2d;
  421. procedure StarCirclesDraw(Bitmap: TBitmap; col: TColor);
  422. function StarSearch(var idx: integer; x,y: double): boolean;
  423. procedure SubPixelShift(SourceBitmap : TBitmap; out DestBitmap : TBitmap;
  424.                                   OffsetX, OffsetY: double);
  425.  
  426. // Photometrical methods
  427.  
  428. function SingleStarPhotometry(Bitmap:TBitmap;      // Source bitmap
  429.                               x,y: integer;        // Coord's in bitmap
  430.                               R: integer;          // Radius
  431.                               Threshold: integer)  // Threshold level
  432.                               : TStarRecord;       // Record of star
  433. function SimplePhotometry(Bitmap: TBitmap; x,y: Double; var Star : TStarRecord): boolean;
  434. function GetAverageIntensityOfStar(Bitmap: TBitmap; x,y, Radius: Double): double;
  435. function SimplePhotometryG(Bitmap: TBitmap; x,y: Double; var Star : TStarRecord): boolean;
  436. function GetAverageIntensityOfStarG(Bitmap: TBitmap; x,y, Radius: Double): double;
  437. procedure TotalPhotometry(Bitmap: TBitmap);
  438.  
  439. // SttarArray rutins
  440. // ---------------------------------------------------------------------------
  441.  
  442. // Megkeresi a legfényesebb csillagot és visszaadja tömbbeli indexét
  443. function GetMaxStar(ar: array of TStarRecord): integer;
  444.  
  445. // HISTOGRAM
  446.  
  447. function HistogramInit: TRGBColorsArray;
  448. function GetRGBHistogram(Bitmap: TBitmap): TRGBColorsArray;
  449. function RGBStatisticInit: TRGBStatisticArray;
  450. function GetRGBStatistic(Bitmap: TBitmap): TRGBStatisticArray;
  451. function GetRGBStatisticMax(Bitmap: TBitmap): TRGB24;
  452.  
  453. // Processes
  454.  
  455. procedure DoProcessList(var Bitmap: TBitmap; PrList: TStringList);
  456.  
  457. implementation
  458.  
  459. // Execute a bitmap process
  460. procedure DoBMPAction( var Bitmap:TBitmap; BMPAction: TBMPAction;
  461.                        Par1, Par2, Par3: Variant);
  462. begin
  463.   if Bitmap<>nil then
  464.   Case BMPAction of
  465.   bacFlipVertical    : FlipVertical(Bitmap);
  466.   bacFlipHorizontal  : FlipHorizontal(Bitmap);
  467.   bacGrayscale       : Grayscale(Bitmap);
  468.   bacNegative        : Negative(Bitmap);
  469.   bacFlaxen          : Flaxen(Bitmap);
  470.   bacEmboss          : Emboss(Bitmap, Par1);
  471.   end;
  472. end;
  473.  
  474. // NEEDED ROUTINS
  475.  
  476. function InRange(Test,Min,Max: integer): Boolean;
  477. begin
  478.   Result:=(Test >= Min) and (Test <= Max);
  479. end;
  480.  
  481. function InRange(Test,Min,Max: double): Boolean;
  482. begin
  483.   Result:=(Test >= Min) and (Test <= Max);
  484. end;
  485.  
  486. // Forces that test value be in range
  487. function Range(Test,Min,Max: Integer): Integer;
  488. begin
  489.   Result := Test;
  490.   if Test<Min then Result := Min;
  491.   if Test>Max then Result := Max;
  492. end;
  493.  
  494. function BoolToStr(bVal: boolean): string;
  495. begin
  496.   if bVal then Result := 'True'
  497.   else Result := 'False';
  498. end;
  499.  
  500. function IntToByte(i:Integer):Byte;
  501. begin
  502.   if i > 255 then
  503.     Result := 255
  504.   else if i < 0 then
  505.     Result := 0
  506.   else
  507.     Result := i;
  508. end;
  509.  
  510. function FloatToByte(i:double):Byte;
  511. begin
  512.   Result := IntToByte(Round(i));
  513. end;
  514.  
  515. function PointToCoord(p: TPoint): string;
  516. begin
  517.   Result := inttostr(p.x)+':'+inttostr(p.y);
  518. end;
  519.  
  520. function GetCoordStr(x,y: integer): string;
  521. begin
  522.   Result := inttostr(x)+':'+inttostr(y);
  523. end;
  524.  
  525. function GetCoordStr(x,y: double): string;
  526. begin
  527.   Result := Format('%6.2f',[x])+':'+Format('%6.2f',[y]);
  528. end;
  529.  
  530. function GetRGBStr(co: TColor): string;
  531. begin
  532.   Result := IntToStr(GetRValue(co))+':'+IntToStr(GetGValue(co))+':'+IntToStr(GetBValue(co));
  533. end;
  534.  
  535. // Central magnifíe a Rect
  536. function RectMagnify(R: TRect; n: double):TRect;
  537. var dx,dy: double;
  538.     CentX,CentY : double;
  539.     RR : TRect;
  540. begin
  541.    RR    := CorrectRect(R);
  542.    CentX := (RR.Left+RR.Right)/2;
  543.    CentY := (RR.Top+RR.Bottom)/2;
  544.    dx    := n*(RR.Right-RR.Left)/2;
  545.    dy    := n*(RR.Bottom-RR.Top)/2;
  546.    Result:= Rect(Round(CentX-dx),Round(CentY-dy),Round(CentX+dx),Round(CentY+dy));
  547. end;
  548.  
  549. // Increase or decrease a Rect
  550. function RectInflate(R: TRect; dx,dy: integer):TRect;
  551. Var RR : TRect;
  552. begin
  553.    RR    := CorrectRect(R);
  554.    Result:= Rect(RR.Left-dx,RR.Top-dy,RR.Right+dx,RR.Bottom+dy);
  555. end;
  556.  
  557. // Vector from FromP to ToP
  558.  
  559. function Vektor(FromP, Top: TPoint): TPoint;
  560. begin
  561.   Result.x := Top.x - FromP.x;
  562.   Result.y := Top.y - FromP.y;
  563. end;
  564.  
  565. // new x-component of the vector
  566. function xComp(Vektor: TPoint; Angle: Extended): Integer;
  567. begin
  568.   Result := Round(Vektor.x * cos(Angle) - (Vektor.y) * sin(Angle));
  569. end;
  570.  
  571. procedure quicksort(var a: array of integer);
  572.  
  573. procedure sort(l,r: integer);
  574. var
  575.   i,j,x,y: integer;
  576. begin
  577.   i:=l; j:=r; x:=a[(l+r) DIV 2];
  578.   repeat
  579.     while a[i]<x do i:=i+1;
  580.     while x<a[j] do j:=j-1;
  581.     if i<=j then
  582.     begin
  583.       y:=a[i]; a[i]:=a[j]; a[j]:=y;
  584.       i:=i+1; j:=j-1;
  585.     end;
  586.   until i>j;
  587.   if l<j then sort(l,j);
  588.   if i<r then sort(i,r);
  589. end;
  590.  
  591. begin {quicksort};
  592.   sort(0,High(a));
  593. end;
  594.  
  595. // Load a BMP or JPG into bitmap
  596. function Load_Bitmap(FName: string; BM: TBitmap): boolean;
  597. var ext: string;
  598.     jpgIMG: TJpegImage;
  599. begin
  600. Try
  601.   Result := False;
  602.   if FileExists(FName) then
  603.   Try
  604.      ext := UpperCase(ExtractFileExt(FName));
  605.      If ext='.BMP' then BM.LoadFromFile(FName);
  606.      If ext='.JPG' then
  607.      begin
  608.         jpgIMG := TJpegImage.Create;
  609.         jpgIMG.LoadFromFile(FName);
  610.         BM.Assign(jpgIMG);
  611.         if jpgIMG<>nil then jpgIMG.Free;
  612.      end;
  613.   except
  614.     if jpgIMG<>nil then jpgIMG.Free;
  615.     exit;
  616.   end;
  617. finally
  618.   BM.PixelFormat := pf24bit;
  619.   Result := True;
  620. end;
  621. end;
  622.  
  623. function Save_Bitmap(FName: string; BM: TBitmap): boolean;
  624. var ext: string;
  625.     jpgIMG: TJpegImage;
  626. begin
  627. Try
  628.   Result := False;
  629.   BM.PixelFormat := pf24bit;
  630.      ext := UpperCase(ExtractFileExt(FName));
  631.      If ext='.BMP' then BM.SaveToFile(FName);
  632.      If ext='.JPG' then
  633.      begin
  634.         jpgIMG := TJpegImage.Create;
  635.         jpgIMG.Assign(BM);
  636.         jpgIMG.SaveToFile(FName);
  637.         SLEEP(1000);
  638.         if jpgIMG<>nil then jpgIMG.Free;
  639.      end;
  640. finally
  641.   Result := True;
  642. end;
  643. end;
  644.  
  645. // Delete an existing file from disk
  646. function Delete_file(FName: string): boolean;
  647. begin
  648. Try
  649.   Result := False;
  650.   if FileExists(FName) then
  651.   if MessageDlg('Do you really want to delete ' + ExtractFileName(FName) + '?',
  652.                 mtWarning, [mbYes,mbNo],0) = mrYes then
  653.   begin
  654.     Result := DeleteFile(FName);
  655.   end;
  656. except
  657.   Result := False;
  658. end;
  659. end;
  660.  
  661. // new y-component of the vector
  662. function yComp(Vektor: TPoint; Angle: Extended): Integer;
  663. begin
  664.   Result := Round((Vektor.x) * (sin(Angle)) + (vektor.y) * cos(Angle));
  665. end;
  666.  
  667. // Resize the input bitmap
  668. function BMPResize( Bitmap:TBitmap ; const x,y: integer ):boolean;
  669. begin
  670. Try
  671.   Result := True;
  672.   Bitmap.width := x;
  673.   Bitmap.Height := y;
  674. except
  675.   Result := False;
  676. end;
  677. end;
  678.  
  679. // Copy SourceBitmap to DestBitmap and corrigate the DestBitmap dimensions
  680. function BMPCopy( SourceBitmap : TBitmap; DestBitmap : TBitmap ):boolean;
  681. begin
  682. Try
  683.   BMPResize(DestBitmap,SourceBitmap.Width,SourceBitmap.Height);
  684.   DestBitmap.Canvas.Draw(0,0,SourceBitmap);
  685. except
  686.   Result := False;
  687. end;
  688. end;
  689.  
  690. procedure GetSubDirs(const sRootDir: string; slt: TStrings);
  691. var
  692.   srSearch: TSearchRec;
  693.   sSearchPath: string;
  694.   sltSub: TStrings;
  695.   i: Integer;
  696. begin
  697.   sltSub := TStringList.Create;
  698.   slt.BeginUpdate;
  699.   try
  700.     sSearchPath := sRootDir+'\';
  701.     if FindFirst(sSearchPath + '*', faDirectory, srSearch) = 0 then
  702.       repeat
  703.         if ((srSearch.Attr and faDirectory) = faDirectory) and
  704.           (srSearch.Name <> '.') and
  705.           (srSearch.Name <> '..') then
  706.         begin
  707.           slt.Add(sSearchPath + srSearch.Name);
  708.           sltSub.Add(sSearchPath + srSearch.Name);
  709.         end;
  710.       until (FindNext(srSearch) <> 0);
  711.  
  712.     FindClose(srSearch);
  713.  
  714.     for i := 0 to sltSub.Count - 1 do
  715.       GetSubDirs(sltSub.Strings[i], slt);
  716.   finally
  717.     slt.EndUpdate;
  718.     FreeAndNil(sltSub);
  719.   end;
  720.  
  721. end;
  722.  
  723. function WinExecAndWait32(FileName: string; Visibility: Integer): Longword;
  724. var { by Pat Ritchey }
  725.   zAppName: array[0..512] of Char;
  726.   zCurDir: array[0..255] of Char;
  727.   WorkDir: string;
  728.   StartupInfo: TStartupInfo;
  729.   ProcessInfo: TProcessInformation;
  730. begin
  731.   StrPCopy(zAppName, FileName);
  732.   GetDir(0, WorkDir);
  733.   StrPCopy(zCurDir, WorkDir);
  734.   FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  735.   StartupInfo.cb          := SizeOf(StartupInfo);
  736.   StartupInfo.dwFlags     := STARTF_USESHOWWINDOW;
  737.   StartupInfo.wShowWindow := Visibility;
  738.   if not CreateProcess(nil,
  739.     zAppName, // pointer to command line string
  740.     nil, // pointer to process security attributes
  741.     nil, // pointer to thread security attributes
  742.     False, // handle inheritance flag
  743.     CREATE_NEW_CONSOLE or // creation flags
  744.     NORMAL_PRIORITY_CLASS,
  745.     nil, //pointer to new environment block
  746.     nil, // pointer to current directory name
  747.     StartupInfo, // pointer to STARTUPINFO
  748.     ProcessInfo) // pointer to PROCESS_INF
  749.     then Result := WAIT_FAILED
  750.   else
  751.   begin
  752.     WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  753.     GetExitCodeProcess(ProcessInfo.hProcess, Result);
  754.     CloseHandle(ProcessInfo.hProcess);
  755.     CloseHandle(ProcessInfo.hThread);
  756.   end;
  757. end; { WinExecAndWait32 }
  758.  
  759. procedure ShellExecute_AndWait(FileName: string; Params: string);
  760. var
  761.   exInfo: TShellExecuteInfo;
  762.   Ph: DWORD;
  763. begin
  764.   FillChar(exInfo, SizeOf(exInfo), 0);
  765.   with exInfo do
  766.   begin
  767.     cbSize := SizeOf(exInfo);
  768.     fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
  769.     Wnd := GetActiveWindow();
  770.     ExInfo.lpVerb := 'open';
  771.     ExInfo.lpParameters := PChar(Params);
  772.     lpFile := PChar(FileName);
  773.     nShow := SW_SHOWNORMAL;
  774.   end;
  775.   if ShellExecuteEx(@exInfo) then
  776.     Ph := exInfo.HProcess
  777.   else
  778.   begin
  779.     ShowMessage(SysErrorMessage(GetLastError));
  780.     Exit;
  781.   end;
  782.   while WaitForSingleObject(ExInfo.hProcess, 50) <> WAIT_OBJECT_0 do
  783.     Application.ProcessMessages;
  784.   CloseHandle(Ph);
  785. end;
  786.  
  787.  
  788. function ReadMWord(f: TFileStream): Word;
  789. type
  790.   TMotorolaWord = record
  791.     case Byte of
  792.       0: (Value: Word);
  793.       1: (Byte1, Byte2: Byte);
  794.   end;
  795. var
  796.   MW: TMotorolaWord;
  797. begin
  798.   { It would probably be better to just read these two bytes in normally }
  799.   { and then do a small ASM routine to swap them.  But we aren't talking }
  800.   { about reading entire files, so I doubt the performance gain would be }
  801.   { worth the trouble. }
  802.   f.read(MW.Byte2, SizeOf(Byte));
  803.   f.read(MW.Byte1, SizeOf(Byte));
  804.   Result := MW.Value;
  805. end;
  806.  
  807. procedure GetJPGSize(const sFile: string; var wWidth, wHeight: word);
  808. const
  809.   ValidSig: array[0..1] of Byte = ($FF, $D8);
  810.   Parameterless = [$01, $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7];
  811. var
  812.   Sig: array[0..1] of byte;
  813.   f: TFileStream;
  814.   x: integer;
  815.   Seg: byte;
  816.   Dummy: array[0..15] of byte;
  817.   Len: word;
  818.   ReadLen: LongInt;
  819. begin
  820.   FillChar(Sig, SizeOf(Sig), #0);
  821.   f := TFileStream.Create(sFile, fmOpenRead);
  822.   try
  823.     ReadLen := f.read(Sig[0], SizeOf(Sig));
  824.  
  825.     for x := Low(Sig) to High(Sig) do
  826.       if Sig[x] <> ValidSig[x] then ReadLen := 0;
  827.  
  828.     if ReadLen > 0 then
  829.     begin
  830.       ReadLen := f.read(Seg, 1);
  831.       while (Seg = $FF) and (ReadLen > 0) do
  832.       begin
  833.         ReadLen := f.read(Seg, 1);
  834.         if Seg <> $FF then
  835.         begin
  836.           if (Seg = $C0) or (Seg = $C1) then
  837.           begin
  838.             ReadLen := f.read(Dummy[0], 3); { don't need these bytes }
  839.             wHeight := ReadMWord(f);
  840.             wWidth  := ReadMWord(f);
  841.           end
  842.           else
  843.           begin
  844.             if not (Seg in Parameterless) then
  845.             begin
  846.               Len := ReadMWord(f);
  847.               f.Seek(Len - 2, 1);
  848.               f.read(Seg, 1);
  849.             end
  850.             else
  851.               Seg := $FF; { Fake it to keep looping. }
  852.           end;
  853.         end;
  854.       end;
  855.     end;
  856.   finally
  857.     f.Free;
  858.   end;
  859. end;
  860.  
  861. procedure GetPNGSize(const sFile: string; var wWidth, wHeight: Word);
  862. type
  863.   TPNGSig = array[0..7] of Byte;
  864. const
  865.   ValidSig: TPNGSig = (137,80,78,71,13,10,26,10);
  866. var
  867.   Sig: TPNGSig;
  868.   f: tFileStream;
  869.   x: integer;
  870. begin
  871.   FillChar(Sig, SizeOf(Sig), #0);
  872.   f := TFileStream.Create(sFile, fmOpenRead);
  873.   try
  874.     f.read(Sig[0], SizeOf(Sig));
  875.     for x := Low(Sig) to High(Sig) do
  876.       if Sig[x] <> ValidSig[x] then Exit;
  877.     f.Seek(18, 0);
  878.     wWidth := ReadMWord(f);
  879.     f.Seek(22, 0);
  880.     wHeight := ReadMWord(f);
  881.   finally
  882.     f.Free;
  883.   end;
  884. end;
  885.  
  886. procedure GetGIFSize(const sGIFFile: string; var wWidth, wHeight: Word);
  887. type
  888.   TGIFHeader = record
  889.     Sig: array[0..5] of char;
  890.     ScreenWidth, ScreenHeight: Word;
  891.     Flags, Background, Aspect: Byte;
  892.   end;
  893.  
  894.   TGIFImageBlock = record
  895.     Left, Top, Width, Height: Word;
  896.     Flags: Byte;
  897.   end;
  898. var
  899.   f: file;
  900.   Header: TGifHeader;
  901.   ImageBlock: TGifImageBlock;
  902.   nResult: integer;
  903.   x: integer;
  904.   c: char;
  905.   DimensionsFound: boolean;
  906. begin
  907.   wWidth  := 0;
  908.   wHeight := 0;
  909.  
  910.   if sGifFile = '' then
  911.     Exit;
  912.  
  913.   {$I-}
  914.   FileMode := 0;   { read-only }
  915.   AssignFile(f, sGifFile);
  916.   reset(f, 1);
  917.   if IOResult <> 0 then
  918.     { Could not open file }
  919.     Exit;
  920.  
  921.   { Read header and ensure valid file. }
  922.   BlockRead(f, Header, SizeOf(TGifHeader), nResult);
  923.   if (nResult <> SizeOf(TGifHeader)) or (IOResult <> 0) or
  924.     (StrLComp('GIF', Header.Sig, 3) <> 0) then
  925.   begin
  926.     { Image file invalid }
  927.     Close(f);
  928.     Exit;
  929.   end;
  930.  
  931.   { Skip color map, if there is one }
  932.   if (Header.Flags and $80) > 0 then
  933.   begin
  934.     x := 3 * (1 shl ((Header.Flags and 7) + 1));
  935.     Seek(f, x);
  936.     if IOResult <> 0 then
  937.     begin
  938.       { Color map thrashed }
  939.       Close(f);
  940.       Exit;
  941.     end;
  942.   end;
  943.  
  944.   DimensionsFound := False;
  945.   FillChar(ImageBlock, SizeOf(TGIFImageBlock), #0);
  946.   { Step through blocks. }
  947.   BlockRead(f, c, 1, nResult);
  948.   while (not EOF(f)) and (not DimensionsFound) do
  949.   begin
  950.     case c of
  951.       ',': { Found image }
  952.         begin
  953.           BlockRead(f, ImageBlock, SizeOf(TGIFImageBlock), nResult);
  954.           if nResult <> SizeOf(TGIFImageBlock) then
  955.           begin
  956.             { Invalid image block encountered }
  957.             Close(f);
  958.             Exit;
  959.           end;
  960.           wWidth := ImageBlock.Width;
  961.           wHeight := ImageBlock.Height;
  962.           DimensionsFound := True;
  963.         end;
  964.       'y': { Skip }
  965.         begin
  966.           { NOP }
  967.         end;
  968.       { nothing else.  just ignore }
  969.     end;
  970.     BlockRead(f, c, 1, nResult);
  971.   end;
  972.   Close(f);
  973.   {$I+}
  974. end;
  975.  
  976. function ScalePercentBmp(bitmp: TBitmap; iPercent: Integer): Boolean;
  977. var
  978.   TmpBmp: TBitmap;
  979.   ARect: TRect;
  980.   h, w: Real;
  981.   hi, wi: Integer;
  982. begin
  983.   Result := False;
  984.   try
  985.     TmpBmp := TBitmap.Create;
  986.     try
  987.       h := bitmp.Height * (iPercent / 100);
  988.       w := bitmp.Width * (iPercent / 100);
  989.       hi := StrToInt(FormatFloat('#', h)) + bitmp.Height;
  990.       wi := StrToInt(FormatFloat('#', w)) + bitmp.Width;
  991.       TmpBmp.Width := wi;
  992.       TmpBmp.Height := hi;
  993.       ARect := Rect(0, 0, wi, hi);
  994.       TmpBmp.Canvas.StretchDraw(ARect, Bitmp);
  995.       bitmp.Assign(TmpBmp);
  996.     finally
  997.       TmpBmp.Free;
  998.     end;
  999.     Result := True;
  1000.   except
  1001.     Result := False;
  1002.   end;
  1003. end;
  1004.  
  1005. procedure CopyStreamToClipboard(fmt: Cardinal; S: TStream);
  1006. var
  1007.   hMem: THandle;
  1008.   pMem: Pointer;
  1009. begin
  1010.   S.Position := 0;
  1011.   hMem       := GlobalAlloc(GHND or GMEM_DDESHARE, S.Size);
  1012.   if hMem <> 0 then
  1013.   begin
  1014.     pMem := GlobalLock(hMem);
  1015.     if pMem <> nil then
  1016.     begin
  1017.       S.Read(pMem^, S.Size);
  1018.       S.Position := 0;
  1019.       GlobalUnlock(hMem);
  1020.       Clipboard.Open;
  1021.       try
  1022.         Clipboard.SetAsHandle(fmt, hMem);
  1023.       finally
  1024.         Clipboard.Close;
  1025.       end;
  1026.     end { If }
  1027.     else
  1028.     begin
  1029.       GlobalFree(hMem);
  1030.       OutOfMemoryError;
  1031.     end;
  1032.   end { If }
  1033.   else
  1034.     OutOfMemoryError;
  1035. end; { CopyStreamToClipboard }
  1036.  
  1037.  
  1038. procedure CopyStreamFromClipboard(fmt: Cardinal; S: TStream);
  1039. var
  1040.   hMem: THandle;
  1041.   pMem: Pointer;
  1042. begin
  1043.   hMem := Clipboard.GetAsHandle(fmt);
  1044.   if hMem <> 0 then
  1045.   begin
  1046.     pMem := GlobalLock(hMem);
  1047.     if pMem <> nil then
  1048.     begin
  1049.       S.Write(pMem^, GlobalSize(hMem));
  1050.       S.Position := 0;
  1051.       GlobalUnlock(hMem);
  1052.     end { If }
  1053.     else
  1054.       raise Exception.Create('CopyStreamFromClipboard: could not lock global handle ' +
  1055.         'obtained from clipboard!');
  1056.   end; { If }
  1057. end; { CopyStreamFromClipboard }
  1058.  
  1059. procedure TurnLeft(src, dst: tbitmap);
  1060. var w,h,x,y:integer;
  1061.     ps,pd:pbytearray;
  1062. begin
  1063.  h:=src.Height;
  1064.  w:=src.width;
  1065.  src.PixelFormat :=pf24bit;
  1066.  dst.PixelFormat :=pf24bit;
  1067.  dst.Height :=w;
  1068.  dst.Width :=h;
  1069.  for y:=0 to h-1 do begin
  1070.   ps:=src.ScanLine [y];
  1071.   for x:=0 to w-1 do begin
  1072.    pd:=dst.ScanLine [w-1-x];
  1073.    pd[y*3]:=ps[x*3];
  1074.    pd[y*3+1]:=ps[x*3+1];
  1075.    pd[y*3+2]:=ps[x*3+2];
  1076.    end;
  1077.   end;
  1078. end;
  1079.  
  1080. procedure TurnRight(src, dst: Tbitmap);
  1081. var w,h,x,y:integer;
  1082.     ps,pd:pbytearray;
  1083. begin
  1084.  h:=src.Height;
  1085.  w:=src.width;
  1086.  src.PixelFormat :=pf24bit;
  1087.  dst.PixelFormat :=pf24bit;
  1088.  dst.Height :=w;
  1089.  dst.Width :=h;
  1090.  for y:=0 to h-1 do begin
  1091.   ps:=src.ScanLine [y];
  1092.   for x:=0 to w-1 do begin
  1093.    pd:=dst.ScanLine [x];
  1094.    pd[(h-1-y)*3]:=ps[x*3];
  1095.    pd[(h-1-y)*3+1]:=ps[x*3+1];
  1096.    pd[(h-1-y)*3+2]:=ps[x*3+2];
  1097.    end;
  1098.   end;
  1099. end;
  1100.  
  1101. function ColorToTriple(Color:TColor):TRGBTriple;
  1102. type
  1103.   Rec=Record
  1104.   Case TColor of
  1105.   1:( ColorValue:TColor );
  1106.   2:(Bytes: array [0..3] of Byte);
  1107.   end;
  1108. var
  1109.   Col:Rec;
  1110. begin
  1111.   Col.ColorValue:= Color;
  1112.  
  1113.   Result.rgbtRed :=Col.Bytes[3];
  1114.   Result.rgbtGreen :=Col.Bytes[2];
  1115.   Result.rgbtBlue :=Col.Bytes[1];
  1116. end ;
  1117.  
  1118. function TripleToColor( RGB: TRGBTriple):TColor;
  1119. begin
  1120.   Result := RGB.rgbtRed + 256*RGB.rgbtGreen + 65536*RGB.rgbtBlue;
  1121. end;
  1122.  
  1123. function ChangeRGBColor(var color:TRGBTriple;R,G,B:integer):TRGBTriple;
  1124. begin
  1125. if  B+Color.rgbtBlue >255 then Color.rgbtBlue :=255 else
  1126. if  B+Color.rgbtBlue <0 then  Color.rgbtBlue :=0 else
  1127. inc(Color.rgbtBlue,B) ;
  1128.  
  1129.  
  1130. if  G+Color.rgbtGreen >255 then Color.rgbtGreen :=255 else
  1131. if  G+Color.rgbtGreen <0 then  Color.rgbtGreen :=0 else
  1132. inc(Color.rgbtGreen,G) ;
  1133.  
  1134. if  R+Color.rgbtRed >255 then Color.rgbtRed :=255 else
  1135. if  R+Color.rgbtRed <0 then  Color.rgbtRed :=0 else
  1136. inc(Color.rgbtRed,R) ;
  1137. Result:=Color;
  1138.  
  1139. end;
  1140.  
  1141. // Changes the RGB colors all pixesl of bitmap
  1142. // RGB = 1 : not modifies; <1: decreas; >1: increse
  1143. procedure ChangeRGB(var Bitmap: TBitmap; R,G,B: double);
  1144. var
  1145.   H,V: integer;
  1146.   Row: pPixelArray;
  1147. begin
  1148.  Bitmap.PixelFormat:=pf24bit;
  1149.  for V:=0 to Bitmap.Height -1 do
  1150.   begin
  1151.       Row := Bitmap.ScanLine[V];
  1152.       for H:=0 to Bitmap.Width -1 do
  1153.       WITH Row[H] DO
  1154.       begin
  1155.            rgbtRed   := FloatToByte(rgbtRed*R);
  1156.            rgbtGreen := FloatToByte(rgbtGreen*G);
  1157.            rgbtBlue  := FloatToByte(rgbtBlue*B);
  1158.       end;
  1159.   end;
  1160. end;
  1161.  
  1162. procedure Flaxen( Bitmap:TBitmap);
  1163. var
  1164. H,V:Integer;
  1165. WSK,WSK2,WSK3:^TRGBTriple;
  1166. begin
  1167. Bitmap.PixelFormat:=pf24bit;
  1168. for V:=0 to Bitmap.Height-1 do
  1169.   begin
  1170. Wsk:=Bitmap.ScanLine[V];
  1171. Wsk2:=Wsk;
  1172. Wsk3:=Wsk;
  1173. inc(Wsk2);
  1174. inc(Wsk3,2);
  1175.  
  1176. for H:=0 to Bitmap.Width -1 do
  1177.     begin
  1178.     Wsk.rgbtRed  := (Wsk.rgbtRed + Wsk2.rgbtGreen  +
  1179.     Wsk3.rgbtBlue) div 3;
  1180.     Wsk2.rgbtGreen := (Wsk.rgbtGreen + Wsk2.rgbtGreen +
  1181.     Wsk3.rgbtBlue) div 3;
  1182.     Wsk2.rgbtBlue := (Wsk.rgbtBlue + Wsk2.rgbtGreen +
  1183.     Wsk3.rgbtBlue) div 3;
  1184.     inc(Wsk);inc(Wsk2);inc(Wsk3);
  1185.     end;
  1186.   end;
  1187.  
  1188. end;
  1189.  
  1190. procedure Emboss(Bitmap : TBitmap; AMount : Integer);
  1191. var
  1192.   x, y, i : integer;
  1193.   p1, p2: PByteArray;
  1194. begin
  1195.   for i := 0 to AMount do
  1196.   begin
  1197.     for y := 0 to Bitmap.Height-2 do
  1198.     begin
  1199.       p1 := Bitmap.ScanLine[y];
  1200.       p2 := Bitmap.ScanLine[y+1];
  1201.       for x := 0 to Bitmap.Width do
  1202.       begin
  1203.         p1[x*3] := (p1[x*3]+(p2[(x+3)*3] xor $FF)) shr 1;
  1204.         p1[x*3+1] := (p1[x*3+1]+(p2[(x+3)*3+1] xor $FF)) shr 1;
  1205.         p1[x*3+2] := (p1[x*3+1]+(p2[(x+3)*3+1] xor $FF)) shr 1;
  1206.       end;
  1207.     end;
  1208.   end;
  1209. end;
  1210.  
  1211. procedure MonoNoise(var Bitmap: TBitmap; Amount: Integer);
  1212. var
  1213. Row:^TRGBTriple;
  1214. H,V,a: Integer;
  1215. begin
  1216.   for V:=0 to Bitmap.Height-1 do
  1217.   begin
  1218.     Row:=Bitmap.ScanLine[V];
  1219.     for H:=0 to Bitmap.Width-1 do
  1220.     begin
  1221.       a:=Random(Amount)-(Amount shr 1);
  1222.  
  1223.       Row.rgbtBlue :=IntToByte(Row.rgbtBlue+a);
  1224.       Row.rgbtGreen :=IntToByte(Row.rgbtGreen+a);
  1225.       Row.rgbtRed :=IntToByte(Row.rgbtRed+a);
  1226.       inc(Row);
  1227.     end;
  1228.   end;
  1229. end;
  1230.  
  1231.  
  1232. procedure ColorNoise( Bitmap: TBitmap; Amount: Integer);
  1233. var
  1234. WSK:^Byte;
  1235. H,V,a: Integer;
  1236. begin
  1237. Bitmap.PixelFormat:=pf24bit;
  1238.   for V:=0 to Bitmap.Height-1 do
  1239.   begin
  1240.     Wsk:=Bitmap.ScanLine[V];
  1241.     for H:=0 to Bitmap.Width*3-1 do
  1242.     begin
  1243.     Wsk^:=IntToByte(Wsk^+(Random(Amount)-(Amount shr 1)));
  1244.       inc(Wsk);
  1245.     end;
  1246.   end;
  1247. end;
  1248.  
  1249. Procedure GrayScale(var Bitmap:TBitmap);
  1250. var
  1251.    Row:^TRGBTriple;
  1252.    H,V,Index:Integer;
  1253. begin
  1254.  Bitmap.PixelFormat:=pf24bit;
  1255.  for V:=0 to Bitmap.Height-1 do
  1256.   begin
  1257.     Row:=Bitmap.ScanLine[V];
  1258.     for H:=0 to Bitmap.Width -1 do
  1259.     begin
  1260.     Index := ((Row.rgbtRed * 77 +
  1261.        Row.rgbtGreen* 150 +
  1262.        Row.rgbtBlue * 29) shr 8);
  1263.        Row.rgbtBlue:=Index;
  1264.        Row.rgbtGreen:=Index;
  1265.        Row.rgbtRed:=Index;
  1266.        inc(Row);
  1267.     end;
  1268.   end;
  1269. end;
  1270.  
  1271. procedure RedToGreen(Bitmap: TBitmap);
  1272. var
  1273.   x, y, i : integer;
  1274.   p : PByteArray;
  1275. begin
  1276.  Bitmap.PixelFormat:=pf24bit;
  1277.   for y := 0 to Bitmap.Height-1 do begin
  1278.     P := Bitmap.ScanLine[y];
  1279.     for x := 0 to Bitmap.Width do
  1280.       begin
  1281.         p[x*3+2] := p[(x*3)];
  1282.       end;
  1283.   end;
  1284. end;
  1285.  
  1286. // Adjust RGB colors of bitmat.
  1287. // Amount = 1   : not change the color chanel;
  1288. //          0.5 : 50% half intensity of color
  1289. //          1.8 : 180% intensity of color
  1290. Procedure ColorAdjust(var Bitmap:TBitmap; AmountR, AmountG, AmountB: double);
  1291. var
  1292.    Row:^TRGBTriple;
  1293. //   Row:pbytearray;
  1294.    X,Y:Integer;
  1295.    e: byte;
  1296. begin
  1297.  Bitmap.PixelFormat:=pf24bit;
  1298.  for Y:=0 to Bitmap.Height-1 do
  1299.   begin
  1300.     Row:=Bitmap.ScanLine[Y];
  1301.     for X:=0 to Bitmap.Width -1 do
  1302.     begin
  1303.  (*
  1304.        e := Row[x*3];
  1305.        Row[x*3]   := FloatToByte(Row[x*3] * AmountB);
  1306.        Row[x*3+1] := FloatToByte(Row[x*3+1] * AmountG);
  1307.        Row[x*3+2] := FloatToByte(Row[x*3+2] * AmountR);
  1308.  *)
  1309.        Row.rgbtRed   := FloatToByte(Row.rgbtRed * AmountR);
  1310.        Row.rgbtGreen := FloatToByte(Row.rgbtGreen * AmountG);
  1311.        Row.rgbtBlue  := FloatToByte(Row.rgbtBlue * AmountB);
  1312.        inc(Row);
  1313.     end;
  1314.   end;
  1315. end;
  1316.  
  1317. // Adjust RGB colors of bitmap.
  1318. //    Threshold alatt 0
  1319. Procedure ColorAdjustEx(var Bitmap:TBitmap; Threshold: byte);
  1320. var
  1321. Wsk:^Byte;
  1322. H,V: Integer;
  1323. begin
  1324.   Bitmap.pixelformat:=pf24bit;
  1325.   for V:=0 to Bitmap.Height-1 do begin
  1326.     WSK:=Bitmap.ScanLine[V];
  1327.     for H:=0 to Bitmap.Width*3-1 do
  1328.     begin
  1329.     if Wsk^>Threshold then
  1330.        Wsk^:= Round(Wsk^*(1-((255-Wsk^)/255)))
  1331.     else
  1332.        Wsk^:= 0;
  1333.     inc(Wsk);
  1334.   end;
  1335.  end;
  1336. end;
  1337. (*var
  1338.    Row:^TRGBTriple;
  1339.    H,V:Integer;
  1340.    th: TThresHold;
  1341. begin
  1342.  Bitmap.PixelFormat:=pf24bit;
  1343.  TH := GetAverageThreshold(Bitmap);
  1344.  for V:=0 to Bitmap.Height-1 do
  1345.   begin
  1346.     Row:=Bitmap.ScanLine[V];
  1347.     for H:=0 to Bitmap.Width -1 do
  1348.     begin
  1349.        Row.rgbtRed   := Round(100*(255-Row.rgbtRed)/255);
  1350.        Row.rgbtRed   := Round(100*(255-Row.rgbtRed)/255);
  1351.        Row.rgbtRed   := Round(100*(255-Row.rgbtRed)/255);
  1352.        if Row.rgbtRed<=3*th.R then
  1353.        Row.rgbtRed   := Round(Row.rgbtRed * AmountR);
  1354.        if Row.rgbtGreen<=2*th.G then
  1355.        Row.rgbtGreen := Round(Row.rgbtGreen * AmountG);
  1356.        if Row.rgbtBlue<=2*th.B then
  1357.        Row.rgbtBlue  := Round(Row.rgbtBlue * AmountB);
  1358.        inc(Row);
  1359.     end;
  1360.   end;
  1361. end;*)
  1362.  
  1363. // Az egyszínű pixelek eltávolítása
  1364. Procedure ColorNoiseElimination(var Bitmap:TBitmap);
  1365. var
  1366.    Row:^TRGBTriple;
  1367.    H,V:Integer;
  1368.    szorzo: double;
  1369. begin
  1370.  szorzo:=1.2;
  1371.  Bitmap.PixelFormat:=pf24bit;
  1372.  for V:=0 to Bitmap.Height-1 do
  1373.   begin
  1374.     Row:=Bitmap.ScanLine[V];
  1375.     for H:=0 to Bitmap.Width -1 do
  1376.     begin
  1377.        if (Row.rgbtRed>szorzo*Row.rgbtGreen) or (Row.rgbtGreen=0) or (Row.rgbtBlue=0) then
  1378.           Row.rgbtRed   := 0;
  1379.        if (Row.rgbtGreen>szorzo*Row.rgbtRed) or (Row.rgbtRed=0) or (Row.rgbtBlue=0) then
  1380.           Row.rgbtGreen := 0;
  1381.        if (Row.rgbtBlue>szorzo*Row.rgbtRed) or (Row.rgbtGreen=0) or (Row.rgbtRed=0) then
  1382.           Row.rgbtBlue  := 0;
  1383.        inc(Row);
  1384.     end;
  1385.   end;
  1386. end;
  1387.  
  1388.  
  1389. // BASIC IMAGE PROCESSES
  1390. // ============================================================================
  1391.  
  1392. procedure Darkness( Bitmap:TBitmap; Amount: integer);
  1393. var
  1394. Wsk:^Byte;
  1395. H,V: Integer;
  1396. begin
  1397.   Bitmap.pixelformat:=pf24bit;
  1398.   for V:=0 to Bitmap.Height-1 do begin
  1399.     WSK:=Bitmap.ScanLine[V];
  1400.     for H:=0 to Bitmap.Width*3-1 do
  1401.     begin
  1402.     Wsk^:=IntToByte(Wsk^-(Wsk^*Amount)div 255);
  1403.     inc(Wsk);
  1404.   end;
  1405.  end;
  1406. end;
  1407.  
  1408. procedure Threshold( Bitmap:TBitmap ; const Light:TRgbTriple; const Dark:TRgbTriple; Amount:Integer = 128);
  1409. var
  1410. Row:^TRGBTriple;
  1411. H,V,Index:Integer;
  1412. begin
  1413.  Bitmap.PixelFormat:=pf24bit;
  1414.  for V:=0 to Bitmap.Height-1 do
  1415.   begin
  1416.     Row:=Bitmap.ScanLine[V];
  1417.     for H:=0 to Bitmap.Width -1 do
  1418.     begin
  1419.     Index := ((Row.rgbtRed * 77 +
  1420.        Row.rgbtGreen* 150 +
  1421.        Row.rgbtBlue * 29) shr 8);
  1422.        if Index>Amount then
  1423.       Row^:=Light  else Row^:=Dark ;
  1424.        inc(Row);
  1425.     end;
  1426.   end;
  1427. end;
  1428.  
  1429. procedure Posterize(Bitmap: TBitmap; amount: integer);
  1430. var
  1431. H,V:Integer;
  1432. Wsk:^Byte;
  1433. begin
  1434.   Bitmap.PixelFormat :=pf24bit;
  1435.   for V:=0 to Bitmap.Height -1 do
  1436.   begin
  1437.    Wsk:=Bitmap.scanline[V];
  1438.    for H:=0 to Bitmap.Width*3 -1 do
  1439.    begin
  1440.      Wsk^:= round(WSK^/amount)*amount ;
  1441.      inc(Wsk);
  1442.      end;
  1443.    end;
  1444. end;
  1445.  
  1446. procedure Mosaic(var Bm:TBitmap;size:Integer);
  1447. var
  1448.    x,y,i,j:integer;
  1449.    p1,p2:pbytearray;
  1450.    r,g,b:byte;
  1451. begin
  1452.   y:=0;
  1453.   repeat
  1454.     p1:=bm.scanline[y];
  1455.     x:=0;
  1456.     repeat
  1457.       j:=1;
  1458.       repeat
  1459.       p2:=bm.scanline[y];
  1460.       x:=0;
  1461.       repeat
  1462.         r:=p1[x*3];
  1463.         g:=p1[x*3+1];
  1464.         b:=p1[x*3+2];
  1465.         i:=1;
  1466.        repeat
  1467.        p2[x*3]:=r;
  1468.        p2[x*3+1]:=g;
  1469.        p2[x*3+2]:=b;
  1470.        inc(x);
  1471.        inc(i);
  1472.        until (x>=bm.width) or (i>size);
  1473.       until x>=bm.width;
  1474.       inc(j);
  1475.       inc(y);
  1476.       until (y>=bm.height) or (j>size);
  1477.     until (y>=bm.height) or (x>=bm.width);
  1478.   until y>=bm.height;
  1479. end;
  1480.  
  1481. procedure Crop(var Bitmap:TBitmap; Rec: TRect);
  1482. var BM: TBitmap;
  1483. begin
  1484.   Try
  1485.     BM := TBitmap.Create;
  1486.     BMPResize(BM,Rec.Right-Rec.Left,Rec.Bottom-Rec.Top);
  1487.     BM.Canvas.CopyRect(BM.Canvas.Cliprect,Bitmap.Canvas,Rec);
  1488.     BMPCopy(BM,Bitmap);
  1489.   finally
  1490.     BM.Free;
  1491.   end;
  1492. end;
  1493.  
  1494. procedure FlipHorizontal(var Bitmap:TBitmap);
  1495. type
  1496. ByteTriple =array[0..2] of byte        ; // musimy czytać po 3 bajty żeby nie zamienić kolejności BGR na RGB
  1497. var
  1498. ByteL,ByteR:^ByteTriple;
  1499. ByteTemp:ByteTriple;
  1500. H,V:Integer;
  1501. begin
  1502. Bitmap.PixelFormat:=pf24bit;
  1503. for V:=0 to (Bitmap.Height -1 )  do
  1504.   begin
  1505.   ByteL:=Bitmap.ScanLine[V];
  1506.   ByteR:=Bitmap.ScanLine[V];
  1507.   inc(ByteR,Bitmap.Width -1);
  1508.     for H:=0 to (Bitmap.Width -1) div 2  do
  1509.     begin
  1510.     ByteTemp:=ByteL^;
  1511.     ByteL^:=ByteR^;
  1512.     ByteR^:=ByteTemp;
  1513.     Inc(ByteL);
  1514.     Dec(ByteR);
  1515.     end;
  1516.   end;
  1517. end;
  1518.  
  1519. procedure FlipVertical(var Bitmap:TBitmap);
  1520. var
  1521. ByteTop,ByteBottom:^Byte;
  1522. ByteTemp:Byte;
  1523. H,V:Integer;
  1524. begin
  1525. for V:=0 to (Bitmap.Height -1 ) div 2 do
  1526.   begin
  1527.   ByteTop:=Bitmap.ScanLine[V];
  1528.   ByteBottom:=Bitmap.ScanLine[Bitmap.Height -1-V];
  1529.   for H:=0 to Bitmap.Width *3 -1 do
  1530.     begin
  1531.     ByteTemp:=ByteTop^;
  1532.     ByteTop^:=ByteBottom^;
  1533.     ByteBottom^:=ByteTemp;
  1534.     inc(ByteTop);
  1535.     inc(ByteBottom);
  1536.     end;
  1537.   end;
  1538. end;
  1539.  
  1540. function RotImage(srcbit: TBitmap; Angle: Extended; FPoint: TPoint;
  1541.   Background: TColor): TBitmap;
  1542. var
  1543.   highest, lowest, mostleft, mostright: TPoint;
  1544.   topoverh, leftoverh: integer;
  1545.   x, y, newx, newy: integer;
  1546. begin
  1547.   Result := TBitmap.Create;
  1548.  
  1549.   // Calculate angle down on one rotation, if necessary
  1550.   while Angle >= (2 * pi) do
  1551.   begin
  1552.     angle := Angle - (2 * pi);
  1553.   end;
  1554.  
  1555.   // specify new size
  1556.   if (angle <= (pi / 2)) then
  1557.   begin
  1558.     highest := Point(0,0);
  1559.     Lowest := Point(Srcbit.Width, Srcbit.Height);
  1560.     mostleft := Point(0,Srcbit.Height);
  1561.     mostright := Point(Srcbit.Width, 0);
  1562.   end
  1563.   else if (angle <= pi) then
  1564.   begin
  1565.     highest := Point(0,Srcbit.Height);
  1566.     Lowest := Point(Srcbit.Width, 0);
  1567.     mostleft := Point(Srcbit.Width, Srcbit.Height);
  1568.     mostright := Point(0,0);
  1569.   end
  1570.   else if (Angle <= (pi * 3 / 2)) then
  1571.   begin
  1572.     highest := Point(Srcbit.Width, Srcbit.Height);
  1573.     Lowest := Point(0,0);
  1574.     mostleft := Point(Srcbit.Width, 0);
  1575.     mostright := Point(0,Srcbit.Height);
  1576.   end
  1577.   else
  1578.   begin
  1579.     highest := Point(Srcbit.Width, 0);
  1580.     Lowest := Point(0,Srcbit.Height);
  1581.     mostleft := Point(0,0);
  1582.     mostright := Point(Srcbit.Width, Srcbit.Height);
  1583.   end;
  1584.  
  1585.   topoverh := yComp(Vektor(FPoint, highest), Angle);
  1586.   leftoverh := xComp(Vektor(FPoint, mostleft), Angle);
  1587.   Result.Height := Abs(yComp(Vektor(FPoint, lowest), Angle)) + Abs(topOverh);
  1588.   Result.Width  := Abs(xComp(Vektor(FPoint, mostright), Angle)) + Abs(leftoverh);
  1589.  
  1590.   // change of FPoint in the new picture in relation on srcbit
  1591.   Topoverh := TopOverh + FPoint.y;
  1592.   Leftoverh := LeftOverh + FPoint.x;
  1593.  
  1594.   // at first fill with background color
  1595.   Result.Canvas.Brush.Color := Background;
  1596.   Result.Canvas.pen.Color   := background;
  1597.   Result.Canvas.Fillrect(Rect(0,0,Result.Width, Result.Height));
  1598.  
  1599.   // Start of actual rotation
  1600.   for y := 0 to srcbit.Height - 1 do
  1601.   begin                       // Rows
  1602.     for x := 0 to srcbit.Width - 1 do
  1603.     begin                    // Columns
  1604.       newX := xComp(Vektor(FPoint, Point(x, y)), Angle);
  1605.       newY := yComp(Vektor(FPoint, Point(x, y)), Angle);
  1606.       newX := FPoint.x + newx - leftoverh;
  1607.       newy := FPoint.y + newy - topoverh;
  1608.       // Move beacause of new size
  1609.       Result.Canvas.Pixels[newx, newy] := srcbit.Canvas.Pixels[x, y];
  1610.       // also fil lthe pixel beside to prevent empty pixels
  1611.       if ((angle < (pi / 2)) or
  1612.         ((angle > pi) and
  1613.         (angle < (pi * 3 / 2)))) then
  1614.       begin
  1615.         Result.Canvas.Pixels[newx, newy + 1] := srcbit.Canvas.Pixels[x, y];
  1616.       end
  1617.       else
  1618.       begin
  1619.         Result.Canvas.Pixels[newx + 1,newy] := srcbit.Canvas.Pixels[x, y];
  1620.       end;
  1621.     end;
  1622.   end;
  1623. end;
  1624.  
  1625. procedure Negative(var Bitmap:TBitmap);
  1626. var
  1627. H,V:Integer;
  1628. WskByte:^Byte;
  1629. begin
  1630. Bitmap.PixelFormat:=pf24bit;
  1631. for V:=0 to Bitmap.Height-1 do
  1632.   begin
  1633.     WskByte:=Bitmap.ScanLine[V]; // V jest to pozycja  danej linii bitmapy (od góry )
  1634.     for  H:=0 to (Bitmap.Width *3)-1 do
  1635.     begin
  1636.       WskByte^:= not WskByte^ ;// (odwracamy wartość na którą pokazuje wskaźnik)
  1637.       inc(WskByte);//Przesuwam wskaźnik
  1638.     end;
  1639.   end;
  1640. end;
  1641.  
  1642. procedure BlackAndWhite(var Bitmap:TBitmap );
  1643. VAR
  1644.   i  :  INTEGER;
  1645.   j  :  INTEGER;
  1646.   Row:  pPixelArray;
  1647.   Gray: byte;
  1648. begin
  1649. TRY
  1650.   Bitmap.PixelFormat := pf24bit;
  1651.   FOR j := 0 TO Bitmap.Height-1 DO
  1652.   BEGIN
  1653.     Row := Bitmap.Scanline[j];
  1654.     FOR i := 0 TO Bitmap.Width-1 DO
  1655.     BEGIN
  1656.       WITH Row[i] DO
  1657.       BEGIN
  1658.         Gray := (rgbtRed + rgbtGreen + rgbtBlue) div 3;
  1659.         rgbtRed   := Gray;
  1660.         rgbtGreen := Gray;
  1661.         rgbtBlue  := Gray;
  1662.       END
  1663.     END
  1664.   END;
  1665. FINALLY
  1666. END
  1667. end;
  1668.  
  1669. procedure Saturation(var  Bitmap: TBitmap; Amount: Integer);
  1670. var
  1671.   Wsk:^TRGBTriple;
  1672.   Gray,H,V: Integer;
  1673. begin
  1674.   for V:=0 to Bitmap.Height-1 do
  1675.   begin
  1676.     Wsk:=Bitmap.ScanLine[V];
  1677.     for H:=0 to Bitmap.Width-1 do
  1678.     begin
  1679.     Gray:=(Wsk.rgbtBlue+Wsk.rgbtGreen+Wsk.rgbtRed) div 3;
  1680.     Wsk.rgbtRed:=IntToByte(Gray+(((Wsk.rgbtRed-Gray)*Amount)div 255));
  1681.     Wsk.rgbtGreen:=IntToByte(Gray+(((Wsk.rgbtGreen-Gray)*Amount)div 255));
  1682.     Wsk.rgbtBlue:=IntToByte(Gray+(((Wsk.rgbtBlue-Gray)*Amount)div 255));
  1683.     inc(Wsk);
  1684.     end;
  1685.   end;
  1686. end;
  1687.  
  1688.  
  1689. procedure Contrast(var Bitmap:TBitmap; Amount: Integer);
  1690. var
  1691. ByteWsk:^Byte;
  1692. H,V:  Integer;
  1693. begin
  1694. if Amount<>0 then
  1695.   for V:=0 to Bitmap.Height-1 do
  1696.   begin
  1697.     ByteWsk:=Bitmap.ScanLine[V];
  1698.     for H:=0 to Bitmap.Width*3 -1  do
  1699.     begin
  1700.       ByteWsk^:=IntToByte(ByteWsk^-((127-ByteWsk^)*Amount)div 255);
  1701.       Inc(ByteWsk);
  1702.     end;
  1703.   end;
  1704. end;
  1705.  
  1706. procedure ContrastNess(var clip: tbitmap; Amount: Integer);
  1707. var
  1708. p0:pbytearray;
  1709. rg,gg,bg,r,g,b,x,y:  Integer;
  1710. begin
  1711.   for y:=0 to clip.Height-1 do
  1712.   begin
  1713.     p0:=clip.scanline[y];
  1714.     for x:=0 to clip.Width-1 do
  1715.     begin
  1716.       r:=p0[x*3];
  1717.       g:=p0[x*3+1];
  1718.       b:=p0[x*3+2];
  1719.       rg:=(Abs(127-r)*Amount)div 255;
  1720.       gg:=(Abs(127-g)*Amount)div 255;
  1721.       bg:=(Abs(127-b)*Amount)div 255;
  1722.       if r>127 then r:=r+rg else r:=r-rg;
  1723.       if g>127 then g:=g+gg else g:=g-gg;
  1724.       if b>127 then b:=b+bg else b:=b-bg;
  1725.       p0[x*3]:=IntToByte(r);
  1726.       p0[x*3+1]:=IntToByte(g);
  1727.       p0[x*3+2]:=IntToByte(b);
  1728.     end;
  1729.   end;
  1730. end;
  1731.  
  1732. procedure Gamma(var Bitmap:TBitmap; Amount: double);
  1733. var
  1734. ByteWsk:^Byte;
  1735. H,V:  Integer;
  1736. begin
  1737.   for V:=0 to Bitmap.Height-1 do
  1738.   begin
  1739.     ByteWsk:=Bitmap.ScanLine[V];
  1740.     for H:=0 to Bitmap.Width*3 -1  do
  1741.     begin
  1742.       ByteWsk^:=FloatToByte(ByteWsk^*Amount);
  1743.       Inc(ByteWsk);
  1744.     end;
  1745.   end;
  1746. end;
  1747.  
  1748. procedure KeepBlue(src: Tbitmap; factor: extended);
  1749. var x,y,w,h:integer;
  1750.     p0:pbytearray;
  1751. begin
  1752.   src.PixelFormat :=pf24bit;
  1753.   w:=src.width;
  1754.   h:=src.height;
  1755.   for y:=0 to h-1 do begin
  1756.     p0:=src.scanline[y];
  1757.    for x:=0 to w-1 do begin
  1758.     p0[x*3]:=round(factor*p0[x*3]);
  1759.     p0[x*3+1]:=0;
  1760.     p0[x*3+2]:=0;
  1761.     end;
  1762.    end;
  1763. end;
  1764.  
  1765. procedure KeepGreen(src: Tbitmap; factor: extended);
  1766. var x,y,w,h:integer;
  1767.     p0:pbytearray;
  1768. begin
  1769.   src.PixelFormat :=pf24bit;
  1770.   w:=src.width;
  1771.   h:=src.height;
  1772.   for y:=0 to h-1 do begin
  1773.     p0:=src.scanline[y];
  1774.    for x:=0 to w-1 do begin
  1775.     p0[x*3+1]:=round(factor*p0[x*3+1]);
  1776.     p0[x*3]:=0;
  1777.     p0[x*3+2]:=0;
  1778.     end;
  1779.    end;
  1780. end;
  1781.  
  1782. procedure KeepRed(src: Tbitmap; factor: extended);
  1783. var x,y,w,h:integer;
  1784.     p0:pbytearray;
  1785. begin
  1786.   src.PixelFormat :=pf24bit;
  1787.   w:=src.width;
  1788.   h:=src.height;
  1789.   for y:=0 to h-1 do begin
  1790.     p0:=src.scanline[y];
  1791.    for x:=0 to w-1 do begin
  1792.     p0[x*3+2]:=round(factor*p0[x*3+2]);
  1793.     p0[x*3+1]:=0;
  1794.     p0[x*3]:=0;
  1795.     end;
  1796.    end;
  1797. end;
  1798.  
  1799. // =========== ROTATTE BITMAP =====================================
  1800.  
  1801. function TStretchBitmap.StretchBitm(Bitmap, Target: TBitmap; R: TRotateRec): Boolean;
  1802. var
  1803.   i: integer;
  1804.   pptr1, pptr2: array of TArray;
  1805.   ptrscanline1, ptrscanline2: array of integer;
  1806. begin
  1807. if (Bitmap<>nil) and (Target<>nil) then begin
  1808.    SetLength(ptrscanline1, bitmap.Height);
  1809.    SetLength(ptrscanline2, target.Height);
  1810.    for i := 0 to bitmap.Height - 1 do
  1811.      ptrscanline1[i] := integer(bitmap.ScanLine[i]);
  1812.    for i := 0 to target.Height - 1 do
  1813.      ptrscanline2[i] := integer(target.ScanLine[i]);
  1814.    r.maxw := target.Width;
  1815.    r.maxh := target.Height;
  1816.    r.w := (r.x2 - r.x1);
  1817.    r.h := (r.y2 - r.y1);
  1818.    SetLength(pptr1, Max(abs(r.x2s-r.x1s), abs(r.y2s-r.y1s)) + 1);
  1819.    SetLength(pptr2, Max(abs(r.x3s-r.x1s), abs(r.y3s-r.y1s)) + 1);
  1820.    r.ptr1 := integer(pptr1);
  1821.    r.ptr2 := integer(pptr2);
  1822.    r.ptrscanline1 := integer(ptrscanline1);
  1823.    r.ptrscanline2 := integer(ptrscanline2);
  1824.    MakeArray(r.x1s, r.x2s, r.y1s, r.y2s, r.w, @r.ww, pptr1);
  1825.    MakeArray(r.x1s, r.x3s, r.y1s, r.y3s, r.h, @r.hh, pptr2);
  1826.    Result := true;
  1827.    try
  1828.      StretchArea(r, integer(@ErrorX), integer(@ErrorY));
  1829.    except
  1830.      on EAccessViolation do
  1831.      begin
  1832.        beep;
  1833.        ErrorX := pptr1[ErrorX div 12].cor;
  1834.        ErrorY := pptr2[ErrorY div 12].cor;
  1835.        Result := false;
  1836.      end;
  1837.    end;
  1838. end;
  1839. end;
  1840.  
  1841. procedure TStretchBitmap.MakeArray(X1S, X2S, Y1S, Y2S, W: integer; WW_ptr, ptr: Pointer);
  1842. var
  1843.   WW: integer;
  1844.   WW_int_ptr: ^integer;
  1845.   h, place_1, place_2: integer;
  1846.   adder_x, adder_y: integer;
  1847.   base, sum_add, step, ptr1: integer;
  1848. label
  1849.   label1, label2, label3, label4, label5,
  1850.   label6, label7, label8, label9;
  1851. begin
  1852.   ptr1 := integer(ptr);
  1853.   WW_int_ptr := WW_ptr;
  1854.   asm
  1855.     push   eax
  1856.     push   ebx
  1857.     push   ecx
  1858.     push   edx
  1859.     push   esi
  1860.     push   edi
  1861.     pushf
  1862.  
  1863.     mov    ecx,1
  1864.     mov    edx,1
  1865.     mov    eax,X2S
  1866.     sub    eax,X1S     //eax = X1S - X2S
  1867.     cmp    eax,0
  1868.     jge    label1      //if eax >= 0 then goto label1
  1869.     neg    eax         //else reverse sign so that is positive
  1870.     mov    ecx,-1      //and mark that X1S - X2S is negative
  1871. label1:
  1872.     inc    eax
  1873.     mov    ebx,Y2S
  1874.     sub    ebx,Y1S
  1875.     cmp    ebx,0
  1876.     jge    label2
  1877.     neg    ebx
  1878.     mov    edx,-1
  1879. label2:
  1880.     inc    ebx
  1881.     mov    place_1,0
  1882.     mov    place_2,4
  1883.     cmp    eax,ebx
  1884.     jge    label3
  1885.     xchg   eax,ebx
  1886.     xchg   ecx,edx
  1887.     mov    place_1,4
  1888.     mov    place_2,0
  1889. label3:
  1890.     mov    h,ebx
  1891.     shl    eax,2
  1892.     mov    WW,eax
  1893.     shl    eax,1
  1894.     add    WW,eax
  1895.     shr    eax,3
  1896.     mov    adder_x,ecx
  1897.     mov    adder_y,edx
  1898.     shr    ebx,1
  1899.     xor    esi,esi
  1900.     mov    edi,ebx
  1901.     mov    ecx,ptr1
  1902.     add    ecx,place_1
  1903.     mov    edx,ptr1
  1904.     add    edx,place_2
  1905.     mov    esi,12
  1906. label4:
  1907.     mov    ebx,adder_x
  1908.     mov    dword ptr [ecx+esi],ebx
  1909.     mov    dword ptr [edx+esi],0
  1910.     add    edi,h
  1911.     cmp    edi,eax
  1912.     jl     label5
  1913.     mov    ebx,adder_y
  1914.     mov    dword ptr [edx+esi],ebx
  1915.     sub    edi,eax
  1916. label5:
  1917.     add    esi,12
  1918.     cmp    esi,WW
  1919.     jl     label4
  1920.  
  1921.     mov    edi,ptr1
  1922.     add    edi,8
  1923.     dec    eax
  1924.     mov    ebx,W
  1925.     xchg   eax,ebx                    {EAX = h ęáé EBX = w}
  1926.     cmp    ebx,eax                    {óýăęńéóç w ęáé h}
  1927.     jl     label6
  1928.     inc    eax                        {EAX = h = y2 - y1 + 1}
  1929.     inc    ebx                        {EBX = w = x2 - x1 + 1}
  1930.     mov    ecx,eax                    {áí w >= h ôüôĺ}
  1931.     shr    ecx,1
  1932.     mov    base,ecx                   {base = int(h/2)}
  1933.     mov    step,0                     {step = 0}
  1934.     mov    sum_add,eax                {sum_add = h}
  1935.     jmp    label7
  1936. label6:                                 {áí w <= h ôüôĺ}
  1937.     mov    ecx,ebx
  1938.     shr    ecx,1
  1939.     mov    base,ecx                   {base = int(w/2)}
  1940.     push   eax                        {áđďčŢęĺőóç ôçň ôéěŢň h ôďő EAX}
  1941.     xor    edx,edx                    {ď EDX:EAX đńďĺôďéěÜćĺôáé ăéá
  1942. äéáßńĺóç}
  1943.     div    ebx                        {äéáßńĺóç EDX:EAX/EBX}
  1944.     mov    step,eax                   {step = EAX = int(h/w) (ôď áęÝńáéď
  1945. ěÝńďň ôçň äéáßńĺóçň)}
  1946.     mov    sum_add,edx                {sum_add = EDX = h mod w (ôď őđüëďéđď
  1947. ôçň äéáßńĺóçň)}
  1948.     pop    eax                        {áíÜęôçóç ôçň ôéěŢň h ôďő EAX}
  1949. label7:
  1950.     xor    esi,esi                    {ESI = i = 0}
  1951.     mov    ecx,base                   {ECX = sum = base}
  1952.     mov    edx,0                      {EDX = level = 0}
  1953.     mov    eax,WW                     {EAX = limit}
  1954. label8:
  1955.     mov    dword ptr [edi+esi],edx    {ç array óôď offset i đáßńíĺé ôçí ôéěŢ
  1956. level}
  1957.     add    ecx,sum_add                {sum = sum + sum_add}
  1958.     add    edx,step                   {level = level + step}
  1959.     cmp    ecx,ebx
  1960.     jl     label9                     {áí sum >= w ôüôĺ}
  1961.     inc    edx                        {level = level + 1}
  1962.     sub    ecx,ebx                    {sum = sum - w}
  1963. label9:
  1964.     add    esi,12                      {i = i + 4 (äéüôé ôá đĺńéĺ÷üěĺíá ôçň
  1965. array ôďđďčĺôďýíôáé áíÜ 4 bytes}
  1966.     cmp    esi,WW
  1967.     jl     label8                       {áí i = limit ôüôĺ ôÝëďň ôçň
  1968. ńďőôßíáň}
  1969.  
  1970.     popf
  1971.     pop    edi
  1972.     pop    esi
  1973.     pop    edx
  1974.     pop    ecx
  1975.     pop    ebx
  1976.     pop    eax
  1977.   end;
  1978.   WW_int_ptr^ := WW;
  1979. end;
  1980.  
  1981. procedure TStretchBitmap.StretchArea(R: TRotateRec; ErrX, ErrY: integer);
  1982. var
  1983.   ptr_y, x_prev, y_prev, maxh4: integer;
  1984. label
  1985.   label1, label2, label3, label4, label5, label6, label7;
  1986. begin
  1987.   asm
  1988.     pushad
  1989.     pushf
  1990.     xor    ebx,ebx
  1991.     xor    ecx,ecx
  1992.     xor    edx,edx
  1993.     xor    edi,edi
  1994.     mov    eax,R.maxh      //takes the height of the target bitmap
  1995.     shl    eax,2           //multiply by 4
  1996.     mov    maxh4,eax       //maxh4 stores the height of the target bitmap x 4
  1997. label1:
  1998.     mov    y_prev,ebx      //y_prev takes the previous value of y correspondance in source bitmap
  1999.     mov    ebx,ErrY        //address of ErrY is loaded on ebx
  2000.     mov    dword ptr [ebx],edi   //index of array of y correspondances is stored in ErrY
  2001.     mov    ebx,R.ptr2      //array of y correspondances is loaded on ebx
  2002.     mov    eax,dword ptr [ebx+edi]     //eax takes the step in x axis
  2003.     mov    esi,dword ptr [ebx+edi+4]   //esi takes the step in y axis
  2004.     mov    ebx,dword ptr [ebx+edi+8]   //ebx takes the y correspondance in source bitmap
  2005.     push   edi         //push index of array of y correspondances in stack
  2006.     add    ecx,eax     //ecx is the x position in the target bitmap
  2007.     add    edx,esi     //ecx is the y position in the target bitmap
  2008.     test   eax,esi     //if steps in both axis is <> 0 then continue
  2009.     jz     label5      //else goto to label5
  2010.     push   ebx         //push y correspondance in source bitmap in stack
  2011.     push   ecx         //push x position in target bitmap in stack
  2012.     push   edx         //push y position in target bitmap in stack
  2013.     add    ecx,R.x1s   //ecx get the relative position in x axis of target bitmap
  2014.     shl    ecx,1       //ecx is doubled
  2015.     sub    ecx,eax     //step in x axis is subtrscted from ecx
  2016.                        //ecx now has the intermediate value of relative position
  2017.                        //in x axis of target bitmap, doubled so that it is an
  2018.                        //integer value
  2019.     add    edx,R.y1s {R.y1s}
  2020.     shl    edx,1
  2021.     sub    edx,esi     //the same as ecx, for the y axis of target bitmap
  2022.     add    ebx,y_prev  //add previous value of y correspondance in source bitmap to the present value
  2023.     shr    ebx,1       //divide ebx by 2, in order to find the intermediate value
  2024.     add    ebx,r.y1    //get the relative to y1 value
  2025.     shl    ebx,2       //multiply by 4, in order to get the index of the address of the line
  2026.     add    ebx,R.ptrscanline1  //ebx gets the array of the line adresses of the source bitmap
  2027.     mov    ebx,dword ptr [ebx]  //get the line address of the source bitmap
  2028. {    add    ebx,r.x1}     {8bit}
  2029.     mov    esi,r.x1       {24bit}  //esi = x1
  2030.     add    ebx,esi        {24bit}
  2031.     add    ebx,esi        {24bit}
  2032.     add    ebx,esi        {24bit}  //get the address of x1 in line array
  2033.     mov    ptr_y,ebx    //ptr_y is the address of x1 in source bitmap
  2034.     xor    ebx,ebx
  2035.     xor    esi,esi
  2036. label2:
  2037.     mov    x_prev,ebx  //x_prev takes the previous value of x correspondance in source bitmap
  2038.     mov    ebx,ErrX    //address of ErrX is loaded on ebx
  2039.     mov    dword ptr [ebx],esi  //index of array of x correspondances is stored in ErrX
  2040.     mov    ebx,R.ptr1  //array of y correspondances is loaded on ebx
  2041.     mov    eax,dword ptr[ebx+esi]  //eax takes the step in x axis
  2042.     mov    edi,dword ptr[ebx+esi+4]  //edi takes the step in y axis
  2043.     mov    ebx,dword ptr[ebx+esi+8]  //ebx takes the x correspondance in source bitmap
  2044.     add    ecx,eax
  2045.     add    ecx,eax     //ecx has the final x position of target bitmap, doubled
  2046.     add    edx,edi
  2047.     add    edx,edi     //edx has the final y position of target bitmap, doubled
  2048.     test   eax,edi     //if steps in both axis is <> 0 then continue
  2049.     jz     label4      //else goto label4
  2050.     push   ebx         //push x correspondance in source bitmap in stack
  2051.     push   ecx         //push final x position in target bitmap in stack
  2052.     push   edx         //push final y position in target bitmap in stack
  2053.     sub    edx,edi     //edx has the final intermediate y position, doubled
  2054.     shl    edx,1       //final intermediate y position, quadrupled
  2055.     cmp    edx,maxh4   //check if y position in target bitmap exceeds bitmap limits
  2056.     jge    label3      //if it exceeds then continue to next point
  2057.     sub    ecx,eax     //ecx has the final intermediate x position, doubled
  2058.     shr    ecx,1       //ecx has the final intermediate x position
  2059.     cmp    ecx,R.maxw  //check if x position in target bitmap exceeds bitmap limits
  2060.     jge    label3      //if it exceeds then continue to next point
  2061.     add    edx,R.ptrscanline2  //edx gets the array of the line adresses of the target bitmap
  2062. {    add    ecx,dword ptr [edx]}  {8bit}
  2063.     mov    edx,dword ptr [edx]    {24bit}  //get the line address of the target bitmap
  2064.     add    edx,ecx                {24bit}
  2065.     add    edx,ecx                {24bit}
  2066.     add    ecx,edx                {24bit}  //ecx = edx + 3 * ecx
  2067.     add    ebx,x_prev  //add previous value of x correspondance in source bitmap to the present value
  2068.     shr    ebx,1       //divide ebx by 2, in order to find the intermediate value
  2069.     mov    edx,ebx                {24bit}  //edx takes intermediate x position in source bitmap
  2070.     add    ebx,ebx                {24bit}  //ebx takes intermediate x position in source bitmap, doubled
  2071.     add    ebx,ptr_y   //ebx = (address of the source point) - edx
  2072.  
  2073. //    mov    bl,byte ptr [ebx]    //8bit
  2074. //    mov    byte ptr [ecx],bl    //8bit
  2075.     mov    al, byte ptr [ebx+edx]   //al gets the first byte of the 24bit source color
  2076.     mov    byte ptr [ecx], al       //the first byte of the 24bit source color is assigned to target bitmap
  2077.     mov    ax, word ptr [ebx+edx+1] //al gets the next 2 bytes of the 24bit source color
  2078.     mov    word ptr [ecx+1], ax     //the next 2 bytes of the 24bit source color are assigned to target bitmap
  2079. label3:
  2080.     pop    edx
  2081.     pop    ecx
  2082.     pop    ebx
  2083. label4:
  2084.     add    esi,12
  2085.     cmp    esi,R.ww
  2086.     jl     label2
  2087.     pop    edx
  2088.     pop    ecx
  2089.     pop    ebx
  2090. label5:
  2091.     push   ebx
  2092.     push   ecx
  2093.     push   edx
  2094.     add    ecx,R.x1s
  2095.     add    edx,R.y1s
  2096.     mov    edi,R.ptrscanline1
  2097.     xor    esi,esi
  2098.     add    ebx,r.y1
  2099.     shl    ebx,2
  2100.     mov    ebx,dword ptr [ebx+edi]
  2101. {    add    ebx,r.x1}       {8bit}
  2102.     mov    edi,r.x1         {24bit}
  2103.     add    ebx,edi          {24bit}
  2104.     add    ebx,edi          {24bit}
  2105.     add    ebx,edi          {24bit}
  2106.     mov    ptr_y,ebx
  2107.     mov    edi,R.ptrscanline2
  2108. label6:
  2109.     mov    ebx,ErrX
  2110.     mov    dword ptr [ebx],esi
  2111.     mov    ebx,R.ptr1
  2112.     add    ecx,dword ptr [ebx+esi]
  2113.     add    edx,dword ptr [ebx+esi+4]
  2114.     cmp    edx,R.maxh
  2115.     jge    label7
  2116.     cmp    ecx,R.maxw
  2117.     jge    label7
  2118.     mov    ebx,dword ptr [ebx+esi+8]
  2119.     mov    eax,ebx              {24bit}
  2120.     add    ebx,ebx              {24bit}
  2121.     add    ebx,ptr_y
  2122.  
  2123. {    mov    bl,byte ptr [ebx]}  {8bit}
  2124.     add    ebx,eax
  2125.     mov    eax,edx
  2126.     shl    eax,2
  2127.     mov    eax,dword ptr [eax+edi]
  2128.     add    eax,ecx
  2129.     add    eax,ecx             //24bit
  2130.     add    eax,ecx             //24bit
  2131.     push   ecx
  2132.     mov    cl,byte ptr [ebx] //24bit
  2133.     mov    byte ptr [eax],cl //24bit
  2134.     mov    cx,word ptr [ebx+1] //24bit
  2135. //    mov    byte ptr [eax],bl //8bit
  2136.     mov    word ptr [eax+1],cx //24bit
  2137.     pop    ecx
  2138. label7:
  2139.     add    esi,12
  2140.     cmp    esi,R.ww
  2141.     jl     label6
  2142.     pop    edx
  2143.     pop    ecx
  2144.     pop    ebx
  2145.     pop    edi
  2146.     add    edi,12
  2147.     cmp    edi,R.hh
  2148.     jl     label1
  2149.     popf
  2150.     popad
  2151.   end;
  2152. end;
  2153.  
  2154. function TStretchBitmap.StretchIt: Boolean;
  2155. var
  2156.   sr: TRect;
  2157.   res: Boolean;
  2158. begin
  2159.   if SourceBitmap = nil then
  2160.   begin
  2161.     MessageDlg('No source bitmap.', mtError, [mbOk], 0);
  2162.     exit;
  2163.   end;
  2164.   if TargetBitmap = nil then
  2165.   begin
  2166.     MessageDlg('No target bitmap.', mtError, [mbOk], 0);
  2167.     exit;
  2168.   end;
  2169.   if SourceBitmap = TargetBitmap then
  2170.   begin
  2171.     MessageDlg('Source and Target bitmaps cannot be the same.', mtError, [mbOk], 0);
  2172.     exit;
  2173.   end;
  2174.   if (SourceBitmap.PixelFormat <> pf24bit) or (TargetBitmap.PixelFormat <> pf24bit) then
  2175.   begin
  2176. //    MessageDlg('Both bitmaps must be 24bit.', mtError, [mbOk], 0);
  2177.     exit;
  2178.   end;
  2179.   StretchHeader.SourcePlane.PlaneType := ptOrthogonal;
  2180.   StretchHeader.TargetPlane.PlaneType := ptStretched;
  2181.   if not CheckPlane(StretchHeader.SourcePlane) then exit;
  2182.   sr := Rect(0, 0, SourceBitmap.Width, SourceBitmap.Height);
  2183.   with StretchHeader.SourcePlane do
  2184.     if not (PtInRect(sr, Origin) and PtInRect(sr, X_Axis) and PtInRect(sr, Y_Axis)) then
  2185.     begin
  2186. //      MessageDlg('Source plane out of bitmap bounds.', mtError, [mbOk], 0);
  2187.       exit;
  2188.     end;
  2189.   if ResizeTargetBitmap then
  2190.   begin
  2191.     TargetBitmap.Width := 0;
  2192.     TargetBitmap.Height := 0;
  2193.   end;
  2194.   AdjustTargetPlaneToBitmap;
  2195.   R.x1 := StretchHeader.SourcePlane.Origin.x;
  2196.   R.y1 := StretchHeader.SourcePlane.Origin.y;
  2197.   R.x2 := StretchHeader.SourcePlane.X_Axis.x;
  2198.   R.y2 := StretchHeader.SourcePlane.Y_Axis.y;
  2199.   R.x1s := StretchHeader.TargetPlane.Origin.x;
  2200.   R.y1s := StretchHeader.TargetPlane.Origin.y;
  2201.   R.x2s := StretchHeader.TargetPlane.X_Axis.x;
  2202.   R.y2s := StretchHeader.TargetPlane.X_Axis.y;
  2203.   R.x3s := StretchHeader.TargetPlane.Y_Axis.x;
  2204.   R.y3s := StretchHeader.TargetPlane.Y_Axis.y;
  2205.   TargetBitmap.Canvas.Brush.Color := BackgroundColor;
  2206.   sr := Rect(0, 0, TargetBitmap.Width, TargetBitmap.Height);
  2207.   TargetBitmap.Canvas.FillRect(sr);
  2208.   Result := StretchBitm(SourceBitmap, TargetBitmap, R);
  2209.   if Result then
  2210.   begin
  2211.     ErrorX := 0;
  2212.     ErrorY := 0;
  2213.   end;
  2214. end;
  2215.  
  2216. function TStretchBitmap.CheckPlane(pl: TPlane): Boolean;
  2217. begin
  2218.   if pl.PlaneType = ptOrthogonal then
  2219.   begin
  2220.     if (pl.X_Axis.y <> pl.Origin.y) or (pl.Y_Axis.x <> pl.Origin.x) then
  2221.     begin
  2222.       MessageDlg('Othogonal plane not properly set.', mtError, [mbOk], 0);
  2223.       CheckPlane := false;
  2224.       exit;
  2225.     end;
  2226.   end;
  2227.   CheckPlane := true;
  2228. end;
  2229.  
  2230. procedure TStretchBitmap.AdjustTargetPlaneToBitmap;
  2231. var
  2232.   p4, maxp, minp, dims: TPoint;
  2233. begin
  2234. if (SourceBitmap<>nil) and (TargetBitmap<>nil) then begin
  2235.   with StretchHeader.TargetPlane do
  2236.   begin
  2237.     p4.x := X_Axis.x + Y_Axis.x - Origin.x;
  2238.     p4.y := X_Axis.y + Y_Axis.y - Origin.y;
  2239.     maxp.x := MaxIntValue([X_Axis.x, Y_Axis.x, Origin.x, p4.x]);
  2240.     maxp.y := MaxIntValue([X_Axis.y, Y_Axis.y, Origin.y, p4.y]);
  2241.     minp.x := MinIntValue([X_Axis.x, Y_Axis.x, Origin.x, p4.x]);
  2242.     minp.y := MinIntValue([X_Axis.y, Y_Axis.y, Origin.y, p4.y]);
  2243.     Origin.x := Origin.x - minp.x;
  2244.     Origin.y := Origin.y - minp.y;
  2245.     X_Axis.x := X_Axis.x - minp.x;
  2246.     X_Axis.y := X_Axis.y - minp.y;
  2247.     Y_Axis.x := Y_Axis.x - minp.x;
  2248.     Y_Axis.y := Y_Axis.y - minp.y;
  2249.     dims.x := maxp.x - minp.x + 1;
  2250.     dims.y := maxp.y - minp.y + 1;
  2251.   end;
  2252.   if ResizeTargetBitmap then
  2253.   begin
  2254.     TargetBitmap.Width := dims.x;
  2255.     TargetBitmap.Height := dims.y;
  2256.   end;
  2257. end;
  2258. end;
  2259.  
  2260. function TStretchBitmap.RotateIt(RotationAngle: Single): Boolean;
  2261. var
  2262.   pnew: TPoint;
  2263.   rad, sinf, cosf: Double;
  2264. begin
  2265. if (SourceBitmap<>nil) and (TargetBitmap<>nil) then begin
  2266.   rad := - Pi * RotationAngle / 180;
  2267.   sinf := Sin(rad);
  2268.   cosf := Cos(rad);
  2269.   StretchHeader.SourcePlane.Origin := Point(0, 0);
  2270.   StretchHeader.SourcePlane.X_Axis := Point(SourceBitmap.Width - 1, 0);
  2271.   StretchHeader.SourcePlane.Y_Axis := Point(0, SourceBitmap.Height - 1);
  2272.   StretchHeader.TargetPlane.Origin := Point(0, 0);
  2273.   pnew.x := trunc((SourceBitmap.Width - 1) * cosf + 0.5);
  2274.   pnew.y := trunc((SourceBitmap.Width - 1) * sinf + 0.5);
  2275.   StretchHeader.TargetPlane.X_Axis := pnew;
  2276.   pnew.x := -trunc((SourceBitmap.Height - 1) * sinf + 0.5);
  2277.   pnew.y := trunc((SourceBitmap.Height - 1) * cosf + 0.5);
  2278.   StretchHeader.TargetPlane.Y_Axis := pnew;
  2279.   Result := StretchIt;
  2280. end;
  2281. end;
  2282.  
  2283. { A cél bitmap-et úgy nagyítja, hogy az elforgatott téglalap befoglalója legyen }
  2284. function TStretchBitmap.RotateIt(RotationAngle,Magnify: double): Boolean;
  2285. var
  2286.   pnew: TPoint;
  2287.   rad, sinf, cosf: Double;
  2288. begin
  2289. if (SourceBitmap<>nil) and (TargetBitmap<>nil) then begin
  2290.   rad := - Pi * RotationAngle / 180;
  2291.   sinf := Sin(rad);
  2292.   cosf := Cos(rad);
  2293.   StretchHeader.SourcePlane.Origin := Point(0, 0);
  2294.   StretchHeader.SourcePlane.X_Axis := Point(SourceBitmap.Width - 1, 0);
  2295.   StretchHeader.SourcePlane.Y_Axis := Point(0, SourceBitmap.Height - 1);
  2296.   StretchHeader.TargetPlane.Origin := Point(0, 0);
  2297.   pnew.x := trunc(Magnify*(SourceBitmap.Width - 1) * cosf + 0.5);
  2298.   pnew.y := trunc(Magnify*(SourceBitmap.Width - 1) * sinf + 0.5);
  2299.   StretchHeader.TargetPlane.X_Axis := pnew;
  2300.   pnew.x := -trunc(Magnify*(SourceBitmap.Height - 1) * sinf + 0.5);
  2301.   pnew.y := trunc(Magnify*(SourceBitmap.Height - 1) * cosf + 0.5);
  2302.   StretchHeader.TargetPlane.Y_Axis := pnew;
  2303.   Result := StretchIt;
  2304. end;
  2305. end;
  2306.  
  2307. procedure TStretchBitmap.TransBMP
  2308.             ( src,dst  : TBitmap;
  2309.               srcRect  : TRect;
  2310.               Cent     : TPoint2d;
  2311.               Zoom     : double;
  2312.               RotAngle : double);
  2313. var R: TRotateRec;
  2314.     T: TTeglalap;
  2315. begin
  2316.   // Cél paralelogramma elforgatva, nagyítva
  2317.   T := RotateTegla(Cent,Zoom*(srcRect.Right-srcRect.Left),
  2318.                          Zoom*(srcRect.Bottom-srcRect.Top),RotAngle);
  2319. //  DrawTegla(dst.Canvas,T);
  2320.   R.x1:= srcRect.Left;
  2321.   R.y1:= srcRect.Top;
  2322.   R.x2:= srcRect.Right;
  2323.   R.Y2:= srcRect.Bottom;
  2324.   R.w := 0;
  2325.   R.H := 0;
  2326.   R.x1s:= Round(T.a.x);
  2327.   R.y1s:= Round(T.a.y);
  2328.   R.x2s:= Round(T.b.x);
  2329.   R.y2s:= Round(T.b.y);
  2330.   R.x3s:= Round(T.d.x);
  2331.   R.y3s:= Round(T.d.y);
  2332.   StretchBitm(src,dst,R);
  2333. end;
  2334.  
  2335. function TStretchBitmap.SkewIt(Horizontally, Vertically: Single): Boolean;
  2336. var
  2337.   pnew: TPoint;
  2338. begin
  2339. if (SourceBitmap<>nil) and (TargetBitmap<>nil) then begin
  2340.   StretchHeader.SourcePlane.Origin := Point(0, 0);
  2341.   StretchHeader.SourcePlane.X_Axis := Point(SourceBitmap.Width - 1, 0);
  2342.   StretchHeader.SourcePlane.Y_Axis := Point(0, SourceBitmap.Height - 1);
  2343.   StretchHeader.TargetPlane.Origin := Point(0, 0);
  2344.   pnew.x := SourceBitmap.Width - 1;
  2345.   pnew.y := trunc((SourceBitmap.Height - 1) * Vertically / 100 + 0.5);
  2346.   StretchHeader.TargetPlane.X_Axis := pnew;
  2347.   pnew.x := trunc( - (SourceBitmap.Width - 1) * Horizontally / 100 + 0.5);
  2348.   pnew.y := SourceBitmap.Height - 1;
  2349.   StretchHeader.TargetPlane.Y_Axis := pnew;
  2350.   Result := StretchIt;
  2351. end;
  2352. end;
  2353.  
  2354. constructor TStretchBitmap.Create;
  2355. begin
  2356.   StretchHeader.SourcePlane.PlaneType := ptOrthogonal;
  2357.   StretchHeader.TargetPlane.PlaneType := ptStretched;
  2358.   ResizeTargetBitmap := True;
  2359.   BackgroundColor := clBlack;
  2360. //  SourceBitmap := TBitMap.Create;
  2361. //  TargetBitmap := TBitMap.Create;
  2362. //  SourceBitmap.PixelFormat := pf24bit;
  2363. //  TargetBitmap.PixelFormat := pf24bit;
  2364. end;
  2365.  
  2366. destructor TStretchBitmap.Destroy;
  2367. begin
  2368. //  SourceBitmap.Free;
  2369. //  TargetBitmap.Free;
  2370. end;
  2371.  
  2372. procedure TStretchBitmap.SetBackgroundColor(const Value: TColor);
  2373. begin
  2374.   FBackgroundColor := Value;
  2375. end;
  2376.  
  2377. // ============== ROTATE BITMAP =========================
  2378.  
  2379. // Creates rotated bitmap of the specified bitmap.
  2380. function CreateRotatedBitmap(Bitmap: TBitmap; const Angle: Extended; bgColor: TColor): TBitmap;
  2381. type
  2382.   PRGBQuadArray = ^TRGBQuadArray;
  2383.   TRGBQuadArray = array[0..0] of TRGBQuad;
  2384. var
  2385.   bgRGB: TRGBQuad;
  2386.   NormalAngle: Extended;
  2387.   CosTheta, SinTheta: Extended;
  2388.   iCosTheta, iSinTheta: Integer;
  2389.   xSrc, ySrc: Integer;
  2390.   xDst, yDst: Integer;
  2391.   xODst, yODst: Integer;
  2392.   xOSrc, yOSrc: Integer;
  2393.   xPrime, yPrime: Integer;
  2394.   srcWidth, srcHeight: Integer;
  2395.   dstWidth, dstHeight: Integer;
  2396.   yPrimeSinTheta, yPrimeCosTheta: Integer;
  2397.   srcRGBs: PRGBQuadArray;
  2398.   dstRGBs: PRGBQuadArray;
  2399.   dstRGB: PRGBQuad;
  2400.   BitmapInfo: TBitmapInfo;
  2401.   srcBMP, dstBMP: HBITMAP;
  2402.   DC: HDC;
  2403. begin
  2404.   { Converts bgColor to true RGB Color }
  2405.   bgColor := ColorToRGB(bgColor);
  2406.   with bgRGB do
  2407.   begin
  2408.     rgbRed := Byte(bgColor);
  2409.     rgbGreen := Byte(bgColor shr 8);
  2410.     rgbBlue := Byte(bgColor shr 16);
  2411.     rgbReserved := Byte(bgColor shr 24);
  2412.   end;
  2413.  
  2414.   { Calculates Sine and Cosine of the rotation angle }
  2415.   NormalAngle := Frac(Angle / 360.0) * 360.0;
  2416.   SinCos(Pi * -NormalAngle / 180, SinTheta, CosTheta);
  2417.   iSinTheta := Trunc(SinTheta * (1 shl 16));
  2418.   iCosTheta := Trunc(CosTheta * (1 shl 16));
  2419.  
  2420.   { Prepares the required data for the source bitmap }
  2421.   srcBMP := Bitmap.Handle;
  2422.   srcWidth := Bitmap.Width;
  2423.   srcHeight := Bitmap.Height;
  2424.   xOSrc := srcWidth shr 1;
  2425.   yOSrc := srcHeight shr 1;
  2426.  
  2427.   { Prepares the required data for the target bitmap }
  2428.   dstWidth := SmallInt((srcWidth * Abs(iCosTheta) + srcHeight * Abs(iSinTheta)) shr 16);
  2429.   dstHeight := SmallInt((srcWidth * Abs(iSinTheta) + srcHeight * Abs(iCosTheta)) shr 16);
  2430.   xODst := dstWidth shr 1;
  2431.   if not Odd(dstWidth) and ((NormalAngle = 0.0) or (NormalAngle = -90.0)) then
  2432.     Dec(xODst);
  2433.   yODst := dstHeight shr 1;
  2434.   if not Odd(dstHeight) and ((NormalAngle = 0.0) or (NormalAngle = +90.0)) then
  2435.     Dec(yODst);
  2436.  
  2437.   // Initializes bitmap header
  2438.   FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
  2439.   with BitmapInfo.bmiHeader do
  2440.   begin
  2441.     biSize := SizeOf(BitmapInfo.bmiHeader);
  2442.     biCompression := BI_RGB;
  2443.     biBitCount := 32;
  2444.     biPlanes := 1;
  2445.   end;
  2446.  
  2447.   // Get source and target RGB bits
  2448.   DC := CreateCompatibleDC(0);
  2449.   try
  2450.     BitmapInfo.bmiHeader.biWidth := srcWidth;
  2451.     BitmapInfo.bmiHeader.biHeight := srcHeight;
  2452.     GetMem(srcRGBs, srcWidth * srcHeight * SizeOf(TRGBQuad));
  2453.     GdiFlush;
  2454.     GetDIBits(DC, srcBMP, 0, srcHeight, srcRGBS, BitmapInfo, DIB_RGB_COLORS);
  2455.     BitmapInfo.bmiHeader.biWidth := dstWidth;
  2456.     BitmapInfo.bmiHeader.biHeight := dstHeight;
  2457.     dstBMP := CreateDIBSection(DC, BitmapInfo, DIB_RGB_COLORS, Pointer(dstRGBs), 0, 0);
  2458.   finally
  2459.     DeleteDC(DC);
  2460.   end;
  2461.  
  2462.   { Pefroms rotation on RGB bits }
  2463.   dstRGB := @dstRGBs[(dstWidth * dstHeight) - 1];
  2464.   yPrime := yODst;
  2465.   for yDst := dstHeight - 1 downto 0 do
  2466.   begin
  2467.     yPrimeSinTheta := yPrime * iSinTheta;
  2468.     yPrimeCosTheta := yPrime * iCosTheta;
  2469.     xPrime := xODst;
  2470.     for xDst := dstWidth - 1 downto 0 do
  2471.     begin
  2472.       xSrc := SmallInt((xPrime * iCosTheta - yPrimeSinTheta) shr 16) + xOSrc;
  2473.       ySrc := SmallInt((xPrime * iSinTheta + yPrimeCosTheta) shr 16) + yOSrc;
  2474.       {$IFDEF COMPILER4_UP}
  2475.       if (DWORD(ySrc) < DWORD(srcHeight)) and (DWORD(xSrc) < DWORD(srcWidth)) then
  2476.       {$ELSE} // Delphi 3 compiler ignores unsigned type cast and generates signed comparison code!
  2477.       if (ySrc >= 0) and (ySrc < srcHeight) and (xSrc >= 0) and (xSrc < srcWidth) then
  2478.       {$ENDIF}
  2479.         dstRGB^ := srcRGBs[ySrc * srcWidth + xSrc]
  2480.       else
  2481.         dstRGB^ := bgRGB;
  2482.       Dec(dstRGB);
  2483.       Dec(xPrime);
  2484.     end;
  2485.     Dec(yPrime);
  2486.   end;
  2487.  
  2488.   { Releases memory for source bitmap RGB bits }
  2489.   FreeMem(srcRGBs);
  2490.  
  2491.   { Create result bitmap }
  2492.   Result := TBitmap.Create;
  2493.   Result.Handle := dstBMP;
  2494. end;
  2495.  
  2496. Procedure RotateBitmap( SourceBitmap : TBitmap; out DestBitmap : TBitmap;
  2497.                         Center : TPoint; Angle : Double) ;
  2498. Var
  2499.    cosRadians : Double;
  2500.    inX : Integer;
  2501.    inXOriginal : Integer;
  2502.    inXPrime : Integer;
  2503.    inXPrimeRotated : Integer;
  2504.    inY : Integer;
  2505.    inYOriginal : Integer;
  2506.    inYPrime : Integer;
  2507.    inYPrimeRotated : Integer;
  2508.    OriginalRow : pPixelArray;
  2509.    Radians : Double;
  2510.    RotatedRow : pPixelArray;
  2511.    sinRadians : Double;
  2512. begin
  2513.    DestBitmap.Width := SourceBitmap.Width;
  2514.    DestBitmap.Height := SourceBitmap.Height;
  2515.    DestBitmap.PixelFormat := pf24bit;
  2516.    Radians := -(Angle) * PI / 180;
  2517.    sinRadians := Sin(Radians) ;
  2518.    cosRadians := Cos(Radians) ;
  2519.    For inX := DestBitmap.Height-1 Downto 0 Do
  2520.    Begin
  2521.      RotatedRow := DestBitmap.Scanline[inX];
  2522.      inXPrime := 2*(inX - Center.y) + 1;
  2523.      For inY := DestBitmap.Width-1 Downto 0 Do
  2524.      Begin
  2525.        inYPrime := 2*(inY - Center.x) + 1;
  2526.        inYPrimeRotated := Round(inYPrime * CosRadians - inXPrime * sinRadians) ;
  2527.        inXPrimeRotated := Round(inYPrime * sinRadians + inXPrime * cosRadians) ;
  2528.        inYOriginal := (inYPrimeRotated - 1) Div 2 + Center.x;
  2529.        inXOriginal := (inXPrimeRotated - 1) Div 2 + Center.y;
  2530.        If
  2531.          (inYOriginal >= 0) And
  2532.          (inYOriginal <= SourceBitmap.Width-1) And
  2533.          (inXOriginal >= 0) And
  2534.          (inXOriginal <= SourceBitmap.Height-1)
  2535.        Then
  2536.        Begin
  2537.          OriginalRow := SourceBitmap.Scanline[inXOriginal];
  2538.          RotatedRow[inY] := OriginalRow[inYOriginal]
  2539.        End
  2540.        Else
  2541.        Begin
  2542.          RotatedRow[inY].rgbtBlue := 100;
  2543.          RotatedRow[inY].rgbtGreen := 100;
  2544.          RotatedRow[inY].rgbtRed := 100
  2545.        End;
  2546.      End;
  2547.    End;
  2548.    SourceBitmap.Assign(DestBitmap);
  2549. End;
  2550.  
  2551. // ============== END ROTATE BITMAP =========================
  2552.  
  2553. procedure AntiAlias(clip: tbitmap);
  2554. begin
  2555. AntiAliasRect(clip,0,0,clip.width,clip.height);
  2556. end;
  2557.  
  2558. procedure AntiAliasRect(clip: tbitmap; XOrigin, YOrigin,
  2559.   XFinal, YFinal: Integer);
  2560. var Memo,x,y: Integer; (* Composantes primaires des points environnants *)
  2561.     p0,p1,p2:pbytearray;
  2562.  
  2563. begin
  2564.    if XFinal<XOrigin then begin Memo:=XOrigin; XOrigin:=XFinal; XFinal:=Memo; end;  (* Inversion des valeurs   *)
  2565.    if YFinal<YOrigin then begin Memo:=YOrigin; YOrigin:=YFinal; YFinal:=Memo; end;  (* si diff‚rence n‚gative*)
  2566.    XOrigin:=max(1,XOrigin);
  2567.    YOrigin:=max(1,YOrigin);
  2568.    XFinal:=min(clip.width-2,XFinal);
  2569.    YFinal:=min(clip.height-2,YFinal);
  2570.    clip.PixelFormat :=pf24bit;
  2571.    for y:=YOrigin to YFinal do begin
  2572.     p0:=clip.ScanLine [y-1];
  2573.     p1:=clip.scanline [y];
  2574.     p2:=clip.ScanLine [y+1];
  2575.     for x:=XOrigin to XFinal do begin
  2576.       p1[x*3]:=(p0[x*3]+p2[x*3]+p1[(x-1)*3]+p1[(x+1)*3])div 4;
  2577.       p1[x*3+1]:=(p0[x*3+1]+p2[x*3+1]+p1[(x-1)*3+1]+p1[(x+1)*3+1])div 4;
  2578.       p1[x*3+2]:=(p0[x*3+2]+p2[x*3+2]+p1[(x-1)*3+2]+p1[(x+1)*3+2])div 4;
  2579.       end;
  2580.    end;
  2581. end;
  2582.  
  2583.  
  2584. procedure Sepia ( Bitmap:TBitmap;depth:byte);
  2585. var
  2586. Row:^TRGBTriple;
  2587. H,V:Integer;
  2588. begin
  2589.  Bitmap.PixelFormat:=pf24bit;
  2590.  for V:=0 to Bitmap.Height-1 do
  2591.   begin
  2592.     Row:=Bitmap.ScanLine[V];
  2593.     for H:=0 to Bitmap.Width -1 do
  2594.     begin
  2595.       Row.rgbtBlue :=(Row.rgbtBlue +Row.rgbtGreen +Row.rgbtRed)div 3;
  2596.       Row.rgbtGreen:=Row.rgbtBlue;
  2597.       Row.rgbtRed  :=Row.rgbtBlue;
  2598.       inc(Row.rgbtRed,depth*2); //dodane wartosci
  2599.       inc(Row.rgbtGreen,depth);
  2600.       if Row.rgbtRed < (depth*2) then Row.rgbtRed:=255;
  2601.       if  Row.rgbtGreen < (depth) then Row.rgbtGreen:=255;
  2602.       inc(Row);
  2603.     end;
  2604.   end;
  2605. end;
  2606.  
  2607. Procedure Blur( var Bitmap :TBitmap);
  2608. var
  2609.    TL,TC,TR,BL,BC,BR,LL,LC,LR:^TRGBTriple;
  2610.    H,V:Integer;
  2611. begin
  2612.      Bitmap.PixelFormat :=pf24bit;
  2613. for V := 1 to Bitmap.Height - 2 do
  2614. begin
  2615. TL:= Bitmap.ScanLine[V - 1];
  2616. TC:=TL;    // to samo Scanline  Bitmap.ScanLine[V - 1]; tylko oszczędniej
  2617. TR:=TL;
  2618. BL:= Bitmap.ScanLine[V];
  2619. BC:=BL;
  2620. BR:=BL;
  2621. LL:= Bitmap.ScanLine[V + 1];
  2622. LC:=LL;
  2623. LR:=LL;
  2624. inc(TC); inc(TR,2);
  2625. inc(BC); inc(BR,2);
  2626. inc(LC); inc(LR,2);
  2627.  
  2628. for H := 1 to (Bitmap.Width  - 2) do
  2629. begin
  2630. //Wyciągam srednią z 9 sąsiadujących pixeli
  2631.   BC.rgbtRed:= (BC.rgbtRed+ BL.rgbtRed+BR.rgbtRed+
  2632.   TC.rgbtRed+ TL.rgbtRed+TR.rgbtRed+
  2633.   LL.rgbtRed+ LC.rgbtRed+LR.rgbtRed) div 9 ;
  2634.  
  2635.   BC.rgbtGreen:=( BC.rgbtGreen+ BL.rgbtGreen+BR.rgbtGreen+
  2636.   TC.rgbtGreen+ TL.rgbtGreen+TR.rgbtGreen+
  2637.   LL.rgbtGreen+ LC.rgbtGreen+LR.rgbtGreen) div 9 ;
  2638.  
  2639.   BC.rgbtBlue:=( BC.rgbtBlue+ BL.rgbtBlue+BR.rgbtBlue+
  2640.   TC.rgbtBlue+ TL.rgbtBlue+TR.rgbtBlue+
  2641.   LL.rgbtBlue+ LC.rgbtBlue+LR.rgbtBlue )div 9 ;
  2642. //zwiększam wskaźniki biorąc następne 9 pixeli
  2643.   inc(TL);inc(TC);inc(TR);
  2644.   inc(BL);inc(BC);inc(BR);
  2645.   inc(LL);inc(LC);inc(LR);
  2646.     end;
  2647.   end;
  2648. end;
  2649.  
  2650. procedure SplitBlur(var clip: tbitmap; Amount: integer);
  2651. var
  2652. p0,p1,p2:pbytearray;
  2653. cx,i,x,y: Integer;
  2654. Buf:   array[0..3,0..2]of byte;
  2655. begin
  2656.   if Amount=0 then Exit;
  2657.   for y:=0 to clip.Height-1 do
  2658.   begin
  2659.     p0:=clip.scanline[y];
  2660.     if y-Amount<0         then p1:=clip.scanline[y]
  2661.     else {y-Amount>0}          p1:=clip.ScanLine[y-Amount];
  2662.     if y+Amount<clip.Height    then p2:=clip.ScanLine[y+Amount]
  2663.     else {y+Amount>=Height}    p2:=clip.ScanLine[clip.Height-y];
  2664.  
  2665.     for x:=0 to clip.Width-1 do
  2666.     begin
  2667.       if x-Amount<0     then cx:=x
  2668.       else {x-Amount>0}      cx:=x-Amount;
  2669.       Buf[0,0]:=p1[cx*3];
  2670.       Buf[0,1]:=p1[cx*3+1];
  2671.       Buf[0,2]:=p1[cx*3+2];
  2672.       Buf[1,0]:=p2[cx*3];
  2673.       Buf[1,1]:=p2[cx*3+1];
  2674.       Buf[1,2]:=p2[cx*3+2];
  2675.       if x+Amount<clip.Width     then cx:=x+Amount
  2676.       else {x+Amount>=Width}     cx:=clip.Width-x;
  2677.       Buf[2,0]:=p1[cx*3];
  2678.       Buf[2,1]:=p1[cx*3+1];
  2679.       Buf[2,2]:=p1[cx*3+2];
  2680.       Buf[3,0]:=p2[cx*3];
  2681.       Buf[3,1]:=p2[cx*3+1];
  2682.       Buf[3,2]:=p2[cx*3+2];
  2683.       p0[x*3]:=(Buf[0,0]+Buf[1,0]+Buf[2,0]+Buf[3,0])shr 2;
  2684.       p0[x*3+1]:=(Buf[0,1]+Buf[1,1]+Buf[2,1]+Buf[3,1])shr 2;
  2685.       p0[x*3+2]:=(Buf[0,2]+Buf[1,2]+Buf[2,2]+Buf[3,2])shr 2;
  2686.     end;
  2687.   end;
  2688. end;
  2689.  
  2690. procedure GaussianBlur(var clip: tbitmap; Amount: integer);
  2691. var
  2692. i: Integer;
  2693. begin
  2694.   for i:=Amount downto 0 do
  2695.   SplitBlur(clip,3);
  2696. end;
  2697.  
  2698. procedure Lightness( Bitmap:TBitmap; Amount: Integer);
  2699. var
  2700. Wsk:^Byte;
  2701. H,V: Integer;
  2702. begin
  2703.   Bitmap.PixelFormat:=Graphics.pf24bit;
  2704.   for V:=0 to Bitmap.Height-1 do
  2705.   begin
  2706.     Wsk:=Bitmap.ScanLine[V];
  2707.     for H:=0 to Bitmap.Width*3-1 do
  2708.     begin
  2709.     Wsk^:=IntToByte(Wsk^+((255-Wsk^)*Amount)div 255);
  2710.     inc(Wsk);
  2711.     end;
  2712.   end;
  2713. end;
  2714.  
  2715. // Brighten or Darken (-255..0..+255)
  2716. procedure Brightness( Bitmap:TBitmap; Amount: integer);
  2717. begin
  2718.   If Amount>=0 then
  2719.      Lightness(Bitmap,Amount)
  2720.   else
  2721.      Darkness(Bitmap,-Amount);
  2722. end;
  2723.  
  2724. function ShowBaloonHint(Point: TPoint; Handle: THandle; Title: String;
  2725. Msg: String; Icon: Integer): Boolean;
  2726. var
  2727.   hwnd: THandle;
  2728.   ti: TToolInfo;
  2729.   hCursor: THandle;
  2730.   Rect: TRect;
  2731.   IconData: TNotifyIconData;
  2732.  
  2733. const
  2734.   TTS_BALLOON = $40;
  2735.   TTS_CLOSE = $80;
  2736.  
  2737.   procedure SetToolTipTitle(tt: THandle; IconType: Integer; Title: string);
  2738.   var
  2739.     buffer: array[0..255] of Char;
  2740.   const
  2741.     TTM_SETTITLE = (WM_USER + 32);
  2742.   begin
  2743.     FillChar(buffer, SizeOf(buffer), #0);
  2744.     lstrcpy(buffer, PChar(Title));
  2745.     SendMessage(tt, TTM_SETTITLE, IconType, Integer(@buffer));
  2746.   end;
  2747.  
  2748. begin
  2749.   hwnd:= CreateWindowEx(0,
  2750.                         TOOLTIPS_CLASS,
  2751.                         nil,
  2752.                         TTS_ALWAYSTIP or TTS_BALLOON or TTS_CLOSE,
  2753.                         CW_USEDEFAULT,
  2754.                         CW_USEDEFAULT,
  2755.                         CW_USEDEFAULT,
  2756.                         CW_USEDEFAULT,
  2757.                         Application.MainForm.Handle,
  2758.                         0,
  2759.                         Application.Handle,
  2760.                         0);
  2761.  
  2762.   SetWindowPos( hwnd,
  2763.                 HWND_TOPMOST,
  2764.                 0,
  2765.                 0,
  2766.                 0,
  2767.                 0,
  2768.                 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
  2769.  
  2770.   GetClientRect(Handle, Rect);
  2771.  
  2772.   with ti do
  2773.     begin
  2774.       cbSize:= Sizeof(TToolInfo);
  2775.       uFlags:= TTF_TRACK;
  2776.       hwnd:= Handle;
  2777.       hInst:= Application.Handle;
  2778.       uId:= Handle;
  2779.       lpszText:= PChar(Msg);
  2780.     end;
  2781.  
  2782.   ti.Rect.Left:= Rect.Left;
  2783.   ti.Rect.Top:= Rect.Top;
  2784.   ti.Rect.Right:= Rect.Right;
  2785.   ti.Rect.Bottom:= Rect.Bottom;
  2786.  
  2787.   SendMessage(hwnd,TTM_ADDTOOL,1,Integer(@ti));
  2788.   SetToolTipTitle(hwnd,Icon,Title);
  2789.  
  2790.   SendMessage(hwnd, TTM_TRACKPOSITION, 0, MakeLParam(Point.x,Point.y));
  2791.  
  2792.   SendMessage(hwnd, TTM_TRACKACTIVATE, Integer(True), Integer(@ti));
  2793. end;
  2794.  
  2795. procedure DrawShape(Canv: TCanvas; DrawingTool:TDrawingTool; T,B: TPoint;
  2796.            AMode: TPenMode);
  2797. begin
  2798.     Canv.Pen.Mode := AMode;
  2799.     If (T.X<>B.x) OR (T.Y<>B.Y) then
  2800.     begin
  2801.     case DrawingTool of
  2802.       dtPoint: Canv.Rectangle(T.X-1,T.Y-1,T.X+1,T.Y+1);
  2803.       dtLine: begin
  2804.                 Canv.MoveTo(T.X, T.Y);
  2805.                 Canv.LineTo(B.X, B.Y);
  2806.               end;
  2807.       dtRectangle: begin
  2808.            Canv.Rectangle(T.X, T.Y, B.X, B.Y);
  2809.            end;
  2810.       dtEllipse:   Canv.Ellipse(T.X, T.Y, B.X, B.Y);
  2811.       dtRoundRect: Canv.RoundRect(T.X, T.Y, B.X, B.Y,
  2812.         (T.X - B.X) div 2, (T.Y - B.Y) div 2);
  2813.     end;
  2814.     case DrawingTool of
  2815.       dtFillRect: begin
  2816.         Canv.Rectangle(T.X, T.Y, B.X, B.Y);
  2817.         end;
  2818.       dtFillEllipse: begin
  2819.         Canv.Ellipse(T.X, T.Y, B.X, B.Y);
  2820.         end;
  2821.       dtFillRoundRect: begin
  2822.         Canv.RoundRect(T.X, T.Y, B.X, B.Y,
  2823.         (T.X - B.X) div 2, (T.Y - B.Y) div 2);
  2824.         end;
  2825.     end;
  2826.     end;
  2827.     Canv.Refresh;
  2828. end;
  2829.  
  2830.  
  2831. // Fade out the image: Elhalványítja a képet
  2832. procedure FadeOut(const Bmp: TImage; Pause: Integer);
  2833. var
  2834.   BytesPorScan, counter, w, h: Integer;
  2835.   p: pByteArray;
  2836. begin
  2837. if not (Bmp.Picture.Bitmap.Empty) then begin
  2838.   if not (Bmp.Picture.Bitmap.PixelFormat in [pf24Bit, pf32Bit]) then
  2839.      Bmp.Picture.Bitmap.PixelFormat := pf24Bit;
  2840. //    raise Exception.Create('Error, bitmap format is not supporting.');
  2841.   try
  2842.     BytesPorScan := Abs(Integer(Bmp.Picture.Bitmap.ScanLine[1]) -
  2843.       Integer(Bmp.Picture.Bitmap.ScanLine[0]));
  2844.   except
  2845.     raise Exception.Create('Error!!');
  2846.   end;
  2847.  
  2848.   for counter := 1 to 256 do
  2849.   begin
  2850.     for h := 0 to Bmp.Picture.Bitmap.Height - 1 do
  2851.     begin
  2852.       P := Bmp.Picture.Bitmap.ScanLine[h];
  2853.       for w := 0 to BytesPorScan - 1 do
  2854.         if P^[w] > 0 then P^[w] := P^[w] - 1;
  2855.     end;
  2856.     Sleep(Pause);
  2857.     Bmp.Refresh;
  2858.   end;
  2859. end;
  2860. end;
  2861.  
  2862. procedure DrawCentralCross(Ca: TCanvas; cPen: Tpen);
  2863. var R: TRect;
  2864. begin
  2865.   With Ca do begin
  2866.     R := Ca.ClipRect;
  2867.     Pen.Assign(cPen);
  2868.     MoveTo((R.Left+R.Right) div 2,R.Top);
  2869.     LineTo((R.Left+R.Right) div 2,R.Bottom);
  2870.     MoveTo(R.Left,(R.Top+R.Bottom) div 2);
  2871.     LineTo(R.Right,(R.Top+R.Bottom) div 2);
  2872.   end;
  2873. end;
  2874.  
  2875. // Deletes the False chanels
  2876. procedure ChangeRGBChanel(Bitmap : TBitmap; RCh,GCh,BCh: boolean);
  2877. var
  2878.    Row:^TRGBTripleArray;
  2879.    i,j:Integer;
  2880. begin
  2881. If (Bitmap<>nil) and (not Bitmap.Empty) then begin
  2882. TRY
  2883.   Bitmap.PixelFormat := pf24bit;
  2884.   FOR j := 0 TO Bitmap.Height-1 DO
  2885.   BEGIN
  2886.     Row := Bitmap.Scanline[j];
  2887.     FOR i := 0 TO Bitmap.Width-1 DO
  2888.       WITH Row[i] DO
  2889.       BEGIN
  2890.         if not RCh then rgbtRed := 0;
  2891.         if not GCh then rgbtGreen := 0;
  2892.         if not BCh then rgbtBlue := 0;
  2893.       END
  2894.   END;
  2895. FINALLY
  2896. END;
  2897. end;
  2898. end;
  2899.  
  2900. // Change the RGB chanels to monochrome, and set the visibility of rgb chanels
  2901. procedure ChangeRGBChanel(Bitmap : TBitmap; Mono,RCh,GCh,BCh: boolean);
  2902. var
  2903.    Row:^TRGBTripleArray;
  2904.    i,j:Integer;
  2905.    v: integer;
  2906. begin
  2907.   if Mono then
  2908.      ChangeRGBChanelToMonochrome(Bitmap,RCh,GCh,BCh)
  2909.   else
  2910.      ChangeRGBChanel(Bitmap,RCh,GCh,BCh);
  2911. end;
  2912.  
  2913. // Change the RGB chanels to monochrome
  2914. procedure ChangeRGBChanelToMonochrome(Bitmap : TBitmap; RCh,GCh,BCh: boolean);
  2915. var
  2916.    Row:^TRGBTripleArray;
  2917.    i,j,v:Integer;
  2918. begin
  2919. If (Bitmap<>nil) and (not Bitmap.Empty) then begin
  2920.   Bitmap.PixelFormat := pf24bit;
  2921.   FOR j := 0 TO Bitmap.Height-1 DO
  2922.   BEGIN
  2923.     Row := Bitmap.Scanline[j];
  2924.     FOR i := 0 TO Bitmap.Width-1 DO
  2925.       WITH Row[i] DO
  2926.       BEGIN
  2927.         if RCh and GCh and BCh then begin
  2928.            v := (rgbtRed+rgbtGreen+rgbtBlue) div 3;
  2929.            rgbtRed   := v;
  2930.            rgbtGreen := v;
  2931.            rgbtBlue  := v;
  2932.         end;
  2933. //         else begin
  2934.         if RCh then begin
  2935.            rgbtGreen := rgbtRed;
  2936.            rgbtBlue := rgbtRed;
  2937.         end;
  2938.         if GCh then begin
  2939.            rgbtRed := rgbtGreen;
  2940.            rgbtBlue := rgbtGreen;
  2941.         end;
  2942.         if BCh then begin
  2943.            rgbtRed := rgbtBlue;
  2944.            rgbtGreen := rgbtBlue;
  2945.         end;
  2946. //        end;
  2947.       END
  2948.   END;
  2949. end;
  2950. end;
  2951.  
  2952.     function AbovePass(var vol: byte; amount: byte):byte;
  2953.     begin
  2954.       if vol >= amount then vol:=$FF else vol:=0;
  2955.     end;
  2956.  
  2957.     function BelowPass(var vol: byte; amount: byte):byte;
  2958.     begin
  2959.       if vol <= amount then vol:=$FF else vol:=0;
  2960.     end;
  2961.  
  2962.     function EqualPass(var vol: byte; amount: byte):byte;
  2963.     begin
  2964.       if vol = amount then vol:=$FF else vol:=0;
  2965.     end;
  2966.  
  2967.  
  2968. // Remains only those pixels has a value abova (>=) then amount
  2969. procedure HighPass(Bitmap: TBitmap; R,G,B: byte);
  2970. var x,y:integer;
  2971.    Row:^TRGBTripleArray;
  2972.  
  2973.     function SliceOfByte(var vol: byte; amount: byte):byte;
  2974.     begin
  2975.       if vol <= amount then vol:=0;
  2976.     end;
  2977.  
  2978. begin
  2979.   Bitmap.PixelFormat := pf24bit;
  2980.   for y:=0 to Bitmap.height-1 do begin
  2981.     Row:=Bitmap.scanline[y];
  2982.     for x:=0 to Bitmap.width-1 do begin
  2983.       WITH Row[x] DO
  2984.       BEGIN
  2985.         SliceOfByte(rgbtRed,R);
  2986.         SliceOfByte(rgbtGreen,G);
  2987.         SliceOfByte(rgbtBlue,B);
  2988.       END
  2989.     end;
  2990.   end;
  2991. end;
  2992.  
  2993. // Remains only those pixels has a value abova (>=) then amount
  2994. procedure LowPass(Bitmap: TBitmap; R,G,B: byte);
  2995. var x,y:integer;
  2996.    Row:^TRGBTripleArray;
  2997.  
  2998.     function SliceOfByte(var vol: byte; amount: byte):byte;
  2999.     begin
  3000.       if vol >= amount then vol:=0;
  3001.     end;
  3002.  
  3003. begin
  3004.   Bitmap.PixelFormat := pf24bit;
  3005.   for y:=0 to Bitmap.height-1 do begin
  3006.     Row:=Bitmap.scanline[y];
  3007.     for x:=0 to Bitmap.width-1 do begin
  3008.       WITH Row[x] DO
  3009.       BEGIN
  3010.         SliceOfByte(rgbtRed,R);
  3011.         SliceOfByte(rgbtGreen,G);
  3012.         SliceOfByte(rgbtBlue,B);
  3013.       END
  3014.     end;
  3015.   end;
  3016. end;
  3017.  
  3018. // Remains only those pixels has a value abova (>=) then amount
  3019. procedure HighPassEx(Bitmap: TBitmap; amount:integer);
  3020. var x,y:integer;
  3021.     Row:^TRGBTripleArray;
  3022. begin
  3023.   Bitmap.PixelFormat := pf24bit;
  3024.   for y:=0 to Bitmap.height-1 do begin
  3025.     Row:=Bitmap.scanline[y];
  3026.     for x:=0 to Bitmap.width-1 do begin
  3027.       WITH Row[x] DO
  3028.       BEGIN
  3029.         AbovePass(rgbtRed,amount);
  3030.         AbovePass(rgbtGreen,amount);
  3031.         AbovePass(rgbtBlue,amount);
  3032.       END
  3033.     end;
  3034.   end;
  3035. end;
  3036.  
  3037. // Remains only those pixels has a value abova (>=) then amount
  3038. procedure LowPassEx(Bitmap: TBitmap; amount:integer);
  3039. var x,y:integer;
  3040.     Row:^TRGBTripleArray;
  3041. begin
  3042.   Bitmap.PixelFormat := pf24bit;
  3043.   for y:=0 to Bitmap.height-1 do begin
  3044.     Row:=Bitmap.scanline[y];
  3045.     for x:=0 to Bitmap.width-1 do begin
  3046.       WITH Row[x] DO
  3047.       BEGIN
  3048.         BelowPass(rgbtRed,amount);
  3049.         BelowPass(rgbtGreen,amount);
  3050.         BelowPass(rgbtBlue,amount);
  3051.       END
  3052.     end;
  3053.   end;
  3054. end;
  3055.  
  3056. // Remains only those pixels has a value abova (>=) then amount
  3057. procedure SlicePass(Bitmap: TBitmap; Low,High:integer);
  3058. var x,y:integer;
  3059.     Row:^TRGBTripleArray;
  3060.  
  3061.     function SliceByte(var vol: byte; amount1,amount2: byte):byte;
  3062.     begin
  3063.       if (vol < amount1) or (vol > amount2) then vol:=0;
  3064.     end;
  3065.  
  3066. begin
  3067.   Bitmap.PixelFormat := pf24bit;
  3068.   for y:=0 to Bitmap.height-1 do begin
  3069.     Row:=Bitmap.scanline[y];
  3070.     for x:=0 to Bitmap.width-1 do begin
  3071.       WITH Row[x] DO
  3072.       BEGIN
  3073.         SliceByte(rgbtRed,Low,High);
  3074.         SliceByte(rgbtGreen,Low,High);
  3075.         SliceByte(rgbtBlue,Low,High);
  3076.       END
  3077.     end;
  3078.   end;
  3079. end;
  3080.  
  3081. // Summerize all pixel intensity of BMP
  3082. function GetBMPSum(Bitmap: TBitmap):Longint;
  3083. var
  3084. ByteWsk:^Byte;
  3085. H,V:  Integer;
  3086. begin
  3087.   Result := 0;
  3088.   for V:=0 to Bitmap.Height-1 do
  3089.   begin
  3090.     ByteWsk:=Bitmap.ScanLine[V];
  3091.     for H:=0 to (Bitmap.Width-1)*3 do
  3092.     begin
  3093.       Result := Result + ByteWsk^;
  3094.       Inc(ByteWsk);
  3095.     end;
  3096.   end;
  3097. end;
  3098.  
  3099.  
  3100. function GetBMPAverage(Bitmap: TBitmap; HighLimit: byte): TRGB24;
  3101. var
  3102.     Row        :^TRGBTripleArray;
  3103.     x,y        :Integer;
  3104.     Ra,Ga,Ba   : double;
  3105.     PixCount   : integer;
  3106.     PixR,PixG,PixB : integer;   // Count of RGB pixels
  3107. begin
  3108.   PixCount := Bitmap.Width*Bitmap.Height;
  3109. if PixCount>0 then begin
  3110.   Ra:=0;Ga:=0;Ba:=0;
  3111.   PixR:=0;PixG:=0;PixB:=0;
  3112.  
  3113.   for y:=0 to (Bitmap.height-1) do begin
  3114.     Row:=Bitmap.scanline[y];
  3115.     for x:=0 to (Bitmap.width-1) do begin
  3116.       WITH Row[x] DO
  3117.       BEGIN
  3118.       if rgbtRed  <= HighLimit
  3119.          then begin
  3120.             Ra   := Ra + rgbtRed;
  3121.             Inc(PixR);
  3122.          end;
  3123.       if rgbtGreen<= HighLimit
  3124.          then begin
  3125.             Ga := Ga + rgbtGreen;
  3126.             Inc(PixG);
  3127.          end;
  3128.       if rgbtBlue <= HighLimit
  3129.          then begin
  3130.             Ba  := Ba + rgbtBlue;
  3131.             Inc(PixB);
  3132.          end;
  3133.       END;
  3134.     end;
  3135.   end;
  3136.  
  3137.   AvgThreshold.R  := Round(Ra/PixR);
  3138.   AvgThreshold.G  := Round(Ga/PixG);
  3139.   AvgThreshold.B  := Round(Ba/PixB);
  3140. end else begin
  3141.   AvgThreshold.R  := 0;
  3142.   AvgThreshold.G  := 0;
  3143.   AvgThreshold.B  := 0;
  3144. end;
  3145.   Result := AvgThreshold;
  3146. end;
  3147.  
  3148. function GetAverageThreshold(Bitmap: TBitmap): TThreshold;
  3149. var
  3150.     Row        :^TRGBTripleArray;
  3151.     x,y        :Integer;
  3152.     Ra,Ga,Ba   : double;
  3153.     PixCount   : integer;
  3154. begin
  3155. (*
  3156.   PixCount := Bitmap.Width*Bitmap.Height;
  3157. if PixCount>0 then begin
  3158.   Ra:=0;Ga:=0;Ba:=0;
  3159.  
  3160.   for y:=0 to (Bitmap.height-1) do begin
  3161.     Row:=Bitmap.scanline[y];
  3162.     for x:=0 to (Bitmap.width-1) do begin
  3163.       WITH Row[x] DO
  3164.       BEGIN
  3165.       if rgbtRed  < 120
  3166.          then Ra   := Ra + rgbtRed;
  3167.       if rgbtGreen< 100
  3168.          then Ga := Ga + rgbtGreen;
  3169.       if rgbtBlue < 120
  3170.          then Ba  := Ba + rgbtBlue;
  3171.       END;
  3172.     end;
  3173.   end;
  3174.  
  3175.   AvgThreshold.R  := Round(Ra/PixCount);
  3176.   AvgThreshold.G  := Round(Ga/PixCount);
  3177.   AvgThreshold.B  := Round(Ba/PixCount);
  3178. end else begin
  3179.   AvgThreshold.R  := 0;
  3180.   AvgThreshold.G  := 0;
  3181.   AvgThreshold.B  := 0;
  3182. end;*)
  3183.   GetBMPAverage(Bitmap,60);
  3184.   Result := AvgThreshold;
  3185. end;
  3186.  
  3187.  
  3188. // Háttérzaj levonása a teljes képből: Factor = küszöb szorzó
  3189. procedure ThresholdElimination(Bitmap: TBitmap; avgTres: TThreshold; factor: double);
  3190. var
  3191.    Row:^TRGBTripleArray;
  3192.    x,y :Integer;
  3193. begin
  3194.   Bitmap.PixelFormat := pf24bit;
  3195.   for y:=0 to Bitmap.height-1 do begin
  3196.     Row:=Bitmap.scanline[y];
  3197.     for x:=0 to Bitmap.width-1 do begin
  3198.       WITH Row[x] DO
  3199.       BEGIN
  3200.       if rgbtRed  < factor*avgTres.R
  3201.          then rgbtRed   := 0
  3202.          else rgbtRed   := rgbtRed - Round(factor*avgTres.R);
  3203.       if rgbtGreen< factor*avgTres.G
  3204.          then rgbtGreen := 0
  3205.          else rgbtGreen := rgbtGreen - Round(factor*avgTres.G);
  3206.       if rgbtBlue < factor*avgTres.B
  3207.          then rgbtBlue  := 0
  3208.          else rgbtBlue  := rgbtBlue  - Round(factor*avgTres.B);
  3209.       END;
  3210.     end;
  3211.   end;
  3212. end;
  3213.  
  3214. procedure AutomaticThresholdElimination(Bitmap: TBitmap; factor: double);
  3215. begin
  3216.   AvgThreshold := GetBMPAverage(Bitmap,100);
  3217.   ThresholdElimination(Bitmap,AvgThreshold,Factor);
  3218.   RGBMultiplication(Bitmap,1+AvgThreshold.R/255,1+AvgThreshold.G/255,1+AvgThreshold.B/255);
  3219. end;
  3220.  
  3221. // All pixel is white if intenzity<>0
  3222. // Minden pixel telített, ha értéke <> 0
  3223. procedure To2Bit(Bitmap: TBitmap; Threshold: byte);
  3224. var Treshold : integer;
  3225.     xx,yy: integer;
  3226.     Row:  pRGBTripleArray;
  3227. begin
  3228. //   Treshold := 13;
  3229.     for yy:=0 to Bitmap.Height-1 do begin
  3230.         Row := Bitmap.Scanline[yy];
  3231.         for xx:=0 to Bitmap.Width-1 do begin
  3232.             WITH Row[xx] DO
  3233.             BEGIN
  3234.                 if rgbtGreen>Threshold then begin
  3235.                    rgbtRed   := 255;
  3236.                    rgbtGreen   := 255;
  3237.                    rgbtBlue   := 255;
  3238.                 end else begin
  3239.                    rgbtRed   := 0;
  3240.                    rgbtGreen   := 0;
  3241.                    rgbtBlue   := 0;
  3242.                 end;
  3243.             END
  3244.         end; // xx
  3245.     end; // yy
  3246. end;
  3247.  
  3248. procedure RGBMultiplication(Bitmap: TBitmap; Rm,Gm,Bm: double);
  3249. var
  3250.    Row:^TRGBTripleArray;
  3251.    x,y :Integer;
  3252.    kuszob: integer;
  3253.    i          : integer;
  3254.    PixCount   : integer;
  3255.  
  3256.     function RGBLimit(l: double):byte;
  3257.     // l paraméter 0-255 között lehet: ha negatív=0; l>255 = 255
  3258.     begin
  3259.       Result:=Trunc(l);
  3260.       if l<0 then Result:=0;
  3261.       if l>255 then Result:=255;
  3262.     end;
  3263.  
  3264. begin
  3265.   kuszob := 10;
  3266.   Bitmap.PixelFormat := pf24bit;
  3267.   PixCount := Bitmap.Width*Bitmap.Height;
  3268.  
  3269.   for y:=0 to Bitmap.height-1 do begin
  3270.     Row:=Bitmap.scanline[y];
  3271.     for x:=0 to Bitmap.width-1 do begin
  3272.       WITH Row[x] DO
  3273.       BEGIN
  3274.            rgbtRed   := RGBLimit(Rm * rgbtRed);
  3275.            rgbtGreen := RGBLimit(Gm * rgbtGreen);
  3276.            rgbtBlue  := RGBLimit(Bm * rgbtBlue);
  3277.       END;
  3278.     end;
  3279.   end;
  3280.  
  3281. end;
  3282.  
  3283.  
  3284. // Automac Star Detection from photographic bitmap
  3285. //         Result = Star Count
  3286. Function AutomaticStarDetection(Bitmap: TBitmap): integer;
  3287. var BMP        : TBitmap;               // For manipulation
  3288.     thRGB      : TStarRecord;
  3289.     xx,yy      : integer;
  3290.     Row,starRow: pRGBTripleArray;
  3291.     endLine    : boolean;
  3292.     i,j        : integer;
  3293.     starRect   : TRect;
  3294.     FirstRed,EndRed: integer;
  3295.     p          : TPoint2d;
  3296. begin
  3297. Try
  3298.   Try
  3299.     Result := 0;
  3300.     BMP    := TBitmap.Create;
  3301.     BMP.Assign(Bitmap);
  3302.     BMP.PixelFormat := pf24bit;
  3303.     BMP.Canvas.Brush.Style:=bsSolid;
  3304.     for yy:=0 to BMP.Height-1 do begin
  3305.         Row := BMP.Scanline[yy];
  3306.         for xx:=0 to BMP.Width-1 do begin
  3307.             if Row[xx].rgbtRed = 255 then begin
  3308.                j := yy;
  3309.                starRect := Rect(xx,yy,xx,yy);
  3310.                BMP.Canvas.Brush.Color := clRed;
  3311.                BMP.Canvas.FloodFill(xx,yy,clWhite,fsSurface);
  3312.                endLine := False;
  3313.                while not endLine do begin
  3314.                      endLine := False;
  3315.                      starRow := BMP.Scanline[j];
  3316.                      FirstRed := -1;
  3317.                      for i:=0 to BMP.Width-1 do begin
  3318.                          if ((starRow[i].rgbtRed = 255) and (starRow[i].rgbtBlue = 0)) then
  3319.                            begin
  3320.                              if FirstRed<0 then FirstRed := i;
  3321.                              EndRed := i;
  3322.                            end;
  3323.                     end;
  3324.                      if FirstRed = -1 then begin
  3325.                         endLine := True;
  3326.                         starRect.Bottom := j-1;
  3327.                      end else begin
  3328.                      if FirstRed < starRect.Left
  3329.                         then starRect.Left := FirstRed;
  3330.                      if EndRed > starRect.Right
  3331.                         then starRect.Right := EndRed;
  3332.                      end;
  3333.                      Inc(j);
  3334.                      if j>BMP.Height-1 then
  3335.                         exit;
  3336.                end;
  3337.                BMP.Canvas.Brush.Color := clBlack;
  3338.                BMP.Canvas.FloodFill(xx,yy,clRed,fsSurface);
  3339.                // Csillag középpont mentése
  3340.                with StarArray[Result] do begin
  3341.                     ID := Result;
  3342.                     x := 0.5+(starRect.Right + starRect.Left)/2;
  3343.                     y := 0.5+(starRect.Bottom + starRect.Top)/2;
  3344.                     Radius := ((starRect.Right - starRect.Left)
  3345.                               +(starRect.Bottom - starRect.Top))/2;
  3346. (*                    p:=GetStarCentroid(Bitmap,x,y,Radius);
  3347.                     x := p.X+0.5;
  3348.                     y := p.y+0.5;*)
  3349.                     Deleted := False;
  3350.                end;
  3351.  
  3352.                Inc(Result);
  3353.                StarCount := Result;
  3354.             end;
  3355.         end; // xx
  3356.     end; // yy
  3357.   finally
  3358.     BMP.Free;
  3359.   end;
  3360. except
  3361.   if BMP<>nil then BMP.Free;
  3362.   exit;
  3363. end;
  3364. end;
  3365.  
  3366.  
  3367. procedure StarCirclesDraw(Bitmap: TBitmap; col: TColor);
  3368. var i: integer;
  3369.     RR: double;
  3370. begin
  3371.   if StarCount>0 then
  3372.   with Bitmap.Canvas do begin
  3373.        Pen.Color := col;
  3374.        Pen.Width := 1;
  3375.        Brush.Style := bsClear;
  3376.        For i:=0 to StarCount-1 do begin
  3377.            RR := StarArray[i].Radius;
  3378.            if RR<2 then RR:=2;
  3379.            Ellipse(Round(StarArray[i].x-RR),
  3380.                    Round(StarArray[i].y-RR),
  3381.                    Round(StarArray[i].x+RR),
  3382.                    Round(StarArray[i].y+RR));
  3383.        end;    
  3384.   end;
  3385. end;
  3386.  
  3387. // Search for star from image x,y coordinates
  3388. //        idx = index of StarArray element
  3389. function StarSearch(var idx: integer; x,y: double): boolean;
  3390. var R : double;
  3391.     i : integer;
  3392. begin
  3393.   Result := False;
  3394.   idx    := -1;
  3395.   if StarCount<>0 then
  3396.   for i:=0 to StarCount-1 do begin
  3397.       R := StarArray[i].Radius;
  3398.       if R<4 then R:=4;
  3399.       if (Abs(StarArray[i].x-x)<=R) and (Abs(StarArray[i].y-y)<=R) then
  3400.       begin
  3401.         idx    := i;
  3402.         Result := True;
  3403.         Exit;
  3404.       end;
  3405.   end;
  3406. end;
  3407.  
  3408.  
  3409. procedure StepRGB(Bitmap: TBitmap; Step: byte);
  3410. var
  3411.     x,y: integer;
  3412.     Row:  pRGBTripleArray;
  3413. begin
  3414.   Bitmap.PixelFormat := pf24bit;
  3415.   for y:=0 to Bitmap.height-1 do begin
  3416.     Row:=Bitmap.scanline[y];
  3417.     for x:=0 to Bitmap.width-1 do begin
  3418.       WITH Row[x] DO
  3419.       BEGIN
  3420.            rgbtRed   := Step * Trunc(rgbtRed / Step);
  3421.            rgbtGreen := Step * Trunc(rgbtGreen / Step);
  3422.            rgbtBlue  := Step * Trunc(rgbtBlue / Step);
  3423.       END;
  3424.     end;
  3425.   end;
  3426. end;
  3427.  
  3428. procedure StepRGBContur(Bitmap: TBitmap; Step: byte;
  3429.                                 ConturColor: TColor);
  3430. var
  3431.     x,y: integer;
  3432.     Row,RowNext:  pRGBTripleArray;
  3433.     cR,cB,cG : byte;
  3434.     oldR,oldB,oldG : byte;
  3435. begin
  3436.   Bitmap.PixelFormat := pf24bit;
  3437.   cR := GetRValue(ConturColor);
  3438.   cG := GetGValue(ConturColor);
  3439.   cB := GetBValue(ConturColor);
  3440.   oldR := 0; oldG:=0; oldB:=0;
  3441.   Row:=Bitmap.scanline[0];
  3442.   for y:=0 to Bitmap.height-2 do begin
  3443.     RowNext:=Bitmap.scanline[y+1];
  3444.     for x:=0 to Bitmap.width-1 do begin
  3445.       WITH Row[x] DO
  3446.       BEGIN
  3447.        if Trunc(oldG/Step)<>Trunc(rgbtGreen/Step) then begin
  3448.            oldR := rgbtRed; oldG:=rgbtGreen; oldB:=rgbtBlue;
  3449.            rgbtRed := cR;
  3450.            rgbtGreen := cG;
  3451.            rgbtBlue := cB;
  3452.         end else
  3453.         if Trunc(rgbtGreen/Step)<>Trunc(RowNext[x].rgbtGreen/Step) then begin
  3454.            rgbtRed := cR;
  3455.            rgbtGreen := cG;
  3456.            rgbtBlue := cB;
  3457.         end;
  3458.       END;
  3459.     end;
  3460.     Row := RowNext;
  3461.   end;
  3462. end;
  3463.  
  3464. // Take a preprocesses on the Bitmap (Threshold elimination+HighPass filter)
  3465. // and execute the StarDetect with multilevel HighPass;
  3466. // Save the detected stars into the StarArray for all highpass level.
  3467. // After calculete the real stars and store datas in the final StarArray,
  3468. // and you can access the datas from the global StarArray.
  3469. //       Result = Star Count
  3470.  
  3471. Function PrecisionStarDetection(Bitmap: TBitmap; ThresholdFactor: double;
  3472.                                  HighPassLevel: byte): integer;
  3473. var BMP        : TBitmap;        // For manipulation
  3474.     StarList   : TList;          // List for stars
  3475.     hPass      : byte;           // HighPass value for growing
  3476.     TempBMP    : TBitmap;        // For large areas analysis
  3477.     TempCorner : TPoint;
  3478.     TempRadius : integer;
  3479.     EndAnalysis: boolean;        // Significant the end of analysis
  3480.     sStream    : TMemoryStream;  // For founded real stars;
  3481.  
  3482.     // Recursive calling while found a
  3483.     function SmallAreaAnalysis(tBMP: TBitmap; TopLeft: TPoint): integer;
  3484.     begin
  3485.     end;
  3486.  
  3487. begin
  3488. Try
  3489.     StarList   := TList.Create;
  3490.     BMP        := TBitmap.Create;
  3491.     TempBMP    := TBitmap.Create;
  3492.     hPass      := HighPassLevel;
  3493.     EndAnalysis:= False;
  3494.     BMP.Assign(Bitmap);
  3495.     BMP.PixelFormat := pf24bit;
  3496.     Blur(BMP);
  3497.     AutomaticThresholdElimination(BMP, ThresholdFactor);
  3498.     Repeat
  3499.        HighPassEx(BMP,hPass);
  3500.        AutomaticStarDetection(BMP);
  3501.        Inc(hPass,20);
  3502.        EndAnalysis := hPass>235;
  3503.     Until EndAnalysis;
  3504. finally
  3505.     TempBMP.Free;
  3506.     BMP.Free;
  3507.     StarList.Free;
  3508. end;
  3509. end;
  3510.  
  3511. // Calculate the centre position of the star
  3512. // Csillag középpont meghatározás
  3513. function GetStarCentroid(Bitmap: TBitmap;x, y, Radius: double): TPoint2d;
  3514. var i,x0,y0: integer;
  3515.     xx,yy: integer;
  3516.     XPos,YPos: double;
  3517.     XI,YI: double;
  3518.     d: double;
  3519.     n: integer;
  3520.     nPixel: integer;
  3521.     co   : TColor;
  3522. begin
  3523.   x0 := Round(x-Radius);     // befoglaló négyzet bal felső sarka
  3524.   y0 := Round(y-Radius);
  3525.   n  := Round(2*Radius+2);   // befoglaló négyzet oldala
  3526.   nPixel := 0;
  3527.   XPos := 0; YPos := 0;
  3528.   XI := 0; YI := 0;
  3529.   With Bitmap.Canvas do
  3530.     for yy:=y0 to y0+n do begin
  3531.         for xx:=x0 to x0+n do begin
  3532.            d := SQRt(SQR(X-XX)+SQR(Y-YY));
  3533.            IF d<=Radius then begin           // Ha a mérőkörbe esik
  3534.               co := GetGValue(Pixels[xx,yy]);
  3535.               XPos := XPos + (xx-x0) * co;
  3536.               YPos := YPos + (yy-y0) * co;
  3537.               XI   := XI + co;
  3538.               YI   := YI + co;
  3539.               Inc(nPixel);
  3540.            end;
  3541.         end;
  3542.     end;
  3543.     Result.x := x0;
  3544.     Result.y := y0;
  3545.     if XI>0 then begin
  3546.       Result.x := x0 + XPos / XI;
  3547.       Result.y := y0 + YPos / YI;
  3548.     end;
  3549. end;
  3550.  
  3551.  
  3552. // ================ Execute and manipulate a Process, or ProcessList
  3553.  
  3554. procedure DoProcessList(var Bitmap: TBitmap; PrList: TStringList);
  3555. var CommandStr, par1Str, par2Str, par3Str, par4Str : string;
  3556.     i           : integer;
  3557. begin
  3558.   For i:=0 to Pred(PrList.Count) do begin
  3559.   end;
  3560. end;
  3561.  
  3562. // =============== PHOTOMETRICAL METHODS =========================== //
  3563.  
  3564. function GetAverageIntensityOfStar(Bitmap: TBitmap; x,y, Radius: Double): double;
  3565. Var StarTopLeft  : TPoint;     // To left coordinate of Inner rectanle
  3566.     xx,yy,RR     : integer;    // Pixel coordinates, RR = width of star rectangle
  3567.     co           : TColor;     // Color of actual pixel
  3568.     d            : double;     // Distance from the star's centre
  3569.     nPixel       : integer;    // Count of star's pixels are inner the Radius
  3570. begin
  3571.   Result := 0;
  3572. If Radius>0 then
  3573. Try
  3574.   nPixel := 0;
  3575.   StarTopLeft := Point(Round(x-Radius),Round(y-Radius));
  3576.   RR := Round(2*Radius);
  3577.   For yy:=StarTopLeft.y to StarTopLeft.y+RR do
  3578.       For xx:=StarTopLeft.x to StarTopLeft.x+RR do begin
  3579.            d := SQRt(SQR(X-XX)+SQR(Y-YY));
  3580.            IF d<Radius then begin               // if distance < Radius
  3581.               co := Bitmap.Canvas.Pixels[xx,yy];
  3582.               Result := Result + co;
  3583.               Inc(nPixel);
  3584.            end;
  3585.       end;
  3586. Finally
  3587.    Result := Result / nPixel;
  3588. end;
  3589. end;
  3590.  
  3591. function SingleStarPhotometry(Bitmap:TBitmap;      // Source bitmap
  3592.                               x,y: integer;        // Coord's in bitmap
  3593.                               R: integer;          // Radius
  3594.                               Threshold: integer)  // Threshold level
  3595.                               : TStarRecord;       // Record of star
  3596. Var bmp: TBitmap;
  3597.     xx,yy      : integer;
  3598.     Row,starRow:  pRGBTripleArray;
  3599.     endLine    : boolean;
  3600.     i,j        : integer;
  3601.     sRect      : TRect;
  3602.     pCent      : TPoint2d;
  3603. begin
  3604.   Try
  3605.     BMP := TBitmap.Create;
  3606.     BMP.PixelFormat := pf24bit;
  3607.     BMPResize(bmp,2*R+1,2*R+1);
  3608.     BMP.Canvas.CopyRect(BMP.Canvas.Cliprect,Bitmap.Canvas,
  3609.                    Rect(x-R,y-R,x+R,y+R));
  3610.  
  3611.     // Automatic star detect in x,y position (not precise!)
  3612.     HighPassEx(BMP,Threshold);
  3613.     sRect:=Rect(MaxInt,MaxInt,-MaxInt,-MaxInt);
  3614.     BMP.Canvas.Brush.Color := clRed;
  3615.     BMP.Canvas.FloodFill(R,R,clRed,fsSurface);
  3616.     for yy:=0 to BMP.Height-1 do begin
  3617.         Row := BMP.Scanline[yy];
  3618.         for xx:=0 to BMP.Width-1 do begin
  3619.             if Row[xx].rgbtRed = 255 then begin
  3620.                if sRect.Left>xx then sRect.Left:=xx;
  3621.                if sRect.Right<xx then sRect.Right:=xx;
  3622.                if sRect.Top>yy then sRect.Top:=yy;
  3623.                if sRect.Bottom<yy then sRect.Bottom:=yy;
  3624.             end;
  3625.         end;
  3626.     end;
  3627.     Result.x := (sRect.Right + sRect.Left)/2;
  3628.     Result.y := (sRect.Bottom + sRect.Top)/2;
  3629.     Result.Radius := ((sRect.Right - sRect.Left)
  3630.                    +(sRect.Bottom - sRect.Top))/4;
  3631.     BMP.Canvas.CopyRect(BMP.Canvas.Cliprect,Bitmap.Canvas,
  3632.                    Rect(x-R,y-R,x+R,y+R));
  3633.  
  3634.     // Get the original part of source image
  3635.     // and take a precise star detect
  3636.     pCent := GetStarCentroid(Bitmap,Result.x,Result.y,Result.Radius);
  3637.     (*
  3638.     for yy:=0 to BMP.Height-1 do begin
  3639.         Row := BMP.Scanline[yy];
  3640.         for xx:=0 to BMP.Width-1 do begin
  3641.         end;
  3642.     end;
  3643.     *)
  3644.     Result.x := (x-R)+pCent.x;
  3645.     Result.y := (y-R)+pCent.y;
  3646.   finally
  3647.     bmp.Free;
  3648.   end;
  3649. end;
  3650.  
  3651. // Photomety for a single star:
  3652. // x,y = the coordinates of the star;
  3653. // Result = TStarRecord;
  3654. function SimplePhotometry(Bitmap: TBitmap; x,y: Double; var Star : TStarRecord): boolean;
  3655. var StarCent : TPoint2D;         // Centre of star
  3656.     scPoint  : TPoint;
  3657.     StarRec  : TRect2D;
  3658.     MaxIntensity   : integer;    // Maximal intenzity of peek of star
  3659.     PixIntensity   : integer;    // One pixel intenzity while stepping
  3660.     HalfIntensity  : double;     // Half of MaxIntensity
  3661.     AvgIntensity   : double;     // Average intensity of the star in the radius
  3662.     xx,yy          : integer;    // Pixel coordinates
  3663.     OutOfBitmap    : boolean;    // True if measuring step out from the image
  3664. BEGIN
  3665.   With Bitmap.Canvas do begin
  3666.     StarCent      := Point2d(x,y);
  3667.     // Centre pixel of star
  3668.     scPoint       := Point(Trunc(StarCent.x),Trunc(StarCent.y));
  3669.     MaxIntensity  := Pixels[scPoint.x,scPoint.y];
  3670.     HalfIntensity := MaxIntensity/2;
  3671.  
  3672.     // Measuring the half-wide of star curve
  3673.     // -------------------------------------
  3674.     // Get the left edge
  3675.     xx := scPoint.x;
  3676.     yy := scPoint.y;
  3677.     Repeat
  3678.        Dec(xx);
  3679.        PixIntensity := Pixels[xx,yy];
  3680.        if PixIntensity<=HalfIntensity then
  3681.           StarRec.x1 := xx;
  3682.        OutOfBitmap := xx<1;
  3683.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3684.     // Get the right edge
  3685.     xx := scPoint.x;
  3686.     Repeat
  3687.        Inc(xx);
  3688.        PixIntensity := Pixels[xx,yy];
  3689.        if PixIntensity<=HalfIntensity then
  3690.           StarRec.x2 := xx;
  3691.        OutOfBitmap := xx>Bitmap.Width-2;
  3692.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3693.     // Get the Bottom edge
  3694.     xx := scPoint.x;
  3695.     yy := scPoint.y;
  3696.     Repeat
  3697.        Inc(yy);
  3698.        PixIntensity := Pixels[xx,yy];
  3699.        if PixIntensity<=HalfIntensity then
  3700.           StarRec.y2 := yy;
  3701.        OutOfBitmap := yy>Bitmap.Height-2;
  3702.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3703.     // Get the Top edge
  3704.     yy := scPoint.y;
  3705.     Repeat
  3706.        Dec(yy);
  3707.        PixIntensity := Pixels[xx,yy];
  3708.        if PixIntensity<=HalfIntensity then
  3709.           StarRec.y1 := yy;
  3710.        OutOfBitmap := yy<1;
  3711.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3712.  
  3713.     Result         := not OutOfBitmap;        // The total star is on the bitmap
  3714.  
  3715.     if Result then begin
  3716.     Star.HalfRad   := ((StarRec.x2-StarRec.x1)+(StarRec.y2-StarRec.y1))/2;
  3717.     Star.Radius    := Star.HalfRad;
  3718.  
  3719.     xx := Trunc((StarRec.x2+StarRec.x1)/2);
  3720.     xx := Trunc((StarRec.y2+StarRec.y1)/2);
  3721.     StarCent      := GetStarCentroid(Bitmap,Trunc(xx),Trunc(yy),Round(Star.Radius));
  3722.     AvgIntensity := GetAverageIntensityOfStar(Bitmap, x,y, Star.HalfRad);
  3723.  
  3724.     // Finally set the Result parameters
  3725.     Star.x         := StarCent.x;
  3726.     Star.y         := StarCent.y;
  3727.     Star.Intensity := AvgIntensity;
  3728.     end;
  3729.   end;
  3730. END;
  3731.  
  3732. function GetAverageIntensityOfStarG(Bitmap: TBitmap; x,y, Radius: Double): double;
  3733. Var StarTopLeft  : TPoint;     // To left coordinate of Inner rectanle
  3734.     xx,yy,RR     : integer;    // Pixel coordinates, RR = width of star rectangle
  3735.     co           : TColor;     // Color of actual pixel
  3736.     d            : double;     // Distance from the star's centre
  3737.     nPixel       : integer;    // Count of star's pixels are inner the Radius
  3738. begin
  3739.   Result := 0;
  3740. If Radius>0 then
  3741. Try
  3742.   nPixel := 0;
  3743.   StarTopLeft := Point(Round(x-Radius),Round(y-Radius));
  3744.   RR := Round(2*Radius);
  3745.   For yy:=StarTopLeft.y to StarTopLeft.y+RR do
  3746.       For xx:=StarTopLeft.x to StarTopLeft.x+RR do begin
  3747.            d := SQRt(SQR(X-XX)+SQR(Y-YY));
  3748.            IF d<=Radius then begin               // if distance < Radius
  3749.               co := GetGValue(Bitmap.Canvas.Pixels[xx,yy]);
  3750.               Result := Result + co;
  3751.               Inc(nPixel);
  3752.            end;
  3753.       end;
  3754. Finally
  3755.    if nPixel=0 then
  3756.    Result := 0
  3757.    else
  3758.    Result := Result / nPixel;
  3759. end;
  3760. end;
  3761.  
  3762. // Photomety for a single star:
  3763. // x,y = the coordinates of the star;
  3764. // Result = TStarRecord;
  3765. function SimplePhotometryG(Bitmap: TBitmap; x,y: Double; var Star : TStarRecord): boolean;
  3766. var StarCent : TPoint2D;         // Centre of star
  3767.     scPoint  : TPoint;
  3768.     StarRec  : TRect2D;
  3769.     MaxIntensity   : integer;    // Maximal intenzity of peek of star
  3770.     PixIntensity   : integer;    // One pixel intenzity while stepping
  3771.     HalfIntensity  : double;     // Half of MaxIntensity
  3772.     AvgIntensity   : double;     // Average intensity of the star in the radius
  3773.     xx,yy          : integer;    // Pixel coordinates
  3774.     OutOfBitmap    : boolean;    // True if measuring step out from the image
  3775. BEGIN
  3776.   With Bitmap.Canvas do begin
  3777. //    StarCent := Point2d(x,y);
  3778.     StarCent      := GetStarCentroid(Bitmap,Trunc(x),Trunc(y),10);
  3779.     // Centre pixel of star
  3780.     scPoint       := Point(Trunc(StarCent.x),Trunc(StarCent.y));
  3781.     MaxIntensity  := GetGValue(Pixels[scPoint.x,scPoint.y]);
  3782.     HalfIntensity := MaxIntensity/2;
  3783.  
  3784.     // Measuring the half-wide of star curve
  3785.     // -------------------------------------
  3786.     // Get the left edge
  3787.     xx := scPoint.x;
  3788.     yy := scPoint.y;
  3789.     Repeat
  3790.        Dec(xx);
  3791.        PixIntensity := GetGValue(Pixels[xx,yy]);
  3792.        if PixIntensity<=HalfIntensity then
  3793.           StarRec.x1 := xx;
  3794.        OutOfBitmap := xx<1;
  3795.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3796.     // Get the right edge
  3797.     xx := scPoint.x;
  3798.     Repeat
  3799.        Inc(xx);
  3800.        PixIntensity := GetGValue(Pixels[xx,yy]);
  3801.        if PixIntensity<=HalfIntensity then
  3802.           StarRec.x2 := xx;
  3803.        OutOfBitmap := xx>Bitmap.Width-2;
  3804.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3805.     // Get the Bottom edge
  3806.     xx := scPoint.x;
  3807.     yy := scPoint.y;
  3808.     Repeat
  3809.        Inc(yy);
  3810.        PixIntensity := GetGValue(Pixels[xx,yy]);
  3811.        if PixIntensity<=HalfIntensity then
  3812.           StarRec.y2 := yy;
  3813.        OutOfBitmap := yy>Bitmap.Height-2;
  3814.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3815.     // Get the Top edge
  3816.     yy := scPoint.y;
  3817.     Repeat
  3818.        Dec(yy);
  3819.        PixIntensity := GetGValue(Pixels[xx,yy]);
  3820.        if PixIntensity<=HalfIntensity then
  3821.           StarRec.y1 := yy;
  3822.        OutOfBitmap := yy<1;
  3823.     Until (PixIntensity<=HalfIntensity) or OutOfBitmap;
  3824.  
  3825.     Result         := not OutOfBitmap;        // The total star is on the bitmap
  3826.  
  3827.     if Result then begin
  3828.     Star.HalfRad   := ((StarRec.x2-StarRec.x1)+(StarRec.y2-StarRec.y1))/4;
  3829.  
  3830.     If Star.HalfRad>0 then Star.Radius := Star.HalfRad else Star.Radius:=1;
  3831.  
  3832.     AvgIntensity := GetAverageIntensityOfStarG(Bitmap, x,y, Star.HalfRad);
  3833.  
  3834.     // Finally set the Result parameters
  3835.     Star.x         := StarCent.x+0.5;
  3836.     Star.y         := StarCent.y+0.5;
  3837.     Star.Intensity := AvgIntensity;
  3838.     end;
  3839.   end;
  3840. END;
  3841.  
  3842. // Photometry of all detected stars
  3843. procedure TotalPhotometry(Bitmap: TBitmap);
  3844. var i: integer;
  3845. begin
  3846.   if StarCount > 0 then
  3847.   for i:=0 to StarCount-1 do begin
  3848.       SimplePhotometryG(Bitmap,StarArray[i].x,StarArray[i].y,StarArray[i]);
  3849.   end;
  3850. end;
  3851.  
  3852. // Move away the source bitmap with offsets (0<=Offset<=1)
  3853. procedure SubPixelShift(SourceBitmap : TBitmap; out DestBitmap : TBitmap;
  3854.                                   OffsetX, OffsetY: double);
  3855. Var Row1,Row2,ROW: pRGBTripleArray;
  3856.     X,Y          : integer;
  3857.     ofx,ofy      : double;
  3858.     t1,t2,t3,t4  : double;
  3859.     r,g,b        : integer;
  3860. begin
  3861.    DestBitmap.Width  := SourceBitmap.Width;
  3862.    DestBitmap.Height := SourceBitmap.Height;
  3863.    DestBitmap.PixelFormat := pf24bit;
  3864.    Cls(DestBitmap.Canvas,clBlack);
  3865.    ofx := Frac(OffsetX);
  3866.    ofy := Frac(OffsetY);
  3867.    t1 := (1-ofx)*(1-ofy);
  3868.    t2 := ofx*(1-ofy);
  3869.    t3 := (1-ofx)*ofy;
  3870.    t4 := ofx*ofy;
  3871.    Row1 := SourceBitmap.Scanline[0];
  3872.    For Y :=0 to SourceBitmap.Height-2 Do
  3873.    Begin
  3874.      Row2 := SourceBitmap.Scanline[Y+1];
  3875.      ROW  := DestBitmap.Scanline[Y];
  3876.      For X :=0 to SourceBitmap.Width-2 Do
  3877.          WITH ROW[x] DO
  3878.          BEGIN
  3879.            r         := Trunc(t1*Row1[x].rgbtRed+t2*Row1[x+1].rgbtRed
  3880.                         +t3*Row2[x].rgbtRed+t4*Row2[x+1].rgbtRed);
  3881.            rgbtRed   := IntToByte(r);
  3882.            g         := Trunc(t1*Row1[x].rgbtGreen+t2*Row1[x+1].rgbtGreen
  3883.                         +t3*Row2[x].rgbtGreen+t4*Row2[x+1].rgbtGreen);
  3884.            rgbtGreen := IntToByte(g);
  3885.            b         := Trunc(t1*Row1[x].rgbtBlue+t2*Row1[x+1].rgbtBlue
  3886.                         +t3*Row2[x].rgbtBlue+t4*Row2[x+1].rgbtBlue);
  3887.            rgbtBlue  := IntToByte(b);
  3888.          END;
  3889.      Row1 := Row2;
  3890.    end;
  3891. end;
  3892.  
  3893.     (*  BAD PIXEL CORRECTIONS *)
  3894.  
  3895. function FixStuckPixels(Bitmap: TBitmap; Threshold: byte; difference: byte): integer;
  3896. // Result = Count of stuck pixels
  3897. VAR
  3898.   i  :  INTEGER;
  3899.   j  :  INTEGER;
  3900.   x,y:  integer;
  3901.   Row        :  array[0..2] of pPixelArray;
  3902.   prevPixel  : TRGBTriple;        // Previous pixel RGB
  3903.   nextPixel  : TRGBTriple;        // Next pixel RGB
  3904.   next1Pixel : TRGBTriple;        // Next pixel RGB 1
  3905.   next2Pixel : TRGBTriple;        // Next pixel RGB 2
  3906.   avgR, avgG, avgB  : integer;    // Average  pixel RGB
  3907.   RandomI           : integer;    // Random
  3908. //  bBMP       : TBitmap;           // 4x4 Bitmap for bad stuck pixel
  3909. begin
  3910. TRY
  3911.   Result := 0;
  3912.   Bitmap.PixelFormat := pf24bit;
  3913.   Row[0] := Bitmap.Scanline[0];
  3914.   Row[1] := Bitmap.Scanline[1];
  3915.   FOR j := 2 TO Bitmap.Height-3 DO
  3916.   BEGIN
  3917.     Row[2] := Bitmap.Scanline[j];
  3918.     prevPixel := ChangeRGBColor(prevPixel,0,0,0);
  3919.     FOR i := 1 TO Bitmap.Width-2 DO
  3920.     BEGIN
  3921.       nextPixel := Row[1][i+1];
  3922.       next1Pixel := Row[2][i-1];
  3923.       next2Pixel := Row[2][i+1];
  3924.  
  3925.       WITH Row[1][i] DO
  3926.       BEGIN
  3927.       // Only the very high pixels
  3928.       if ((Row[1][i].rgbtGreen-prevPixel.rgbtGreen)>difference) and
  3929.          ((Row[1][i].rgbtGreen-nextPixel.rgbtGreen)>difference)
  3930.       then
  3931.       begin
  3932.         if ((rgbtRed+rgbtGreen+rgbtBlue) div 3)>Threshold then
  3933.         begin
  3934.            iF (next1Pixel.rgbtGreen<Row[1][i].rgbtGreen) and
  3935.               (next2Pixel.rgbtGreen<Row[1][i].rgbtGreen)
  3936.            then begin
  3937.            // Stuck pixel R,G,B are about equal between 20 difference
  3938.              // 3x3 matrix RGB average around the stuck pixel
  3939.              avgR := 0; avgG := 0; avgB := 0;
  3940.              for y:=0 to 2 do
  3941.                  for x:=-1 to 1 do
  3942.                  begin
  3943.                    avgR := avgR + Row[y][x+i].rgbtRed;
  3944.                    avgG := avgG + Row[y][x+i].rgbtGreen;
  3945.                    avgB := avgB + Row[y][x+i].rgbtBlue;
  3946.                  end;
  3947.  
  3948.              avgR := avgR - (Row[1][i].rgbtRed DIV 2);
  3949.              avgG := avgG - (Row[1][i].rgbtGreen DIV 2);
  3950.              avgB := avgB - (Row[1][i].rgbtBlue DIV 2);
  3951.  
  3952.              avgR := avgR div 9;
  3953.              avgG := avgG div 9;
  3954.              avgB := avgB div 9;
  3955.  
  3956.              for y:=0 to 2 do
  3957.                  for x:=-1 to 1 do
  3958.                  begin
  3959.                    RandomI := Random(difference);
  3960.                    RandomI := RandomI - (difference div 4);
  3961.                    RandomI := 0;
  3962.                    Row[y][x+i].rgbtRed   := avgR + RandomI;
  3963.                    Row[y][x+i].rgbtGreen := avgG + RandomI;
  3964.                    Row[y][x+i].rgbtBlue  := avgB + RandomI;
  3965.                  end;
  3966.  
  3967.  
  3968.              Inc(Result);
  3969.            end;
  3970.         end;
  3971.       end;
  3972.       END;
  3973.       prevPixel := Row[1][i];
  3974.     END;
  3975.     Row[0] := Row[1];
  3976.     Row[1] := Row[2];
  3977.   END;
  3978. FINALLY
  3979. END
  3980. end;
  3981.  
  3982. function GetStuckPixelsStatistic(Bitmap: TBitmap; VAR stpa: array of TPoint;
  3983.                                  Threshold: byte; difference: byte): integer;
  3984. // Result = Count of stuck pixels
  3985. VAR
  3986.   i  :  INTEGER;
  3987.   j  :  INTEGER;
  3988.   x,y:  integer;
  3989.   Row        :  array[0..2] of pPixelArray;
  3990.   prevPixel  : TRGBTriple;        // Previous pixel RGB
  3991.   nextPixel  : TRGBTriple;        // Next pixel RGB
  3992.   next1Pixel : TRGBTriple;        // Next pixel RGB 1
  3993.   next2Pixel : TRGBTriple;        // Next pixel RGB 2
  3994.   avgR, avgG, avgB  : integer;    // Average  pixel RGB
  3995.   RandomI           : integer;    // Random
  3996. //  bBMP       : TBitmap;           // 4x4 Bitmap for bad stuck pixel
  3997. begin
  3998. TRY
  3999.   Result := 0;
  4000.   Bitmap.PixelFormat := pf24bit;
  4001.   Row[0] := Bitmap.Scanline[0];
  4002.   Row[1] := Bitmap.Scanline[1];
  4003.   FOR j := 2 TO Bitmap.Height-3 DO
  4004.   BEGIN
  4005.     Row[2] := Bitmap.Scanline[j];
  4006.     prevPixel := ChangeRGBColor(prevPixel,0,0,0);
  4007.     FOR i := 1 TO Bitmap.Width-2 DO
  4008.     BEGIN
  4009.       nextPixel := Row[1][i+1];
  4010.       next1Pixel := Row[2][i-1];
  4011.       next2Pixel := Row[2][i+1];
  4012.  
  4013.       WITH Row[1][i] DO
  4014.       BEGIN
  4015.       // Only the very high pixels
  4016.       if ((Row[1][i].rgbtGreen-prevPixel.rgbtGreen)>difference) and
  4017.          ((Row[1][i].rgbtGreen-nextPixel.rgbtGreen)>difference)
  4018.       then
  4019.       begin
  4020.         if ((rgbtRed+rgbtGreen+rgbtBlue) div 3)>Threshold then
  4021.         begin
  4022.            iF (next1Pixel.rgbtGreen<Row[1][i].rgbtGreen) and
  4023.               (next2Pixel.rgbtGreen<Row[1][i].rgbtGreen)
  4024.            then begin
  4025.              Inc(Result);
  4026.            end;
  4027.         end;
  4028.       end;
  4029.       END;
  4030.       prevPixel := Row[1][i];
  4031.     END;
  4032.     Row[0] := Row[1];
  4033.     Row[1] := Row[2];
  4034.   END;
  4035. FINALLY
  4036. END
  4037. end;
  4038.  
  4039. // Dark Frame Substaction from Src : Result = Src
  4040. function SubtractDark(SrcBitmap, DarkBitmap: TBitmap): boolean;
  4041. Var
  4042.   i  :  INTEGER;
  4043.   j  :  INTEGER;
  4044.   w,h:  integer;
  4045.   sRow :  pPixelArray;
  4046.   dRow :  pPixelArray;
  4047. begin
  4048.   Result := False;
  4049. IF (SrcBitmap<>nil) and (DarkBitmap<>nil) then
  4050. Try
  4051.   SrcBitmap.PixelFormat  := pf24bit;
  4052.   DarkBitmap.PixelFormat := pf24bit;
  4053.   if DarkBitmap.Width<SrcBitmap.Width then w:=DarkBitmap.Width
  4054.      else w:=SrcBitmap.Width;
  4055.   if DarkBitmap.Height<SrcBitmap.Height then h:=DarkBitmap.Height
  4056.      else h:=SrcBitmap.Height;
  4057.   FOR j := 0 TO h-1 DO
  4058.   BEGIN
  4059.     sRow := SrcBitmap.Scanline[j];
  4060.     dRow := DarkBitmap.Scanline[j];
  4061.     FOR i := 0 TO w-1 DO
  4062.     BEGIN
  4063.       sRow[i].rgbtRed   := IntToByte(sRow[i].rgbtRed - dRow[i].rgbtRed);
  4064.       sRow[i].rgbtGreen := IntToByte(sRow[i].rgbtGreen - dRow[i].rgbtGreen);
  4065.       sRow[i].rgbtBlue  := IntToByte(sRow[i].rgbtBlue - dRow[i].rgbtBlue);
  4066.     END;
  4067.   END;
  4068.   Result := True;
  4069. except
  4070.   Result := False;
  4071. end;
  4072. end;
  4073.  
  4074. function FlatCorrection(SrcBitmap, FlatBitmap: TBitmap): boolean;
  4075. Var
  4076.   i  :  INTEGER;
  4077.   j  :  INTEGER;
  4078.   w,h:  integer;
  4079.   sRow   :  pPixelArray;
  4080.   dRow   :  pPixelArray;
  4081.   thRec  :  TThreshold;
  4082. begin
  4083. Result := False;
  4084. if (SrcBitmap<>nil) and (FlatBitmap<>nil) then
  4085. Try
  4086.   Result := True;
  4087.   SrcBitmap.PixelFormat   := pf24bit;
  4088.   FlatBitmap.PixelFormat  := pf24bit;
  4089.   thRec := GetBMPAverage(FlatBitmap,255);
  4090.   if thRec.R=0 then thRec.R:=1;
  4091.   if thRec.B=0 then thRec.B:=1;
  4092.   if thRec.G=0 then thRec.G:=1;
  4093.   if FlatBitmap.Width<>SrcBitmap.Width then
  4094.      FlatBitmap.Width        := SrcBitmap.Width;
  4095.   if FlatBitmap.Height<>SrcBitmap.Height then
  4096.      FlatBitmap.Height       := SrcBitmap.Height;
  4097.   FOR j := 0 TO SrcBitmap.Height-1 DO
  4098.   BEGIN
  4099.     sRow  := SrcBitmap.Scanline[j];
  4100.     dRow  := FlatBitmap.Scanline[j];
  4101.     FOR i := 0 TO SrcBitmap.Width-1 DO
  4102.     BEGIN
  4103.     if dRow[i].rgbtRed>0 then
  4104.       sRow[i].rgbtRed   := IntToByte(Round(sRow[i].rgbtRed   * (thRec.R/dRow[i].rgbtRed)));
  4105.     if dRow[i].rgbtGreen>0 then
  4106.       sRow[i].rgbtGreen := IntToByte(Round(sRow[i].rgbtGreen * (thRec.G/dRow[i].rgbtGreen)));
  4107.     if dRow[i].rgbtBlue>0 then
  4108.       sRow[i].rgbtBlue  := IntToByte(Round(sRow[i].rgbtBlue  * (thRec.B/dRow[i].rgbtBlue)));
  4109.     END;
  4110.   END;
  4111. except
  4112.   Result := False;
  4113. end;
  4114. end;
  4115.  
  4116. function AddFrames(SrcBitmap1, SrcBitmap2: TBitmap; var DstkBitmap: TBitmap): boolean;
  4117. Var
  4118.   i  :  INTEGER;
  4119.   j  :  INTEGER;
  4120.   w,h:  integer;
  4121.   sRow1,sRow2 :  pPixelArray;
  4122.   dRow :  pPixelArray;
  4123. begin
  4124. Try
  4125.   Result := True;
  4126.   SrcBitmap1.PixelFormat  := pf24bit;
  4127.   SrcBitmap2.PixelFormat  := pf24bit;
  4128.   DstkBitmap.PixelFormat  := pf24bit;
  4129.   DstkBitmap.Width := SrcBitmap1.Width;
  4130.   DstkBitmap.Height := SrcBitmap1.Height;
  4131.   FOR j := 0 TO SrcBitmap1.Height-1 DO
  4132.   BEGIN
  4133.     sRow1 := SrcBitmap1.Scanline[j];
  4134.     sRow2 := SrcBitmap2.Scanline[j];
  4135.     dRow  := DstkBitmap.Scanline[j];
  4136.     FOR i := 0 TO SrcBitmap1.Width-1 DO
  4137.     BEGIN
  4138.       dRow[i].rgbtRed   := IntToByte(sRow1[i].rgbtRed + sRow2[i].rgbtRed);
  4139.       dRow[i].rgbtGreen := IntToByte(sRow1[i].rgbtGreen + sRow2[i].rgbtGreen);
  4140.       dRow[i].rgbtBlue  := IntToByte(sRow1[i].rgbtBlue + sRow2[i].rgbtBlue);
  4141.     END;
  4142.   END;
  4143. except
  4144.   Result := False;
  4145. end;
  4146. end;
  4147.  
  4148. function AddFramesLimited(SrcBitmap1, SrcBitmap2: TBitmap; var DstkBitmap: TBitmap;
  4149.                           Limit: integer ): boolean;
  4150. Var
  4151.   i  :  INTEGER;
  4152.   j  :  INTEGER;
  4153.   w,h:  integer;
  4154.   sRow1,sRow2 :  pPixelArray;
  4155.   dRow :  pPixelArray;
  4156.   thRec1,thRec2: TThreshold;
  4157. begin
  4158. Try
  4159.   Result := True;
  4160.   SrcBitmap1.PixelFormat  := pf24bit;
  4161.   SrcBitmap2.PixelFormat  := pf24bit;
  4162.   DstkBitmap.PixelFormat  := pf24bit;
  4163.   DstkBitmap.Width := SrcBitmap1.Width;
  4164.   DstkBitmap.Height := SrcBitmap1.Height;
  4165.   thRec1 := GetBMPAverage(SrcBitmap1,Limit);
  4166.   thRec2 := GetBMPAverage(SrcBitmap2,Limit);
  4167.   FOR j := 0 TO SrcBitmap1.Height-1 DO
  4168.   BEGIN
  4169.     sRow1 := SrcBitmap1.Scanline[j];
  4170.     sRow2 := SrcBitmap2.Scanline[j];
  4171.     dRow  := DstkBitmap.Scanline[j];
  4172.     FOR i := 0 TO SrcBitmap1.Width-1 DO
  4173.     BEGIN
  4174.       if (thRec1.R<sRow1[i].rgbtRed) and (thRec2.R<sRow2[i].rgbtRed) then
  4175.       dRow[i].rgbtRed   := IntToByte(sRow1[i].rgbtRed + sRow2[i].rgbtRed);
  4176.       if (thRec1.G<sRow1[i].rgbtGreen) and (thRec2.G<sRow2[i].rgbtGreen) then
  4177.       dRow[i].rgbtGreen := IntToByte(sRow1[i].rgbtGreen + sRow2[i].rgbtGreen);
  4178.       if (thRec1.B<sRow1[i].rgbtBlue) and (thRec2.B<sRow2[i].rgbtBlue) then
  4179.       dRow[i].rgbtBlue  := IntToByte(sRow1[i].rgbtBlue + sRow2[i].rgbtBlue);
  4180.     END;
  4181.   END;
  4182. except
  4183.   Result := False;
  4184. end;
  4185. end;
  4186.  
  4187. // Align 2 fames, where the difference of bitmaps is minimal
  4188. function AlignFrames(SrcBitmap1, SrcBitmap2: TBitmap):TPoint;
  4189. var minIntensity: Longint;
  4190.     defRadius   : integer;
  4191.     BMP1,BMP2   : TBitmap;
  4192.     RC,R        : TRect;
  4193.     V,H         : integer;
  4194.     sumI        : Longint;   // smal image summerized intensity
  4195.     WI,HE       : integer;
  4196. begin
  4197. Try
  4198.   defRadius := 50;
  4199.   Result := Point(0,0);
  4200.   minIntensity:=High(Longint);
  4201.   WI := SrcBitmap1.Width div 2;
  4202.   HE := SrcBitmap1.Height div 2;
  4203.   BMP1 := TBitmap.Create;
  4204.   BMP2 := TBitmap.Create;
  4205.   BMP1.Canvas.CopyMode := cmSrcCopy;
  4206.   BMPResize(BMP1,2*defRadius,2*defRadius);
  4207.   BMPResize(BMP2,2*defRadius,2*defRadius);
  4208.   SrcBitmap1.PixelFormat  := pf24bit;
  4209.   SrcBitmap2.PixelFormat  := pf24bit;
  4210.   RC := Rect((SrcBitmap2.Width div 2)-defRadius,(SrcBitmap2.Height div 2)-defRadius,
  4211.              (SrcBitmap2.Width div 2)+defRadius,(SrcBitmap2.Height div 2)+defRadius);
  4212.   BMP2.canvas.CopyRect(BMP2.Canvas.ClipRect,SrcBitmap2.Canvas,RC);
  4213.   for V:=HE-100 to HE+100 do
  4214.   begin
  4215.     for H:=WI-100 to WI+100 do begin
  4216.       RC := Rect(H,V,H+(2*defRadius),V+(2*defRadius));
  4217.       BMP1.canvas.CopyRect(BMP1.Canvas.ClipRect,SrcBitmap2.Canvas,RC);
  4218.       SubtractDark(BMP1,BMP2);
  4219.       sumI := GetBMPSum(BMP1);
  4220.       if sumI<minIntensity then begin
  4221.          minIntensity := sumI;
  4222.          Result := Point(H,V);
  4223.       end;
  4224.     end;
  4225.   end;
  4226. finally
  4227.   Result := Point(WI-(Result.x+defRadius),HE-(Result.y+defRadius));
  4228.   BMP1.Free;
  4229.   BMP2.Free;
  4230. end;
  4231. end;
  4232.  
  4233. procedure EdgeDetect(Bitmap: TBitmap);
  4234. var
  4235.    nTemp      : double;
  4236.    c          : double;
  4237.    min, max   : double;
  4238.    sum        : double;
  4239.    mean       : double;
  4240.    d,s        : double;
  4241.    mdl, Size  : integer;
  4242.    n,l,k      : integer;
  4243.    bmp        : TBitmap;
  4244. Const
  4245.     MASK : array[1..12, 1..12] of double =
  4246.         (
  4247.         (-0.000699762,  -0.000817119,   -0.000899703,   -0.000929447,   -0.000917118,   -0.000896245,   -0.000896245,   -0.000917118,   -0.000929447,   -0.000899703,   -0.000817119,   -0.000699762),
  4248.         (-0.000817119,  -0.000914231,   -0.000917118,   -0.000813449,   -0.000655442,   -0.000538547,   -0.000538547,   -0.000655442,   -0.000813449,   -0.000917118,   -0.000914231,   -0.000817119),
  4249.         (-0.000899703,  -0.000917118,   -0.000745635,   -0.000389918,   0.0000268,  0.000309618,    0.000309618,    0.0000268,  -0.000389918,   -0.000745635,   -0.000917118,   -0.000899703),
  4250.         (-0.000929447,  -0.000813449,   -0.000389918,   0.000309618,    0.001069552,    0.00156934, 0.00156934, 0.001069552,    0.000309618,    -0.000389918,   -0.000813449,   -0.000929447),
  4251.         (-0.000917118,  -0.000655442,   0.0000268,  0.001069552,    0.002167033,    0.002878738,    0.002878738,    0.002167033,    0.001069552,    0.0000268,  -0.000655442,   -0.000917118),
  4252.         (-0.000896245,  -0.000538547,   0.000309618,    0.00156934, 0.002878738,    0.003722998,    0.003722998,    0.002878738,    0.00156934, 0.000309618,    -0.000538547,   -0.000896245),
  4253.         (-0.000896245,  -0.000538547,   0.000309618,    0.00156934, 0.002878738,    0.003722998,    0.003722998,    0.002878738,    0.00156934, 0.000309618,    -0.000538547,   -0.000896245),
  4254.         (-0.000917118,  -0.000655442,   0.0000268,  0.001069552,    0.002167033,    0.002878738,    0.002878738,    0.002167033,    0.001069552,    0.0000268,  -0.000655442,   -0.000917118),
  4255.         (-0.000929447,  -0.000813449,   -0.000389918,   0.000309618,    0.001069552,    0.00156934, 0.00156934, 0.001069552,    0.000309618,    -0.000389918,   -0.000813449,   -0.000929447),
  4256.         (-0.000899703,  -0.000917118,   -0.000745635,   -0.000389918,   0.0000268,  0.000309618,    0.000309618,    0.0000268,  -0.000389918,   -0.000745635,   -0.000917118,   -0.000899703),
  4257.         (-0.000817119,  -0.000914231,   -0.000917118,   -0.000813449,   -0.000655442,   -0.000538547,   -0.000538547,   -0.000655442,   -0.000813449,   -0.000917118,   -0.000914231,   -0.000817119),
  4258.     (-0.000699762,  -0.000817119,   -0.000899703,   -0.000929447,   -0.000917118,   -0.000896245,   -0.000896245,   -0.000917118,   -0.000929447,   -0.000899703,   -0.000817119,   -0.000699762)
  4259.     );
  4260.  
  4261. begin
  4262. end;
  4263.  
  4264. PROCEDURE Convolve(ABitmap : TBitmap ; AMask : T3x3FloatArray ; ABias : integer);
  4265. Var
  4266.   LRow1, LRow2, LRow3, LRowOut : PRGBTripleArray;
  4267.   LRow, LCol : integer;
  4268.   LNewBlue, LNewGreen, LNewRed : Extended;
  4269.   LCoef : Extended;
  4270.   BMP   : TBitmap;
  4271. begin
  4272. Try
  4273.  
  4274.   LCoef := 0;
  4275.   for LRow := 0 to 2 do for LCol := 0 to 2 do LCoef := LCoef + AMask[LCol, LRow];
  4276.   if LCoef = 0 then LCoef := 1;
  4277.  
  4278.   BMP := TBitmap.Create;
  4279.  
  4280.   BMP.Width := ABitmap.Width - 2;
  4281.   BMP.Height := ABitmap.Height - 2;
  4282.   BMP.PixelFormat := pf24bit;
  4283.  
  4284.   LRow2 := ABitmap.ScanLine[0];
  4285.   LRow3 := ABitmap.ScanLine[1];
  4286.  
  4287.   for LRow := 1 to ABitmap.Height - 2 do begin
  4288.  
  4289.     LRow1 := LRow2;
  4290.     LRow2 := LRow3;
  4291.     LRow3 := ABitmap.ScanLine[LRow + 1];
  4292.    
  4293.     LRowOut := BMP.ScanLine[LRow - 1];
  4294.  
  4295.     for LCol := 1 to ABitmap.Width - 2 do begin
  4296.  
  4297.       LNewBlue :=
  4298.         (LRow1[LCol-1].rgbtBlue*AMask[0,0]) + (LRow1[LCol].rgbtBlue*AMask[1,0]) + (LRow1[LCol+1].rgbtBlue*AMask[2,0]) +
  4299.         (LRow2[LCol-1].rgbtBlue*AMask[0,1]) + (LRow2[LCol].rgbtBlue*AMask[1,1]) + (LRow2[LCol+1].rgbtBlue*AMask[2,1]) +
  4300.         (LRow3[LCol-1].rgbtBlue*AMask[0,2]) + (LRow3[LCol].rgbtBlue*AMask[1,2]) + (LRow3[LCol+1].rgbtBlue*AMask[2,2]);
  4301.       LNewBlue := (LNewBlue / LCoef) + ABias;
  4302.       if LNewBlue > 255 then LNewBlue := 255;
  4303.       if LNewBlue < 0 then LNewBlue := 0;
  4304.  
  4305.       LNewGreen :=
  4306.         (LRow1[LCol-1].rgbtGreen*AMask[0,0]) + (LRow1[LCol].rgbtGreen*AMask[1,0]) + (LRow1[LCol+1].rgbtGreen*AMask[2,0]) +
  4307.         (LRow2[LCol-1].rgbtGreen*AMask[0,1]) + (LRow2[LCol].rgbtGreen*AMask[1,1]) + (LRow2[LCol+1].rgbtGreen*AMask[2,1]) +
  4308.         (LRow3[LCol-1].rgbtGreen*AMask[0,2]) + (LRow3[LCol].rgbtGreen*AMask[1,2]) + (LRow3[LCol+1].rgbtGreen*AMask[2,2]);
  4309.       LNewGreen := (LNewGreen / LCoef) + ABias;
  4310.       if LNewGreen > 255 then LNewGreen := 255;
  4311.       if LNewGreen < 0 then LNewGreen := 0;
  4312.  
  4313.       LNewRed :=
  4314.         (LRow1[LCol-1].rgbtRed*AMask[0,0]) + (LRow1[LCol].rgbtRed*AMask[1,0]) + (LRow1[LCol+1].rgbtRed*AMask[2,0]) +
  4315.         (LRow2[LCol-1].rgbtRed*AMask[0,1]) + (LRow2[LCol].rgbtRed*AMask[1,1]) + (LRow2[LCol+1].rgbtRed*AMask[2,1]) +
  4316.         (LRow3[LCol-1].rgbtRed*AMask[0,2]) + (LRow3[LCol].rgbtRed*AMask[1,2]) + (LRow3[LCol+1].rgbtRed*AMask[2,2]);
  4317.       LNewRed := (LNewRed / LCoef) + ABias;
  4318.       if LNewRed > 255 then LNewRed := 255;
  4319.       if LNewRed < 0 then LNewRed := 0;
  4320.  
  4321.       LRowOut[LCol-1].rgbtBlue  := trunc(LNewBlue);
  4322.       LRowOut[LCol-1].rgbtGreen := trunc(LNewGreen);
  4323.       LRowOut[LCol-1].rgbtRed   := trunc(LNewRed);
  4324.  
  4325.     end;
  4326.  
  4327.   end;
  4328. finally
  4329.   ABitmap.Assign(BMP);
  4330.   BMP.Free;
  4331. end;
  4332. end;
  4333.  
  4334. {This just forces a value to be 0 - 255 for rgb purposes.  I used asm in an
  4335.  attempt at speed, but I don't think it helps much.}
  4336. function Set255(Clr : integer) : integer;
  4337. asm
  4338.   MOV  EAX,Clr  // store value in EAX register (32-bit register)
  4339.   CMP  EAX,254  // compare it to 254
  4340.   JG   @SETHI   // if greater than 254 then go set to 255 (max value)
  4341.   CMP  EAX,1    // if less than 255, compare to 1
  4342.   JL   @SETLO   // if less than 1 go set to 0 (min value)
  4343.   RET           // otherwise it doesn't change, just exit
  4344. @SETHI:         // Set value to 255
  4345.   MOV  EAX,255  // Move 255 into the EAX register
  4346.   RET           // Exit (result value is the EAX register value)
  4347. @SETLO:         // Set value to 0
  4348.   MOV  EAX,0    // Move 0 into EAX register
  4349. end;            // Result is in EAX
  4350.  
  4351. {The Expand version of a 3 x 3 convolution.
  4352.  
  4353.  This approach is similar to the mirror version, except that it copies
  4354.  or duplicates the pixels from the edges to the same edge.  This is
  4355.  probably the best version if you're interested in quality, but don't need
  4356.  a tiled (seamless) image. }
  4357. procedure ConvolveE(ray: array of integer; z: word;
  4358.   aBmp: TBitmap);
  4359. var
  4360.   O, T, C, B : pPixelArray;  // Scanlines
  4361.   x, y : integer;
  4362.   tBufr : TBitmap; // temp bitmap for 'enlarged' image
  4363. begin
  4364.   tBufr := TBitmap.Create;
  4365.   tBufr.Width:=aBmp.Width+2;  // Add a box around the outside...
  4366.   tBufr.Height:=aBmp.Height+2;
  4367.   tBufr.PixelFormat := pf24bit;
  4368.   O := tBufr.ScanLine[0];   // Copy top corner pixels
  4369.   T := aBmp.ScanLine[0];
  4370.   O[0] := T[0];  // Left
  4371.   O[tBufr.Width - 1] := T[aBmp.Width - 1];  // Right
  4372.   // Copy top lines
  4373.   tBufr.Canvas.CopyRect(RECT(1,0,tBufr.Width - 1,1),aBmp.Canvas,
  4374.           RECT(0,0,aBmp.Width,1));
  4375.  
  4376.   O := tBufr.ScanLine[tBufr.Height - 1]; // Copy bottom corner pixels
  4377.   T := aBmp.ScanLine[aBmp.Height - 1];
  4378.   O[0] := T[0];
  4379.   O[tBufr.Width - 1] := T[aBmp.Width - 1];
  4380.   // Copy bottoms
  4381.   tBufr.Canvas.CopyRect(RECT(1,tBufr.Height-1,tBufr.Width - 1,tBufr.Height),
  4382.          aBmp.Canvas,RECT(0,aBmp.Height-1,aBmp.Width,aBmp.Height));
  4383.   // Copy rights
  4384.   tBufr.Canvas.CopyRect(RECT(tBufr.Width-1,1,tBufr.Width,tBufr.Height-1),
  4385.          aBmp.Canvas,RECT(aBmp.Width-1,0,aBmp.Width,aBmp.Height));
  4386.   // Copy lefts
  4387.   tBufr.Canvas.CopyRect(RECT(0,1,1,tBufr.Height-1),
  4388.          aBmp.Canvas,RECT(0,0,1,aBmp.Height));
  4389.   // Now copy main rectangle
  4390.   tBufr.Canvas.CopyRect(RECT(1,1,tBufr.Width - 1,tBufr.Height - 1),
  4391.     aBmp.Canvas,RECT(0,0,aBmp.Width,aBmp.Height));
  4392.   // bmp now enlarged and copied, apply convolve
  4393.   for x := 0 to aBmp.Height - 1 do begin  // Walk scanlines
  4394.     O := aBmp.ScanLine[x];      // New Target (Original)
  4395.     T := tBufr.ScanLine[x];     //old x-1  (Top)
  4396.     C := tBufr.ScanLine[x+1];   //old x    (Center)
  4397.     B := tBufr.ScanLine[x+2];   //old x+1  (Bottom)
  4398.   // Now do the main piece
  4399.     for y := 1 to (tBufr.Width - 2) do begin  // Walk pixels
  4400.       O[y-1].rgbtRed := Set255(
  4401.           ((T[y-1].rgbtRed*ray[0]) +
  4402.           (T[y].rgbtRed*ray[1]) + (T[y+1].rgbtRed*ray[2]) +
  4403.           (C[y-1].rgbtRed*ray[3]) +
  4404.           (C[y].rgbtRed*ray[4]) + (C[y+1].rgbtRed*ray[5])+
  4405.           (B[y-1].rgbtRed*ray[6]) +
  4406.           (B[y].rgbtRed*ray[7]) + (B[y+1].rgbtRed*ray[8])) div z
  4407.           );
  4408.       O[y-1].rgbtBlue := Set255(
  4409.           ((T[y-1].rgbtBlue*ray[0]) +
  4410.           (T[y].rgbtBlue*ray[1]) + (T[y+1].rgbtBlue*ray[2]) +
  4411.           (C[y-1].rgbtBlue*ray[3]) +
  4412.           (C[y].rgbtBlue*ray[4]) + (C[y+1].rgbtBlue*ray[5])+
  4413.           (B[y-1].rgbtBlue*ray[6]) +
  4414.           (B[y].rgbtBlue*ray[7]) + (B[y+1].rgbtBlue*ray[8])) div z
  4415.           );
  4416.       O[y-1].rgbtGreen := Set255(
  4417.           ((T[y-1].rgbtGreen*ray[0]) +
  4418.           (T[y].rgbtGreen*ray[1]) + (T[y+1].rgbtGreen*ray[2]) +
  4419.           (C[y-1].rgbtGreen*ray[3]) +
  4420.           (C[y].rgbtGreen*ray[4]) + (C[y+1].rgbtGreen*ray[5])+
  4421.           (B[y-1].rgbtGreen*ray[6]) +
  4422.           (B[y].rgbtGreen*ray[7]) + (B[y+1].rgbtGreen*ray[8])) div z
  4423.           );
  4424.     end;
  4425.   end;
  4426.   tBufr.Free;
  4427. end;
  4428.  
  4429. {The Ignore (basic) version of a 3 x 3 convolution.
  4430.  
  4431.  The 3 x 3 convolve uses the eight surrounding pixels as part of the
  4432.  calculation.  But, for the pixels on the edges, there is nothing to use
  4433.  for the top row values.  In other words, the leftmost pixel in the 3rd
  4434.  row, or scanline, has no pixels on its left to use in the calculations.
  4435.  This version just ignores the outermost edge of the image, and doesn't
  4436.  alter those pixels at all.  Repeated applications of filters will
  4437.  eventually cause a pronounced 'border' effect, as those pixels never
  4438.  change but all others do. However, this version is simpler, and the
  4439.  logic is easier to follow.  It's the fastest of the three in this
  4440.  application, and works great if the 'borders' are not an issue. }
  4441. procedure ConvolveI(ray: array of integer; z: word;
  4442.   aBmp: TBitmap);
  4443. var
  4444.   O, T, C, B : pPixelArray;  // Scanlines
  4445.   x, y : integer;
  4446.   tBufr : TBitmap; // temp bitmap
  4447. begin
  4448.   tBufr := TBitmap.Create;
  4449.   CopyMe(tBufr,aBmp);
  4450.   for x := 1 to aBmp.Height - 2 do begin  // Walk scanlines
  4451.     O := aBmp.ScanLine[x];      // New Target (Original)
  4452.     T := tBufr.ScanLine[x-1];     //old x-1  (Top)
  4453.     C := tBufr.ScanLine[x];   //old x    (Center)
  4454.     B := tBufr.ScanLine[x+1];   //old x+1  (Bottom)
  4455.   // Now do the main piece
  4456.     for y := 1 to (tBufr.Width - 2) do begin  // Walk pixels
  4457.       O[y].rgbtRed := Set255(
  4458.           ((T[y-1].rgbtRed*ray[0]) +
  4459.           (T[y].rgbtRed*ray[1]) + (T[y+1].rgbtRed*ray[2]) +
  4460.           (C[y-1].rgbtRed*ray[3]) +
  4461.           (C[y].rgbtRed*ray[4]) + (C[y+1].rgbtRed*ray[5])+
  4462.           (B[y-1].rgbtRed*ray[6]) +
  4463.           (B[y].rgbtRed*ray[7]) + (B[y+1].rgbtRed*ray[8])) div z
  4464.           );
  4465.       O[y].rgbtBlue := Set255(
  4466.           ((T[y-1].rgbtBlue*ray[0]) +
  4467.           (T[y].rgbtBlue*ray[1]) + (T[y+1].rgbtBlue*ray[2]) +
  4468.           (C[y-1].rgbtBlue*ray[3]) +
  4469.           (C[y].rgbtBlue*ray[4]) + (C[y+1].rgbtBlue*ray[5])+
  4470.           (B[y-1].rgbtBlue*ray[6]) +
  4471.           (B[y].rgbtBlue*ray[7]) + (B[y+1].rgbtBlue*ray[8])) div z
  4472.           );
  4473.       O[y].rgbtGreen := Set255(
  4474.           ((T[y-1].rgbtGreen*ray[0]) +
  4475.           (T[y].rgbtGreen*ray[1]) + (T[y+1].rgbtGreen*ray[2]) +
  4476.           (C[y-1].rgbtGreen*ray[3]) +
  4477.           (C[y].rgbtGreen*ray[4]) + (C[y+1].rgbtGreen*ray[5])+
  4478.           (B[y-1].rgbtGreen*ray[6]) +
  4479.           (B[y].rgbtGreen*ray[7]) + (B[y+1].rgbtGreen*ray[8])) div z
  4480.           );
  4481.     end;
  4482.   end;
  4483.   tBufr.Free;
  4484. end;
  4485.  
  4486. {The mirror version of a 3 x 3 convolution.
  4487.  
  4488.  The 3 x 3 convolve uses the eight surrounding pixels as part of the
  4489.  calculation.  But, for the pixels on the edges, there is nothing to use
  4490.  for the top row values.  In other words, the leftmost pixel in the 3rd
  4491.  row, or scanline, has no pixels on its left to use in the calculations.
  4492.  I compensate for this by increasing the size of the bitmap by one pixel
  4493.  on top, left, bottom, and right.  The mirror version is used in an
  4494.  application that creates seamless tiles, so I copy the opposite sides to
  4495.  maintain the seamless integrity.  }
  4496. procedure ConvolveM(ray: array of integer; z: word;
  4497.   aBmp: TBitmap);
  4498. var
  4499.   O, T, C, B : ^TPixelArray;  // Scanlines
  4500.   x, y : integer;
  4501.   tBufr : TBitmap; // temp bitmap for 'enlarged' image
  4502. begin
  4503.   tBufr := TBitmap.Create;
  4504.   tBufr.Width:=aBmp.Width+2;  // Add a box around the outside...
  4505.   tBufr.Height:=aBmp.Height+2;
  4506.   tBufr.PixelFormat := pf24bit;
  4507.   O := tBufr.ScanLine[0];   // Copy top corner pixels
  4508.   T := aBmp.ScanLine[0];
  4509.   O[0] := T[0];  // Left
  4510.   O[tBufr.Width - 1] := T[aBmp.Width - 1];  // Right
  4511.   // Copy bottom line to our top - trying to remain seamless...
  4512.   tBufr.Canvas.CopyRect(RECT(1,0,tBufr.Width - 1,1),aBmp.Canvas,
  4513.           RECT(0,aBmp.Height - 1,aBmp.Width,aBmp.Height-2));
  4514.  
  4515.   O := tBufr.ScanLine[tBufr.Height - 1]; // Copy bottom corner pixels
  4516.   T := aBmp.ScanLine[aBmp.Height - 1];
  4517.   O[0] := T[0];
  4518.   O[tBufr.Width - 1] := T[aBmp.Width - 1];
  4519.   // Copy top line to our bottom
  4520.   tBufr.Canvas.CopyRect(RECT(1,tBufr.Height-1,tBufr.Width - 1,tBufr.Height),
  4521.          aBmp.Canvas,RECT(0,0,aBmp.Width,1));
  4522.   // Copy left to our right
  4523.   tBufr.Canvas.CopyRect(RECT(tBufr.Width-1,1,tBufr.Width,tBufr.Height-1),
  4524.          aBmp.Canvas,RECT(0,0,1,aBmp.Height));
  4525.   // Copy right to our left
  4526.   tBufr.Canvas.CopyRect(RECT(0,1,1,tBufr.Height-1),
  4527.          aBmp.Canvas,RECT(aBmp.Width - 1,0,aBmp.Width,aBmp.Height));
  4528.   // Now copy main rectangle
  4529.   tBufr.Canvas.CopyRect(RECT(1,1,tBufr.Width - 1,tBufr.Height - 1),
  4530.     aBmp.Canvas,RECT(0,0,aBmp.Width,aBmp.Height));
  4531.   // bmp now enlarged and copied, apply convolve
  4532.   for x := 0 to aBmp.Height - 1 do begin  // Walk scanlines
  4533.     O := aBmp.ScanLine[x];      // New Target (Original)
  4534.     T := tBufr.ScanLine[x];     //old x-1  (Top)
  4535.     C := tBufr.ScanLine[x+1];   //old x    (Center)
  4536.     B := tBufr.ScanLine[x+2];   //old x+1  (Bottom)
  4537.   // Now do the main piece
  4538.     for y := 1 to (tBufr.Width - 2) do begin  // Walk pixels
  4539.       O[y-1].rgbtRed := Set255(
  4540.           ((T[y-1].rgbtRed*ray[0]) +
  4541.           (T[y].rgbtRed*ray[1]) + (T[y+1].rgbtRed*ray[2]) +
  4542.           (C[y-1].rgbtRed*ray[3]) +
  4543.           (C[y].rgbtRed*ray[4]) + (C[y+1].rgbtRed*ray[5])+
  4544.           (B[y-1].rgbtRed*ray[6]) +
  4545.           (B[y].rgbtRed*ray[7]) + (B[y+1].rgbtRed*ray[8])) div z
  4546.           );
  4547.       O[y-1].rgbtBlue := Set255(
  4548.           ((T[y-1].rgbtBlue*ray[0]) +
  4549.           (T[y].rgbtBlue*ray[1]) + (T[y+1].rgbtBlue*ray[2]) +
  4550.           (C[y-1].rgbtBlue*ray[3]) +
  4551.           (C[y].rgbtBlue*ray[4]) + (C[y+1].rgbtBlue*ray[5])+
  4552.           (B[y-1].rgbtBlue*ray[6]) +
  4553.           (B[y].rgbtBlue*ray[7]) + (B[y+1].rgbtBlue*ray[8])) div z
  4554.           );
  4555.       O[y-1].rgbtGreen := Set255(
  4556.           ((T[y-1].rgbtGreen*ray[0]) +
  4557.           (T[y].rgbtGreen*ray[1]) + (T[y+1].rgbtGreen*ray[2]) +
  4558.           (C[y-1].rgbtGreen*ray[3]) +
  4559.           (C[y].rgbtGreen*ray[4]) + (C[y+1].rgbtGreen*ray[5])+
  4560.           (B[y-1].rgbtGreen*ray[6]) +
  4561.           (B[y].rgbtGreen*ray[7]) + (B[y+1].rgbtGreen*ray[8])) div z
  4562.           );
  4563.     end;
  4564.   end;
  4565.   tBufr.Free;
  4566. end;
  4567.  
  4568. procedure ConvolveFilter(filternr,edgenr:integer;src:TBitmap);
  4569. var
  4570.   z : integer;
  4571.   ray : array [0..8] of integer;
  4572.   OrigBMP : TBitmap;              // Bitmap for temporary use
  4573. begin
  4574.   z := 1;  // just to avoid compiler warnings!
  4575.   case filternr of
  4576.     0 : begin // Laplace
  4577.       ray[0] := -1; ray[1] := -1; ray[2] := -1;
  4578.       ray[3] := -1; ray[4] :=  8; ray[5] := -1;
  4579.       ray[6] := -1; ray[7] := -1; ray[8] := -1;
  4580.       z := 1;
  4581.       end;
  4582.     1 : begin  // Hipass
  4583.       ray[0] := -1; ray[1] := -1; ray[2] := -1;
  4584.       ray[3] := -1; ray[4] :=  9; ray[5] := -1;
  4585.       ray[6] := -1; ray[7] := -1; ray[8] := -1;
  4586.       z := 1;
  4587.       end;
  4588.     2 : begin  // Find Edges (top down)
  4589.       ray[0] :=  1; ray[1] :=  1; ray[2] :=  1;
  4590.       ray[3] :=  1; ray[4] := -2; ray[5] :=  1;
  4591.       ray[6] := -1; ray[7] := -1; ray[8] := -1;
  4592.       z := 1;
  4593.       end;
  4594.     3 : begin  // Sharpen
  4595.       ray[0] := -1; ray[1] := -1; ray[2] := -1;
  4596.       ray[3] := -1; ray[4] := 16; ray[5] := -1;
  4597.       ray[6] := -1; ray[7] := -1; ray[8] := -1;
  4598.       z := 8;
  4599.       end;
  4600.     4 : begin  // Edge Enhance
  4601.       ray[0] :=  0; ray[1] := -1; ray[2] :=  0;
  4602.       ray[3] := -1; ray[4] :=  5; ray[5] := -1;
  4603.       ray[6] :=  0; ray[7] := -1; ray[8] :=  0;
  4604.       z := 1;
  4605.       end;
  4606.     5 : begin  // Color Emboss (Sorta)
  4607.       ray[0] :=  1; ray[1] :=  0; ray[2] :=  1;
  4608.       ray[3] :=  0; ray[4] :=  0; ray[5] :=  0;
  4609.       ray[6] :=  1; ray[7] :=  0; ray[8] := -2;
  4610.       z := 1;
  4611.       end;
  4612.     6 : begin  // Soften
  4613.       ray[0] :=  2; ray[1] :=  2; ray[2] :=  2;
  4614.       ray[3] :=  2; ray[4] :=  0; ray[5] :=  2;
  4615.       ray[6] :=  2; ray[7] :=  2; ray[8] :=  2;
  4616.       z := 16;
  4617.       end;
  4618.     7 : begin  // Blur
  4619.       ray[0] :=  3; ray[1] :=  3; ray[2] :=  3;
  4620.       ray[3] :=  3; ray[4] :=  8; ray[5] :=  3;
  4621.       ray[6] :=  3; ray[7] :=  3; ray[8] :=  3;
  4622.       z := 32;
  4623.       end;
  4624.     8 : begin  // Soften less
  4625.       ray[0] :=  0; ray[1] :=  1; ray[2] :=  0;
  4626.       ray[3] :=  1; ray[4] :=  2; ray[5] :=  1;
  4627.       ray[6] :=  0; ray[7] :=  1; ray[8] :=  0;
  4628.       z := 6;
  4629.       end;
  4630.     else exit;
  4631.   end;
  4632.   OrigBMP := TBitmap.Create;  // Copy image to 24-bit bitmap
  4633.   CopyMe(OrigBMP,src);
  4634.   case Edgenr of
  4635.     0 : ConvolveM(ray,z,OrigBMP);
  4636.     1 : ConvolveE(ray,z,OrigBMP);
  4637.     2 : ConvolveI(ray,z,OrigBMP);
  4638. //  else
  4639. //    Convolv
  4640.   end;
  4641.   src.Assign(OrigBMP);  //  Assign filtered image to Image1
  4642.   OrigBMP.Free;
  4643. end;
  4644.  
  4645. procedure CopyMe(tobmp: TBitmap; frbmp : TGraphic);
  4646. begin
  4647.   tobmp.Width := frbmp.Width;
  4648.   tobmp.Height := frbmp.Height;
  4649.   tobmp.PixelFormat := pf24bit;
  4650.   tobmp.Canvas.Draw(0,0,frbmp);
  4651. end;
  4652.  
  4653. procedure SortArray(var A : array of integer);
  4654. var
  4655.   i,j,v,x : integer;
  4656. begin
  4657.   for i:=0 to 4 do begin
  4658.     v:=A[i]; x:=0;
  4659.     for j:=i+1 to 8 do begin
  4660.       if A[j]<v then begin v:=A[j]; x:=j; end;
  4661.     end;
  4662.     A[x]:=A[i]; A[i]:=v;
  4663.   end;
  4664. end;
  4665.  
  4666. function MedianAverage(var A : array of integer) : integer;
  4667. begin
  4668.   SortArray(A);;
  4669.   Result:=A[High(A) div 2];
  4670. end;
  4671.  
  4672. procedure Median(src:TBitmap);
  4673. Type
  4674.     dArr = array[0..8] of integer;
  4675. var xx,yy,ii,jj : integer;
  4676.     dPixArray : dArr;
  4677.     dRow      : array[0..2] of PByteArray;
  4678.     SFill     : integer;
  4679.     dRowS     : PByteArray;
  4680.     SFillS    : integer;
  4681.     dCount    : integer;
  4682.     Intensity : integer;
  4683.     BMP       : TBitmap;
  4684.     Pix       : TPoint;
  4685.  
  4686. procedure SortArray(var a: array of integer; Lo,Hi: integer);
  4687. procedure sort(l,r: integer);
  4688. var
  4689.   i,j,x,y: integer;
  4690. begin
  4691.   i:=l; j:=r; x:=a[(l+r) DIV 2];
  4692.   repeat
  4693.     while a[i]<x do i:=i+1;
  4694.     while x<a[j] do j:=j-1;
  4695.     if i<=j then
  4696.     begin
  4697.       y:=a[i]; a[i]:=a[j]; a[j]:=y;
  4698.       i:=i+1; j:=j-1;
  4699.     end;
  4700.   until i>j;
  4701.   if l<j then sort(l,j);
  4702.   if i<r then sort(i,r);
  4703. end;
  4704. begin {quicksort};
  4705.   sort(Lo,Hi);
  4706. end;
  4707.  
  4708. function Median9(var A : array of integer) : integer;
  4709. var
  4710.   i,j,v,x : integer;
  4711. begin
  4712.   for i:=0 to 4 do begin
  4713.     v:=A[i]; x:=0;
  4714.     for j:=i+1 to 8 do begin
  4715.       if A[j]<v then begin v:=A[j]; x:=j; end;
  4716.     end;
  4717.     A[x]:=A[i]; A[i]:=v;
  4718.   end;
  4719.   Result:=A[4];
  4720. end;
  4721.  
  4722. begin
  4723.  
  4724. Try
  4725.   Try
  4726.      BMP    := TBitmap.Create;
  4727.      BMP.Assign(src);
  4728.      BMP.PixelFormat := pf24bit;
  4729.      dRowS  := PByteArray(src.ScanLine[1]);
  4730.      SFillS := Integer(src.ScanLine[2]) - Integer(dRowS);
  4731.      for jj:=0 to 2 do
  4732.          dRow[jj]   := PByteArray(BMP.ScanLine[jj]);
  4733.      SFill  := Integer(BMP.ScanLine[1]) - Integer(BMP.ScanLine[0]);
  4734.  
  4735.      For yy:=1 to src.Height-2 do begin
  4736.          For xx:=3 to 3*(src.Width-2) do begin
  4737.  
  4738.              // Fill the 3*3 pixel kernel around the actual pixel
  4739.              for jj:=0 to 2 do
  4740.                  For ii:=-1 to 1 do begin
  4741.                      dPixArray[3*jj+(ii+1)] := dRow[jj][xx+3*ii];
  4742.                  end;
  4743.  
  4744.              // Calculate the median average
  4745.              dRowS[xx] := MedianAverage(dPixArray);
  4746.          end;
  4747.          for jj:=0 to 2 do
  4748.              Inc(Integer(dRow[jj]), SFill);
  4749.          Inc(Integer(dRowS), SFillS);
  4750.      end;
  4751.  
  4752.   finally
  4753.      BMP.Free;
  4754.   end;
  4755. except
  4756. end;
  4757.  
  4758. end;
  4759.  
  4760. procedure Median1(src:TBitmap);
  4761. Type
  4762.     dlist = array[0..8] of integer;
  4763. var xx,yy,ii,jj : integer;
  4764.     dPixArray : dList;
  4765.     dRow      : array[0..2] of PByteArray;
  4766.     SFill     : integer;
  4767.     dRowS     : PByteArray;
  4768.     SFillS    : integer;
  4769.     dCount    : integer;
  4770.     Intensity : integer;
  4771.     BMP       : TBitmap;
  4772.     Pix       : TPoint;
  4773.  
  4774. procedure SortArray(var a: dlist; Lo,Hi: integer);
  4775. procedure sort(l,r: integer);
  4776. var
  4777.   i,j,x,y: integer;
  4778. begin
  4779.   i:=l; j:=r; x:=a[(l+r) DIV 2];
  4780.   repeat
  4781.     while a[i]<x do i:=i+1;
  4782.     while x<a[j] do j:=j-1;
  4783.     if i<=j then
  4784.     begin
  4785.       y:=a[i]; a[i]:=a[j]; a[j]:=y;
  4786.       i:=i+1; j:=j-1;
  4787.     end;
  4788.   until i>j;
  4789.   if l<j then sort(l,j);
  4790.   if i<r then sort(i,r);
  4791. end;
  4792. begin {quicksort};
  4793.   sort(Lo,Hi);
  4794. end;
  4795.  
  4796. begin
  4797.  
  4798. Try
  4799.   Try
  4800.      BMP    := TBitmap.Create;
  4801.      BMP.Assign(src);
  4802.      BMP.PixelFormat := pf24bit;
  4803.      dRowS  := PByteArray(src.ScanLine[1]);
  4804.      SFillS := Integer(src.ScanLine[2]) - Integer(dRowS);
  4805.      for jj:=0 to 2 do
  4806.          dRow[jj]   := PByteArray(BMP.ScanLine[jj]);
  4807.      SFill  := Integer(BMP.ScanLine[1]) - Integer(BMP.ScanLine[0]);
  4808.  
  4809.      For yy:=1 to src.Height-2 do begin
  4810.          For xx:=3 to 3*(src.Width-2) do begin
  4811.  
  4812.              // Fill the 3*3 pixel kernel around the actual pixel
  4813.              for jj:=0 to 2 do
  4814.                  For ii:=-1 to 1 do begin
  4815.                      dPixArray[3*jj+(ii+1)] := dRow[jj][xx+3*ii];
  4816.                  end;
  4817.  
  4818.              // Calculate the median average
  4819.              SortArray(dPixArray,0,8);
  4820.              dRowS[xx] := dPixArray[4];
  4821.          end;
  4822.          for jj:=0 to 2 do
  4823.              Inc(Integer(dRow[jj]), SFill);
  4824.          Inc(Integer(dRowS), SFillS);
  4825.      end;
  4826.  
  4827.   finally
  4828.      BMP.Free;
  4829.   end;
  4830. except
  4831. end;
  4832.  
  4833. end;
  4834.  
  4835. // SttarArray rutins
  4836. // ---------------------------------------------------------------------------
  4837.  
  4838. // Megkeresi a legfényesebb csillagot és visszaadja tömbbeli indexét
  4839. function GetMaxStar(ar: array of TStarRecord): integer;
  4840. var     i: integer;
  4841.         r: double;
  4842. begin
  4843.   r:=0;
  4844.   For i:=0 to High(ar) do begin
  4845.       if (ar[i].Radius>r) AND (not ar[i].Deleted) then begin
  4846.          r := ar[i].Radius;
  4847.          Result := i;
  4848.       end;
  4849.   end;
  4850. end;
  4851.  
  4852.  
  4853. function HistogramInit: TRGBColorsArray;
  4854. var i,j: integer;
  4855. begin
  4856.   For i:=0 to 2 do
  4857.    For j:=0 to 255 do
  4858.     Result[i,j] := 0; // RGB szinek tömbjét 0-ázza
  4859. end;
  4860.  
  4861. function GetRGBHistogram(Bitmap: TBitmap): TRGBColorsArray;
  4862. VAR
  4863.   i  :  INTEGER;
  4864.   j  :  INTEGER;
  4865.   Row:  pPixelArray;
  4866. begin
  4867. TRY
  4868.   Result := HistogramInit;
  4869.   Bitmap.PixelFormat := pf24bit;
  4870.   FOR j := 0 TO Bitmap.Height-1 DO
  4871.   BEGIN
  4872.     Row := Bitmap.Scanline[j];
  4873.     FOR i := 0 TO Bitmap.Width-1 DO
  4874.       WITH Row[i] DO
  4875.       BEGIN
  4876.         Inc(Result[0,rgbtRed]);
  4877.         Inc(Result[1,rgbtGreen]);
  4878.         Inc(Result[2,rgbtBlue]);
  4879.       END
  4880.   END;
  4881. FINALLY
  4882. END
  4883. end;
  4884.  
  4885.  
  4886. function RGBStatisticInit: TRGBStatisticArray;
  4887. var i,j: integer;
  4888. begin
  4889.   FOR j := 0 TO 2 DO
  4890.     FOR i := 0 TO 255 DO
  4891.         Result[j,i] := 0;
  4892. end;
  4893.  
  4894. // Kigyüjti a kép pixeleinek RGB statisztikáját %-os eloszlásban
  4895. function GetRGBStatistic(Bitmap: TBitmap): TRGBStatisticArray;
  4896. VAR
  4897.   i  :  INTEGER;
  4898.   j  :  INTEGER;
  4899.   Row:  pPixelArray;
  4900.   pixCount : integer;
  4901.   RGBColorsArray : TRGBColorsArray;
  4902. begin
  4903. TRY
  4904.   pixCount := Bitmap.Width * Bitmap.Height;
  4905.   if PixCount>0 then begin
  4906.   RGBColorsArray := GetRGBHistogram(Bitmap);
  4907.   FOR j := 0 TO 2 DO
  4908.     FOR i := 0 TO 255 DO
  4909.         Result[j,i] := 100*RGBColorsArray[j,i]/pixCount;
  4910.   end else
  4911.         Result := RGBStatisticInit;
  4912. FINALLY
  4913. END
  4914. end;
  4915.  
  4916. // Megnézi hogy a kép pixeleinek RGB maximuma, mely intenzitásértékeknél van.
  4917. // Valószínűleg ez adja az alapzaj szintjeit.
  4918. function GetRGBStatisticMax(Bitmap: TBitmap): TRGB24;
  4919. Var
  4920.   Colors  : TRGBStatisticArray;
  4921.   i,j     : integer;
  4922.   MaxArr  : array[0..2] of integer;
  4923.   maxCol  : double;
  4924. begin
  4925.   Colors := GetRGBStatistic(Bitmap);
  4926.   For i:=0 to 2 do begin
  4927.    MaxArr[i]:=0;
  4928.    maxCol   :=0;
  4929.    For j:=5 to 255 do begin
  4930.        if Colors[i,j]>MaxCol then begin
  4931.           maxCol := Colors[i,j];
  4932.           MaxArr[i]:=j;
  4933.        end;
  4934.    end;
  4935.   end;
  4936.   With Result do begin
  4937.        R := MaxArr[0];
  4938.        G := MaxArr[1];
  4939.        B := MaxArr[2];
  4940.   end;
  4941. end;
  4942.  
  4943. procedure AutoNoiseReduction(Bitmap: TBitmap; factor: DOUBLE);
  4944. var avgTres  : TRGB24;
  4945.     Row      : pRGBTripleArray;
  4946.     Rfactor,Gfactor,Bfactor: double;
  4947.     x,y      : integer;
  4948. begin
  4949.   // Meghaározzuk az átlagos RGB zaj szintet
  4950.   //  factor:=3; ÉRTÉKNÉL JÓ EREDMÉNY VÁRHATÓ
  4951.   avgTres := GetRGBStatisticMax(Bitmap);
  4952.   Rfactor := factor*(1+avgTres.R/255);
  4953.   Gfactor := factor*(1+avgTres.G/255);
  4954.   Bfactor := factor*(1+avgTres.B/255);
  4955.   // Az ez alatti zajt eltávolítjuk, levágjuk, majd visszaszorozzuk
  4956.   Bitmap.PixelFormat := pf24bit;
  4957.   for y:=0 to Bitmap.height-1 do begin
  4958.     Row:=Bitmap.scanline[y];
  4959.     for x:=0 to Bitmap.width-1 do begin
  4960.       WITH Row[x] DO
  4961.       BEGIN
  4962.         rgbtRed   := FloatToByte(Rfactor * (rgbtRed - avgTres.R));
  4963.         rgbtGreen := FloatToByte(Gfactor * (rgbtGreen - avgTres.G));
  4964.         rgbtBlue  := FloatToByte(Bfactor * (rgbtBlue - avgTres.B));
  4965.       END;
  4966.     end;
  4967.   end;
  4968. end;
  4969.  
  4970. procedure AutoNoiseReduction_1(Bitmap: TBitmap; factor: DOUBLE);
  4971. var avgTres  : TRGB24;
  4972.     Row      : pRGBTripleArray;
  4973.     Rfactor,Gfactor,Bfactor: double;
  4974.     x,y      : integer;
  4975. begin
  4976.   // Meghaározzuk az átlagos RGB zaj szintet
  4977.   //  factor:=3; ÉRTÉKNÉL JÓ EREDMÉNY VÁRHATÓ
  4978.   avgTres := GetRGBStatisticMax(Bitmap);
  4979.   Rfactor := factor*(1+avgTres.R/255);
  4980.   Gfactor := factor*(1+avgTres.G/255);
  4981.   Bfactor := factor*(1+avgTres.B/255);
  4982.   // Az ez alatti zajt eltávolítjuk, levágjuk, majd visszaszorozzuk
  4983.   Bitmap.PixelFormat := pf24bit;
  4984.   for y:=0 to Bitmap.height-1 do begin
  4985.     Row:=Bitmap.scanline[y];
  4986.     for x:=0 to Bitmap.width-1 do begin
  4987.       WITH Row[x] DO
  4988.       BEGIN
  4989.         rgbtRed   := FloatToByte(Rfactor * (rgbtRed - avgTres.R));
  4990.         rgbtGreen := FloatToByte(Gfactor * (rgbtGreen - avgTres.G));
  4991.         rgbtBlue  := FloatToByte(Bfactor * (rgbtBlue - avgTres.B));
  4992.       END;
  4993.     end;
  4994.   end;
  4995. end;
  4996.  
  4997.  
  4998. initialization
  4999.   DecimalSeparator := '.';
  5000.   bmp:= TBitmap.Create;
  5001.   wbmp:= TBitmap.Create;
  5002.   Origbmp:= TBitmap.Create;
  5003.   ProcessList := TStringList.Create;
  5004.  
  5005. finalization
  5006.   bmp.Free;
  5007.   wbmp.Free;
  5008.   Origbmp.Free;
  5009.   ProcessList.Free;
  5010.  
  5011. end.
  5012.  
  5013. (*
  5014.         /// <summary>
  5015.         /// This function used to detect edges on Input image using standard deviation.
  5016.         /// </summary>
  5017.         /// <param name="SrcImage"></param>
  5018.         /// <returns></returns>
  5019.         ///
  5020.         private Bitmap LoG12x12(Bitmap SrcImage)
  5021.         {
  5022.             double[,] MASK = new double[12, 12] {
  5023.                                 {-0.000699762,  -0.000817119,   -0.000899703,   -0.000929447,   -0.000917118,   -0.000896245,   -0.000896245,   -0.000917118,   -0.000929447,   -0.000899703,   -0.000817119,   -0.000699762},
  5024.                                 {-0.000817119,  -0.000914231,   -0.000917118,   -0.000813449,   -0.000655442,   -0.000538547,   -0.000538547,   -0.000655442,   -0.000813449,   -0.000917118,   -0.000914231,   -0.000817119},
  5025.                                 {-0.000899703,  -0.000917118,   -0.000745635,   -0.000389918,   0.0000268,  0.000309618,    0.000309618,    0.0000268,  -0.000389918,   -0.000745635,   -0.000917118,   -0.000899703},
  5026.                                 {-0.000929447,  -0.000813449,   -0.000389918,   0.000309618,    0.001069552,    0.00156934, 0.00156934, 0.001069552,    0.000309618,    -0.000389918,   -0.000813449,   -0.000929447},
  5027.                                 {-0.000917118,  -0.000655442,   0.0000268,  0.001069552,    0.002167033,    0.002878738,    0.002878738,    0.002167033,    0.001069552,    0.0000268,  -0.000655442,   -0.000917118},
  5028.                                 {-0.000896245,  -0.000538547,   0.000309618,    0.00156934, 0.002878738,    0.003722998,    0.003722998,    0.002878738,    0.00156934, 0.000309618,    -0.000538547,   -0.000896245},
  5029.                                 {-0.000896245,  -0.000538547,   0.000309618,    0.00156934, 0.002878738,    0.003722998,    0.003722998,    0.002878738,    0.00156934, 0.000309618,    -0.000538547,   -0.000896245},
  5030.                                 {-0.000917118,  -0.000655442,   0.0000268,  0.001069552,    0.002167033,    0.002878738,    0.002878738,    0.002167033,    0.001069552,    0.0000268,  -0.000655442,   -0.000917118},
  5031.                                 {-0.000929447,  -0.000813449,   -0.000389918,   0.000309618,    0.001069552,    0.00156934, 0.00156934, 0.001069552,    0.000309618,    -0.000389918,   -0.000813449,   -0.000929447},
  5032.                                 {-0.000899703,  -0.000917118,   -0.000745635,   -0.000389918,   0.0000268,  0.000309618,    0.000309618,    0.0000268,  -0.000389918,   -0.000745635,   -0.000917118,   -0.000899703},
  5033.                                 {-0.000817119,  -0.000914231,   -0.000917118,   -0.000813449,   -0.000655442,   -0.000538547,   -0.000538547,   -0.000655442,   -0.000813449,   -0.000917118,   -0.000914231,   -0.000817119},
  5034.                                 {-0.000699762,  -0.000817119,   -0.000899703,   -0.000929447,   -0.000917118,   -0.000896245,   -0.000896245,   -0.000917118,   -0.000929447,   -0.000899703,   -0.000817119,   -0.000699762}
  5035.                             };
  5036.  
  5037.             double nTemp = 0.0;
  5038.             double c = 0;
  5039.  
  5040.             int mdl, size;
  5041.             size = 12;
  5042.             mdl = size/2;
  5043.            
  5044.             double min, max;
  5045.             min = max = 0.0;
  5046.  
  5047.             double sum = 0.0;
  5048.             double mean;
  5049.             double d = 0.0;
  5050.             double s = 0.0;
  5051.             int n = 0;
  5052.  
  5053.             Bitmap bitmap = new Bitmap(SrcImage.Width + mdl, SrcImage.Height + mdl);
  5054.             int l, k;
  5055.  
  5056.             BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
  5057.             BitmapData srcData = SrcImage.LockBits(new Rectangle(0, 0, SrcImage.Width, SrcImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  5058.  
  5059.             unsafe
  5060.             {
  5061.                 int offset = 3;
  5062.  
  5063.                 for (int colm = 0; colm < srcData.Height - size; colm++)
  5064.                 {
  5065.                     byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
  5066.                     byte* bitmapPtr = (byte*)bitmapData.Scan0 + (colm * bitmapData.Stride);
  5067.  
  5068.                     for (int row = 0; row < srcData.Width - size; row++)
  5069.                     {
  5070.                         nTemp = 0.0;
  5071.  
  5072.                         min = double.MaxValue;
  5073.                         max = double.MinValue;
  5074.  
  5075.                         for (k = 0; k < size; k++)
  5076.                         {
  5077.                             for (l = 0; l < size; l++)
  5078.                             {
  5079.                                 byte* tempPtr = (byte*)srcData.Scan0 + ((colm + l) * srcData.Stride);
  5080.                                 c = (tempPtr[((row + k) * offset)] + tempPtr[((row + k) * offset) + 1] + tempPtr[((row + k) * offset) + 2]) / 3;
  5081.  
  5082.                                 nTemp += (double)c * MASK[k, l];
  5083.  
  5084.                             }
  5085.                         }
  5086.  
  5087.                         sum += nTemp;
  5088.                         n++;
  5089.                     }
  5090.                 }
  5091.                 mean = ((double)sum / n);
  5092.                 d = 0.0;
  5093.  
  5094.                 for (int i = 0; i < srcData.Height - size; i++)
  5095.                 {
  5096.                     byte* ptr = (byte*)srcData.Scan0 + (i * srcData.Stride);
  5097.                     byte* tptr = (byte*)bitmapData.Scan0 + (i * bitmapData.Stride);
  5098.  
  5099.                     for (int j = 0; j < srcData.Width - size; j++)
  5100.                     {
  5101.                         nTemp = 0.0;
  5102.  
  5103.                         min = double.MaxValue;
  5104.                         max = double.MinValue;
  5105.  
  5106.                         for (k = 0; k < size; k++)
  5107.                         {
  5108.                             for (l = 0; l < size; l++)
  5109.                             {
  5110.                                 byte* tempPtr = (byte*)srcData.Scan0 + ((i + l) * srcData.Stride);
  5111.                                 c = (tempPtr[((j + k) * offset)] + tempPtr[((j + k) * offset) + 1] + tempPtr[((j + k) * offset) + 2]) / 3;
  5112.  
  5113.                                 nTemp += (double)c * MASK[k, l];
  5114.  
  5115.                             }
  5116.                         }
  5117.  
  5118.                         s = (mean - nTemp);
  5119.                         d += (s * s);
  5120.                     }
  5121.                 }
  5122.  
  5123.  
  5124.                 d = d / (n - 1);
  5125.                 d = Math.Sqrt(d);
  5126.                 d = d * 2;
  5127.  
  5128.                 for (int colm = mdl; colm < srcData.Height - mdl; colm++)
  5129.                 {
  5130.                     byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
  5131.                     byte* bitmapPtr = (byte*)bitmapData.Scan0 + (colm * bitmapData.Stride);
  5132.  
  5133.                     for (int row = mdl; row < srcData.Width - mdl; row++)
  5134.                     {
  5135.                         nTemp = 0.0;
  5136.  
  5137.                         min = double.MaxValue;
  5138.                         max = double.MinValue;
  5139.  
  5140.                         for (k = (mdl * -1); k < mdl; k++)
  5141.                         {
  5142.                             for (l = (mdl * -1); l < mdl; l++)
  5143.                             {
  5144.                                 byte* tempPtr = (byte*)srcData.Scan0 + ((colm + l) * srcData.Stride);
  5145.                                 c = (tempPtr[((row + k) * offset)] + tempPtr[((row + k) * offset) + 1] + tempPtr[((row + k) * offset) + 2]) / 3;
  5146.  
  5147.                                 nTemp += (double)c * MASK[mdl + k, mdl + l];
  5148.  
  5149.                             }
  5150.                         }
  5151.  
  5152.                         if (nTemp > d)
  5153.                         {
  5154.                             bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = bitmapPtr[row * offset + 2] = 255;
  5155.                         }
  5156.                         else
  5157.                             bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = bitmapPtr[row * offset + 2] = 0;
  5158.  
  5159.                     }
  5160.                 }
  5161.             }
  5162.  
  5163.             bitmap.UnlockBits(bitmapData);
  5164.             SrcImage.UnlockBits(srcData);
  5165.  
  5166.             return bitmap;
  5167.         }
  5168.  
  5169. *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement