บทความเทคนิค

รัน Tesseract in-process จาก Delphi ด้วย HotPDF

HotPDF รัน Tesseract ข้างใน process ของ Delphi คุณผ่าน HPDFCreateTesseractDLLOCREngine factory ที่เพิ่มมาใน v2.772.0 ซึ่งโหลด DLL ที่เข้ากันได้กับ Tesseract 5 แบบ dynamic ขับเคลื่อน C API ของมัน (TessBaseAPIInit2, TessBaseAPIRecognize กับ result iterator) แล้วคืน IHPDFOCREngine THotPDF.ApplyLoadedOCRTextLayer ใช้ engine ตัวนั้นเพิ่ม text layer Unicode มองไม่เห็นที่ค้นหาได้ลงหน้า PDF ที่สแกน

recognizer ตัวเดิมเข้าถึงได้แล้วผ่านadapter ของ tesseract.exe ภายนอกที่เขียน BMP แล้ว parse TSV เส้นทางนั้นใช้ได้ แต่ทุกหน้าจ่ายค่าปลุก process ค่าไฟล์ bitmap ชั่วคราว และค่า format ข้อความที่ไม่มี baseline กับไม่มีทางคุม page segmentation การเรียก DLL ตัดทั้งสามอย่างทิ้ง มันยังตัดกำแพง process ด้วย ซึ่งแปลว่า binding ของ Pascal นั่งวางตรง ๆ บนโครงสร้าง C, Boolean แบบ C และ string ที่ฝั่ง C จอง สิ่งที่ควรรู้เกี่ยวกับ adapter ตัวนี้ส่วนใหญ่จึงคือจุดที่ binding พังไปเงียบ ๆ ได้ที่ไหน

รัน Tesseract in-process จาก Delphi ด้วย HotPDF อย่างไร

การรัน Tesseract in-process ด้วย HotPDF ใช้ factory call ครั้งเดียวในยูนิต HPDFTesseractRecognition กับ call ApplyLoadedOCRTextLayer ชุดเดิมที่ OCR engine ทุกตัวของ HotPDF ใช้ factory ตรวจแบบเร่งรัด ไฟล์ DLL กับไดเรกทอรี tessdata ต้องมีอยู่จริง identifier ของภาษามีได้แค่ตัวอักษร ASCII ตัวเลข _ กับ + model ทุกตัวในคู่ผสมอย่าง chi_sim+eng ต้องมีไฟล์ .traineddata ตรงกัน และ export ที่จำเป็นทั้ง 21 ตัวต้อง resolve ได้ก่อน engine จะถูกคืน ข้อผิดพลาดด้านการตั้งค่า raise EArgumentException DLL ที่โหลดไม่ขึ้น raise EOSError พร้อมรหัส error ของ Windows และคำใบ้ให้เช็คสถาปัตยกรรมกับ dependency

uses
  SysUtils, HPDFDoc, HPDFTesseractRecognition;

procedure MakeSearchable(const SourceFile, TargetFile: string);
var
  Doc: THotPDF;
  Engine: IHPDFOCREngine;
  Options: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  // แอป Win64 ต้องใช้ DLL 64 บิต dependency DLL วางเคียงตัวมันไว้
  Engine := HPDFCreateTesseractDLLOCREngine('C:\OCR\Win64\libtesseract-5.dll',
    'C:\OCR\tessdata', 'chi_sim+eng');   // THPDFTesseractOptions.Default
  Doc := THotPDF.Create(nil);
  try
    Doc.AutoLaunch := False;
    if Doc.LoadFromFile(SourceFile) < 1 then
      raise Exception.Create('Cannot load ' + SourceFile);
    Options := THPDFOCRTextLayerOptions.Default;   // 300 DPI, MinimumConfidence 0.5
    // รายการหน้าว่างหมายถึงทุกหน้า หน้าที่มี text อยู่แล้วถูกข้าม
    if not Doc.ApplyLoadedOCRTextLayer([], Engine, Options, Info) then
      raise Exception.Create(string(Info.Diagnostic));
    Writeln(string(Info.EngineName), ': ', Info.AcceptedWordCount,
      ' words accepted, ', Info.DroppedWordCount, ' dropped');
    Doc.SaveLoadedDocument(TargetFile);
  finally
    Doc.Free;
  end;
