Hi All,
I know a few of you have been following this for a while, and I said when I found a solution I would put it up. As of today we can with one click now, scan both sides of a business card (if back is blank, it gets ignored), automatically populate memo field with the location of the image, automatically store the image based on specific record ID (i.e. it makes directories to store the physical card image data which is then referenced and updates a image base-class on the form).
So Here's the solution (note this uses EZTWAIN and Transym OCR, though the latter is totally transparent):
[Note: we parameterized this with 4 parameters: Top, Left, Width and Height. This is because we discovered that cards basically come in 2 types. Short ones, and tall ones. (No need to worry over any other part). Interestingly Tall usually means "Tall narrow, just treat it as Tall and wide". So "click" is the event you are seeing the code for. We put a different set of parameters on the RIGHTClICK and just call it from the Rightclick method: This.Click(0.0,0,0,3.55,2.15) This makes for taller and wider cards. The default (when no parameters are passed) is (0.0,0.0,3.4,2.0) so slightly shorter and narrower. Since the only difference is the TWAIN_SetRegion, we can maintain a single simple code set to manage any card size functions we want, and just change the region. This is setup for our Canon P-208II duplex scanner, which we've hard-coded, because we don't want users trying to use any input scanner willy-nilly. But you can adjust it as you see fit, and even leave the OpenSource with () to call a list.
It's actually a very elegant solution overall. EZTWAIN does an awesome job of just working with any default OCR engine, and we found Transym to be very reasonable cost ($100 USD) and very powerful (great OCR result).
Now, we have the text in a Memo field, which we can parse out into the various components... and that becomes the next step in our quest for "Card Automation".
Best Regards,
Scott
ATS, CDCE, CTIA, CTDC
"Everything should be made as simple as possible, and no simpler."
I know a few of you have been following this for a while, and I said when I found a solution I would put it up. As of today we can with one click now, scan both sides of a business card (if back is blank, it gets ignored), automatically populate memo field with the location of the image, automatically store the image based on specific record ID (i.e. it makes directories to store the physical card image data which is then referenced and updates a image base-class on the form).
So Here's the solution (note this uses EZTWAIN and Transym OCR, though the latter is totally transparent):
[Note: we parameterized this with 4 parameters: Top, Left, Width and Height. This is because we discovered that cards basically come in 2 types. Short ones, and tall ones. (No need to worry over any other part). Interestingly Tall usually means "Tall narrow, just treat it as Tall and wide". So "click" is the event you are seeing the code for. We put a different set of parameters on the RIGHTClICK and just call it from the Rightclick method: This.Click(0.0,0,0,3.55,2.15) This makes for taller and wider cards. The default (when no parameters are passed) is (0.0,0.0,3.4,2.0) so slightly shorter and narrower. Since the only difference is the TWAIN_SetRegion, we can maintain a single simple code set to manage any card size functions we want, and just change the region. This is setup for our Canon P-208II duplex scanner, which we've hard-coded, because we don't want users trying to use any input scanner willy-nilly. But you can adjust it as you see fit, and even leave the OpenSource with () to call a list.
Code:
LPARAMETERS lnTop, lnLeft, lnWidth, lnHeight
IF PARAMETERS() = 0
lnTop = 0.0
lnLeft = 0.0
lnWidth = 3.4
lnHeight = 2.0
ENDIF
LOCAL fileName AS STRING
LOCAL i AS INT
LOCAL hdib AS HANDLE
*
ThisForm.LockScreen = .T.
*
TWAIN_SetHideUI(1)
TWAIN_SetFileAppendFlag(0)
OCR_SelectDefaultEngine()
TWAIN_SetAutoOCR(1)
TWAIN_SetJpegQuality(100)
IF TWAIN_OpenSource("Canon P-208II TWAIN")<>0
TWAIN_EnableDuplex(1)
TWAIN_SetPixelType(5)
TWAIN_SetResolution(600)
TWAIN_SetAutoDeskew(1)
TWAIN_SetXferCount(-1)
TWAIN_SetAutoScan(1)
TWAIN_SetRegion(lnTop, lnLeft, lnWidth, lnHeight)
TWAIN_SetMultiTransfer(1)
i = 1
DO WHILE .T.
lcTextMergeStringIMG = ADDBS(SYS(5)+SYS(2003))+"\CARDS\"+;
ADDBS(ALLTRIM(STR(COMPANY.COMPANYID)))+ADDBS(ALLTRIM(STR(CONTACT.CONTACTID)))+;
ALLTRIM(CONTACT.CONTACTFIRSTNAME)+ALLTRIM(CONTACT.CONTACTLASTNAME)+"<<i>>.jpg"
*
fileNameIMG = TEXTMERGE(lcTextMergeStringIMG)
*
lcSaveNameIMG = TEXTMERGE("\CARDS\"+;
ADDBS(ALLTRIM(STR(COMPANY.COMPANYID)))+ADDBS(ALLTRIM(STR(CONTACT.CONTACTID)))+;
ALLTRIM(CONTACT.CONTACTFIRSTNAME)+ALLTRIM(CONTACT.CONTACTLASTNAME)+"<<i>>.jpg")
*
lcTextMergeStringPDF = ADDBS(SYS(5)+SYS(2003))+"\CARDS\"+;
ADDBS(ALLTRIM(STR(COMPANY.COMPANYID)))+ADDBS(ALLTRIM(STR(CONTACT.CONTACTID)))+;
ALLTRIM(CONTACT.CONTACTFIRSTNAME)+ALLTRIM(CONTACT.CONTACTLASTNAME)+"<<i>>.PDF"
*
fileNamePDF = TEXTMERGE(lcTextMergeStringPDF)
*
lcSaveNamePDF = TEXTMERGE("\CARDS\"+;
ADDBS(ALLTRIM(STR(COMPANY.COMPANYID)))+ADDBS(ALLTRIM(STR(CONTACT.CONTACTID)))+;
ALLTRIM(CONTACT.CONTACTFIRSTNAME)+ALLTRIM(CONTACT.CONTACTLASTNAME)+"<<i>>.PDF")
*
* If you can't get a Window handle, use 0:
lnHDIB = TWAIN_Acquire(THISFORM.HWND)
IF lnHDIB = 0
EXIT
ENDIF
*
SELECT (ThisForm.ActiveDBF)
* This processes the front of the card (in duplex still considered "first pass" it just buffers the 2nd page
IF i = 1
REPLACE CONTACT.BUSINESSCARDFRONT WITH lcSaveNameIMG &&stores the path and file name in a memo field
DIB_WriteToFilename(lnHDIB, fileNameIMG) && writes the .JPG image file of front of card to that path
DIB_WriteTOFilename(lnHDIB, filenamePDF) && writes the PDF which has also been "magically" OCRd during scan
REPLACE CONTACT.CONTACTCARDOCR WITH OCR_Text() && Puts the OCR text ouput into memo field in contact for use later
ENDIF
* This processes the back of card: we're only interested in keeping the image
IF i = 2
REPLACE CONTACT.BUSINESSCARDBACK WITH lcSaveNameIMG && writes the path and file name of the card image to memo
DIB_WriteToFilename(lnHDIB, fileNameIMG) && savest the back card image file
ENDIF
* Cleanup and finish
DIB_Free(lnHDIB)
i = i+1
IF TWAIN_IsDone()<>0 THEN
EXIT
ENDIF
*
* No need to keep the OCRd PDF around
DELETE FILE (fileNamePDF)
ENDDO
TWAIN_CloseSource()
ENDIF
*
IF TWAIN_LastErrorCode()<>0
TWAIN_ReportLastError("Unable to scan.")
ENDIF
*
SELECT (ThisForm.ActiveDBF)
*
IF NOT TABLEUPDATE()
WAIT WINDOW "Unable to Save"
TABLEREVERT()
ENDIF
*
ThisForm.Refresh()
ThisForm.LockScreen = .F.
It's actually a very elegant solution overall. EZTWAIN does an awesome job of just working with any default OCR engine, and we found Transym to be very reasonable cost ($100 USD) and very powerful (great OCR result).
Now, we have the text in a Memo field, which we can parse out into the various components... and that becomes the next step in our quest for "Card Automation".
Best Regards,
Scott
ATS, CDCE, CTIA, CTDC
"Everything should be made as simple as possible, and no simpler."