summaryrefslogtreecommitdiffstats
path: root/kooka/kadmosocr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kooka/kadmosocr.cpp')
-rw-r--r--kooka/kadmosocr.cpp432
1 files changed, 432 insertions, 0 deletions
diff --git a/kooka/kadmosocr.cpp b/kooka/kadmosocr.cpp
new file mode 100644
index 00000000..72f9324b
--- /dev/null
+++ b/kooka/kadmosocr.cpp
@@ -0,0 +1,432 @@
+/***************************************************************************
+ kadmosocr.cpp - Kadmos cpp interface
+ -------------------
+ begin : Fri Jun 30 2000
+
+ (c) 2002 re Recognition AG Hafenstrasse 50b CH-8280 Kreuzlingen
+ Switzerland Phone: +41 (0)71 6780000 Fax: +41 (0)71 6780099
+ Website: www.reRecognition.com E-mail: info@reRecognition.com
+
+ Author: Tamas Nagy (nagy@rerecognition.com)
+ Klaas Freitag <freitag@suse.de>
+ Heike Stuerzenhofecker <heike@freisturz.de>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This file may be distributed and/or modified under the terms of the *
+ * GNU General Public License version 2 as published by the Free Software *
+ * Foundation and appearing in the file COPYING included in the *
+ * packaging of this file. *
+ *
+ * As a special exception, permission is given to link this program *
+ * with any version of the KADMOS ocr/icr engine of reRecognition GmbH, *
+ * Kreuzlingen and distribute the resulting executable without *
+ * including the source code for KADMOS in the source distribution. *
+ *
+ * As a special exception, permission is given to link this program *
+ * with any edition of Qt, and distribute the resulting executable, *
+ * without including the source code for Qt in the source distribution. *
+ * *
+ ***************************************************************************/
+
+/* Kadmos CPP object oriented interface */
+
+#include <qimage.h>
+#include <qpainter.h>
+#include <qstring.h>
+#include <qrect.h>
+#include <qstringlist.h>
+
+#include <assert.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <kdebug.h>
+
+#include "kadmosocr.h"
+#include "ocrword.h"
+
+#ifdef HAVE_KADMOS
+
+using namespace Kadmos;
+
+/* -------------------- CRep -------------------- */
+CRep::CRep()
+ :QObject()
+{
+ memset(&m_RepData, 0, sizeof(m_RepData));
+ m_Error = RE_SUCCESS;
+ m_undetectChar = QChar('_');
+}
+
+CRep::~CRep()
+{
+}
+
+RelGraph* CRep::getGraphKnode(int line, int offset )
+{
+ Kadmos::RepResult *res = getRepResult(line);
+ if( res )
+ return ( &(getRepResult(line)->rel_graph[0])+offset);
+ else
+ return 0L;
+
+}
+
+
+RepResult* CRep::getRepResult(int line)
+{
+ if( line<0 || line >= m_RepData.rep_result_len ) return 0L;
+ return &(m_RepData.rep_result[line]);
+}
+
+RelResult* CRep::getRelResult(int line, RelGraph* graph, int alternative)
+{
+ if( ! ( graph && getRepResult(line))) return 0L;
+ int offset = graph->result_number[alternative];
+ return( &(getRepResult(line)->rel_result[0]) + offset );
+}
+
+
+KADMOS_ERROR CRep::Init(const char* ClassifierFilename)
+{
+ /* prepare RepData structure */
+ m_RepData.init.rel_grid_maxlen = GRID_MAX_LEN;
+ m_RepData.init.rel_graph_maxlen = GRAPH_MAX_LEN;
+ m_RepData.init.rel_result_maxlen = CHAR_MAX_LEN;
+ m_RepData.init.rep_memory_size = LINE_MAX_LEN * sizeof(RepResult) +
+ (long)LINE_MAX_LEN * CHAR_MAX_LEN * (sizeof(RelGraph)+
+ sizeof(RelResult));
+ m_RepData.init.rep_memory = malloc( m_RepData.init.rep_memory_size );
+ if (!m_RepData.init.rep_memory) {
+ CheckError();
+ return m_Error;
+ }
+ strcpy(m_RepData.init.version, INC_KADMOS);
+
+ m_Error = rep_init(&m_RepData, (char*)ClassifierFilename);
+ CheckError();
+ return m_Error;
+}
+
+void CRep::run() // KADMOS_ERROR CRep::Recognize()
+{
+ kdDebug(28000) << "ooo Locked and ocr!" << endl;
+ m_Error = rep_do(&m_RepData);
+ CheckError();
+}
+
+KADMOS_ERROR CRep::End()
+{
+ m_Error = rep_end(&m_RepData);
+ CheckError();
+ return m_Error;
+}
+
+int CRep::GetMaxLine()
+{
+ return m_RepData.rep_result_len;
+}
+
+const char* CRep::RepTextLine(int nLine, unsigned char RejectLevel, int RejectChar, long Format)
+{
+ m_Error = rep_textline(&m_RepData, nLine, m_Line,
+ 2*CHAR_MAX_LEN, RejectLevel, RejectChar, Format);
+ CheckError();
+ return m_Line;
+}
+
+/**
+ * This method handles the given line. It takes repRes and goes through the
+ * kadmos result tree structures recursivly.
+ */
+ocrWordList CRep::getLineWords( int line )
+{
+ ocrWordList repWords;
+ bool ok = true;
+
+ Kadmos::RepResult *repRes = getRepResult(line);
+
+ if( ! repRes )
+ {
+ kdDebug(28000) << "repRes-Pointer is null" << endl;
+ ok = false;
+ }
+
+ if( ok )
+ {
+ int nextKnode=0;
+
+ do
+ {
+ QString resultWord;
+ QRect boundingRect;
+
+ int newNextKnode = nextBestWord( line, nextKnode, resultWord, boundingRect );
+ boundingRect.moveBy( repRes->left, repRes->top );
+
+ ocrWord newWord;
+ newWord = resultWord;
+ newWord.setKnode(nextKnode);
+ newWord.setLine(line);
+ newWord.setRect(boundingRect);
+ repWords.push_back(newWord);
+
+ /* set nextKnode to the next Knode */
+ nextKnode = newNextKnode;
+
+
+ // Alternativen:
+ // partStrings( line, nextKnode, QString()); // fills m_parts - list with alternative words
+ // nextKnode = newNextKnode;
+ // kdDebug(28000) << "NextKnodeWord: " << resultWord << endl;
+ }
+ while( nextKnode > 0 );
+ }
+ return repWords;
+}
+
+
+/* This fills theWord with the next best word and returns the
+ * next knode or 0 if there is no next node
+ */
+int CRep::nextBestWord( int line, int knode, QString& theWord, QRect& brect )
+{
+
+ Kadmos::RelGraph *relg = getGraphKnode( line, knode );
+ // kdDebug(28000) << "GraphKnode is " << knode << endl;
+ int nextKnode = knode;
+
+ while( relg )
+ {
+ Kadmos::RelResult *relr = getRelResult( line, relg, 0 ); // best alternative
+ if( relr )
+ {
+ // kdDebug(28000) << "Leading Blanks: " << relg->leading_blanks <<
+ // " und Knode " << knode << endl;
+ char c = relr->rec_char[0][0];
+ QChar newChar = c;
+ if( c == 0 )
+ {
+ kdDebug(28000) << "Undetected char found !" << endl;
+ newChar = m_undetectChar;
+ }
+
+ if ( (nextKnode != knode) && (relg->leading_blanks > 0))
+ {
+ /* this means the word ends here. */
+ // kdDebug(28000) << "----" << theWord << endl;
+ relg = 0L; /* Leave the loop. */
+ }
+ else
+ {
+ /* append the character */
+ theWord.append(newChar);
+
+ /* save the bounding rect */
+ // kdDebug(28000) << "LEFT: " << relr->left << " TOP: " << relr->top << endl;
+ QRect r( relr->left, relr->top, relr->width, relr->height );
+
+ if( brect.isNull() )
+ {
+ brect = r;
+ }
+ else
+ {
+ brect = brect.unite( r );
+ }
+
+ /* next knode */
+ if( relg->next[0] > 0 )
+ {
+ nextKnode = relg->next[0];
+ relg = getGraphKnode( line, nextKnode );
+ }
+ else
+ {
+ /* end of the line */
+ nextKnode = 0;
+ relg = 0L;
+ }
+ }
+ }
+ }
+ return( nextKnode );
+}
+
+
+
+void CRep::partStrings( int line, int graphKnode, QString soFar )
+{
+ /* The following knodes after a word break */
+ Kadmos::RelGraph *relg = getGraphKnode( line, graphKnode );
+ // kdDebug(28000) << "GraphKnode is " << graphKnode << endl;
+
+ QString theWord="";
+ for( int resNo=0; resNo < SEG_ALT; resNo++ )
+ {
+ // kdDebug(28000) << "Alternative " << resNo << " is " << relg->result_number[resNo] << endl;
+ if( relg->result_number[resNo] == -1 )
+ {
+ /* This means that there is no other alternative. Go out here. */
+ break;
+ }
+
+ Kadmos::RelResult *relr = getRelResult( line, relg, resNo );
+ theWord = QChar(relr->rec_char[0][0]);
+
+ if ( !soFar.isEmpty() && relg->leading_blanks )
+ {
+ /* this means the previous words end. */
+ // TODO: This forgets the alternatives of _this_ first character of the new word.
+
+ kdDebug(28000) << "---- " << soFar << endl;
+ m_parts << soFar;
+ break;
+ }
+ else
+ {
+ /* make a QString from this single char and append it. */
+ soFar += theWord;
+ }
+
+ if( relg->next[resNo] > 0 )
+ {
+ /* There is a follower to this knode. Combine the result list from a recursive call
+ * to this function with the follower knode.
+ */
+ partStrings( line, relg->next[resNo], soFar );
+ }
+ else
+ {
+ /* There is no follower */
+ kdDebug(28000) << "No followers - theWord is " << soFar << endl;
+ m_parts<<soFar;
+ break;
+ }
+ }
+}
+
+
+
+void CRep::drawCharBox( QPixmap *pix, const QRect& r )
+{
+ drawBox( pix, r, QColor( Qt::red ));
+}
+
+void CRep::drawLineBox( QPixmap* pix, const QRect& r )
+{
+ drawBox( pix, r, QColor( Qt::blue ));
+}
+
+void CRep::drawBox( QPixmap* pix, const QRect& r, const QColor& color )
+{
+ QPainter p;
+ p.begin(pix);
+
+ p.setPen( color );
+ p.drawRect(r);
+}
+
+
+
+KADMOS_ERROR CRep::SetImage( const QString file )
+{
+ ReImageHandle image_handle;
+ image_handle = re_readimage(file.latin1(), &m_RepData.image);
+ if( ! image_handle )
+ {
+ kdDebug(28000) << "Can not load input file" << endl;
+ }
+ CheckError();
+ return RE_SUCCESS;
+
+}
+
+KADMOS_ERROR CRep::SetImage(QImage *Image)
+{
+ // memcpy(&m_RepData.image, Image.bits(), Image.numBytes());
+ if( !Image ) return RE_PARAMETERERROR;
+
+ kdDebug(28000) << "Setting image manually." << endl;
+ m_RepData.image.data = (void*)Image->bits();
+ m_RepData.image.imgtype = IMGTYPE_PIXELARRAY;
+ m_RepData.image.width = Image->width();
+ m_RepData.image.height = Image->height();
+ m_RepData.image.bitsperpixel = Image->depth();
+ m_RepData.image.alignment = 1;
+ m_RepData.image.fillorder = FILLORDER_MSB2LSB;
+ // color
+ if( Image->depth() == 1 || (Image->numColors()==2 && Image->depth() == 8) )
+ {
+ m_RepData.image.color=COLOR_BINARY;
+ kdDebug(28000) << "Setting Binary" << endl;
+ } else if( Image->isGrayscale() ) {
+ m_RepData.image.color = COLOR_GRAY;
+ kdDebug(28000) << "Setting GRAY" << endl;
+
+ } else {
+ m_RepData.image.color = COLOR_RGB;
+ kdDebug(28000) << "Setting Color RGB" << endl;
+ }
+ // orientation
+ m_RepData.image.orientation = ORIENTATION_TOPLEFT;
+ m_RepData.image.photometric = PHOTOMETRIC_MINISWHITE;
+ m_RepData.image.resunit = RESUNIT_INCH;
+ m_RepData.image.xresolution = 200;
+ m_RepData.image.yresolution = 200;
+
+ CheckError();
+
+ return RE_SUCCESS;
+}
+
+void CRep::SetNoiseReduction(bool bNoiseReduction)
+{
+ if (bNoiseReduction) {
+ m_RepData.parm.prep |= PREP_AUTO_NOISEREDUCTION;
+ }
+ else {
+ m_RepData.parm.prep &= !PREP_AUTO_NOISEREDUCTION;
+ }
+}
+
+void CRep::SetScaling(bool bScaling)
+{
+ if (bScaling) {
+ m_RepData.parm.prep |= PREP_SCALING;
+ }
+ else {
+ m_RepData.parm.prep &= !PREP_SCALING;
+ }
+}
+
+void CRep::CheckError()
+{
+ if ( kadmosError() )
+ {
+ kdDebug(28000) << "KADMOS ERROR: " << getErrorText() << endl;
+ }
+}
+
+/* returns a QString containing the string describing the kadmos error */
+QString CRep::getErrorText() const
+{
+ re_ErrorText Err;
+ re_GetErrorText(&Err);
+ return QString::fromLocal8Bit( Err.text );
+}
+
+bool CRep::kadmosError()
+{
+ return m_Error != RE_SUCCESS;
+}
+
+#include "kadmosocr.moc"
+
+#endif /* HAVE_KADMOS */
+
+
+// } /* End of Kadmos namespace */