Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update Tessract.h & Tessract.mm, adding clear method to avoid memory lea... #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion External/Tesseract-Wrapper/Tesseract.h
Original file line number Diff line number Diff line change
@@ -9,19 +9,65 @@

#import <Foundation/Foundation.h>

@interface Tesseract : NSObject {
extern NSString * const OcrEngineModeTesseractOnly;
extern NSString * const OcrEngineModeCubeOnly;
extern NSString * const OcrEngineModeTesseractCubeCombined;
extern NSString * const OcrEngineModeDefault;

@interface Tesseract : NSObject {
NSString* _dataPath;
NSString* _language;
NSMutableDictionary* _variables;
}

+ (NSString *)version;

/**
* Returns <code>NO</code> or <code>nil</code> on failure. On success, Returns
* an initialized <code>Tesseract</code> object set up to use the given tessdata
* path, language, and OCR engine mode, configured with the given variables and
* configuration filenames.
*
* @param dataPath
* The name of the parent directory of tessdata. Must end in / . Any name after
* the last / will be stripped.
* @param language
* An ISO 639-3 string or nil, which will default to eng.
* The language may be a string of the form [~]<lang>[+[~]<lang>]* indicating
* that multiple languages are to be loaded. Eg hin+eng will load Hindi and
* English. Languages may specify internally that they want to be loaded with
* one or more other languages, so the ~ sign is available to override that.
* Eg if hin were set to load eng by default, then hin+~eng would force loading
* only hin. The number of loaded languages is limited only by memory, with the
* caveat that loading additional languages will impact both speed and
* accuracy, as there is more work to do to decide on the applicable language,
* and there is more chance of hallucinating incorrect words.
* @param mode
* The OcrEngineMode to use or nil, which is equivalent to OcrEngineModeDefault
* @param configFilenames
* The names (including paths) of config files to use. Example config files can
* be found at
* http://code.google.com/p/tesseract-ocr/source/browse/#svn/trunk/tessdata/configs
* @param variables
* A dictionary of tesseract variables to set. Each key must be an NSString
* instance corresponding to a tesseract variable, and each value must be an
* NSString instance containing a valid value for that variable.
* Eg @{@"tessedit_char_whitelist" : @"0123456789.-"}
* @param setOnlyNonDebugParams
* If true, only params that do not contain "debug" in the name will be set.
*/
- (id)initWithDataPath:(NSString *)dataPath
language:(NSString *)language
ocrEngineMode:(NSString *)mode
configFilenames:(NSArray*)configFilenames
variables:(NSDictionary*)variables
setOnlyNonDebugParams:(BOOL)setOnlyNonDebugParams;
- (id)initWithDataPath:(NSString *)dataPath language:(NSString *)language;
- (void)setVariableValue:(NSString *)value forKey:(NSString *)key;
- (void)setImage:(UIImage *)image;
- (BOOL)setLanguage:(NSString *)language;
- (BOOL)recognize;
- (NSString *)recognizedText;
- (void)clear;

@end
102 changes: 97 additions & 5 deletions External/Tesseract-Wrapper/Tesseract.mm
Original file line number Diff line number Diff line change
@@ -13,13 +13,22 @@
#import "environ.h"
#import "pix.h"

NSString * const OcrEngineModeTesseractOnly = @"OcrEngineModeTesseractOnly";
NSString * const OcrEngineModeCubeOnly = @"OcrEngineModeCubeOnly";
NSString * const OcrEngineModeTesseractCubeCombined = @"OcrEngineModeTesseractCubeCombined";
NSString * const OcrEngineModeDefault = @"OcrEngineModeDefault";

namespace tesseract {
class TessBaseAPI;
};

@interface Tesseract () {
tesseract::TessBaseAPI* _tesseract;
uint32_t* _pixels;
bool _setOnlyNonDebugParams;
tesseract::OcrEngineMode _ocrEngineMode;

NSArray* _configFilenames;
}

@end
@@ -30,26 +39,99 @@ + (NSString *)version {
return [NSString stringWithFormat:@"%s", tesseract::TessBaseAPI::Version()];
}

- (id)initWithDataPath:(NSString *)dataPath language:(NSString *)language {
- (id)initWithDataPath:(NSString *)dataPath
language:(NSString *)language
ocrEngineMode:(NSString *)mode
configFilenames:(NSArray*)configFilenames
variables:(NSDictionary*)variables
setOnlyNonDebugParams:(BOOL)setOnlyNonDebugParams {
self = [super init];
if (self) {
_dataPath = dataPath;
_language = language;
_variables = [[NSMutableDictionary alloc] init];

if (mode) {
if ([mode isEqualToString:OcrEngineModeTesseractOnly]) {
_ocrEngineMode = tesseract::OEM_TESSERACT_ONLY;
} else if ([mode isEqualToString:OcrEngineModeCubeOnly]) {
_ocrEngineMode = tesseract::OEM_CUBE_ONLY;
} else if ([mode isEqualToString:OcrEngineModeTesseractCubeCombined]) {
_ocrEngineMode = tesseract::OEM_TESSERACT_CUBE_COMBINED;
} else {
_ocrEngineMode = tesseract::OEM_DEFAULT;
}
} else {
_ocrEngineMode = tesseract::OEM_DEFAULT;
}

_configFilenames = configFilenames;

if (variables) {
_variables = [variables mutableCopyWithZone:NULL];
} else {
_variables = [[NSMutableDictionary alloc] init];
}

if (setOnlyNonDebugParams) {
_setOnlyNonDebugParams = true;
} else {
_setOnlyNonDebugParams = false;
}

[self copyDataToDocumentsDirectory];
_tesseract = new tesseract::TessBaseAPI();

BOOL success = [self initEngine];
if (!success) {
return NO;
return nil;
}
}
return self;
}

- (id)initWithDataPath:(NSString *)dataPath language:(NSString *)language {
return [self initWithDataPath:dataPath
language:language
ocrEngineMode:OcrEngineModeDefault
configFilenames:nil
variables:nil
setOnlyNonDebugParams:NO];
}

- (BOOL)initEngine {
int returnCode = _tesseract->Init([_dataPath UTF8String], [_language UTF8String]);
char **configs = NULL;
int configs_size = 0;
GenericVector<STRING> keys;
GenericVector<STRING> values;

if (_configFilenames && _configFilenames.count > 0) {
configs = (char**) malloc(_configFilenames.count * sizeof(char*));
for (; configs_size < _configFilenames.count; configs_size++) {
configs[configs_size] = (char*) malloc((((NSString*)(_configFilenames[configs_size])).length + 1) * sizeof(char));
strncpy(configs[configs_size], [_configFilenames[configs_size] UTF8String], ((NSString*)(_configFilenames[configs_size])).length + 1);
}
}

for (NSString* key in _variables) {
keys.push_back([key UTF8String]);
values.push_back([_variables[key] UTF8String]);
}

int returnCode = _tesseract->Init(_dataPath ? [_dataPath UTF8String] : NULL,
_language ? [_language UTF8String] : NULL,
_ocrEngineMode,
configs,
configs_size,
&keys,
&values,
_setOnlyNonDebugParams);
if (configs) {
for (int filenameIndex = 0; filenameIndex < configs_size; filenameIndex++) {
free(configs[filenameIndex]);
}
free(configs);
}

return (returnCode == 0) ? YES : NO;
}

@@ -113,7 +195,17 @@ - (BOOL)recognize {

- (NSString *)recognizedText {
char* utf8Text = _tesseract->GetUTF8Text();
return [NSString stringWithUTF8String:utf8Text];
NSString *text = utf8Text ? [NSString stringWithUTF8String: utf8Text] : @"";
delete[] utf8Text;
return text;
}

- (void)clear
{
free(_pixels);
_tesseract->Clear();
_tesseract->End();
delete _tesseract;
}

- (void)setImage:(UIImage *)image
13 changes: 13 additions & 0 deletions OCR-Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
48E5A2F419AE0ECC005BBE59 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 48E5A2F319AE0ECC005BBE59 /* Images.xcassets */; };
7462256B173DCADA003EE853 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7462256A173DCADA003EE853 /* UIKit.framework */; };
7462256D173DCADA003EE853 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7462256C173DCADA003EE853 /* Foundation.framework */; };
7462256F173DCADA003EE853 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7462256E173DCADA003EE853 /* CoreGraphics.framework */; };
@@ -28,6 +29,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
48E5A2F319AE0ECC005BBE59 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
74622567173DCADA003EE853 /* OCR-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OCR-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
7462256A173DCADA003EE853 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
7462256C173DCADA003EE853 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -255,6 +257,7 @@
7462258E173DCD74003EE853 /* ResultsViewController.mm */,
746226E4173DDDC9003EE853 /* ImageProcessing.h */,
746226E5173DDDC9003EE853 /* ImageProcessing.mm */,
48E5A2F319AE0ECC005BBE59 /* Images.xcassets */,
74622571173DCADA003EE853 /* Supporting Files */,
);
path = "OCR-Example";
@@ -530,6 +533,7 @@
buildActionMask = 2147483647;
files = (
74622575173DCADA003EE853 /* InfoPlist.strings in Resources */,
48E5A2F419AE0ECC005BBE59 /* Images.xcassets in Resources */,
7462257D173DCADA003EE853 /* Default.png in Resources */,
7462257F173DCADA003EE853 /* Default@2x.png in Resources */,
74622581173DCADA003EE853 /* Default-568h@2x.png in Resources */,
@@ -636,8 +640,11 @@
7462258B173DCADA003EE853 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
CODE_SIGN_IDENTITY = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "OCR-Example/OCR-Example-Prefix.pch";
@@ -647,16 +654,21 @@
"\"$(SRCROOT)/OCR-Example/tesseract-ios-lib/lib\"",
"\"$(SRCROOT)/External/tesseract-ios-lib/lib\"",
);
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
VALID_ARCHS = "armv7 armv7s";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
7462258C173DCADA003EE853 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
CODE_SIGN_IDENTITY = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "OCR-Example/OCR-Example-Prefix.pch";
@@ -667,6 +679,7 @@
"\"$(SRCROOT)/External/tesseract-ios-lib/lib\"",
);
PRODUCT_NAME = "$(TARGET_NAME)";
VALID_ARCHS = "armv7 armv7s";
WRAPPER_EXTENSION = app;
};
name = Release;
38 changes: 38 additions & 0 deletions OCR-Example/Images.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "1x",
"size" : "57x57"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "57x57"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
42 changes: 42 additions & 0 deletions OCR-Example/Images.xcassets/LaunchImage.launchimage/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default@2x.png",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default-568h@2x.png",
"minimum-system-version" : "7.0",
"subtype" : "retina4",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default.png",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default@2x.png",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default-568h@2x.png",
"subtype" : "retina4",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion OCR-Example/OCR-Example-Info.plist
Original file line number Diff line number Diff line change
@@ -8,8 +8,12 @@
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
<string>Christopher-Constable.${PRODUCT_NAME:rfc1034identifier}</string>
<string>com.glory.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
1 change: 1 addition & 0 deletions OCR-Example/ResultsViewController.mm
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ - (void)viewDidAppear:(BOOL)animated
completion:^(BOOL finished) {
self.loadingView.hidden = YES;
[self.resultsTextView setText:[tesseract recognizedText]];
[tesseract clear];
}];
});
});
Loading