PageRenderTime 53ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/General-Purpose-Units/FormInformationUnit.pas

http://my-units.googlecode.com/
Pascal | 2509 lines | 1784 code | 383 blank | 342 comment | 192 complexity | 86e3a2e851d1ad0c93cb9bf8684c984c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. {?}unit FormInformationUnit;
  2. interface
  3. uses
  4. SysUtils, Graphics, Types, FMLImage, GeometryUnit,
  5. ComponentsUnit;
  6. const
  7. BlackThr: Integer= 20;
  8. type
  9. TArrBitmap= array of TBitmap;
  10. PointerArray= array of Pointer;
  11. TMyBitmap= class
  12. private
  13. //{$UNSAFECODE ON$}
  14. Pixels: PointerArray;
  15. //{$UNSAFECODE OFF$}
  16. IncValue: Integer;
  17. function ConvertToRGB (Color: TColor): TRGB;
  18. public
  19. Width: Integer;
  20. Height: Integer;
  21. function Body (x, y: Integer): TRGB;
  22. //{$UNSAFECODE ON$}
  23. function GetPixels: Pointer;//unsafe;
  24. //{$UNSAFECODE OFF$}
  25. constructor Create (Bitmap: TBitmap);
  26. procedure Free;
  27. end;
  28. EFormBoxRangeCheckError= class (Exception);
  29. TBox= class (TObject)
  30. private
  31. FUpperLeftPoint: TPoint;
  32. FUpperRightPoint: TPoint;
  33. FLowerLeftPoint: TPoint;
  34. FLowerRightPoint: TPoint;
  35. FTitle: WideString;
  36. procedure Complete;//Change the place of UpperLeftPoint and LowerRightPoint if needed
  37. procedure SetLowerRightPoint (const Value: TPoint);
  38. procedure SetUpperLeftPoint (const Value: TPoint);
  39. public
  40. property UpperLeftPoint: TPoint read FUpperLeftPoint write SetUpperLeftPoint;
  41. property LowerRightPoint: TPoint read FLowerRightPoint write SetLowerRightPoint;
  42. property Title: WideString read FTitle;
  43. function Copy: TBox;
  44. procedure SaveToFile (var OutputFile: TextFile);
  45. procedure LoadFromFile (var InputFile: TextFile; LoadTitle: Boolean= False);
  46. function IsSame (Box: TBox): Boolean;
  47. function Rotate (Angle: Extended): TBox;
  48. function Move (Delta: TPoint): TBox;
  49. constructor Create;
  50. procedure Free;
  51. end;
  52. TBoxArray= array of TBox;
  53. TBoxData= class (TObject)
  54. private
  55. IsValid: Boolean;
  56. // FBox: TBox;
  57. FBoxArray: TBoxArray;
  58. FKind: TInputKind;
  59. FPostProcessorFileName: String;
  60. FTitle: WideString;
  61. FNumberOfElement: Integer;
  62. FRotateAngle: Extended;
  63. FSource: TPoint;
  64. public
  65. // property Box: TBox read FBox;
  66. property BoxArray: TBoxArray read FBoxArray;
  67. property NoOfElement: Integer read FNumberOfElement;
  68. property Kind: TInputKind read FKind;
  69. property PostProcessorFile: String read FPostProcessorFileName;
  70. property Title: WideString read FTitle;
  71. property Source: TPoint read FSource write FSource;
  72. property RotateAngle: Extended read FRotateAngle write FRotateAngle;
  73. function IsSame (Box: TBoxData): Boolean;
  74. function Copy: TBoxData;
  75. procedure LoadFromFile (var InputFile: TextFile);
  76. procedure SaveToFile (var OutputFile: TextFile);
  77. procedure DrawInBitmap (BitmapImage: TBitmap);
  78. function ExtractFromBitmap (BitmapImage: TBitmap): TImageCollection;
  79. constructor Create;overload;
  80. constructor Create (Box: TBox; InputKind: TInputKind);overload;
  81. procedure Free;
  82. end;
  83. TCompType= (ctStart, ctFirstName, ctLastName, ctCity, ctState, ctInteger, ctSingleChoice,
  84. ctEnd);
  85. TStringArray= array of String;
  86. TWideStringArray= array of WideString;
  87. TWideStringArrayOfArray= array of array of WideString;
  88. PColor= ^TColor;
  89. PByte= ^Byte;
  90. TDataComponent= class
  91. private
  92. FCount: Integer;
  93. Boxes: array of Integer;
  94. FCompType: TCompType;
  95. FName: String;
  96. function GetBoxByIndex (Index: Integer): Integer;
  97. public
  98. DataComponent: TCompType;
  99. property Count: Integer read FCount;
  100. property Box [Index: Integer]: Integer read GetBoxByIndex;
  101. property Name: String read FName;
  102. constructor Create (Name: String);
  103. procedure Free;
  104. procedure SaveToFile (var FileHandle: TextFile);
  105. procedure LoadFromFile (var FileHandle: TextFile);
  106. procedure AddBox (BoxIndex: Integer);
  107. procedure DeleteBox (Index: Integer);
  108. end;
  109. TField= class (TObject);
  110. TCheckBoxField= class (TObject);
  111. TFormsBox= class (TObject)
  112. private
  113. MinX, MaxX: Integer;
  114. MinY, Maxy: Integer;
  115. FWidth,
  116. FHeight: Integer;
  117. FAllBoxes: array of TBoxData;
  118. FIsLastChangeSaved: Boolean;
  119. FFileName: String;
  120. Components: array of TDataComponent;
  121. FFormID: Integer;
  122. FSaveResultsAsBitmaps: Boolean;
  123. DataPath: String;
  124. BitmapImage: TBitmap;
  125. function GetBoxes (Index: Integer): TBoxData;
  126. function GetBoxCount: Integer;
  127. procedure SetFileName (const Value: String);
  128. function GetHeight: Integer;
  129. function GetWidth: Integer;
  130. // function DeleteNoise (MyBitmapImage: TMyBitmap; NoiseColor: TRGB): TBitmap;
  131. function ConvertToHSI (Color: TColor): THSI;
  132. function ConvertToRGB (Color: TColor): TRGB;
  133. function FindComponent (MyBitmap: TMyBitmap; Box: TBox; HelpBarColor: TRGB; ContinueSearchOverBorders: Integer= 1): TComponentCollection;
  134. function FindHelpBar (MyBitmap: TMyBitmap; Box: TBox; HelpBarColor: TRGB; ContinueSearchOverBorders: Integer= 1): TComponentCollection;
  135. function GetNumberOfCheckBoxFeilds: Integer;
  136. function GetNumberOfNumeralFeilds: Integer;
  137. function GetNumberOfAlphabeticFeilds: Integer;
  138. function GetPostprocessingTypeOfAlphabeticFeilds: TStringArray;
  139. function GetFeildsTitles: TWideStringArray;
  140. function GetCheckBoxOptionTitles: TWideStringArrayOfArray;
  141. procedure SetSaveResultsAsBitmaps(const Value: Boolean);
  142. function ExtractBox (BitmapImage: TBitmap; UseDialation: Boolean= True): TImageCollection;
  143. function GetAlphaNumericalFieldsArray(Index: Integer): TField;
  144. function GetCheckBoxFieldsArray(Index: Integer): TCheckBoxField;
  145. function FindSkewAndReplacenent (Bitmap: TBitmap): Boolean;
  146. public
  147. property Boxes [Index: Integer]: TBoxData read GetBoxes;
  148. property BoxNumber: Integer read GetBoxCount;
  149. property IsLastChangeSaved: Boolean read FIsLastChangeSaved;
  150. property FileName: String read FFileName write SetFileName;
  151. property Width: Integer read GetWidth;
  152. property Height: Integer read GetHeight;
  153. property FormID: Integer read FFormID;
  154. property NumberOfCheckBoxFeilds: Integer read GetNumberOfCheckBoxFeilds;
  155. property NumberOfNumeralFeilds: Integer read GetNumberOfNumeralFeilds;
  156. property NumberOfAlphabeticFeilds: Integer read GetNumberOfAlphabeticFeilds;
  157. property PostprocessingTypeOfAlphabeticFeilds: TStringArray
  158. read GetPostprocessingTypeOfAlphabeticFeilds;
  159. property FeildsTitles: TWideStringArray read GetFeildsTitles;
  160. property CheckBoxOptionTitles: TWideStringArrayOfArray read GetCheckBoxOptionTitles;
  161. property SaveResultsAsBitmaps: Boolean read FSaveResultsAsBitmaps write SetSaveResultsAsBitmaps;
  162. property AlphaNumericalFieldsArray [Index: Integer]: TField read GetAlphaNumericalFieldsArray;
  163. property CheckBoxFieldsArray [Index: Integer]: TCheckBoxField read GetCheckBoxFieldsArray;
  164. function AddBox (Box: TBoxData): Boolean;
  165. procedure AddComponent (DataComponent: TDataComponent);
  166. function DeleteBox (Index: Integer): Boolean;
  167. procedure SaveToFile (FileName: String);overload;
  168. procedure SaveToFile;overload;
  169. procedure LoadConfigFile (FileName: String);overload;
  170. procedure LoadFromFile;overload;
  171. function LoadTheForm (FileName: String): TBitmap;overload;
  172. function LoadTheForm (Bitmap: TBitmap): TBitmap;overload;
  173. procedure DrawInBitmap (BitmapImage: TBitmap);
  174. procedure ExtractAllBox;
  175. function GenerateOutput (FormImage: TBitmap; Data: array of Integer): TBitmap;overload;
  176. // procedure GenerateHtml (Data: array of Integer);
  177. constructor Create; overload;
  178. constructor Create (DataPath: String); overload;
  179. procedure Free;
  180. end;
  181. function InputKindToString (Value: TInputKind): String;
  182. function ComponentTypeToString (Value: TCompType): String;
  183. function ColorIsNotWhite (Color: TColor): Boolean;
  184. function ColorsAreTheSame (Color1, Color2: TRGB): Boolean;
  185. function ColorsAreInSameRange (Color1, Color2: TRGB): Boolean;
  186. const
  187. WidthSearchThreshld= 5;
  188. HeightarchThreshld= 5;
  189. function CheckForLine (x, y: Integer; BitmapImage: TBitmap;
  190. WidthCheck: Integer= WidthSearchThreshld;
  191. HeightCheck: Integer= HeightarchThreshld): Boolean;
  192. function FindTopRightPointInLine (x, y: Integer; BitmapImage: TBitmap): TPoint;
  193. function FindTopLeftPointInLine (x, y: Integer; BitmapImage: TBitmap): TPoint;
  194. function FindBottomRightPointInLine (x, y: Integer; BitmapImage: TBitmap): TPoint;
  195. function FindBottomLeftPointInLine (x, y: Integer; BitmapImage: TBitmap): TPoint;
  196. implementation
  197. uses
  198. Dialogs, Math{, Borland.Vcl.ComCtrls, Borland.Vcl.Grids, Borland.Vcl.Controls,};
  199. function ComponentTypeToString (Value: TCompType): String;
  200. begin
  201. case value of
  202. ctFirstName:
  203. Result:= 'First Name';
  204. ctLastName:
  205. Result:= 'Last Name';
  206. ctCity:
  207. Result:= 'City';
  208. ctState:
  209. Result:= 'State';
  210. ctInteger:
  211. Result:= 'Integer';
  212. ctSingleChoice:
  213. Result:= 'Single Choice Box';
  214. end;
  215. end;
  216. function InputKindToString (Value: TInputKind): String;
  217. begin
  218. case Value of
  219. ikNumeral:
  220. Result:= 'Numercial';
  221. ikAlphabet:
  222. Result:= 'Alphabet';
  223. ikCheckBox:
  224. Result:= 'CheckBox';
  225. ikPicture:
  226. Result:= 'Picture';
  227. ikHelpBar:
  228. Result:= 'HelpBar';
  229. end;
  230. end;
  231. { TBox }
  232. procedure TBox.Complete;
  233. var
  234. MaxY, MinY, MaxX, MinX: Integer;
  235. begin
  236. try
  237. if (LowerRightPoint= nil) or (UpperLeftPoint= nil) then
  238. Exit;
  239. MinY:= LowerRightPoint.y;
  240. MaxY:= UpperLeftPoint.y;
  241. MaxX:= LowerRightPoint.x;
  242. MinX:= UpperLeftPoint.x;
  243. if MaxY< MinY then
  244. begin
  245. MinY:= MinY xor MaxY;
  246. MaxY:= MinY xor MaxY;
  247. MinY:= MinY xor MaxY;
  248. end;
  249. if MaxX< MinX then
  250. begin
  251. MinX:= MinX xor MaxX;
  252. MaxX:= MinX xor MaxX;
  253. MinX:= MinX xor MaxX;
  254. end;
  255. LowerRightPoint.x:= MaxX;
  256. LowerRightPoint.y:= MaxY;
  257. UpperLeftPoint.x:= MinX;
  258. UpperLeftPoint.y:= MinY;
  259. except
  260. on EPointIsNotInitialized do
  261. Exit;
  262. end;
  263. end;
  264. function TBox.Copy: TBox;
  265. begin
  266. Result:= TBox.Create;
  267. Result.UpperLeftPoint:= Self.UpperLeftPoint;
  268. Result.LowerRightPoint:= Self.LowerRightPoint;
  269. Result.UpperLeftPoint:= Self.UpperLeftPoint;
  270. Result.LowerRightPoint:= Self.LowerRightPoint;
  271. end;
  272. constructor TBox.Create;
  273. begin
  274. inherited;
  275. FTitle:= '';
  276. Self.UpperLeftPoint:= nil;
  277. Self.LowerRightPoint:= nil;
  278. Self.UpperLeftPoint:= nil;
  279. Self.LowerRightPoint:= nil;
  280. end;
  281. procedure TBox.Free;
  282. begin
  283. if FLowerRightPoint<> nil then
  284. FLowerRightPoint.Free;
  285. if FUpperLeftPoint<> nil then
  286. FUpperLeftPoint.Free;
  287. if FLowerLeftPoint<> nil then
  288. FLowerLeftPoint.Free;
  289. if FUpperRightPoint<> nil then
  290. FUpperRightPoint.Free;
  291. inherited;
  292. end;
  293. function TBox.IsSame (Box: TBox): Boolean;
  294. begin
  295. Result:= Self.UpperLeftPoint.IsSame (Box.UpperLeftPoint) and
  296. Self.LowerRightPoint.IsSame (Box.LowerRightPoint);
  297. end;
  298. procedure TBox.LoadFromFile(var InputFile: TextFile; LoadTitle: Boolean= False);
  299. var
  300. Left, Top, Width, Heigth: Integer;
  301. begin
  302. Readln (InputFile, Left);
  303. Readln (InputFile, Top);
  304. Readln (InputFile, Width);
  305. Readln (InputFile, Heigth);
  306. if LoadTitle then
  307. Readln (InputFile, FTitle);
  308. FUpperLeftPoint:= TPoint.Create (Left, Top);
  309. FLowerRightPoint:= TPoint.Create (Left+ Width, Top+ Heigth);
  310. Readln (InputFile);
  311. end;
  312. function TBox.Move (Delta: TPoint): TBox;
  313. begin
  314. FLowerRightPoint.Move (Delta);
  315. FUpperLeftPoint.Move (Delta);
  316. FLowerLeftPoint.Move (Delta);
  317. FUpperRightPoint.Move (Delta);
  318. Result:= Self;
  319. end;
  320. function TBox.Rotate (Angle: Extended): TBox;
  321. begin
  322. LowerRightPoint.Rotate (Angle);
  323. UpperLeftPoint.Rotate (Angle);
  324. Result:= Self;
  325. end;
  326. procedure TBox.SaveToFile (var OutputFile: TextFile);
  327. begin
  328. WriteLn (OutputFile, UpperLeftPoint.ToString);
  329. WriteLn (OutputFile, LowerRightPoint.ToString);
  330. end;
  331. procedure TBox.SetLowerRightPoint (const Value: TPoint);
  332. begin
  333. FLowerRightPoint:= Value;
  334. Complete;
  335. end;
  336. procedure TBox.SetUpperLeftPoint (const Value: TPoint);
  337. begin
  338. FUpperLeftPoint:= Value;
  339. Complete;
  340. end;
  341. { TBoxData }
  342. function TBoxData.Copy: TBoxData;
  343. begin
  344. raise Exception.Create ('Not Implemented Yet!');
  345. {
  346. Result:= TBoxData.Create;
  347. // Result.FBox:= Self.Box.Copy;
  348. Result.FKind:= Self.Kind;
  349. }
  350. end;
  351. constructor TBoxData.Create;
  352. begin
  353. inherited;
  354. IsValid:= False;
  355. FPostProcessorFileName:= '';
  356. FTitle:= '';
  357. SetLength (FBoxArray, 0);
  358. // FBox:= TBox.Create;
  359. FSource:= nil;
  360. FRotateAngle:= 0;
  361. end;
  362. constructor TBoxData.Create (Box: TBox; InputKind: TInputKind);
  363. begin
  364. inherited Create;
  365. // Self.FBox:= Box;
  366. FKind:= InputKind;
  367. FPostProcessorFileName:= '';
  368. FTitle:= '';
  369. FSource:= nil;
  370. end;
  371. procedure TBoxData.DrawInBitmap (BitmapImage: TBitmap);
  372. begin
  373. raise Exception.Create ('Not Implemented Yet!');
  374. {
  375. BitmapImage.Canvas.MoveTo (Box.UpperLeftPoint.x, Box.UpperLeftPoint.y);
  376. BitmapImage.Canvas.LineTo (Box.UpperLeftPoint.x, Box.LowerRightPoint.y);
  377. BitmapImage.Canvas.LineTo (Box.LowerRightPoint.x, Box.LowerRightPoint.y);
  378. BitmapImage.Canvas.LineTo (Box.LowerRightPoint.x, Box.UpperLeftPoint.y);
  379. BitmapImage.Canvas.LineTo (Box.UpperLeftPoint.x, Box.UpperLeftPoint.y);
  380. }
  381. end;
  382. function TBoxData.ExtractFromBitmap (BitmapImage: TBitmap): TImageCollection;
  383. const
  384. SearchAreaY: Integer= 10;
  385. SearchAreaX: Integer= 2;
  386. NumberOfSamples: Integer= 20;
  387. LeastAcceptance: Integer= 10;
  388. MinCountThreshld: Integer= 10;
  389. YPosPlace= 10;
  390. XPosPlace= 10;
  391. function BFS (Px, Py: Integer; MaxX, MaxY, MinX, MinY: Integer): TComponent;//unsafe;
  392. const
  393. AdjancedPixelY: array [dN..dNW] of Integer= (-1, -1, 0, +1, +1, +1, 0, -1);
  394. AdjancedPixelX: array [dN..dNW] of Integer= ( 0, +1, +1, +1, 0, -1, -1, -1);
  395. var
  396. Dir: TDirection;
  397. LastPoint: TPoint;
  398. XOld, YOld,
  399. XNew, YNew: Integer;
  400. CurIndex: Integer;
  401. RGBWhite,
  402. RGBBlack: TRGB;
  403. RowPtr: PByte;
  404. begin
  405. RGBWhite.r:= $FF;RGBWhite.g:= $FF;RGBWhite.b:= $FF;
  406. RGBBlack.r:= $0 ;RGBBlack.g:= $0 ;RGBBlack.b:= $0;
  407. Result:= TComponent.Create;
  408. Result.Add (Px, Py, RGBBlack);
  409. CurIndex:= 0;
  410. while Result.Count> CurIndex do
  411. begin
  412. LastPoint:= Result.GetPixel (CurIndex).Location;
  413. XOld:= LastPoint.x; YOld:= LastPoint.y;
  414. for Dir:= dN to dNW do
  415. begin
  416. XNew:= XOld; YNew:= YOld;
  417. Inc (XNew, AdjancedPixelX [Dir]);
  418. Inc (YNew, AdjancedPixelY [Dir]);
  419. if (XNew< MaxX) and (MinX< XNew) and
  420. (YNew< MaxY) and (MinY< YNew) then
  421. begin
  422. RowPtr:= BitmapImage.ScanLine [yNew];
  423. Inc (RowPtr, 3* xNew);
  424. if ColorIsNotWhite (PColor (RowPtr)^) then
  425. begin
  426. Result.Add (xNew, yNew, RGBBlack);
  427. RowPtr^:= $FF;
  428. Inc (RowPtr);
  429. RowPtr^:= $FF;
  430. Inc (RowPtr);
  431. RowPtr^:= $FF;
  432. end;
  433. end;
  434. end;
  435. Inc (CurIndex);
  436. end;
  437. end;
  438. var
  439. i, Index, Iter,
  440. x, y: Integer;
  441. GuestForPolarUpperLeft,
  442. GuestForPolarLowerRight: TPolarPoint;
  443. GuestForPointUpperLeft,
  444. GuestForPointLowerRight: TPoint;
  445. Angle: Extended;
  446. Ptr: PByte;
  447. UpperRightPoint,
  448. UpperLeftPoint,
  449. LowerRightPoint,
  450. LowerLeftPoint: TPoint;
  451. AcceptCounter,
  452. Width, Height: Integer;
  453. NewImage: TFMLImage;
  454. NewComponet: TComponent;
  455. ComponentCollection: TComponentCollection;
  456. begin
  457. if Self.Kind<> ikCheckBox then
  458. begin
  459. Result:= TImageCollection.Create;
  460. Angle:= RotateAngle;
  461. LowerRightPoint:= nil;
  462. LowerLeftPoint:= nil;
  463. UpperRightPoint:= nil;
  464. UpperLeftPoint:= nil;
  465. for i:= 0 to High (FBoxArray) do
  466. begin
  467. GuestForPointUpperLeft:= FBoxArray [i].FUpperLeftPoint.Copy;
  468. GuestForPointUpperLeft.Move (Source);
  469. GuestForPolarUpperLeft:= GuestForPointUpperLeft.ToPolar;
  470. GuestForPolarUpperLeft.Rotate (Angle);
  471. GuestForPointUpperLeft.Free;
  472. GuestForPointUpperLeft:= GuestForPolarUpperLeft.ToPoint;
  473. GuestForPolarUpperLeft.Free;
  474. GuestForPointLowerRight:= FBoxArray [i].FLowerRightPoint.Copy;
  475. GuestForPointLowerRight.Move (Source);
  476. GuestForPolarLowerRight:= GuestForPointLowerRight.ToPolar;
  477. GuestForPolarLowerRight.Rotate (Angle);
  478. GuestForPointLowerRight.Free;
  479. GuestForPointLowerRight:= GuestForPolarLowerRight.ToPoint;
  480. GuestForPolarLowerRight.Free;
  481. UpperRightPoint:= nil;
  482. UpperLeftPoint:= nil;
  483. try
  484. for y:= GuestForPointUpperLeft.y- SearchAreaY to
  485. GuestForPointUpperLeft.y+ SearchAreaY do
  486. begin
  487. Ptr:= BitmapImage.ScanLine [y];
  488. x:= (GuestForPointUpperLeft.x- SearchAreaX);
  489. Inc (Ptr, 3* x);
  490. Inc (Ptr, 3* (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  491. Inc (x, (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  492. for Iter:= 1 to 9 do
  493. begin
  494. if ColorIsNotWhite (PColor (Ptr)^) then
  495. if CheckForLine (x, y, BitmapImage, 5, 2) then
  496. begin
  497. UpperRightPoint:= FindTopRightPointInLine (x, y, BitmapImage);
  498. UpperLeftPoint:= FindTopLeftPointInLine (x, y, BitmapImage);
  499. Break;
  500. end;
  501. Inc (Ptr, 3* (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  502. Inc (x, (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  503. end;
  504. if UpperRightPoint<> nil then
  505. Break;
  506. end;
  507. LowerRightPoint:= nil;
  508. LowerLeftPoint:= nil;
  509. for y:= GuestForPointLowerRight.y+ SearchAreaY downto
  510. GuestForPointLowerRight.y- SearchAreaY do
  511. begin
  512. Ptr:= BitmapImage.ScanLine [y];
  513. x:= (GuestForPointUpperLeft.x- SearchAreaX);
  514. Inc (Ptr, 3* x);
  515. Inc (Ptr, 3* (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  516. Inc (x, (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  517. for Iter:= 1 to 9 do
  518. begin
  519. if ColorIsNotWhite (PColor (Ptr)^) then
  520. if CheckForLine (x, y, BitmapImage, 5, 2) then
  521. begin
  522. LowerRightPoint:= FindBottomRightPointInLine (x, y, BitmapImage);
  523. LowerLeftPoint:= FindBottomLeftPointInLine (x, y, BitmapImage);
  524. Break;
  525. end;
  526. Inc (Ptr, 3* (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  527. Inc (x, (GuestForPointLowerRight.x- GuestForPointUpperLeft.x) div 10);
  528. end;
  529. if LowerRightPoint<> nil then
  530. Break;
  531. end;
  532. GuestForPointLowerRight.Free;
  533. GuestForPointUpperLeft.Free;
  534. except
  535. Result:= nil;
  536. Exit;
  537. end;
  538. {
  539. ShowMessage (UpperLeftPoint.ToString);
  540. ShowMessage (LowerRightPoint.ToString);
  541. }
  542. Width:= (UpperRightPoint.x- UpperLeftPoint.x) div NumberOfSamples;
  543. Height:= (LowerRightPoint.y- UpperLeftPoint.y) div NumberOfSamples;
  544. for y:= UpperLeftPoint.y to LowerRightPoint.y do
  545. begin
  546. AcceptCounter:= 0;
  547. x:= UpperLeftPoint.x+ Width div 2;
  548. for Index:= 0 to NumberOfSamples- 1 do
  549. begin
  550. if CheckForLine (x, y, BitmapImage, Width div 2, 1) then
  551. Inc (AcceptCounter);
  552. Inc (x, Width);
  553. end;
  554. if LeastAcceptance< AcceptCounter then
  555. begin
  556. UpperRightPoint.y:= y;
  557. UpperLeftPoint.y:= y;
  558. end
  559. else
  560. Break;
  561. end;
  562. for y:= LowerRightPoint.y downto UpperRightPoint.y do
  563. begin
  564. AcceptCounter:= 0;
  565. x:= UpperLeftPoint.x+ Width div 2;
  566. for Index:= 0 to NumberOfSamples- 1 do
  567. begin
  568. if CheckForLine (x, y, BitmapImage, Width div 2, 1) then
  569. Inc (AcceptCounter);
  570. Inc (x, Width);
  571. end;
  572. if LeastAcceptance< AcceptCounter then
  573. begin
  574. LowerRightPoint.y:= y;
  575. LowerLeftPoint.y:= y;
  576. end
  577. else
  578. Break;
  579. end;
  580. for x:= UpperLeftPoint.x to LowerRightPoint.x do
  581. begin
  582. AcceptCounter:= 0;
  583. y:= UpperLeftPoint.y+ Height div 2;
  584. for Index:= 0 to NumberOfSamples- 1 do
  585. begin
  586. if CheckForLine (x, y, BitmapImage, 0, Height div 2) then
  587. Inc (AcceptCounter);
  588. Inc (y, Height);
  589. end;
  590. if LeastAcceptance< AcceptCounter then
  591. begin
  592. LowerLeftPoint.x:= x;
  593. UpperLeftPoint.x:= x;
  594. end
  595. else
  596. Break;
  597. end;
  598. for x:= LowerRightPoint.x downto UpperLeftPoint.x do
  599. begin
  600. AcceptCounter:= 0;
  601. y:= UpperLeftPoint.y+ Height div 2;
  602. for Index:= 0 to NumberOfSamples- 1 do
  603. begin
  604. if CheckForLine (x, y, BitmapImage, 0, Height div 2) then
  605. Inc (AcceptCounter);
  606. Inc (y, Height);
  607. end;
  608. if LeastAcceptance< AcceptCounter then
  609. begin
  610. LowerRightPoint.x:= x;
  611. UpperRightPoint.x:= x;
  612. end
  613. else
  614. Break;
  615. end;
  616. ComponentCollection:= TComponentCollection.Create;
  617. for y:= UpperLeftPoint.y+ YPosPlace to LowerRightPoint.y- YPosPlace do
  618. begin
  619. Ptr:= BitmapImage.ScanLine [y];
  620. Inc (Ptr, 3* (LowerLeftPoint.x+ XPosPlace));
  621. for x:= LowerLeftPoint.x+ XPosPlace to LowerRightPoint.x- XPosPlace do
  622. begin
  623. if ColorIsNotWhite (PColor (Ptr)^) then
  624. begin
  625. NewComponet:= BFS (x, y, LowerRightPoint.x, LowerRightPoint.y,
  626. UpperLeftPoint.x, UpperLeftPoint.y);
  627. if MinCountThreshld< NewComponet.Count then
  628. ComponentCollection.AddComponent (NewComponet)
  629. else
  630. NewComponet.Free;
  631. end;
  632. Inc (Ptr, 3);
  633. end;
  634. end;
  635. ComponentCollection.RemoveInvalidComponents;
  636. Result.AddImage (TFMLImage.Create (ComponentCollection));
  637. ComponentCollection.Free;
  638. end;
  639. end
  640. else
  641. begin
  642. //??!!
  643. NewImage:= TFMLImage.Create;
  644. NewImage.Row:= LowerRightPoint.y- 2* YPosPlace- UpperLeftPoint.y+ 1;
  645. NewImage.Column:= LowerRightPoint.x- 2* XPosPlace- UpperLeftPoint.x+ 1;
  646. for y:= UpperLeftPoint.y+ YPosPlace to LowerRightPoint.y- YPosPlace do
  647. begin
  648. Ptr:= BitmapImage.ScanLine [y];
  649. Inc (Ptr, 3* (LowerLeftPoint.x+ XPosPlace));
  650. for x:= LowerLeftPoint.x+ XPosPlace to LowerRightPoint.x- XPosPlace do
  651. begin
  652. if ColorIsNotWhite (PColor (Ptr)^) then
  653. NewImage.SetPixelBlack (y, x);
  654. Inc (Ptr, 3);
  655. end;
  656. end;
  657. end;
  658. end;
  659. procedure TBoxData.Free;
  660. var
  661. i: Integer;
  662. begin
  663. if Length (FBoxArray)<> 0 then
  664. for i:= 0 to High (FBoxArray) do
  665. FBoxArray [i].Free;
  666. SetLength (FBoxArray, 0);
  667. if FSource<> nil then
  668. FSource.Free;
  669. inherited;
  670. end;
  671. function TBoxData.IsSame (Box: TBoxData): Boolean;
  672. begin
  673. raise Exception.Create ('Not Implemented Yet!');
  674. {
  675. Result:= Self.Box.IsSame (Box.Box);
  676. }
  677. end;
  678. procedure TBoxData.LoadFromFile (var InputFile: TextFile);
  679. function StrToInputKind (S: String): TInputKind;
  680. begin
  681. S:= UpperCase (S);
  682. if S= UpperCase ('Numeral') then
  683. Result:= ikNumeral
  684. else if S= UpperCase ('Alphabetic') then
  685. Result:= ikAlphabet
  686. else if S= UpperCase ('CheckBox') then
  687. Result:= ikCheckBox
  688. else if S= UpperCase ('Picture') then
  689. Result:= ikPicture
  690. else if S= UpperCase ('HelpBar') then
  691. Result:= ikHelpBar
  692. else
  693. Result:= ikNumeral;
  694. end;
  695. var
  696. S: WideString;
  697. i: Integer;
  698. Top, Left,
  699. Width, Height,
  700. SpaceWidth: Integer;
  701. begin
  702. ReadLn (InputFile, S);
  703. ReadLn (InputFile, S);
  704. ReadLn (InputFile, S);
  705. FKind:= StrToInputKind (S);
  706. ReadLn (InputFile, S);
  707. Readln (InputFile, FPostProcessorFileName);
  708. ReadLn (InputFile, S);
  709. Readln (InputFile, FTitle);
  710. ReadLn (InputFile, S);
  711. Readln (InputFile, FNumberOfElement);
  712. SetLength (FBoxArray, FNumberOfElement);
  713. ReadLn (InputFile, S);
  714. if FKind<> ikCheckBox then
  715. begin
  716. Readln (InputFile, Left);
  717. Readln (InputFile, Top);
  718. Readln (InputFile, Width);
  719. Readln (InputFile, Height);
  720. Readln (InputFile, SpaceWidth);
  721. for i:= 0 to FNumberOfElement- 1 do
  722. begin
  723. FBoxArray [i]:= TBox.Create;
  724. FBoxArray [i].FTitle:= Self.Title+ IntToStr (i);
  725. FBoxArray [i].FUpperLeftPoint:=
  726. TPoint.Create (Left+ i* (SpaceWidth+ Width), Top);
  727. FBoxArray [i].FLowerRightPoint:=
  728. TPoint.Create (Left+ Width+ i* (SpaceWidth+ Width), Top+ Height);
  729. end;
  730. end
  731. else
  732. for i:= 0 to FNumberOfElement- 1 do
  733. begin
  734. FBoxArray [i]:= TBox.Create;
  735. FBoxArray [i].LoadFromFile (InputFile, True);
  736. end;
  737. ReadLn (InputFile, S);
  738. end;
  739. procedure TBoxData.SaveToFile (var OutputFile: TextFile);
  740. begin
  741. raise Exception.Create ('Not Implemented Yet!');
  742. {
  743. WriteLn (OutputFile, InputKindToString (Kind));
  744. Box.SaveToFile (OutputFile);
  745. WriteLn (OutputFile);
  746. }
  747. end;
  748. { TFormsBox }
  749. function TFormsBox.AddBox (Box: TBoxData): Boolean;
  750. begin
  751. SetLength (FAllBoxes, BoxNumber+ 1);
  752. FAllBoxes [BoxNumber- 1]:= Box;
  753. FIsLastChangeSaved:= False;
  754. Result:= True;
  755. // Box.Box.Complete;
  756. end;
  757. constructor TFormsBox.Create;
  758. begin
  759. inherited;
  760. SetLength (FAllBoxes, 0);
  761. FIsLastChangeSaved:= True;
  762. FileName:= '';
  763. FWidth:= -1; MaxX:= 0; MinX:= 100000;
  764. FHeight:= -1; MaxY:= 0; MinY:= 100000;
  765. DataPath:= '';
  766. end;
  767. procedure TFormsBox.Free;
  768. var
  769. i: Integer;
  770. begin
  771. for i:= 0 to BoxNumber- 1 do
  772. FAllBoxes [i].Free;
  773. for i:= 0 to High (Components) do
  774. Components [i].Free;
  775. SetLength (FAllBoxes, 0);
  776. SetLength (Components, 0);
  777. inherited;
  778. end;
  779. function TFormsBox.GetBoxCount: Integer;
  780. begin
  781. Result:= Length (FAllBoxes);
  782. end;
  783. function TFormsBox.GetBoxes (Index: Integer): TBoxData;
  784. begin
  785. if (BoxNumber<= Index) or (Index< 0)then
  786. raise EFormBoxRangeCheckError.Create ('Range Check Error!');
  787. Result:= FAllBoxes [Index];
  788. end;
  789. procedure TFormsBox.SaveToFile (FileName: String);
  790. var
  791. i: Integer;
  792. OutputFile: TextFile;
  793. begin
  794. Self.FileName:= FileName;
  795. AssignFile (OutputFile, FileName);
  796. Rewrite (OutputFile);
  797. for i:= 0 to BoxNumber- 1 do
  798. FAllBoxes [i].SaveToFile (OutputFile);
  799. WriteLn;
  800. WriteLn (OutputFile, 'Components');
  801. for i:= 0 to High (Components) do
  802. Components [i].SaveToFile (OutputFile);
  803. CloseFile (OutputFile);
  804. end;
  805. procedure TFormsBox.LoadConfigFile (FileName: String);
  806. function WideStrReadLn (var InputFile: TextFile): WideString;
  807. var
  808. LastCh,
  809. Ch: Char;
  810. begin
  811. Result:= '';
  812. LastCh:= #0;
  813. while not EoLn (InputFile) do
  814. begin
  815. Read (InputFile, Ch);
  816. if (Ch= #10) and (LastCh= #13) then
  817. Exit;
  818. Result:= Result+ Ch;
  819. LastCh:= Ch;
  820. end;
  821. end;
  822. var
  823. InputFile: TextFile;
  824. WideStr: WideString;
  825. Box: TBoxData;
  826. begin
  827. Self.FileName:= FileName;
  828. AssignFile (InputFile, FileName);
  829. Reset (InputFile);
  830. ReadLn (InputFile, WideStr);
  831. Readln (InputFile, FFormID);
  832. while not Eof (InputFile) do
  833. begin
  834. Box:= TBoxData.Create;
  835. Box.LoadFromFile (InputFile);
  836. Self.AddBox (Box);
  837. end;
  838. CloseFile (InputFile);
  839. end;
  840. procedure TFormsBox.SaveToFile;
  841. var
  842. SaveDialog: TSaveDialog;
  843. begin
  844. if FileName= '' then
  845. begin
  846. SaveDialog:= TSaveDialog.Create (nil);
  847. SaveDialog.DefaultExt:= '.txt';
  848. SaveDialog.Filter:= 'Text Files|*.txt|All Files|*.*';
  849. if SaveDialog.Execute then
  850. FileName:= SaveDialog.FileName
  851. else
  852. begin
  853. SaveDialog.Free;
  854. Exit;
  855. end;
  856. SaveDialog.Free;
  857. end;
  858. SaveToFile (FileName);
  859. end;
  860. procedure TFormsBox.SetFileName (const Value: String);
  861. begin
  862. FFileName:= Value;
  863. end;
  864. procedure TFormsBox.LoadFromFile;
  865. var
  866. OpenDialog: TOpenDialog;
  867. begin
  868. OpenDialog:= TOpenDialog.Create (nil);
  869. OpenDialog.DefaultExt:= '.txt';
  870. OpenDialog.Filter:= 'Text Files|*.txt|All Files|*.*';
  871. if OpenDialog.Execute then
  872. begin
  873. Self.FileName:= OpenDialog.FileName;
  874. Self.LoadConfigFile (OpenDialog.FileName);
  875. Self.FIsLastChangeSaved:= True;
  876. end;
  877. end;
  878. function TFormsBox.GetWidth: Integer;
  879. {
  880. var
  881. i: Integer;
  882. }
  883. begin
  884. raise Exception.Create ('Not Implemented Yet!');
  885. {
  886. if FWidth= -1 then
  887. begin
  888. if BoxNumber> 0 then
  889. MaxX:= FAllBoxes [0].Box.LowerRightPoint.x
  890. else
  891. begin
  892. Result:= 0;
  893. Exit;
  894. end;
  895. for i:= 0 to BoxNumber- 1 do
  896. begin
  897. if MaxX< FAllBoxes [i].FBox.LowerRightPoint.x then
  898. MaxX:= FAllBoxes [i].FBox.LowerRightPoint.x;
  899. end;
  900. FWidth:= MaxX;
  901. end;
  902. Result:= FWidth;
  903. }
  904. end;
  905. function TFormsBox.GetHeight: Integer;
  906. {
  907. var
  908. i: Integer;
  909. }
  910. begin
  911. raise Exception.Create ('Not Implemented Yet!');
  912. {
  913. if FHeight= -1 then
  914. begin
  915. if BoxNumber> 0 then
  916. MaxY:= FAllBoxes [0].Box.LowerRightPoint.y
  917. else
  918. begin
  919. Result:= 0;
  920. Exit;
  921. end;
  922. for i:= 0 to BoxNumber- 1 do
  923. begin
  924. if MaxY< FAllBoxes [i].FBox.LowerRightPoint.y then
  925. MaxY:= FAllBoxes [i].FBox.LowerRightPoint.y;
  926. end;
  927. FHeight:= MaxY;
  928. end;
  929. Result:= FHeight;
  930. }
  931. end;
  932. procedure TFormsBox.DrawInBitmap (BitmapImage: TBitmap);
  933. var
  934. i: Integer;
  935. begin
  936. BitmapImage.Width:= Width;
  937. BitmapImage.Height:= Height;
  938. for i:= 0 to BoxNumber- 1 do
  939. FAllBoxes [i].DrawInBitmap (BitmapImage);
  940. end;
  941. function TFormsBox.ExtractBox (BitmapImage: TBitmap; UseDialation: Boolean): TImageCollection;
  942. const
  943. AdjancedPixelY: array [dN..dNW] of Integer= (-1, -1, 0, +1, +1, +1, 0, -1);
  944. AdjancedPixelX: array [dN..dNW] of Integer= ( 0, +1, +1, +1, 0, -1, -1, -1);
  945. var
  946. ImageCollection: TImageCollection;
  947. i: Integer;
  948. // ComponentCollection: TComponentCollection;
  949. MyBitmap: TMyBitmap;
  950. Box: TBoxData;
  951. begin
  952. {??!!
  953. if BitmapImage.PixelFormat<> pf24Bit then
  954. raise EInvalidImage.Create ('Invalid Image In Find Component');
  955. }
  956. { TODO -oAmir -cPreProcessor : Add Some code to not allow to segment the characters }
  957. Result:= TImageCollection.Create;
  958. MyBitmap:= TMyBitmap.Create (BitmapImage);
  959. for i:= 0 to High (FAllBoxes) do
  960. begin
  961. Box:= FAllBoxes [i];
  962. if Box.Kind= ikCheckBox then
  963. begin
  964. ImageCollection:= Box.ExtractFromBitmap (BitmapImage);
  965. end
  966. else if Box.Kind in [ikNumeral, ikAlphabet] then
  967. begin
  968. try
  969. ImageCollection:= Box.ExtractFromBitmap (BitmapImage);
  970. if UseDialation then
  971. ImageCollection.Dilate;
  972. ImageCollection.SaveFilesAsBitmap (IntToStr (i));
  973. except
  974. on E: Exception do
  975. ShowMessage (E.Message+ IntToStr (i));
  976. end;
  977. end;
  978. end;
  979. MyBitmap.Free;
  980. Result.Free;
  981. end;
  982. function TFormsBox.DeleteBox (Index: Integer): Boolean;
  983. var
  984. i: Integer;
  985. begin
  986. if (Index< 0) or (Index>= BoxNumber) then
  987. raise ERangeError.Create ('Range Check Error');
  988. Boxes [Index].Free;
  989. for i:= Index+ 1 to BoxNumber- 1 do
  990. FAllBoxes [i- 1]:= Boxes [i];
  991. SetLength (FAllBoxes, BoxNumber- 1);
  992. Result:= True;
  993. end;
  994. {procedure TFormsBox.GenerateHtml (Data: array of Integer);
  995. begin
  996. end;
  997. }
  998. function TFormsBox.GenerateOutput (FormImage: TBitmap;
  999. Data: array of Integer): TBitmap;
  1000. const
  1001. Digits: array [0..9] of String= ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
  1002. PersianAlphabet: array [0..31] of String= ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
  1003. '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?');
  1004. {
  1005. var
  1006. Box: TBox;
  1007. i, j: Integer;
  1008. }
  1009. begin
  1010. raise Exception.Create ('Not Implemented Yet!');
  1011. {
  1012. if Length (Data)<> BoxNumber- 1 then
  1013. raise Exception.Create ('Invalid number of entry');
  1014. j:= -1;
  1015. i:= 0;
  1016. while i< BoxNumber- 1 do
  1017. begin
  1018. Inc (j);
  1019. if Boxes [j].Kind= ikHelpBar then
  1020. Continue;
  1021. if Data [i]<= -1 then
  1022. Continue;
  1023. case Boxes [j].Kind of
  1024. ikNumeral:
  1025. begin
  1026. Box:= Boxes [j].Box;
  1027. if (9< Data [i]) then
  1028. raise Exception.Create ('Number '+ IntToStr (Data [i])+ ' in Box '+ IntToStr (i));
  1029. FormImage.Canvas.TextOut ((Box.UpperLeftPoint.x+ Box.LowerRightPoint.x) div 2,
  1030. Box.UpperLeftPoint.y+ 2, Digits [Data [i]]);
  1031. end;
  1032. ikAlphabet:
  1033. begin
  1034. Box:= Boxes [j].Box;
  1035. if (31< Data [i]) then
  1036. raise Exception.Create ('Number '+ IntToStr (Data [i])+ ' in Box '+ IntToStr (i));
  1037. FormImage.Canvas.TextOut ((Box.UpperLeftPoint.x+ Box.LowerRightPoint.x) div 2,
  1038. Box.UpperLeftPoint.y+ 2, PersianAlphabet [Data [i]]);
  1039. end;
  1040. end;
  1041. Inc (i);
  1042. end;
  1043. Result:= FormImage;
  1044. }
  1045. end;
  1046. {
  1047. function TFormsBox.DeleteNoise (MyBitmapImage: TMyBitmap;
  1048. NoiseColor: TRGB): TBitmap;
  1049. var
  1050. x, y: Integer;
  1051. begin
  1052. Result:= TBitmap.Create;
  1053. Result.Width:= MyBitmapImage.Width;
  1054. Result.Height:= MyBitmapImage.Height;
  1055. for y:= 0 to MyBitmapImage.Height- 1 do
  1056. for x:= 0 to MyBitmapImage.Width- 1 do
  1057. if ColorsAreTheSame (NoiseColor, MyBitmapImage.Body (x, y)) then
  1058. Result.Canvas.Pixels [x, y]:= clWhite
  1059. else
  1060. Result.Canvas.Pixels [x, y]:= MyBitmapImage.Body (x, y).Color;
  1061. end;
  1062. }
  1063. function TFormsBox.ConvertToHSI (Color: TColor): THSI;
  1064. var
  1065. Teta: Extended;
  1066. r, g, b: Integer;
  1067. begin
  1068. r:= Color and $FF;
  1069. g:= (Color and $FF00) shr 8;
  1070. b:= (Color and $FF0000) shr 16;
  1071. if (r<> g) or (g<> b) then
  1072. begin
  1073. Teta:= ArcCos ( (r- 0.5* (g+ b))/
  1074. Sqrt ((r- g)* (r- g)+ (r- b)* (g- b))
  1075. );
  1076. if r<= g then
  1077. Result.h:= Round (Teta* 180/ Pi)
  1078. else
  1079. Result.h:= 360- Round (Teta* 180/ Pi);
  1080. end
  1081. else
  1082. Result.h:= -1;
  1083. if (r<> 0) or (g<> 0) or (b<> 0) then
  1084. Result.s:= 1- 3/ (r+ g+ b) * Math.Min (Math.Min (r, g), b)
  1085. else
  1086. Result.s:= 0.0;
  1087. Result.i:= (r+ g+ b) div 3;
  1088. end;
  1089. function ColorsAreInSameRange (Color1, Color2: TRGB): Boolean;
  1090. const
  1091. Thr: Integer= 50;
  1092. begin
  1093. Result:= (Abs (Color1.r- Color2.r)< Thr) and
  1094. (Abs (Color1.g- Color2.g)< Thr) and
  1095. (Abs (Color1.b- Color2.b)< Thr);
  1096. end;
  1097. function ColorsAreTheSame (Color1, Color2: TRGB): Boolean;
  1098. const
  1099. Thr: Integer= 50;
  1100. begin
  1101. Result:= Sqrt (Sqr (Color1.r- Color2.r)+
  1102. Sqr (Color1.g- Color2.g)+
  1103. Sqr (Color1.b- Color2.b))< Thr;
  1104. end;
  1105. function TFormsBox.ConvertToRGB (Color: TColor): TRGB;
  1106. begin
  1107. Result.r:= Color and $FF;
  1108. Result.g:= (Color and $FF00) shr 8;
  1109. Result.b:= (Color and $FF0000) shr 16;
  1110. end;
  1111. //{$UNSAFECODE ON$}
  1112. function TFormsBox.FindHelpBar (MyBitmap: TMyBitmap; Box: TBox; HelpBarColor: TRGB; ContinueSearchOverBorders: Integer= 1): TComponentCollection;//unsafe;
  1113. type
  1114. PByte= ^Byte;
  1115. var
  1116. RowPtrs: PointerArray;
  1117. const
  1118. AdjancedPixelY: array [dN..dNW] of Integer= (-1, -1, 0, +1, +1, +1, 0, -1);
  1119. AdjancedPixelX: array [dN..dNW] of Integer= ( 0, +1, +1, +1, 0, -1, -1, -1);
  1120. function FindContour (StartPointColor: TRGB; Px, Py: Integer): TComponent;//unsafe;
  1121. var
  1122. Found: Boolean;
  1123. i: Integer;
  1124. LastDir,
  1125. Dir: TDirection;
  1126. begin
  1127. Result:= TComponent.Create;
  1128. LastDir:= dE;
  1129. while not Result.IsExists (Px, Py) do
  1130. begin
  1131. Result.Add (Px, Py, StartPointColor);
  1132. Found:= False;
  1133. Dir:= TDirection ((Integer (LastDir)+ 5) mod 8);
  1134. for i:= 0 to 7 do
  1135. begin
  1136. if ColorsAreTheSame (MyBitmap.Body (Px+ AdjancedPixelX [Dir], Py+ AdjancedPixely [Dir]), StartPointColor) then
  1137. begin
  1138. Inc (Px, AdjancedPixelX [Dir]);
  1139. Inc (Py, AdjancedPixelY [Dir]);
  1140. Found:= True;
  1141. LastDir:= Dir;
  1142. Break;
  1143. end;
  1144. Dir:= TDirection ((Integer (Dir)+ 1) mod 8);
  1145. end;
  1146. if not Found then
  1147. begin
  1148. Result:= nil;
  1149. Exit;
  1150. end;
  1151. end;
  1152. end;
  1153. function BFS (StartPointColor: TRGB; Px, Py: Integer; var IsExceeded: Boolean): TComponent;//unsafe;
  1154. var
  1155. Dir: TDirection;
  1156. LastPoint: TPoint;
  1157. xOld, yOld,
  1158. xNew, yNew: Integer;
  1159. // ImageWidth, ImageHeight,
  1160. CurIndex: Integer;
  1161. RGBWhite,
  1162. NewPointColor: TRGB;
  1163. // LastPtr,
  1164. RowPtr: PByte;
  1165. begin
  1166. RGBWhite.r:= $FF;RGBWhite.g:= $FF;RGBWhite.b:= $FF;
  1167. IsExceeded:= False;
  1168. Result:= TComponent.Create;
  1169. Result.Add (Px, Py, StartPointColor);
  1170. CurIndex:= 0;
  1171. // ImageWidth:= MyBitmap.Width;
  1172. // ImageHeight:= MyBitmap.Height;
  1173. while Result.Count> CurIndex do
  1174. begin
  1175. LastPoint:= Result.GetPixel (CurIndex).Location;
  1176. xOld:= LastPoint.x; yOld:= LastPoint.y;
  1177. StartPointColor:= Result.CollectionColor;
  1178. if ColorsAreTheSame (StartPointColor, RGBWhite) then
  1179. begin
  1180. Result.Free;
  1181. Exit;
  1182. end;
  1183. for Dir:= dN to dNW do
  1184. begin
  1185. xNew:= xOld; yNew:= yOld;
  1186. Inc (xNew, AdjancedPixelX [Dir]);
  1187. Inc (yNew, AdjancedPixelY [Dir]);
  1188. RowPtr:= RowPtrs [yNew];
  1189. Inc (RowPtr, 3* xNew);
  1190. NewPointColor.b:= RowPtr^;
  1191. Inc (RowPtr);
  1192. NewPointColor.g:= RowPtr^;
  1193. Inc (RowPtr);
  1194. NewPointColor.r:= RowPtr^;
  1195. if ColorsAreTheSame (StartPointColor, NewPointColor) and (not Result.IsExists (xNew, yNew)) then
  1196. begin
  1197. if ContinueSearchOverBorders= 1 then
  1198. begin
  1199. if (2* xNew< 3* Box.UpperLeftPoint.x- Box.LowerRightPoint.x) or
  1200. (3* Box.LowerRightPoint.x- Box.UpperLeftPoint.x< 2* xNew) or
  1201. (3* Box.LowerRightPoint.y- Box.UpperLeftPoint.y< 2* yNew) or
  1202. (2* yNew< 3* Box.UpperLeftPoint.y- Box.LowerRightPoint.y) then
  1203. begin
  1204. IsExceeded:= True;
  1205. Continue;
  1206. end;
  1207. end
  1208. else if ContinueSearchOverBorders= 0 then
  1209. begin
  1210. if (xNew< Box.UpperLeftPoint.x) or
  1211. (Box.LowerRightPoint.x< xNew) or
  1212. (Box.LowerRightPoint.y< yNew) or
  1213. (yNew< Box.UpperLeftPoint.y) then
  1214. Continue;
  1215. end;
  1216. if (xNew< Box.UpperLeftPoint.x) or
  1217. (Box.LowerRightPoint.x< xNew) or
  1218. (Box.LowerRightPoint.y< yNew) or
  1219. (yNew< Box.UpperLeftPoint.y) then
  1220. if not ColorsAreTheSame (NewPointColor, Result.CollectionColor) then
  1221. Continue;
  1222. Result.Add (xNew, yNew, NewPointColor)
  1223. end;
  1224. end;
  1225. Inc (CurIndex);
  1226. end;
  1227. end;
  1228. const
  1229. WidthThr: Integer= 2;//Change it in remove all invalid componentes, too
  1230. HeightThr: Integer= 2;
  1231. xStep: Integer= 1;
  1232. var
  1233. yStep: Integer;
  1234. // Ptr4Cleaning,
  1235. RowPtr: PByte;
  1236. RGBWhite,
  1237. RGBColor: TRGB;
  1238. // IsExceeded: Boolean;
  1239. MinPoint, MaxPoint: TPoint;
  1240. // i: Integer;
  1241. // xCounter,
  1242. // yCounter,
  1243. x, y: Integer;
  1244. ComponentsPixels: TComponent;
  1245. begin
  1246. RowPtrs:= MyBitmap.Pixels;
  1247. Result:= TComponentCollection.Create;
  1248. RGBWhite:= ConvertToRGB ($FFFFFF);
  1249. x:= MyBitmap.Width div 2;
  1250. yStep:= 1;//(Box.FLowerRightPoint.y- Box.FUpperLeftPoint.y) div 2;
  1251. y:= 50;
  1252. ComponentsPixels:= nil;
  1253. while y< MyBitmap.Height- 1 do
  1254. begin
  1255. y:= y+ yStep;
  1256. RowPtr:= RowPtrs [y];
  1257. Inc (RowPtr, 3* x);
  1258. RGBColor.b:= RowPtr^;
  1259. Inc (RowPtr);
  1260. RGBColor.g:= RowPtr^;
  1261. Inc (RowPtr);
  1262. RGBColor.r:= RowPtr^;
  1263. RGBColor.Color:= RGBColor.b* $10000+ RGBColor.g* $100+ RGBColor.r;
  1264. if not ColorsAreTheSame (RGBWhite, RGBColor) then
  1265. begin
  1266. //Should be improved
  1267. ComponentsPixels:= FindContour (RGBColor, x, y);
  1268. if ComponentsPixels= nil then
  1269. Continue;
  1270. if ComponentsPixels.Count< 2* (Box.FLowerRightPoint.x- Box.FLowerLeftPoint.x) then
  1271. begin
  1272. ComponentsPixels.Free;
  1273. Continue;
  1274. end;
  1275. if (ComponentsPixels.GetEffectiveLength< HeightThr) or
  1276. (ComponentsPixels.GetEffectiveWidth< WidthThr) then
  1277. begin
  1278. ComponentsPixels.Free;
  1279. Continue;
  1280. end;
  1281. Result.AddComponent (ComponentsPixels);
  1282. Break;
  1283. end;
  1284. end;
  1285. if ComponentsPixels=nil then
  1286. begin
  1287. ShowMessage ('Can not Find HelpBar!!');
  1288. Exit;
  1289. end;
  1290. MinPoint:= Result.MinPoint;
  1291. MaxPoint:= Result.MaxPoint;
  1292. for y:= MinPoint.y+ 10 to MaxPoint.y- 10 do
  1293. begin
  1294. RowPtr:= RowPtrs [y];
  1295. Inc (RowPtr, 3* MinPoint.x);
  1296. for x:= (MinPoint.x+ MaxPoint.x) div 2- 5 to (MinPoint.x+ MaxPoint.x) div 2+ 5 do
  1297. begin
  1298. RGBColor.b:= RowPtr^;
  1299. Inc (RowPtr);
  1300. RGBColor.g:= RowPtr^;
  1301. Inc (RowPtr);
  1302. RGBColor.r:= RowPtr^;
  1303. Inc (RowPtr);
  1304. ComponentsPixels.Add (x, y, RGBColor);
  1305. end;
  1306. end;
  1307. MinPoint.Free;
  1308. MaxPoint.Free;
  1309. end;
  1310. function TFormsBox.FindComponent (MyBitmap: TMyBitmap; Box: TBox; HelpBarColor: TRGB;
  1311. ContinueSearchOverBorders: Integer): TComponentCollection;//unsafe;
  1312. type
  1313. PByte= ^Byte;
  1314. var
  1315. RowPtrs: PointerArray;
  1316. IgnoredComponentCollection: TComponentCollection;
  1317. function ColorIsWhite (Color: TRGB): Boolean;
  1318. const
  1319. Thr1: Integer= 10;
  1320. Thr2: Integer= 100;
  1321. Thr3: Integer= 150;
  1322. var
  1323. Count: Integer;
  1324. begin
  1325. if (Abs (Color.r- Color.g)< Thr1) and (Abs (Color.r- Color.b)< Thr1) and
  1326. (Abs (Color.g- Color.b)< Thr1) then
  1327. if Thr2< Color.r then
  1328. begin
  1329. Result:= True;
  1330. Exit;
  1331. end;
  1332. Count:= 0;
  1333. if (Thr3< Color.r) then
  1334. Inc (Count);
  1335. if (Thr3< Color.g) then
  1336. Inc (Count);
  1337. if (Thr3< Color.b) then
  1338. Inc (Count);
  1339. Result:= 2<= Count;
  1340. end;
  1341. function ColorIsBlack (Color: TRGB): Boolean;
  1342. const
  1343. Thr1: Integer= 10;
  1344. Thr2: Integer= 50;
  1345. Thr3: Integer= 30;
  1346. var
  1347. Count: Integer;
  1348. begin
  1349. if (Abs (Color.r- Color.g)< Thr1) and (Abs (Color.r- Color.b)< Thr1) and
  1350. (Abs (Color.g- Color.b)< Thr1) then
  1351. if Color.r< Thr2 then
  1352. begin
  1353. Result:= True;
  1354. Exit;
  1355. end;
  1356. Count:= 0;
  1357. if (Color.r< Thr3) then
  1358. Inc (Count);
  1359. if (Color.g< Thr3) then
  1360. Inc (Count);
  1361. if (Color.b< Thr3) then
  1362. Inc (Count);
  1363. Result:= 2<= Count;
  1364. end;
  1365. function BFS (StartPointColor: TRGB; Px, Py: Integer; var IsExceeded: Boolean): TComponent;//unsafe;
  1366. const
  1367. AdjancedPixelY: array [dN..dNW] of Integer= (-1, -1, 0, +1, +1, +1, 0, -1);
  1368. AdjancedPixelX: array [dN..dNW] of Integer= ( 0, +1, +1, +1, 0, -1, -1, -1);
  1369. var
  1370. Dir: TDirection;
  1371. LastPoint: TPoint;
  1372. xOld, yOld,
  1373. xNew, yNew: Integer;
  1374. CurIndex: Integer;
  1375. RGBWhite,
  1376. NewPointColor: TRGB;
  1377. RowPtr: PByte;
  1378. begin
  1379. RGBWhite.r:= $FF;RGBWhite.g:= $FF;RGBWhite.b:= $FF;
  1380. IsExceeded:= False;
  1381. Result:= TComponent.Create;
  1382. Result.Add (Px, Py, StartPointColor);
  1383. CurIndex:= 0;
  1384. while Result.Count> CurIndex do
  1385. begin
  1386. LastPoint:= Result.GetPixel (CurIndex).Location;
  1387. xOld:= LastPoint.x; yOld:= LastPoint.y;
  1388. StartPointColor:= Result.CollectionColor;
  1389. for Dir:= dN to dNW do
  1390. begin
  1391. xNew:= xOld; yNew:= yOld;
  1392. Inc (xNew, AdjancedPixelX [Dir]);
  1393. Inc (yNew, AdjancedPixelY [Dir]);
  1394. RowPtr:= RowPtrs [yNew];
  1395. Inc (RowPtr, 3* xNew);
  1396. NewPointColor.b:= RowPtr^;
  1397. Inc (RowPtr);
  1398. NewPointColor.g:= RowPtr^;
  1399. Inc (RowPtr);
  1400. NewPointColor.r:= RowPtr^;
  1401. if IgnoredComponentCollection.IsExists (xNew, yNew) then
  1402. Continue;
  1403. if (not ColorsAreTheSame (HelpBarColor, NewPointColor) and not ColorsAreTheSame (RGBWhite, NewPointColor) and
  1404. not ColorIsWhite (NewPointColor) and not ColorIsBlack (NewPointColor))
  1405. and (not Result.IsExists (xNew, yNew)) then
  1406. begin
  1407. if ContinueSearchOverBorders= 1 then
  1408. begin
  1409. if (2* xNew< 3* Box.UpperLeftPoint.x- Box.LowerRightPoint.x) or
  1410. (3* Box.LowerRightPoint.x- Box.UpperLeftPoint.x< 2* xNew) or
  1411. (3* Box.LowerRightPoint.y- Box.UpperLeftPoint.y< 2* yNew) or
  1412. (2* yNew< 3* Box.UpperLeftPoint.y- Box.LowerRightPoint.y) then
  1413. begin
  1414. IsExceeded:= True;
  1415. Continue;
  1416. end;
  1417. end
  1418. else if ContinueSearchOverBorders= 0 then
  1419. begin
  1420. if (xNew< Box.UpperLeftPoint.x) or
  1421. (Box.LowerRightPoint.x< xNew) or
  1422. (Box.LowerRightPoint.y< yNew) or
  1423. (yNew< Box.UpperLeftPoint.y) then
  1424. Continue;
  1425. end;
  1426. if (xNew< Box.UpperLeftPoint.x) or
  1427. (Box.LowerRightPoint.x< xNew) or
  1428. (Box.LowerRightPoint.y< yNew) or
  1429. (yNew< Box.UpperLeftPoint.y) then
  1430. if not ColorsAreTheSame (NewPointColor, Result.CollectionColor) then
  1431. Continue;
  1432. Result.Add (xNew, yNew, NewPointColor)
  1433. end;
  1434. end;
  1435. Inc (CurIndex);
  1436. // Result.HashedData.SaveToFile (IntToStr (CurIndex)+ '.txt');///??!!
  1437. end;
  1438. end;
  1439. {
  1440. const
  1441. WidthThr: Integer= 2;//Change it in remove all invalid componentes, too
  1442. HeightThr: Integer= 2;
  1443. yStep: Integer= 1;
  1444. xStep: Integer= 1;
  1445. PixelsInSameLineThr= 0.80;
  1446. var
  1447. Ptr4Cleaning,
  1448. RowPtr: PByte;
  1449. RGBWhite,
  1450. RGBBlack,
  1451. RGBColor: TRGB;
  1452. IsExceeded: Boolean;
  1453. MinPoint, MaxPoint: TPoint;
  1454. // TempImage: TFMLImage;
  1455. i: Integer;
  1456. // xCounter,
  1457. yCounter,
  1458. x, y: Integer;
  1459. PixelCollection,
  1460. ComponentsPixels: TComponent;
  1461. }
  1462. begin
  1463. {
  1464. RGBBlack.r:= $0; RGBBlack.g:= $0; RGBBlack.b:= $0;
  1465. RowPtrs:= MyBitmap.Pixels;
  1466. Result:= TComponentCollection.Create;
  1467. RGBWhite:= ConvertToRGB ($FFFFFF);
  1468. IgnoredComponentCollection:= TComponentCollection.Create;
  1469. for yCounter:= 0 to (Box.LowerRightPoint.y- Box.UpperRightPoint.y+ yStep- 1) div yStep do
  1470. begin
  1471. y:= yCounter* yStep+ Box.UpperLeftPoint.y;
  1472. RowPtr:= RowPtrs [y];
  1473. // Inc (RowPtr, 3* Box.UpperLeftPoint.x);
  1474. Inc (RowPtr, 3* (Box.UpperLeftPoint.x));
  1475. x:= Box.UpperLeftPoint.x- xStep;
  1476. while x< Box.LowerRightPoint.x do
  1477. begin
  1478. x:= x+ xStep;
  1479. Inc (RowPtr, 3* (xStep- 1));
  1480. RGBColor.b:= RowPtr^;
  1481. Inc (RowPtr);
  1482. RGBColor.g:= RowPtr^;
  1483. Inc (RowPtr);
  1484. RGBColor.r:= RowPtr^;
  1485. Inc (RowPtr);
  1486. RGBColor.Color:= RGBColor.b* $10000+ RGBColor.g* $100+ RGBColor.r;
  1487. if (not ColorsAreTheSame (RGBWhite, RGBColor) and not ColorsAreTheSame (HelpBarColor, RGBColor)) then
  1488. begin
  1489. if IgnoredComponentCollection.IsExists (x, y) then
  1490. Continue;
  1491. ComponentsPixels:= BFS (RGBColor, x, y, IsExceeded);
  1492. if (not IsExceeded) or (ContinueSearchOverBorders= 2) then
  1493. begin
  1494. for i:= 0 to ComponentsPixels.Count- 1 do
  1495. begin
  1496. Ptr4Cleaning:= RowPtrs [ComponentsPixels.GetPixel (i).Location.y];
  1497. Inc (Ptr4Cleaning, 3* ComponentsPixels.GetPixel (i).Location.x);
  1498. Ptr4Cleaning^:= $FF;
  1499. Inc (Ptr4Cleaning);
  1500. Ptr4Cleaning^:= $FF;
  1501. Inc (Ptr4Cleaning);
  1502. Ptr4Cleaning^:= $FF;
  1503. end;
  1504. end
  1505. else
  1506. begin
  1507. IgnoredComponentCollection.AddComponent (ComponentsPixels);
  1508. Continue;
  1509. end;
  1510. if ColorsAreTheSame (ComponentsPixels.CollectionColor, HelpBarColor) or
  1511. ColorsAreTheSame (ComponentsPixels.CollectionColor, RGBWhite) then
  1512. begin
  1513. ComponentsPixels.Free;
  1514. Continue;
  1515. end;
  1516. MinPoint:= ComponentsPixels.GetMinimum;
  1517. MaxPoint:= ComponentsPixels.GetMaximum;
  1518. if (MaxPoint.x- MinPoint.x< WidthThr) or (MaxPoint.y- MinPoint.y< HeightThr) then
  1519. begin
  1520. MinPoint.Free;
  1521. MaxPoint.Free;
  1522. ComponentsPixels.Free;
  1523. Continue;
  1524. end;
  1525. MinPoint.Free;
  1526. MaxPoint.Free;
  1527. if (ComponentsPixels.GetEffectiveLength< HeightThr) or
  1528. (ComponentsPixels.GetEffectiveWidth< WidthThr) or
  1529. (10* ComponentsPixels.Count< ComponentsPixels.GetArea)then
  1530. begin
  1531. ComponentsPixels.Free;
  1532. Continue;
  1533. end;
  1534. PixelCollection:= ComponentsPixels.ExtractContour;
  1535. if (PixelsInSameLineThr< PixelCollection.CountInSameLine) and
  1536. ColorsAreTheSame (PixelCollection.CollectionColor, RGBBlack) and
  1537. ((ComponentsPixels.GetEffectiveLength< 4) or
  1538. (ComponentsPixels.GetEffectiveWidth< 4)) then
  1539. begin
  1540. ComponentsPixels.Free;
  1541. PixelCollection.Free;
  1542. Continue;
  1543. end;
  1544. PixelCollection.Free;
  1545. Result.A

Large files files are truncated, but you can click here to view the full file