end;

THPDFTesseractOptions.Default เซ็ต PageSegMode เป็น tpsAuto, EngineMode เป็น temDefault, TimeoutMilliseconds เป็น 60,000 และ MaxPixels เป็น 16,777,216 งบ pixel สำคัญกว่าที่ดู หน้า US Letter ที่ค่าเริ่มต้น 300 DPI render ได้ 2,550 × 3,300 pixel หรือราว 8.4 ล้าน พอดีกับงบ หน้าเดิมที่ 600 DPI คือ 5,100 × 6,600 หรือราว 33.7 ล้าน และ adapter ปฏิเสธก่อน Tesseract จะได้เห็น pixel สักตัว ให้เพิ่ม MaxPixels (เพดานคือ 67,108,864) หรือปล่อย DPI ไว้เหมือนเดิม แต่ละด้านยังถูกจำกัดที่ 32,767 pixel ด้วย

DLL ถูกโหลดด้วย LoadLibraryEx พร้อม search flag ของโฟลเดอร์ของ DLL เองบวก safe directories ค่าเริ่มต้น image library ที่ Tesseract พึ่งพาจึงวางเคียงมันได้โดยไม่ต้องแตะ PATH หรือ current directory HotPDF ไม่แถมและไม่ดาวน์โหลด runtime หรือ model ของ OCR ใด ๆ ให้คุณจัดหาทั้งคู่

อะไรเปลี่ยนไปเทียบกับ adapter ของ tesseract.exe

adapter ฝั่ง DLL แลก process isolation กับ output ที่อุดมขึ้นและค่าใช้จ่ายต่อหน้าที่ถูกลง ทั้งสอง adapter เสียบเข้า pipeline ของ text layer ตัวเดียวกัน การแมปพิกัด, การกรองด้วย confidence และการ commit แบบ all-or-nothing จึงเหมือนกันเป๊ะ สิ่งที่ต่างคือ pixel ไหลเข้ายังไงและคำไหลออกมายังไง

ด้านadapter ของ tesseract.exeadapter ของ Tesseract DLL
factoryHPDFCreateTesseractOCREngineHPDFCreateTesseractDLLOCREngine
pixel เข้าไฟล์ BMP ในไดเรกทอรีชั่วคราวส่วนตัวbuffer grayscale 8 บิตในหน่วยความจำ
คำออกTSV ระดับคำ จำกัดที่ 64 MiBresult iterator, UTF-8 ต่อคำ
baselineไม่มีให้ใช้ส่งผ่านจาก TessPageIteratorBaseline
page segmentation กับ engine modeautomatic segmentation เท่านั้นTHPDFTesseractPageSegMode, THPDFTesseractEngineMode
timeoutแบบเด็ดขาด child process ถูก terminateแบบ cooperative Tesseract ต้องสังเกตเอง
การกั้น crash กับหน่วยความจำprocess แยกต่างหากไม่มี ใช้ address space เดียวกับคุณ

ต้นทุนหนึ่งอย่างไม่หายไป call Recognize แต่ละครั้งสร้าง instance ของ API ของตัวเองแล้วเรียก TessBaseAPIInit2 language model จึงถูก initialize ต่อหน้า แทนที่จะครั้งเดียวต่อ engine file cache ของระบบปฏิบัติการช่วยลดภาระการโหลดซ้ำ แต่กับชุด model หลายภาษาที่ใหญ่ มันยังเป็นต้นทุนตายตัวต่อหน้าที่ครองเก้าอี้และถูกนับเข้า deadline ของ recognition engine ของ RapidOCR DLL แบบ in-processเลือกดีไซน์สวนทางและเก็บ model ONNX ไว้ตลอดอายุของ engine ส่วนปัญหาเรื่องขอบเขต (C ABI, buffer แบบยืมใช้, งาน native ที่ขัดจังหวะไม่ได้) เป็นตระกูลเดียวกัน

