mirror of
https://github.com/moparisthebest/Simba
synced 2024-11-28 20:12:16 -05:00
First OCR Function - GetTextAtEx. Currently only for UpText - still much of a stub.
git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@166 3f818213-9676-44b0-a9b4-5e4c4e03d09d
This commit is contained in:
parent
f304e759fa
commit
8a101c65f5
@ -30,15 +30,15 @@
|
|||||||
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<Units Count="9">
|
<Units Count="15">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="project1.lpr"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<UnitName Value="project1"/>
|
<UnitName Value="project1"/>
|
||||||
<CursorPos X="20" Y="10"/>
|
<CursorPos X="3" Y="61"/>
|
||||||
<TopLine Value="1"/>
|
<TopLine Value="54"/>
|
||||||
<EditorIndex Value="0"/>
|
<EditorIndex Value="0"/>
|
||||||
<UsageCount Value="28"/>
|
<UsageCount Value="34"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit0>
|
</Unit0>
|
||||||
<Unit1>
|
<Unit1>
|
||||||
@ -51,9 +51,11 @@
|
|||||||
<Unit2>
|
<Unit2>
|
||||||
<Filename Value="../../Units/MMLCore/client.pas"/>
|
<Filename Value="../../Units/MMLCore/client.pas"/>
|
||||||
<UnitName Value="Client"/>
|
<UnitName Value="Client"/>
|
||||||
<CursorPos X="1" Y="1"/>
|
<CursorPos X="26" Y="46"/>
|
||||||
<TopLine Value="1"/>
|
<TopLine Value="51"/>
|
||||||
<UsageCount Value="9"/>
|
<EditorIndex Value="1"/>
|
||||||
|
<UsageCount Value="12"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
</Unit2>
|
</Unit2>
|
||||||
<Unit3>
|
<Unit3>
|
||||||
<Filename Value="../../Units/MMLCore/windowutil.pas"/>
|
<Filename Value="../../Units/MMLCore/windowutil.pas"/>
|
||||||
@ -65,9 +67,11 @@
|
|||||||
<Unit4>
|
<Unit4>
|
||||||
<Filename Value="../../Units/MMLCore/window.pas"/>
|
<Filename Value="../../Units/MMLCore/window.pas"/>
|
||||||
<UnitName Value="Window"/>
|
<UnitName Value="Window"/>
|
||||||
<CursorPos X="40" Y="125"/>
|
<CursorPos X="149" Y="277"/>
|
||||||
<TopLine Value="98"/>
|
<TopLine Value="262"/>
|
||||||
<UsageCount Value="9"/>
|
<EditorIndex Value="3"/>
|
||||||
|
<UsageCount Value="11"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
</Unit4>
|
</Unit4>
|
||||||
<Unit5>
|
<Unit5>
|
||||||
<Filename Value="../../Units/MMLCore/colour_conv.pas"/>
|
<Filename Value="../../Units/MMLCore/colour_conv.pas"/>
|
||||||
@ -79,146 +83,194 @@
|
|||||||
<Unit6>
|
<Unit6>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
||||||
<UnitName Value="finder"/>
|
<UnitName Value="finder"/>
|
||||||
<CursorPos X="44" Y="632"/>
|
<CursorPos X="37" Y="11"/>
|
||||||
<TopLine Value="621"/>
|
<TopLine Value="1"/>
|
||||||
<EditorIndex Value="1"/>
|
<EditorIndex Value="5"/>
|
||||||
<UsageCount Value="14"/>
|
<UsageCount Value="16"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit6>
|
</Unit6>
|
||||||
<Unit7>
|
<Unit7>
|
||||||
<Filename Value="../../Units/MMLCore/input.pas"/>
|
<Filename Value="../../Units/MMLCore/input.pas"/>
|
||||||
<UnitName Value="Input"/>
|
<UnitName Value="Input"/>
|
||||||
<CursorPos X="20" Y="226"/>
|
<CursorPos X="20" Y="35"/>
|
||||||
<TopLine Value="206"/>
|
<TopLine Value="22"/>
|
||||||
<UsageCount Value="10"/>
|
<EditorIndex Value="4"/>
|
||||||
|
<UsageCount Value="12"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
</Unit7>
|
</Unit7>
|
||||||
<Unit8>
|
<Unit8>
|
||||||
<Filename Value="../../Units/MMLCore/mufasatypes.pas"/>
|
<Filename Value="../../Units/MMLCore/mufasatypes.pas"/>
|
||||||
<UnitName Value="MufasaTypes"/>
|
<UnitName Value="MufasaTypes"/>
|
||||||
<CursorPos X="40" Y="52"/>
|
<CursorPos X="50" Y="55"/>
|
||||||
<TopLine Value="41"/>
|
<TopLine Value="31"/>
|
||||||
<EditorIndex Value="2"/>
|
<EditorIndex Value="6"/>
|
||||||
<UsageCount Value="11"/>
|
<UsageCount Value="13"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit8>
|
</Unit8>
|
||||||
|
<Unit9>
|
||||||
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
|
<UnitName Value="ocr"/>
|
||||||
|
<CursorPos X="41" Y="633"/>
|
||||||
|
<TopLine Value="98"/>
|
||||||
|
<EditorIndex Value="2"/>
|
||||||
|
<UsageCount Value="12"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit9>
|
||||||
|
<Unit10>
|
||||||
|
<Filename Value="../../../../Documents/fpc/rtl/objpas/sysutils/diskh.inc"/>
|
||||||
|
<CursorPos X="10" Y="18"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
</Unit10>
|
||||||
|
<Unit11>
|
||||||
|
<Filename Value="../../Units/MMLCore/files.pas"/>
|
||||||
|
<UnitName Value="files"/>
|
||||||
|
<CursorPos X="5" Y="42"/>
|
||||||
|
<TopLine Value="27"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
</Unit11>
|
||||||
|
<Unit12>
|
||||||
|
<Filename Value="../../../../Documents/lazarus/lcl/graphics.pp"/>
|
||||||
|
<UnitName Value="Graphics"/>
|
||||||
|
<CursorPos X="3" Y="1426"/>
|
||||||
|
<TopLine Value="1411"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
</Unit12>
|
||||||
|
<Unit13>
|
||||||
|
<Filename Value="../../Units/MMLCore/bitmaps.pas"/>
|
||||||
|
<UnitName Value="bitmaps"/>
|
||||||
|
<CursorPos X="15" Y="62"/>
|
||||||
|
<TopLine Value="47"/>
|
||||||
|
<UsageCount Value="11"/>
|
||||||
|
</Unit13>
|
||||||
|
<Unit14>
|
||||||
|
<Filename Value="../../../../Documents/fpc/rtl/inc/objpash.inc"/>
|
||||||
|
<CursorPos X="22" Y="177"/>
|
||||||
|
<TopLine Value="162"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
</Unit14>
|
||||||
</Units>
|
</Units>
|
||||||
<JumpHistory Count="29" HistoryIndex="28">
|
<JumpHistory Count="30" HistoryIndex="29">
|
||||||
<Position1>
|
<Position1>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="64" Column="178" TopLine="52"/>
|
<Caret Line="648" Column="62" TopLine="631"/>
|
||||||
</Position1>
|
</Position1>
|
||||||
<Position2>
|
<Position2>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="769" Column="37" TopLine="745"/>
|
<Caret Line="654" Column="64" TopLine="631"/>
|
||||||
</Position2>
|
</Position2>
|
||||||
<Position3>
|
<Position3>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<Caret Line="763" Column="27" TopLine="746"/>
|
<Caret Line="83" Column="3" TopLine="62"/>
|
||||||
</Position3>
|
</Position3>
|
||||||
<Position4>
|
<Position4>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/window.pas"/>
|
||||||
<Caret Line="766" Column="21" TopLine="751"/>
|
<Caret Line="243" Column="44" TopLine="5"/>
|
||||||
</Position4>
|
</Position4>
|
||||||
<Position5>
|
<Position5>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/window.pas"/>
|
||||||
<Caret Line="792" Column="11" TopLine="777"/>
|
<Caret Line="261" Column="20" TopLine="246"/>
|
||||||
</Position5>
|
</Position5>
|
||||||
<Position6>
|
<Position6>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/window.pas"/>
|
||||||
<Caret Line="796" Column="8" TopLine="790"/>
|
<Caret Line="263" Column="19" TopLine="246"/>
|
||||||
</Position6>
|
</Position6>
|
||||||
<Position7>
|
<Position7>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/window.pas"/>
|
||||||
<Caret Line="865" Column="64" TopLine="786"/>
|
<Caret Line="267" Column="29" TopLine="246"/>
|
||||||
</Position7>
|
</Position7>
|
||||||
<Position8>
|
<Position8>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<Caret Line="66" Column="18" TopLine="63"/>
|
<Caret Line="88" Column="27" TopLine="73"/>
|
||||||
</Position8>
|
</Position8>
|
||||||
<Position9>
|
<Position9>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="797" Column="19" TopLine="797"/>
|
<Caret Line="648" Column="16" TopLine="632"/>
|
||||||
</Position9>
|
</Position9>
|
||||||
<Position10>
|
<Position10>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="846" Column="17" TopLine="822"/>
|
<Caret Line="650" Column="73" TopLine="632"/>
|
||||||
</Position10>
|
</Position10>
|
||||||
<Position11>
|
<Position11>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
||||||
<Caret Line="820" Column="3" TopLine="807"/>
|
<Caret Line="632" Column="44" TopLine="621"/>
|
||||||
</Position11>
|
</Position11>
|
||||||
<Position12>
|
<Position12>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="824" Column="21" TopLine="800"/>
|
<Caret Line="650" Column="16" TopLine="630"/>
|
||||||
</Position12>
|
</Position12>
|
||||||
<Position13>
|
<Position13>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="799" Column="38" TopLine="796"/>
|
<Caret Line="659" Column="64" TopLine="637"/>
|
||||||
</Position13>
|
</Position13>
|
||||||
<Position14>
|
<Position14>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="66" Column="46" TopLine="43"/>
|
<Caret Line="635" Column="7" TopLine="628"/>
|
||||||
</Position14>
|
</Position14>
|
||||||
<Position15>
|
<Position15>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="869" Column="48" TopLine="857"/>
|
<Caret Line="641" Column="45" TopLine="626"/>
|
||||||
</Position15>
|
</Position15>
|
||||||
<Position16>
|
<Position16>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="895" Column="22" TopLine="874"/>
|
<Caret Line="649" Column="5" TopLine="626"/>
|
||||||
</Position16>
|
</Position16>
|
||||||
<Position17>
|
<Position17>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="904" Column="21" TopLine="892"/>
|
<Caret Line="508" Column="21" TopLine="493"/>
|
||||||
</Position17>
|
</Position17>
|
||||||
<Position18>
|
<Position18>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="879" Column="12" TopLine="876"/>
|
<Caret Line="649" Column="19" TopLine="629"/>
|
||||||
</Position18>
|
</Position18>
|
||||||
<Position19>
|
<Position19>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="911" Column="33" TopLine="900"/>
|
<Caret Line="645" Column="49" TopLine="625"/>
|
||||||
</Position19>
|
</Position19>
|
||||||
<Position20>
|
<Position20>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<Caret Line="956" Column="62" TopLine="930"/>
|
<Caret Line="87" Column="27" TopLine="69"/>
|
||||||
</Position20>
|
</Position20>
|
||||||
<Position21>
|
<Position21>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="67" Column="61" TopLine="55"/>
|
<Caret Line="508" Column="17" TopLine="503"/>
|
||||||
</Position21>
|
</Position21>
|
||||||
<Position22>
|
<Position22>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="916" Column="35" TopLine="906"/>
|
<Caret Line="471" Column="55" TopLine="456"/>
|
||||||
</Position22>
|
</Position22>
|
||||||
<Position23>
|
<Position23>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="991" Column="53" TopLine="979"/>
|
<Caret Line="649" Column="16" TopLine="626"/>
|
||||||
</Position23>
|
</Position23>
|
||||||
<Position24>
|
<Position24>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="1007" Column="1" TopLine="994"/>
|
<Caret Line="649" Column="19" TopLine="626"/>
|
||||||
</Position24>
|
</Position24>
|
||||||
<Position25>
|
<Position25>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="1035" Column="35" TopLine="1022"/>
|
<Caret Line="646" Column="58" TopLine="625"/>
|
||||||
</Position25>
|
</Position25>
|
||||||
<Position26>
|
<Position26>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<Caret Line="1080" Column="24" TopLine="1057"/>
|
<Caret Line="87" Column="25" TopLine="69"/>
|
||||||
</Position26>
|
</Position26>
|
||||||
<Position27>
|
<Position27>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="64" Column="35" TopLine="46"/>
|
<Caret Line="631" Column="65" TopLine="614"/>
|
||||||
</Position27>
|
</Position27>
|
||||||
<Position28>
|
<Position28>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
<Caret Line="688" Column="19" TopLine="676"/>
|
<Caret Line="633" Column="29" TopLine="618"/>
|
||||||
</Position28>
|
</Position28>
|
||||||
<Position29>
|
<Position29>
|
||||||
<Filename Value="../../Units/MMLCore/finder.pas"/>
|
<Filename Value="project1.lpr"/>
|
||||||
<Caret Line="461" Column="20" TopLine="451"/>
|
<Caret Line="80" Column="29" TopLine="65"/>
|
||||||
</Position29>
|
</Position29>
|
||||||
|
<Position30>
|
||||||
|
<Filename Value="project1.lpr"/>
|
||||||
|
<Caret Line="43" Column="27" TopLine="24"/>
|
||||||
|
</Position30>
|
||||||
</JumpHistory>
|
</JumpHistory>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
@ -227,12 +279,23 @@
|
|||||||
<IncludeFiles Value="$(ProjOutDir)/"/>
|
<IncludeFiles Value="$(ProjOutDir)/"/>
|
||||||
<OtherUnitFiles Value="$(ProjPath)/../../Units/MMLCore/;$(ProjPath)/../../Units/Misc/;$(ProjPath)/../../Units/MMLAddon/;$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)/;$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS)/"/>
|
<OtherUnitFiles Value="$(ProjPath)/../../Units/MMLCore/;$(ProjPath)/../../Units/Misc/;$(ProjPath)/../../Units/MMLAddon/;$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)/;$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS)/"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Optimizations>
|
||||||
|
<OptimizationLevel Value="3"/>
|
||||||
|
</Optimizations>
|
||||||
|
</CodeGeneration>
|
||||||
<Other>
|
<Other>
|
||||||
<CustomOptions Value="-dM_MEMORY_DEBUG"/>
|
<CustomOptions Value="-dM_MEMORY_DEBUG"/>
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
</Other>
|
</Other>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
<Debugging>
|
<Debugging>
|
||||||
|
<BreakPoints Count="1">
|
||||||
|
<Item1>
|
||||||
|
<Source Value="../../Units/MMLCore/ocr.pas"/>
|
||||||
|
<Line Value="510"/>
|
||||||
|
</Item1>
|
||||||
|
</BreakPoints>
|
||||||
<Exceptions Count="3">
|
<Exceptions Count="3">
|
||||||
<Item1>
|
<Item1>
|
||||||
<Name Value="EAbort"/>
|
<Name Value="EAbort"/>
|
||||||
|
@ -9,7 +9,8 @@ uses
|
|||||||
Classes, SysUtils, CustApp,
|
Classes, SysUtils, CustApp,
|
||||||
Forms,Interfaces,
|
Forms,Interfaces,
|
||||||
LCLIntf,
|
LCLIntf,
|
||||||
Client
|
Client,
|
||||||
|
bitmaps
|
||||||
|
|
||||||
|
|
||||||
{ you can add units after this };
|
{ you can add units after this };
|
||||||
@ -35,7 +36,8 @@ var
|
|||||||
ErrorMsg: String;
|
ErrorMsg: String;
|
||||||
Time: DWord;
|
Time: DWord;
|
||||||
C: TClient;
|
C: TClient;
|
||||||
I, W, H, X, Y: Integer;
|
I{, W, H, X, Y}: Integer;
|
||||||
|
bmp: TMufasaBitmap;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// quick check parameters
|
// quick check parameters
|
||||||
@ -55,8 +57,10 @@ begin
|
|||||||
|
|
||||||
{ add your program here }
|
{ add your program here }
|
||||||
C := TClient.Create;
|
C := TClient.Create;
|
||||||
|
{$WARNING Change This Path!}
|
||||||
|
C.MOCR.InitTOCR('/home/merlijn/Programs/mufasa/Fonts/');
|
||||||
|
|
||||||
C.MWindow.GetDimensions(W, H);
|
{C.MWindow.GetDimensions(W, H);
|
||||||
Time := GetTickCount;
|
Time := GetTickCount;
|
||||||
for i := 0 to 100 do
|
for i := 0 to 100 do
|
||||||
C.MFinder.FindColor(X, Y, 0, 0, 0, W - 1, H - 1);
|
C.MFinder.FindColor(X, Y, 0, 0, 0, W - 1, H - 1);
|
||||||
@ -69,11 +73,27 @@ begin
|
|||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
writeln('not found!');
|
writeln('not found!');
|
||||||
end;
|
end; }
|
||||||
|
|
||||||
|
|
||||||
|
bmp := TMufasaBitmap.Create;
|
||||||
|
|
||||||
|
{$WARNING Change This Path!}
|
||||||
|
bmp.LoadFromFile('/home/merlijn/Programs/mufasa/UpText/text5.bmp');
|
||||||
|
|
||||||
|
writeln(inttostr(bmp.Width) + ', ' + inttostr(bmp.height));
|
||||||
|
|
||||||
|
C.MWindow.SetTarget(bmp);
|
||||||
|
|
||||||
|
Time := GetTickCount;
|
||||||
|
for i := 0 to 100 do
|
||||||
|
C.MOCR.GetUpTextAt(0,0);
|
||||||
|
writeln('Time: ' + FloatToStr(((GetTickCount - Time) / (i + 1))));
|
||||||
|
writeln(C.MOCR.GetUpTextAt(0,0));
|
||||||
|
|
||||||
C.Free;
|
C.Free;
|
||||||
|
bmp.OnDestroy:=nil;
|
||||||
|
bmp.Free;
|
||||||
|
|
||||||
|
|
||||||
// stop program loop
|
// stop program loop
|
||||||
|
1014
Units/Linux/xinput.pas
Normal file
1014
Units/Linux/xinput.pas
Normal file
File diff suppressed because it is too large
Load Diff
131
Units/Linux/xtest.pas
Normal file
131
Units/Linux/xtest.pas
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
unit XTest;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
{$linklib Xtst}
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, x, xutil, xlib, ctypes, XKB, xinput;
|
||||||
|
|
||||||
|
{ type
|
||||||
|
PXDevice = Pointer; // ^XDevice ? }
|
||||||
|
|
||||||
|
const
|
||||||
|
X_XTestGetVersion = 0;
|
||||||
|
X_XTestCompareCursor = 1;
|
||||||
|
X_XTestFakeInput = 2;
|
||||||
|
X_XTestGrabControl = 3;
|
||||||
|
XTestNumberEvents = 0;
|
||||||
|
XTestNumberErrors = 0;
|
||||||
|
XTestMajorVersion = 2;
|
||||||
|
XTestMinorVersion = 2;
|
||||||
|
XTestExtensionName = 'XTEST';
|
||||||
|
|
||||||
|
function XTestQueryExtension(dpy:PDisplay; event_basep, error_basep, majorp, minorp:pcint):CBool; cdecl; external;
|
||||||
|
function XTestCompareCursorWithWindow(dpy:PDisplay; window:TWindow; cursor: TCursor):CBool; cdecl; external;
|
||||||
|
function XTestCompareCurrentCursorWithWindow(dpy:pDisplay; window:TWindow):CBool; cdecl; external;
|
||||||
|
function XTestFakeKeyEvent(dpy:PDisplay; keycode: cuint; is_press: CBool; delay: cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeButtonEvent(dpy:PDisplay; button: cuint; is_press: CBool; delay: cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeMotionEvent(dpy:PDisplay; screen, x,y: cint; delay :cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeRelativeMotionEvent(dpy:PDisplay; x,y,delay: cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeDeviceKeyEvent(dpy:PDisplay; dev:pXDevice; keycode:cuint; is_press:cbool;
|
||||||
|
axes:pcint; n_axes:cint; delay:cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeDeviceButtonEvent(dpy:PDisplay; dev:pXDevice; button:cuint; is_press:cbool; axes:pcint;
|
||||||
|
n_axes:cint; delay:cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeProximityEvent(dpy:PDisplay; dev:pXDevice; in_prox:cbool; axes:pcint; n_axes:cint;
|
||||||
|
delay:cuint):cint;cdecl; external;
|
||||||
|
function XTestFakeDeviceMotionEvent(dpy:PDisplay; dev:pXDevice;
|
||||||
|
is_relative:cbool; first_axis:cint; axes:pcint; n_axes:cint; delay:cuint):cint;cdecl; external;
|
||||||
|
function XTestGrabControl(dpy:PDisplay; impervious:cbool):cint;cdecl; external;
|
||||||
|
|
||||||
|
procedure XTestSetGContextOfGC(gc: TGC; gid:TGContext); cdecl; external;
|
||||||
|
procedure XTestSetVisualIDOfVisual(visual:PVisual; visualid: TVisualID); cdecl; external;
|
||||||
|
function XTestDiscard(dpy:pDisplay):TStatus; cdecl; external;
|
||||||
|
|
||||||
|
procedure mouse_move(x,y: integer);
|
||||||
|
procedure mouse_click(left:boolean);
|
||||||
|
procedure keytest;
|
||||||
|
procedure keystest(s:string);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function thing_to_keycode(D: PDisplay; thing: string): TKeyCode;
|
||||||
|
var
|
||||||
|
kc: TKeyCode;
|
||||||
|
ks: TKeySym;
|
||||||
|
begin
|
||||||
|
ks := XStringToKeysym(@thing[1]);
|
||||||
|
if(ks = NoSymbol) then
|
||||||
|
begin
|
||||||
|
writeln('Can''t resolve keysym for ' + thing);
|
||||||
|
result := thing_to_keycode(D, 'space');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
kc := XKeysymToKeycode(D, ks);
|
||||||
|
result := kc;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure mouse_move(x,y: integer);
|
||||||
|
var
|
||||||
|
d: PDisplay;
|
||||||
|
begin
|
||||||
|
d := XOpenDisplay(nil);
|
||||||
|
XTestFakeMotionEvent(d, -1, x, y, CurrentTime);
|
||||||
|
XCloseDisplay(d);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure mouse_click(left:boolean);
|
||||||
|
var
|
||||||
|
d: PDisplay;
|
||||||
|
begin
|
||||||
|
d := XOpenDisplay(nil);
|
||||||
|
if left then
|
||||||
|
begin
|
||||||
|
XTestFakeButtonEvent(d, Button1, True, CurrentTime);
|
||||||
|
XTestFakeButtonEvent(d, Button1, False, CurrentTime);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
XTestFakeButtonEvent(d, Button3, True, CurrentTime);
|
||||||
|
XTestFakeButtonEvent(d, Button3, False, CurrentTime);
|
||||||
|
end;
|
||||||
|
XCloseDisplay(d);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure send_key(D: PDisplay; c: char);
|
||||||
|
begin
|
||||||
|
XTestFakeKeyEvent(d, thing_to_keycode(d, c), True, CurrentTime);
|
||||||
|
XTestFakeKeyEvent(d, thing_to_keycode(d, c), False, CurrentTime);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure send_keys(d:pdisplay; s:string);
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
for i := 1 to length(s) do
|
||||||
|
begin
|
||||||
|
send_key(d, s[i]);
|
||||||
|
XFlush(d);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure keytest;
|
||||||
|
var
|
||||||
|
d:pdisplay;
|
||||||
|
begin
|
||||||
|
d := XOpenDisplay(nil);
|
||||||
|
send_key(d, 'a');
|
||||||
|
XCloseDisplay(d);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure keystest(s:string);
|
||||||
|
var
|
||||||
|
d:pdisplay;
|
||||||
|
begin
|
||||||
|
d := XOpenDisplay(nil);
|
||||||
|
send_keys(d, s);
|
||||||
|
XCloseDisplay(d);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -46,3 +46,8 @@ function Unfreeze: boolean;
|
|||||||
begin
|
begin
|
||||||
result := CurrThread.Client.MWindow.Unfreeze;
|
result := CurrThread.Client.MWindow.Unfreeze;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure SetTargetArray(P: Integer; Size: TPoint);
|
||||||
|
begin
|
||||||
|
CurrThread.Client.MWindow.SetTarget(PRGB32(P), Size);
|
||||||
|
end;
|
||||||
|
@ -67,6 +67,7 @@ Sender.AddFunction(@Unfreeze, 'function unfreeze: boolean;');
|
|||||||
Sender.AddFunction(@GetClientDimensions, 'procedure GetClientDimensions(var w, h:integer);');
|
Sender.AddFunction(@GetClientDimensions, 'procedure GetClientDimensions(var w, h:integer);');
|
||||||
Sender.AddFunction(@SetTargetBitmap,'procedure SetTargetBitmap(Bitmap : integer);');
|
Sender.AddFunction(@SetTargetBitmap,'procedure SetTargetBitmap(Bitmap : integer);');
|
||||||
Sender.AddFunction(@SetDesktopAsClient,'procedure SetDesktopAsClient');
|
Sender.AddFunction(@SetDesktopAsClient,'procedure SetDesktopAsClient');
|
||||||
|
Sender.AddFunction(@SetTargetArray, 'procedure SetTargetArray(P: Integer; Size: TPoint);');
|
||||||
|
|
||||||
|
|
||||||
{other}
|
{other}
|
||||||
|
@ -188,6 +188,7 @@ end;
|
|||||||
{$I PSInc/Wrappers/other.inc}
|
{$I PSInc/Wrappers/other.inc}
|
||||||
{$I PSInc/Wrappers/bitmap.inc}
|
{$I PSInc/Wrappers/bitmap.inc}
|
||||||
{$I PSInc/Wrappers/window.inc}
|
{$I PSInc/Wrappers/window.inc}
|
||||||
|
|
||||||
{$I PSInc/Wrappers/colour.inc}
|
{$I PSInc/Wrappers/colour.inc}
|
||||||
{$I PSInc/Wrappers/math.inc}
|
{$I PSInc/Wrappers/math.inc}
|
||||||
{$I PSInc/Wrappers/mouse.inc}
|
{$I PSInc/Wrappers/mouse.inc}
|
||||||
|
@ -28,7 +28,7 @@ unit files;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils;
|
Classes, SysUtils, MufasaTypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
TMufasaFile = record
|
TMufasaFile = record
|
||||||
@ -62,10 +62,31 @@ type
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// We don't need one per object. :-)
|
||||||
|
function GetFiles(Path, Ext: string): TStringArray;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
{$IFDEF MSWINDOWS}Windows,{$ENDIF} IniFiles;
|
{$IFDEF MSWINDOWS}Windows,{$ENDIF} IniFiles;
|
||||||
|
|
||||||
|
|
||||||
|
function GetFiles(Path, Ext: string): TstringArray;
|
||||||
|
var
|
||||||
|
SearchRec : TSearchRec;
|
||||||
|
c : integer;
|
||||||
|
begin
|
||||||
|
c := 0;
|
||||||
|
if FindFirst(Path + '*.' + ext, faAnyFile, SearchRec) = 0 then
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
inc(c);
|
||||||
|
SetLength(Result,c);
|
||||||
|
Result[c-1] := SearchRec.Name;
|
||||||
|
until FindNext(SearchRec) <> 0;
|
||||||
|
SysUtils.FindClose(SearchRec);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TMFiles.Create;
|
constructor TMFiles.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
@ -32,7 +32,7 @@ uses
|
|||||||
mufasatypes, // for common mufasa types
|
mufasatypes, // for common mufasa types
|
||||||
windowutil // for mufasa window utils
|
windowutil // for mufasa window utils
|
||||||
{$IFDEF LINUX}
|
{$IFDEF LINUX}
|
||||||
,x, xlib // for X* stuff
|
,ctypes,x, xlib{,xtest,keysym} // for X* stuff
|
||||||
// do non silent keys with XTest.
|
// do non silent keys with XTest.
|
||||||
{$ENDIF};
|
{$ENDIF};
|
||||||
type
|
type
|
||||||
@ -45,6 +45,9 @@ type
|
|||||||
procedure MouseButtonAction(x,y : integer; mClick: TClickType; mPress: TMousePress);
|
procedure MouseButtonAction(x,y : integer; mClick: TClickType; mPress: TMousePress);
|
||||||
procedure ClickMouse(X, Y: Integer; mClick: TClickType);
|
procedure ClickMouse(X, Y: Integer; mClick: TClickType);
|
||||||
|
|
||||||
|
procedure KeyUp(key: Integer);
|
||||||
|
procedure KeyDown(key: Integer);
|
||||||
|
|
||||||
{
|
{
|
||||||
Possibly change to GetMouseButtonStates? Then people can get the
|
Possibly change to GetMouseButtonStates? Then people can get the
|
||||||
states bitwise. Like X and WinAPI.
|
states bitwise. Like X and WinAPI.
|
||||||
@ -121,6 +124,18 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMInput.KeyUp(key: Integer);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMInput.KeyDown(key: Integer);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMInput.GetMousePos(var X, Y: Integer);
|
procedure TMInput.GetMousePos(var X, Y: Integer);
|
||||||
{$IFDEF LINUX}
|
{$IFDEF LINUX}
|
||||||
var
|
var
|
||||||
@ -223,7 +238,7 @@ begin
|
|||||||
mouse_Right: Event.xbutton.button:= Button3;
|
mouse_Right: Event.xbutton.button:= Button3;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
event.xbutton.send_event := TBool(1);
|
event.xbutton.send_event := TBool(1); // true if this came from a "send event"
|
||||||
event.xbutton.same_screen:= TBool(1);
|
event.xbutton.same_screen:= TBool(1);
|
||||||
event.xbutton.subwindow:= 0; // this can't be right.
|
event.xbutton.subwindow:= 0; // this can't be right.
|
||||||
event.xbutton.root := TClient(Client).MWindow.DesktopWindow;
|
event.xbutton.root := TClient(Client).MWindow.DesktopWindow;
|
||||||
|
@ -48,6 +48,8 @@ type
|
|||||||
TTargetWindowMode = (w_BMP, w_Window, w_HDC, w_ArrayPtr, w_XWindow);
|
TTargetWindowMode = (w_BMP, w_Window, w_HDC, w_ArrayPtr, w_XWindow);
|
||||||
TClickType = (mouse_Left, mouse_Right, mouse_Middle);
|
TClickType = (mouse_Left, mouse_Right, mouse_Middle);
|
||||||
TMousePress = (mouse_Down, mouse_Up);
|
TMousePress = (mouse_Down, mouse_Up);
|
||||||
|
|
||||||
|
TStringArray = array of String;
|
||||||
TPointArray = array of TPoint;
|
TPointArray = array of TPoint;
|
||||||
T2DPointArray = array of TPointArray;
|
T2DPointArray = array of TPointArray;
|
||||||
TVariantArray = Array of Variant;
|
TVariantArray = Array of Variant;
|
||||||
|
@ -28,33 +28,640 @@ unit ocr;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils;
|
Classes, SysUtils, MufasaTypes, bitmaps, math,
|
||||||
|
{Begin To-Remove units. Replace ReadBmp with TMufasaBitmap stuff later.}
|
||||||
|
FPImgCanv, graphtype, intfgraphics,graphics;
|
||||||
|
|
||||||
|
{End To-Remove unit}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TNormArray = array of integer;
|
||||||
|
TocrGlyphMask = record
|
||||||
|
ascii: char;
|
||||||
|
width,height: integer;
|
||||||
|
l,r,t,b: integer;
|
||||||
|
mask: TNormArray;
|
||||||
|
end;
|
||||||
|
TocrGlyphMaskArray = array of TocrGlyphMask;
|
||||||
|
TocrGlyphMetric = record
|
||||||
|
xoff,yoff: integer;
|
||||||
|
width,height: integer;
|
||||||
|
end;
|
||||||
|
TocrData = record
|
||||||
|
ascii: array[0..255] of TocrGlyphMetric;
|
||||||
|
pos: array of array of integer;
|
||||||
|
pos_adj: array of real;
|
||||||
|
neg: array of array of integer;
|
||||||
|
neg_adj: array of real;
|
||||||
|
map: array of char;
|
||||||
|
width,height: integer;
|
||||||
|
inputs,outputs: integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TocrDataArray = array of TocrData;
|
||||||
|
|
||||||
|
{ We already have PRGB32 -> To be removed later }
|
||||||
|
type
|
||||||
|
tRGB = packed record
|
||||||
|
B, G, R, A: Byte;
|
||||||
|
end;
|
||||||
|
tRGBArray = array of tRGB;
|
||||||
|
|
||||||
|
{Begin To be removed}
|
||||||
|
Tbmp = record
|
||||||
|
data: array of tRGB;
|
||||||
|
width,height: integer;
|
||||||
|
end;
|
||||||
|
{End To be removed}
|
||||||
|
|
||||||
|
|
||||||
|
tLab = record
|
||||||
|
L,a,b: real;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
TMOCR = class(TObject)
|
TMOCR = class(TObject)
|
||||||
constructor Create(Owner: TObject);
|
constructor Create(Owner: TObject);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
function InitTOCR(path: string): boolean;
|
||||||
|
|
||||||
|
function GetUpTextAt(atX, atY: integer): string;
|
||||||
private
|
private
|
||||||
Client: TObject;
|
Client: TObject;
|
||||||
|
OCRData: TocrDataArray;
|
||||||
|
OCRPath: string;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
client;
|
||||||
|
|
||||||
|
function ReadBMP(path: string): Tbmp;
|
||||||
|
var
|
||||||
|
LazIntf : TLazIntfImage;
|
||||||
|
RawImageDesc : TRawImageDescription;
|
||||||
|
data: array of tRGB;
|
||||||
|
begin
|
||||||
|
if FileExists(path) then
|
||||||
|
begin;
|
||||||
|
LazIntf := TLazIntfImage.Create(0,0);
|
||||||
|
RawImageDesc.Init_BPP32_B8G8R8_BIO_TTB(LazIntf.Width,LazIntf.Height);
|
||||||
|
LazIntf.DataDescription := RawImageDesc;
|
||||||
|
LazIntf.LoadFromFile(path);
|
||||||
|
Result.width := LazIntf.Width;
|
||||||
|
Result.height := LazIntf.Height;
|
||||||
|
SetLength(data,LazIntf.Width*LazIntf.Height);
|
||||||
|
Move(LazIntf.PixelData[0],data[0],LazIntf.Width*LazIntf.Height*sizeOf(tRGB));
|
||||||
|
Result.data:= data;
|
||||||
|
LazIntf.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{initalizes the remaining fields from a TocrGlyphMask and finds the global bounds}
|
||||||
|
procedure findBounds(glyphs: TocrGlyphMaskArray; var width,height: integer);
|
||||||
|
var
|
||||||
|
i,x,y,c,w,h: integer;
|
||||||
|
l,r,t,b: integer;
|
||||||
|
dat: TNormArray;
|
||||||
|
begin
|
||||||
|
width:= 0;
|
||||||
|
height:= 0;
|
||||||
|
for c:= 0 to length(glyphs) - 1 do
|
||||||
|
begin
|
||||||
|
dat:= glyphs[c].mask;
|
||||||
|
w:= glyphs[c].width;
|
||||||
|
h:= glyphs[c].height;
|
||||||
|
l:= w;
|
||||||
|
r:= 0;
|
||||||
|
t:= h;
|
||||||
|
b:= 0;
|
||||||
|
for i:= 0 to w*h-1 do
|
||||||
|
begin
|
||||||
|
if dat[i] = 1 then
|
||||||
|
begin
|
||||||
|
x:= i mod w;
|
||||||
|
y:= i div w;
|
||||||
|
if x > r then r:= x;
|
||||||
|
if x < l then l:= x;
|
||||||
|
if y > b then b:= y;
|
||||||
|
if y < t then t:= y;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if l = w then l:= 0;
|
||||||
|
if t = h then t:= 0;
|
||||||
|
glyphs[c].r:= r;
|
||||||
|
glyphs[c].l:= l;
|
||||||
|
glyphs[c].b:= b;
|
||||||
|
glyphs[c].t:= t;
|
||||||
|
if (r - l + 1) > width then width:= r - l + 1;
|
||||||
|
if (b - t + 1) > height then height:= b - t + 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{Use whatever you want if you don't like this}
|
||||||
|
function GetFiles(Path, Ext: string): TstringArray;
|
||||||
|
var
|
||||||
|
SearchRec : TSearchRec;
|
||||||
|
c : integer;
|
||||||
|
begin
|
||||||
|
c := 0;
|
||||||
|
if FindFirst(Path + '*.' + ext, faAnyFile, SearchRec) = 0 then
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
inc(c);
|
||||||
|
SetLength(Result,c);
|
||||||
|
Result[c-1] := SearchRec.Name;
|
||||||
|
until FindNext(SearchRec) <> 0;
|
||||||
|
SysUtils.FindClose(SearchRec);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{This Loads the actual data from the .bmp, but does not init all fields}
|
||||||
|
function LoadGlyphMasks(path: string): TocrGlyphMaskArray;
|
||||||
|
var
|
||||||
|
strs: array of string;
|
||||||
|
bmp: array of Tbmp; {-> TMufasaBitmap, and why use an array? }
|
||||||
|
len,size,i,j: integer;
|
||||||
|
color: tRGB;
|
||||||
|
begin
|
||||||
|
strs:= GetFiles(path,'bmp');
|
||||||
|
len:= length(strs);
|
||||||
|
SetLength(result,len);
|
||||||
|
SetLength(bmp,len);
|
||||||
|
for i:= 0 to len-1 do
|
||||||
|
begin
|
||||||
|
bmp[i]:= ReadBmp(path + strs[i]);
|
||||||
|
size:= bmp[i].width*bmp[i].height;
|
||||||
|
SetLength(result[i].mask,size);
|
||||||
|
for j:= 0 to size-1 do
|
||||||
|
begin
|
||||||
|
color:= bmp[i].data[j];
|
||||||
|
if (color.r = 255) and (color.g = 255) and (color.b = 255) then
|
||||||
|
result[i].mask[j]:= 1
|
||||||
|
else
|
||||||
|
result[i].mask[j]:= 0;
|
||||||
|
end;
|
||||||
|
result[i].width:= bmp[i].width;
|
||||||
|
result[i].height:= bmp[i].height;
|
||||||
|
SetLength(strs[i],Length(strs[i])-4);
|
||||||
|
result[i].ascii:= chr(strtoint(strs[i]));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{Fully initalizes a TocrData structure, this is LoadFont or whatever, call it first}
|
||||||
|
function InitOCR(path: string): TocrData;
|
||||||
|
var
|
||||||
|
masks: TocrGlyphMaskArray;
|
||||||
|
t,b,l,r,w,h,mw: integer;
|
||||||
|
x,y: integer;
|
||||||
|
c,i,len,size: integer;
|
||||||
|
pos: integer;
|
||||||
|
ascii: char;
|
||||||
|
begin
|
||||||
|
masks:= LoadGlyphMasks(path);
|
||||||
|
w:= 0;
|
||||||
|
h:= 0;
|
||||||
|
findBounds(masks,w,h);
|
||||||
|
len:= Length(masks);
|
||||||
|
result.width:= w;
|
||||||
|
result.height:= h;
|
||||||
|
size:= w * h;
|
||||||
|
SetLength(result.pos,len,size);
|
||||||
|
SetLength(result.pos_adj,len);
|
||||||
|
SetLength(result.neg,len,size);
|
||||||
|
SetLength(result.neg_adj,len);
|
||||||
|
SetLength(result.map,len);
|
||||||
|
for i:= 0 to len - 1 do
|
||||||
|
begin
|
||||||
|
ascii:= masks[i].ascii;
|
||||||
|
pos:= 0;
|
||||||
|
l:= masks[i].l;
|
||||||
|
r:= masks[i].r;
|
||||||
|
b:= masks[i].b;
|
||||||
|
t:= masks[i].t;
|
||||||
|
mw:= masks[i].width;
|
||||||
|
for y:= t to b do
|
||||||
|
begin
|
||||||
|
for x:= l to r do
|
||||||
|
begin
|
||||||
|
c:= (x-l) + (y-t)*w;
|
||||||
|
if masks[i].mask[x+y*mw] <> 0 then
|
||||||
|
begin
|
||||||
|
result.pos[i][c]:= 1;
|
||||||
|
inc(pos);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
for c:= 0 to size-1 do
|
||||||
|
result.neg[i][c]:= 1 - result.pos[i][c];
|
||||||
|
if pos = 0 then result.neg_adj[i]:= 1 else result.neg_adj[i]:= 1 / pos;
|
||||||
|
if pos = 0 then result.pos_adj[i]:= 0 else result.pos_adj[i]:= 1 / pos;
|
||||||
|
result.map[i]:= ascii;
|
||||||
|
result.ascii[ord(ascii)].xoff:= masks[i].l;
|
||||||
|
result.ascii[ord(ascii)].yoff:= masks[i].t;
|
||||||
|
result.ascii[ord(ascii)].width:= masks[i].width;
|
||||||
|
result.ascii[ord(ascii)].height:= masks[i].height;
|
||||||
|
end;
|
||||||
|
result.inputs:= size;
|
||||||
|
result.outputs:= len;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{guesses a glyph stored in glyph (which is an 1-0 image of the size specified by width and height in ocrdata}
|
||||||
|
function GuessGlyph(glyph: TNormArray; ocrdata: TocrData): char;
|
||||||
|
var
|
||||||
|
i,c,inputs,outputs,val: integer;
|
||||||
|
pos_weights: array of real;
|
||||||
|
neg_weights: array of real;
|
||||||
|
max, weight: real;
|
||||||
|
begin
|
||||||
|
SetLength(pos_weights,ocrdata.outputs);
|
||||||
|
SetLength(neg_weights,ocrdata.outputs);
|
||||||
|
inputs:= ocrdata.inputs - 1;
|
||||||
|
outputs:= ocrdata.outputs - 1;
|
||||||
|
for i:= 0 to inputs do
|
||||||
|
begin
|
||||||
|
val:= glyph[i];
|
||||||
|
for c:= 0 to outputs do
|
||||||
|
begin
|
||||||
|
pos_weights[c]:= pos_weights[c] + ocrdata.pos[c][i] * val;
|
||||||
|
neg_weights[c]:= neg_weights[c] + ocrdata.neg[c][i] * val;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
max:= 0;
|
||||||
|
for i:= 0 to outputs do
|
||||||
|
begin
|
||||||
|
weight:= pos_weights[i] * ocrdata.pos_adj[i] - neg_weights[i] * ocrdata.neg_adj[i];
|
||||||
|
if (weight > max) then
|
||||||
|
begin
|
||||||
|
max:= weight;
|
||||||
|
result:= ocrdata.map[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{converts a TPA into a 1-0 image of the smallest possible size}
|
||||||
|
function PointsToNorm(points: TpointArray; var w,h: integer): TNormArray;
|
||||||
|
var
|
||||||
|
l,r,t,b: integer;
|
||||||
|
i,len,size: integer;
|
||||||
|
norm: TNormArray;
|
||||||
|
begin
|
||||||
|
len:= length(points);
|
||||||
|
l:= points[0].x;
|
||||||
|
r:= points[0].x;
|
||||||
|
t:= points[0].y;
|
||||||
|
b:= points[0].y;
|
||||||
|
for i:= 1 to len-1 do
|
||||||
|
begin
|
||||||
|
if points[i].x < l then l:= points[i].x;
|
||||||
|
if points[i].x > r then r:= points[i].x;
|
||||||
|
if points[i].y < t then t:= points[i].y;
|
||||||
|
if points[i].y > b then b:= points[i].y;
|
||||||
|
end;
|
||||||
|
w:= r - l + 1;
|
||||||
|
h:= b - t + 1;
|
||||||
|
size:= w * h;
|
||||||
|
SetLength(norm,size);
|
||||||
|
for i:= 0 to len-1 do
|
||||||
|
norm[(points[i].x - l) + (points[i].y - t) * w]:= 1;
|
||||||
|
result:= norm;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ImageToNorm(src: tRGBArray; w,h: integer): TNormArray;
|
||||||
|
var
|
||||||
|
norm: TNormArray;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
SetLength(norm,w*h);
|
||||||
|
for i:= 0 to w*h-1 do
|
||||||
|
if (src[i].r = 255) and (src[i].g = 255) and (src[i].b = 255) then
|
||||||
|
norm[i]:= 1 else norm[i]:= 0;
|
||||||
|
result:= norm;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{takes a mask of only one line of text, a TocrData, and returns the string in it}
|
||||||
|
function ocrDetect(txt: TNormArray; w,h: integer; var ocrdata: TocrData): string;
|
||||||
|
var
|
||||||
|
l,r,t,b,x,y,xx,yy: integer;
|
||||||
|
upper,left,last,spaces: integer;
|
||||||
|
glyph: TNormArray;
|
||||||
|
empty: boolean;
|
||||||
|
ascii: char;
|
||||||
|
begin
|
||||||
|
result:= '';
|
||||||
|
l:= -1;
|
||||||
|
r:= -1;
|
||||||
|
upper:= -9001; //large negative
|
||||||
|
left:= -9001; //large negative
|
||||||
|
x:= 0;
|
||||||
|
while x < w do
|
||||||
|
begin
|
||||||
|
empty:= true;
|
||||||
|
for y:= 0 to h-1 do
|
||||||
|
begin
|
||||||
|
if txt[x+y*w] = 1 then
|
||||||
|
begin
|
||||||
|
empty:= false;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if (l = -1) and (not empty) then
|
||||||
|
begin
|
||||||
|
l:= x
|
||||||
|
end else if (l <> -1) then
|
||||||
|
begin
|
||||||
|
if empty then
|
||||||
|
r:= x - 1
|
||||||
|
else if x = w-1 then
|
||||||
|
r:= x;
|
||||||
|
end;
|
||||||
|
if (r <> -1) and (l <> -1) then
|
||||||
|
begin
|
||||||
|
t:= -1;
|
||||||
|
b:= -1;
|
||||||
|
SetLength(glyph,0);
|
||||||
|
SetLength(glyph,ocrdata.width*ocrdata.height);
|
||||||
|
for yy:= 0 to h-1 do
|
||||||
|
begin
|
||||||
|
for xx:= l to r do
|
||||||
|
if txt[xx+yy*w] = 1 then begin t:= yy; break; end;
|
||||||
|
if t <> -1 then break;
|
||||||
|
end;
|
||||||
|
for yy:= h-1 downto 0 do
|
||||||
|
begin
|
||||||
|
for xx:= l to r do
|
||||||
|
if txt[xx+yy*w] = 1 then begin b:= yy; break; end;
|
||||||
|
if b <> -1 then break;
|
||||||
|
end;
|
||||||
|
if b - t + 1 > ocrdata.height then b:= b - (b-t+1-ocrdata.height);
|
||||||
|
if r - l + 1 > ocrdata.width then r:= r - (r-l+1-ocrdata.width);
|
||||||
|
for yy:= t to b do
|
||||||
|
for xx:= l to r do
|
||||||
|
glyph[(xx-l) + (yy-t)*ocrdata.width]:= txt[xx+yy*w];
|
||||||
|
|
||||||
|
ascii:= GuessGlyph(glyph,ocrdata);
|
||||||
|
if (upper = -9001) or (left = -9001) then
|
||||||
|
begin
|
||||||
|
upper:= t - ocrdata.ascii[ord(ascii)].yoff;
|
||||||
|
left:= l - ocrdata.ascii[ord(ascii)].xoff + ocrdata.ascii[ord(ascii)].width;
|
||||||
|
x:= left;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
last:= left;
|
||||||
|
left:= l - ocrdata.ascii[ord(ascii)].xoff;
|
||||||
|
if last <> left then
|
||||||
|
begin
|
||||||
|
for spaces:= 1 to (left - last) div ocrdata.ascii[32].width do
|
||||||
|
result:= result + ' ';
|
||||||
|
end;
|
||||||
|
left:= left + ocrdata.ascii[ord(ascii)].width;
|
||||||
|
x:= left;
|
||||||
|
end;
|
||||||
|
|
||||||
|
result:= result + ascii;
|
||||||
|
|
||||||
|
l:= -1;
|
||||||
|
r:= -1;
|
||||||
|
|
||||||
|
end;
|
||||||
|
inc(x);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function AvgColors(color1:tRGB; weight1: integer; color2: tRGB; weight2: integer): tRGB;
|
||||||
|
begin
|
||||||
|
result.r:= (color1.r * weight1 + color2.r * weight2) div (weight1 + weight2);
|
||||||
|
result.g:= (color1.g * weight1 + color2.g * weight2) div (weight1 + weight2);
|
||||||
|
result.b:= (color1.b * weight1 + color2.b * weight2) div (weight1 + weight2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure RGBtoXYZ(color: tRGB; var X, Y, Z: real); inline;
|
||||||
|
var
|
||||||
|
nr,ng,nb: real;
|
||||||
|
begin
|
||||||
|
nr:= color.r / 255.0;
|
||||||
|
ng:= color.g / 255.0;
|
||||||
|
nb:= color.b / 255.0;
|
||||||
|
if nr <= 0.04045 then nr:= nr / 12.92 else nr:= power((nr + 0.055)/1.055,2.4);
|
||||||
|
if ng <= 0.04045 then ng:= ng / 12.92 else ng:= power((ng + 0.055)/1.055,2.4);
|
||||||
|
if nb <= 0.04045 then nr:= nb / 12.92 else nb:= power((nb + 0.055)/1.055,2.4);
|
||||||
|
X:= 0.4124*nr + 0.3576*ng + 0.1805*nb;
|
||||||
|
Y:= 0.2126*nr + 0.7152*ng + 0.0722*nb;
|
||||||
|
Z:= 0.0193*nr + 0.1192*ng + 0.9505*nb;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function labmod(i: real): real; inline;
|
||||||
|
begin
|
||||||
|
if i > power(0.206896552,3) then
|
||||||
|
result:= power(i,0.333333333)
|
||||||
|
else
|
||||||
|
result:= 7.787037037*i + 0.137931034;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ColortoLab(c: tRGB): tLab; inline;
|
||||||
|
var
|
||||||
|
X,Y,Z,sum,Xn,Yn,Zn: real;
|
||||||
|
begin
|
||||||
|
RGBtoXYZ(c,X,Y,Z);
|
||||||
|
sum:= X + Y + Z;
|
||||||
|
Xn:= X / sum;
|
||||||
|
Yn:= Y / sum;
|
||||||
|
Zn:= Z / sum;
|
||||||
|
result.L:= 116.0*labmod(y/yn) - 16.0;
|
||||||
|
result.a:= 500.0*(labmod(x/xn)-labmod(y/yn));
|
||||||
|
result.b:= 500.0*(labmod(y/yn)-labmod(z/zn));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function colorDistSqr(a,b:tRGB): integer; inline;
|
||||||
|
begin
|
||||||
|
result:= (a.r-b.r)*(a.r-b.r)+(a.b-b.b)*(a.b-b.b)+(a.g-b.g)*(a.g-b.g);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ExtractText(colors: PRGB32;{colors: tRGBArray;} w,h: integer): TNormArray;
|
||||||
|
const
|
||||||
|
GradientMax = 5.0;
|
||||||
|
white: tRGB = ( b: $FF; g: $FF; r: $FF; a: $00 );
|
||||||
|
cyan: tRGB = ( b: $FF; g: $FF; r: $00; a: $00 );
|
||||||
|
yellow: tRGB = ( b: $00; g: $EF; r: $FF; a: $00 );
|
||||||
|
red: tRGB = ( b: $00; g: $00; r: $FF; a: $00 );
|
||||||
|
var
|
||||||
|
up, left: boolean;
|
||||||
|
len,numblobs,thisblob,lastblob,i,j,used: integer;
|
||||||
|
blobbed,blobcount,stack: array of integer;
|
||||||
|
labs: array of tLab;
|
||||||
|
a,b: tLab;
|
||||||
|
blobcolor: tRGBArray;
|
||||||
|
newcolors: array of integer;
|
||||||
|
c: tRGB;
|
||||||
|
norm: TNormArray;
|
||||||
|
begin
|
||||||
|
len:= w*h;
|
||||||
|
SetLength(blobbed,len);
|
||||||
|
SetLength(blobcount,len);
|
||||||
|
SetLength(blobcolor,len);
|
||||||
|
SetLength(stack,len);
|
||||||
|
SetLength(labs,len);
|
||||||
|
for i:= 0 to len-1 do
|
||||||
|
labs[i]:= ColorToLab(tRGB(colors[i]));
|
||||||
|
numblobs:= 0;
|
||||||
|
for i:= 0 to len-1 do
|
||||||
|
begin
|
||||||
|
a:= labs[i];
|
||||||
|
if i >= w then
|
||||||
|
begin
|
||||||
|
b:= labs[i-w];
|
||||||
|
up:= abs(a.L-b.L)+abs(a.a-b.a)+abs(a.b-b.b) <= GradientMax;
|
||||||
|
end else
|
||||||
|
up:= false;
|
||||||
|
if i mod w <> 0 then
|
||||||
|
begin
|
||||||
|
b:= labs[i-1];
|
||||||
|
left:= abs(a.L-b.L)+abs(a.a-b.a)+abs(a.b-b.b) <= GradientMax;
|
||||||
|
end else
|
||||||
|
left:= false;
|
||||||
|
if left and up then
|
||||||
|
begin
|
||||||
|
thisblob:= blobbed[i-w];
|
||||||
|
blobbed[i]:= thisblob;
|
||||||
|
blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
|
||||||
|
blobcount[thisblob]:= blobcount[thisblob] + 1;
|
||||||
|
lastblob:= blobbed[i-1];
|
||||||
|
if lastblob <> thisblob then
|
||||||
|
begin
|
||||||
|
used:= 1;
|
||||||
|
stack[0]:= i-1;
|
||||||
|
while used > 0 do
|
||||||
|
begin
|
||||||
|
used:= used - 1;
|
||||||
|
j:= stack[used];
|
||||||
|
if blobbed[j] = lastblob then
|
||||||
|
begin
|
||||||
|
blobbed[j]:= thisblob;
|
||||||
|
if j >= w then if blobbed[j-w] = lastblob then begin stack[used]:= j-w; used:= used + 1; end;
|
||||||
|
if j mod w <> 0 then if blobbed[j-1] = lastblob then begin stack[used]:= j-1; used:= used + 1; end;
|
||||||
|
if (j+1) mod w <> 0 then if blobbed[j+1] = lastblob then begin stack[used]:= j+1; used:= used + 1; end;
|
||||||
|
if j < w*h-w then if blobbed[j+w] = lastblob then begin stack[used]:= j+w; used:= used + 1; end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],blobcolor[lastblob],blobcount[lastblob]);
|
||||||
|
blobcount[thisblob]:= blobcount[thisblob] + blobcount[lastblob];
|
||||||
|
blobcount[lastblob]:= 0;
|
||||||
|
end;
|
||||||
|
end else if left then
|
||||||
|
begin
|
||||||
|
thisblob:= blobbed[i-1];
|
||||||
|
blobbed[i]:= thisblob;
|
||||||
|
blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
|
||||||
|
blobcount[thisblob]:= blobcount[thisblob] + 1;
|
||||||
|
end else if up then
|
||||||
|
begin
|
||||||
|
thisblob:= blobbed[i-w];
|
||||||
|
blobbed[i]:= thisblob;
|
||||||
|
blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
|
||||||
|
blobcount[thisblob]:= blobcount[thisblob] + 1;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
blobbed[i]:= numblobs;
|
||||||
|
blobcount[numblobs]:= 1;
|
||||||
|
blobcolor[numblobs]:= tRGB(colors[i]);
|
||||||
|
numblobs:= numblobs + 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SetLength(blobcount,numblobs);
|
||||||
|
SetLength(blobcolor,numblobs);
|
||||||
|
//Done blobfinding, extract char masks
|
||||||
|
SetLength(newcolors,numblobs);
|
||||||
|
for i:= 0 to numblobs-1 do
|
||||||
|
begin
|
||||||
|
j:= blobcount[i];
|
||||||
|
if j > 0 then
|
||||||
|
begin
|
||||||
|
c:= blobcolor[i];
|
||||||
|
if (j > 50) or (j < 2) then
|
||||||
|
newcolors[i]:= 0
|
||||||
|
else if colorDistSqr(white,c) <= 10000 then
|
||||||
|
newcolors[i]:= 1
|
||||||
|
else if colorDistSqr(cyan,c) <= 10000 then
|
||||||
|
newcolors[i]:= 1
|
||||||
|
else if colorDistSqr(yellow,c) <= 10000 then
|
||||||
|
newcolors[i]:= 1
|
||||||
|
else if colorDistSqr(red,c) <= 10000 then
|
||||||
|
newcolors[i]:= 1
|
||||||
|
else
|
||||||
|
newcolors[i]:= 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SetLength(norm,len);
|
||||||
|
for i:= 0 to len-1 do
|
||||||
|
norm[i]:= newcolors[blobbed[i]];
|
||||||
|
result:= norm;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TMOCR.Create(Owner: TObject);
|
constructor TMOCR.Create(Owner: TObject);
|
||||||
|
|
||||||
|
var
|
||||||
|
files: TStringArray;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Self.Client := Owner;
|
Self.Client := Owner;
|
||||||
|
|
||||||
|
SetLength(OCRData, 0);
|
||||||
|
|
||||||
|
//files := GetFiles('/home/merlijn/Programs/mufasa/UpText/upchars', 'bmp');
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TMOCR.Destroy;
|
destructor TMOCR.Destroy;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
inherited Destroy;
|
SetLength(OCRData, 0);
|
||||||
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMOCR.InitTOCR(path: string): boolean;
|
||||||
|
begin
|
||||||
|
{ This must be dynamic }
|
||||||
|
{ '/home/merlijn/Programs/mufasa/UpText/upchars/' }
|
||||||
|
SetLength(OCRData, 1);
|
||||||
|
OCRData[0] := InitOCR(path + '/UpChars/');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMOCR.GetUpTextAt(atX, atY: integer): string;
|
||||||
|
|
||||||
|
var
|
||||||
|
bmp: TMufasaBitmap;
|
||||||
|
n: TNormArray;
|
||||||
|
w,h,ww,hh: integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
TClient(Client).MWindow.GetDimensions(w, h);
|
||||||
|
|
||||||
|
ww := 300;
|
||||||
|
hh := 20;
|
||||||
|
|
||||||
|
if ww > w then
|
||||||
|
ww := w;
|
||||||
|
if hh > h then
|
||||||
|
hh := h;
|
||||||
|
|
||||||
|
bmp := TMufasaBitmap.Create;
|
||||||
|
bmp.SetSize(ww - atX, hh - atY);
|
||||||
|
bmp.OnDestroy:=nil;
|
||||||
|
|
||||||
|
bmp.CopyClientToBitmap(TClient(Client).MWindow, atX, atY, ww, hh);
|
||||||
|
|
||||||
|
n := ExtractText(bmp.FData, bmp.Width, bmp.Height);
|
||||||
|
Result := ocrDetect(n, bmp.Width, bmp.Height, OCRData[0]);
|
||||||
|
|
||||||
|
bmp.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user