ทำไม Delphi ถึงก๊อปโครงสร้าง monitor ของ Tesseract ไม่ได้

Delphi ก๊อป progress monitor ของ Tesseract แบบปลอดภัยไม่ได้ เพราะ ETEXT_DESC มี field ภายในที่ต่างกันไปตามเวอร์ชัน record ที่ก๊อปมือจึงวาง cancel callback กับ deadline ไว้ผิด offset บนบาง build เมื่อเกิดแบบนั้นไม่มีอะไรบ่นดัง ๆ Tesseract แค่อ่าน pointer ของ callback คุณจาก field ที่ตอนนี้ถือของอื่นอยู่ หรือไม่เคยเห็น deadline เลย

HotPDF จึงถือ monitor เป็น pointer กล่องดำแล้วแตะมันผ่าน exported functions เท่านั้น: TessMonitorCreate, TessMonitorSetCancelThis, TessMonitorSetCancelFunc, TessMonitorSetDeadlineMSecs และ TessMonitorDelete ถ้าคุณ bind C API เองเพื่อจุดประสงค์อื่น pattern เดียวกันนี้ใช้ได้ sketch ด้านล่างคือโค้ด binding ของคุณ ไม่ใช่ API ของ HotPDF และสะท้อน declaration ที่ HotPDF ใช้ภายใน

การจัดการ monitor ของ Tesseract DLL ใน HotPDF: การก๊อป record ETEXT_DESC ที่ field ต่างกันไปตามเวอร์ชันทำให้ cancel callback กับ deadline อยู่ผิด offset และพังแบบเงียบ ๆ ขณะที่ HotPDF ถือ monitor เป็นกล่องดำ ขับเคลื่อนผ่าน TessMonitorCreate, TessMonitorSetCancelThis, TessMonitorSetCancelFunc กับ TessMonitorSetDeadlineMSecs แล้วคง callback แบบ cdecl ให้ปลอด exception
pointer กล่องดำบวก export ห้าตัวคือสัญญาทั้งหมด callback ยังเป็น Boolean หนึ่งไบต์ที่อ่านแค่ flag กับนาฬิกา
type
  // C: typedef bool (*TessCancelFunc)(void *cancel_this, int words);
  TTessCancelFunc = function(CancelThis: Pointer; Words: Integer): Boolean; cdecl;
  TTessMonitorCreate = function: Pointer; cdecl;   // ETEXT_DESC*, ห้าม dereference
  TTessMonitorDelete = procedure(Monitor: Pointer); cdecl;
  TTessMonitorSetCancelFunc = procedure(Monitor: Pointer; Func: TTessCancelFunc); cdecl;
  TTessMonitorSetCancelThis = procedure(Monitor, CancelThis: Pointer); cdecl;
  TTessMonitorSetDeadlineMSecs = procedure(Monitor: Pointer; MSecs: Integer); cdecl;
  TTessBaseAPIRecognize = function(Handle, Monitor: Pointer): Integer; cdecl;

  TOCRJob = record
    CancelRequested: Boolean;
    DeadlineTick: UInt64;
  end;
  POCRJob = ^TOCRJob;

function ShouldCancel(CancelThis: Pointer; Words: Integer): Boolean; cdecl;
begin
  // รันบน stack ของ Tesseract: อ่าน flag กับนาฬิกาเท่านั้น ห้าม raise
  Result := (CancelThis = nil) or POCRJob(CancelThis)^.CancelRequested or
    (GetTickCount64 >= POCRJob(CancelThis)^.DeadlineTick);
end;

// วิธีใช้ โดย resolve function pointer ด้วย GetProcAddress:
//   Monitor := MonitorCreate();
//   try
//     MonitorSetCancelThis(Monitor, @Job);
//     MonitorSetCancelFunc(Monitor, ShouldCancel);
//     MonitorSetDeadlineMSecs(Monitor, RemainingMs);
//     RC := BaseAPIRecognize(API, Monitor);
//   finally
//     MonitorDelete(Monitor);
//   end;

รายละเอียดสองจุดใน sketch นั้นตั้งใจ callback คืน Boolean ซึ่งเป็นขนาดหนึ่งไบต์ทั้งใน Delphi กับ Free Pascal ตรงกับ bool ของ C ใน TessCancelFunc BOOL สี่ไบต์ของ Windows หรือ LongBool ของ Delphi ดูเหมือนสลับกันได้แต่ไม่ได้ เมื่อฝั่งหนึ่งเขียนหนึ่งไบต์แล้วอีกฝั่งอ่านสี่ไบต์ ไบต์บนของ register ค่าคืนคือสิ่งที่ค้างอยู่ตรงนั้น และ false ก็มาถึงในรูป true ได้ header เดียวกันยังเพิ่มเกมด้วยเรื่องที่ฟังก์ชันอย่าง TessPageIteratorBoundingBox คืน int ซึ่ง HotPDF ประกาศเป็น Integer ให้อ่านชนิด C ของค่าคืนทุกตัว อย่าสมมติ convention เดียวทั้ง API

รายละเอียดที่สองคือ callback ไม่เคย raise exception ของ Delphi ที่คลี่ผ่าน frame ของ C++ ของ Tesseract เป็น undefined behavior callback ของ HotPDF จึงอ่านแค่ cancellation token กับค่า GetTickCount64 แบบ monotonic adapter เปลี่ยนผลเป็น diagnostic ของการยกเลิกหรือ timeout หลัง TessBaseAPIRecognize กลับมา และมันทำเช็คนั้นไม่ว่ารหัสคืนฝั่ง native จะเป็นอะไร

pointer ฝั่ง native ตัวไหนที่ฝั่ง Delphi เป็นเจ้าของ

adapter ของ Tesseract DLL ใน HotPDF เป็นเจ้าของ object ฝั่ง native สามชิ้นต่อ request คือ instance ของ API, monitor และ result iterator ส่วนที่เหลือยืมใช้ call Recognize แต่ละครั้งสร้างชุดของตัวเองแล้ว release ในบล็อก finally: TessResultIteratorDelete ก่อน ตามด้วย TessMonitorDelete แล้วจึง TessBaseAPIDelete การปล่อย interface ของ engine จะ unload library

ความเป็นเจ้าของ object ฝั่ง native ต่อ call Recognize ใน Tesseract DLL ของ HotPDF: result iterator, monitor กับ instance ของ API ถูกเป็นเจ้าของและถูก free ตามลำดับนั้นข้างใน finally page iterator จาก TessResultIteratorGetPageIterator เป็นมุมมองแบบยืมที่ห้าม free เด็ดขาด และ string จาก GetUTF8Text ถูก copy แล้วคืนผ่าน TessDeleteText
สาม object ที่เป็นเจ้าของ ที่เหลือยืมใช้ทั้งหมด free ตามลำดับตายตัว อย่า free page iterator ซ้ำ และอย่าผสม allocator สองฝั่ง
  • TessResultIteratorGetPageIterator คืนมุมมองแบบยืมเข้าไปใน result iterator ไม่ใช่ object ใหม่ HotPDF ใช้มันกับ TessPageIteratorBoundingBox กับ TessPageIteratorBaseline แล้วไม่เคย free มัน การลบมันแยกจะ free หน่วยความจำเดียวกันสองรอบ
  • TessResultIteratorGetUTF8Text คืน string ที่ runtime ของ DLL เป็นคนจอง HotPDF ก๊อปมันแล้วคืนผ่าน TessDeleteText ในบล็อก finally FreeMem ฝั่ง Pascal จะ release มันบน heap ผิดตัว
  • text ของคำถูกถอดด้วยการตรวจ UTF-8 โหมด strict และเช็คความยาวก่อนแปลง คำที่มีอักขระควบคุม, UTF-8 เสียรูป, box ที่หลุดออกนอกภาพ, สี่เหลี่ยมกลับหัว หรือ confidence นอกช่วง 0–100 ทำให้ request fail ทั้งชุด ไม่ใช่ถูกปะแก้เงียบ ๆ
  • text รวมต่อ request ถูกจำกัดที่ 1,048,576 หน่วย UTF-16 และจำนวนคำต้องพอกับงบที่ ApplyLoadedOCRTextLayer ส่งมอบลงมา

confidence มาถึงในรูป 0–100 และถูกปรับเป็น 0–1 THPDFOCRTextLayerOptions.MinimumConfidence จึงมีความหมายเดียวกันกับทุก engine เมื่อ Tesseract รายงาน baseline ปลายทั้งสองถูกส่งผ่านไป ไม่งั้น pipeline ของ text layer จะย้อนไปใช้การประมาณเชิงเรขาคณิต พอดีกับที่มันทำกับ input แบบ TSV

ทำไมต้อง validate enum ก่อนส่งเข้า DLL

HotPDF ก๊อป ordinal ดิบของ PageSegMode กับ EngineMode ลง Integer ก่อนเช็คช่วง เพราะ compiler อาจสมมติว่าตัวแปร enum ถือค่าที่ประกาศไว้เสมอ แล้วยุบ Ord(X) > Ord(High(T)) เป็น false ค่าคงที่ ordinal ไม่ใช่ของตกแต่ง: THPDFTesseractPageSegMode ไล่หมายเลข page segmentation ของ Tesseract จาก 0 ถึง 13 THPDFTesseractEngineMode ไล่หมายเลข engine mode จาก 0 ถึง 3 และทั้งคู่ถูกส่งเข้า DLL เป็นจำนวนเต็มดิบ ๆ record ของ options ที่ปั้นด้วย FillChar เติมมาจาก stream หรือถูกส่งมาจาก C++Builder พร้อม cast integer สามารถพาไบต์ค่า 200 มาด้วย การ validate ordinal ที่ก๊อปแล้วเปลี่ยนมันเป็น EArgumentException ตอน factory แทนที่จะเป็น mode ไม่นิยามข้างในโค้ด native factory ยังปฏิเสธ tpsOSDOnly กับ tpsAutoOnly ซึ่งไม่ผลิตคำให้เลย และบังคับ osd.traineddata สำหรับ tpsAutoOSD กับ tpsSparseTextOSD

timeout ของ recognition การันตีอะไรจริง ๆ

timeout ของ Tesseract DLL เป็นแบบ cooperative: HotPDF หยุดงานของตัวเองและขอให้ Tesseract หยุดได้ แต่บังคับโค้ด native ให้ return ไม่ได้ นาฬิกาเดินเมื่อ Recognize เริ่ม การแปลง bitmap กับการ initialize model จึงกินงบเดียวกับ recognition HotPDF เช็คเวลาที่ผ่านไปกับ cancellation token ระหว่างการแปลง grayscale และระหว่างคำขณะไล่ผลลัพธ์ แล้วส่งมิลลิวินาทีที่เหลือให้ TessMonitorSetDeadlineMSecs ก่อนเรียก TessBaseAPIRecognize

ช่องว่างอยู่ข้างใน call ฝั่ง native monitor ของ Tesseract ถูกปรึกษาระหว่างการจดจำคำ ไม่ใช่ระหว่าง TessBaseAPIInit2 หรือการวิเคราะห์ layout หน้า model ที่โหลดช้าหรือ layout ที่พิศวงจึงวิ่งเลย deadline ได้ก่อน timeout จะถูกรายงาน งบ pixel กับ output ก็ไม่ได้จำกัดการใช้หน่วยความจำของ library ฝั่ง native เองด้วย ถ้าต้องการ worker ที่ kill ได้ ให้ใช้ adapter ฝั่ง process นั่นคือการแลกแบบซื่อ ๆ ไม่ใช่ฟีเจอร์ที่หายไป

กายวิภาค timeout แบบ cooperative ของ Tesseract DLL ใน HotPDF: นาฬิกาเดินเมื่อ Recognize เริ่มและครอบคลุมการแปลง grayscale, TessBaseAPIInit2 กับการวิเคราะห์ layout แต่ monitor ถูกปรึกษาระหว่างการจดจำคำเท่านั้น การโหลด model กับ layout จึงวิ่งเลยกำหนดได้ก่อน HotPDF จะรายงาน otlsEngineError หรือ otlsCancelled
deadline ตรงนี้เป็นคำขอ ไม่ใช่การการันตี init กับการวิเคราะห์ layout วิ่งนานได้ และ worker ที่ kill ได้จริงต้องใช้ adapter ฝั่ง process

page segmentation คือที่ที่ adapter ฝั่ง DLL เอาค่าตอบแทนบน input ยาก ๆ ฟอร์ม, ป้ายกำกับ และตารางที่สแกนพร้อม field กระจัดกระจายมักถูกจดจำได้ดีกว่าด้วย tpsSparseText มากกว่า automatic segmentation ซึ่งพยายามประกอบ column กับย่อหน้าที่ไม่มีอยู่จริง

procedure OCRFormPages(Doc: THotPDF; const Pages: array of Integer);
var
  Engine: IHPDFOCREngine;
  TessOptions: THPDFTesseractOptions;
  LayerOptions: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  TessOptions := THPDFTesseractOptions.Default;
  TessOptions.PageSegMode := tpsSparseText;  // field กระจัดกระจาย ไม่ประกอบ column
  TessOptions.EngineMode := temLSTMOnly;     // ต้องมี model LSTM ใน tessdata
  TessOptions.TimeoutMilliseconds := 20000;  // รวมการ initialize model ด้วย
  Engine := HPDFCreateTesseractDLLOCREngine('C:\OCR\Win64\libtesseract-5.dll',
    'C:\OCR\tessdata', 'eng+deu', TessOptions);

  LayerOptions := THPDFOCRTextLayerOptions.Default;
  LayerOptions.MinimumConfidence := 0.6;
  if not Doc.ApplyLoadedOCRTextLayer(Pages, Engine, LayerOptions, Info) then
    case Info.Status of
      otlsCancelled:
        Writeln('OCR cancelled, document unchanged');
      otlsEngineError:
        Writeln('Tesseract failed or timed out: ', string(Info.Diagnostic));
    else
      Writeln(string(Info.Diagnostic));
    end;
end;

timeout ปรากฏเป็น otlsEngineError พร้อม diagnostic Tesseract DLL OCR timed out ส่วน token ที่ถูกยกเลิกปรากฏเป็น otlsCancelled ทั้งสองเคส ApplyLoadedOCRTextLayer จดจำหน้าที่เลือกทุกหน้าจบก่อนเริ่ม transaction ของการ commit ความล้มเหลวที่หน้า 40 จาก 50 จึงปล่อยเอกสารที่โหลดไว้ให้เหมือนเดิมเป๊ะ จดไว้ว่า tpsSingleLine, tpsSingleBlock กับ tpsSparseText เปลี่ยนแค่ segmentation ไม่มีตัวไหนทำให้สแกนที่เอียงตรงขึ้น

Free Pascal กับ Lazarus: pixel ค้างเก่ากับจีนที่หายไป

factory ของ Tesseract ทั้งสองตัวทำงานบน Free Pascal ฝั่ง Windows และ Lazarus build Win32 กับ Win64 ตั้งแต่ v2.772.1 หลังการแก้เฉพาะ FPC สองชิ้น rebuild แพ็กเกจของ Lazarus ให้สถาปัตยกรรมเป้าหมายก่อน ส่วน port ภาพรวมเล่าไว้ในHotPDF บน Free Pascal และ Lazarus Win64

การแก้แรกอยู่ที่ pixel TBitmap ของ LCL ที่เขียนผ่าน scanline อัปเดตภาพดิบได้โดยไม่ refresh Windows bitmap handle GetDIBits บน handle นั้นจึงคืน pixel เก่า อาการที่ว่าพอให้งง: ข้อความที่วาดลง bitmap โดยตรงถูกจดจำได้ ขณะที่หน้าที่ render โดย PDF renderer ของ HotPDF ให้รายการคำว่างเปล่า บน FPC adapter ตอนนี้อ่าน snapshot ที่รู้รูปแบบผ่าน CreateIntfImage ซึ่งเคารพ pixel format กับลำดับแถวของภาพดิบ build ฝั่ง Delphi คงเส้นทาง GetDIBits บนสำเนา 24 บิตส่วนตัว ทั้งสอง build ไม่แตะ bitmap ของ caller เลย

การแก้ที่สองเป็นของ adapter ฝั่ง tesseract.exe TStringList ของ FPC เก็บ string แบบ ANSI การ assign text แบบ TSV ที่ถอดเป็น UTF-8 แล้วลง Lines.Text จึงทิ้งอักขระจีนหรือ supplementary plane ทุกตัวที่ system ANSI code page เขียนไม่ได้แบบเงียบ ๆ เส้นทางของ FPC ตอนนี้เก็บ TSV เป็นไบต์ UTF-8 ตัด BOM ที่ระดับไบต์แล้วถอดคำทีละตัวเป็น UnicodeString adapter ฝั่ง DLL ไม่เคยมีปัญหานี้ เพราะมันถอดแต่ละคำจาก iterator โดยตรง

สรุปด่วน

  • factory: HPDFCreateTesseractDLLOCREngine(LibraryPath, TessDataDirectory, Language[, Options]) ใน HPDFTesseractRecognition เพิ่มใน v2.772.0 รองรับ FPC ใน v2.772.1
  • ค่าเริ่มต้น: tpsAuto, temDefault, 60,000 ms, 16,777,216 pixel ช่วง timeout 1–3,600,000 ms เพดาน pixel 67,108,864
  • จับ bitness ของ DLL ให้ตรงแอปพลิเคชัน แล้ววาง dependency DLL เคียงกับ Tesseract DLL
  • ถือ monitor เป็นกล่องดำ ห้ามก๊อป ETEXT_DESC ลง record ของ Pascal เด็ดขาด
  • ประกาศ cancel callback เป็น cdecl พร้อมผลลัพธ์ Boolean หนึ่งไบต์ และห้ามปล่อย exception หลุดออกจากมัน
  • free text ของ iterator ด้วย TessDeleteText ห้าม free page iterator ที่ได้จาก result iterator
  • คาดหวังว่า deadline เป็นแบบ cooperative การ initialize model กับการวิเคราะห์ layout วิ่งเลยมันได้
  • ใช้ adapter ของ tesseract.exe เมื่อต้องการ termination แบบเด็ดขาดหรือการกั้น crash

adapter ฝั่ง Tesseract DLL, adapter ฝั่ง process และ engine OCR ในตัวมาพร้อมกันใน HotPDF Delphi PDF component สำหรับ Delphi, C++Builder และ Free Pascal ดูหน้า product ของ HotPDF สำหรับ edition และดาวน์โหลด