Tesseract ios SDK Error opening data file /tessdata/eng.traineddata - ios

I am developing an app with openCV and Tesseract framework.
It was working well with "NO 64 bit support" but apple requires 64-bit support in every build now onwards.
So i have updated the tesseract framework to
pod 'TesseractOCRiOS', '3.4.0'
in my project.
Now project runs well with all devices.
But when i scan any image, i always get below errors:
Error opening data file /tessdata/eng.traineddata Please make sure the
TESSDATA_PREFIX environment variable is set to the parent directory of
your "tessdata" directory. Failed loading language 'eng' Tesseract
couldn't load any languages!
I have gone through each link on google with no success.
I can make sure that i have "tessdata" folder added as folder reference in my project.

Anyways, i got the solution.
Just update the pod to latest version so your pod file should look like
pod 'TesseractOCRiOS', '4.0.0'
It automaticaly manages "tessdata" if not found in document directory. You just have to make sure it exists in your application bundle.
Then you can initialize it like
_tesseract = new tesseract::TessBaseAPI();
_tesseract->Init([[self pathToLangugeFIle] cStringUsingEncoding:NSUTF8StringEncoding], "eng");
The function should be like
- (NSString*) pathToLangugeFIle{
// Set up the tessdata path. This is included in the application bundle
// but is copied to the Documents directory on the first run.
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = ([documentPaths count] > 0) ? [documentPaths objectAtIndex:0] : nil;
NSString *dataPath = [documentPath stringByAppendingPathComponent:#"tessdata"];
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:dataPath]) {
// get the path to the app bundle (with the tessdata dir)
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *tessdataPath = [bundlePath stringByAppendingPathComponent:#"tessdata"];
if (tessdataPath) {
[fileManager copyItemAtPath:tessdataPath toPath:dataPath error:NULL];
}
}
setenv("TESSDATA_PREFIX", [[documentPath stringByAppendingString:#"/"] UTF8String], 1);
return dataPath;
}

Related

Xcode 6 keeps renaming my app's directory in iOS8 simulator after each run.

I'm running Xcode 6 Beta 5 but this has been happening since the first beta. My app's directory in the simulator keeps being renamed after each run. It took me a while to figure this out. I'm using this to get the doc's dir reference.
NSString *folder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES) lastObject];
NSLog(#"Documents Dir: %#",folder);
Now for example on the first run it'll be:
/Users/Joey/Library/Developer/CoreSimulator/Devices/5B9930EE-A9B4-4B36-BABB-AA864ACAF2DE/data/Containers/Data/Application/4B10C2E4-A5C3-4C64-93B1-4069FCCB9C46/Documents
Second run now it's:
/Users/Joey/Library/Developer/CoreSimulator/Devices/5B9930EE-A9B4-4B36-BABB-AA864ACAF2DE/data/Containers/Data/Application/7E9EB62D-115A-4092-AD23-CB6BA3E5E10F/Documents
Third run:
/Users/Joey/Library/Developer/CoreSimulator/Devices/5B9930EE-A9B4-4B36-BABB-AA864ACAF2DE/data/Containers/Data/Application/EC8F41E8-52ED-4B10-9808-B3ACC46FC6AA/Documents
This is wreaking havoc with my app because it stores path references for certain files within the app. It's not that my NSLog statement is returning incorrect results, I verified this is what happening in Finder. It's changing the name every time. Has anyone seen this happen? Is this a "feature" that I'm misunderstanding?
Turns out Xcode 6 does in fact change the app's UUID every run, and I'm in the wrong for storing absolute paths.
USE SIMPHOLDERS
I used this app on Xcode 5 opens the Documents folder, for the currently running app in the simulator, in Finder.
http://simpholders.com/
not ready for Xcode 6 yet (as of sep 24 2014) but saves all this hassle.
In Xcode 6 / iOS8 The bundle is now separate from the data./ The application GUID is regenerated between runs in Xcode (not sure why)
DOCUMENTS DIR:/Users/gbxc/Library/Developer/CoreSimulator/Devices/AC79941F-EC56-495E-A077-773EEE882732/data/Containers/Data/Application/C220D351-0BE7-46BA-B35E-D16646C61A3F/Documents
mainBundlePath_:/Users/gbxc/Library/Developer/CoreSimulator/Devices/AC79941F-EC56-495E-A077-773EEE882732/data/Containers/Bundle/Application/12200D1D-9B67-408B-BCF7-38206CBE0940/myappname.app/BLANK_BLOG_SCALED.jpg
1. FIND THE DEVICES FOLDER in SIMULATOR
/Users/gbxc/Library/Developer/CoreSimulator/Devices/
open each /device.plist to see which GUID is which device in XCode - I think this is static
3. FIND THE DEVICE you're running on iPad 2 - I think this is static
/Devices/AC79941F-EC56-495E-A077-773EEE882732
4. Find your application /Documents folder
/AC79941F-EC56-495E-A077-773EEE882732/data/Containers/Data/Application/C220D351-0BE7-46BA-B35E-D16646C61A3F/Documents
BEWARE the GUID C220D351-0BE7-46BA-B35E-D16646C61A3F is regenerated everytime the app is run in XCode 6
NSArray *paths_ = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if(paths_){
_docsDir = [paths_ firstObject];
DebugLog(#"DOCUMENTS DIR:%#",_docsDir);
}else{
ErrorLog(#"paths_ is nil - cant get Documents directory");
}
MAIN BUNDLE path
NSString *mainBundlePath_ = [[NSBundle mainBundle] pathForResource:#"someimageinyourbundle" ofType:#"jpg"];
/AC79941F-EC56-495E-A077-773EEE882732/data/Containers/Bundle/Application/12200D1D-9B67-408B-BCF7-38206CBE0940/clarksonsiq.app/BLANK_BLOG_SCALED.jpg
NEVER CACHE THE PATH to /Documents between runs it will change.
I was serializing it to a plist and couldnt figure out why they kept disappearing
The GUID above /Documents keeps changing between runs but if you have /Documents open in Finder the folder stays open.
https://devforums.apple.com/thread/235911?tstart=0
https://devforums.apple.com/thread/238754?tstart=0
Free Solution
Use Open Source Library OpenSim. OpenSim is an open source alternative for SimPholders, written in Swift.
Paid Solution
Use SimPholder application to know current application location.
For xcode 6.0 >
Download SimPholder 2.0 alpha 2
For xcode 5.1 <
Download SimPholders 1.5
I can confirm that this is Xcode 6 related not iOS 8.
I have two development machines. On one of them I have Xcode 5. I was working all the time on that machine and my URL's were fine (photo app, photos are visible).
Yesterday I checked in form git my source on a machine with Xcode 6. I noticed that my photos are not visible any more, only photos that are created during that app session.
After little debugging, I realized that file:///var/mobile/Applications/B6A6BAEF-C90C-4A2A-93DB-E6700B88971F/Documents/ is changing on every app run.
All that time I am working with iOS 7 device.
I am going to check once more on a machine with Xcode 5 to confirm when I get my hands on it.
You need to to save only path inside DocumentDirectory(directory/file name), and add it to the DocumentDirectory every time you load the file...
-(void)saveImage:(UIImage *)image{
NSData *pngData = UIImagePNGRepresentation(image);
NSString *pathInDocumentDirectory = [APP_DocumentDirectory stringByAppendingPathComponent:PROFILE_IMAGE_NAME];
NSString *filePath = [self documentsPathForFileName:pathInDocumentDirectory];
//Save pic file path - DirName/Filename.png
[XYZPreferencesHelper setUserImageFilePath:pathInDocumentDirectory];
//Write the file
[[NSFileManager defaultManager] createFileAtPath:filePath contents:pngData attributes:nil];
}
-(void)loadSavedUserPicture{
//Load saved DirName/Filename.png
NSString *pathInDocumentDirectory = [XYZPreferencesHelper getUserImageFilePath];
if (pathInDocumentDirectory != nil){
//Full path with new app Document Directory
NSString *filePath = [self documentsPathForFileName:pathInDocumentDirectory];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
NSData *pngData = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:pngData];
if (image != nil){
userPicImageView.image = image;
}
}
}
}
- (NSString *)documentsPathForFileName:(NSString *)name
{
NSString *documentsPath = [self createRestcallDirectoryIfNotExist];
return [documentsPath stringByAppendingPathComponent:name];
}
-(NSString *)createRestcallDirectoryIfNotExist{
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
path = [documentsPath stringByAppendingPathComponent:APP_DocumentDirectory];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) //Does directory already exist?
{
if (![[NSFileManager defaultManager] createDirectoryAtPath:path
withIntermediateDirectories:NO
attributes:nil
error:&error])
{
NSLog(#"Create directory error: %#", error);
}
}
return documentsPath;
}
Because app's UUID changes and not reliable 
so we should not store urls instead we should store just file names and reconstruct url at runtime , on update/reinstall iOS creates new home directory, stores app bundle in it and copies documents files so url changes


Get List of Content inside BundlePath Of Directory

I am working on project in which I require Custom Image library where
images comes from only specific directory.
so, I am creating one Directory in Document Directory and copy list
of file from Bundle path Directory named "ImageFolder" as shown in
Screenshot.
I tried different code but always I get the Array nil.I know that there is no folder at the path which i get but how to do please tell me.
-What I want >
Create Directory "xyz" in Documents Directory.
copy all files from "ImageFolder" into "xyz".
//================================================================
//================================================================
The screenshot you show of ImageFolder is a group in the Xcode project, that doesn't mean that anything related to that group will be copied into the app. If the images in that app are in your copy bundle resources build phase then they will be copied directly into the app bundle (not a sub folder).
You need to add a new copy files build phase, set the folder name, and move the images into that folder.
Once you have done that, consider why you want to copy the images. Can the user do some editing? If not then copying the images is a waste of space. If the user can 'delete' some of the images then think about storing a 'deleted items' plist or user default to just hide / filter the list of images.
This code works
-(void) copyDirectory:(NSString *)directory {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:directory];
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:directory];
if (![fileManager fileExistsAtPath:documentDBFolderPath]) {
//Create Directory!
[fileManager createDirectoryAtPath:documentDBFolderPath withIntermediateDirectories:NO attributes:nil error:&error];
NSArray *fileList = [fileManager contentsOfDirectoryAtPath:resourceDBFolderPath error:&error];
for (NSString *s in fileList) {
NSString *newFilePath = [documentDBFolderPath stringByAppendingPathComponent:s];
NSString *oldFilePath = [resourceDBFolderPath stringByAppendingPathComponent:s];
if (![fileManager fileExistsAtPath:newFilePath]) {
//File does not exist, copy it
[fileManager copyItemAtPath:oldFilePath toPath:newFilePath error:&error];
} else {
[fileManager removeItemAtPath:newFilePath error:&error];
[fileManager copyItemAtPath:oldFilePath toPath:newFilePath error:&error];
}
}
[self info:#"Copy finish!"];
}
}
In directory add the name of your folder to copy
Edit:
Your folder must be added by reference. Drag your folder into your project in xCode and select "Create folder references for any added folders"
What you have currently is a group (yellow folder icon) (physically they are not in a subfolder) - What you need to do is to create a folder outside Xcode, put in the images that you need then drag it into your project - You should have a blue folder icon and your command should work.
One other thing, just reference it, that way you do not have to keep on introducing your images to Xcode every time it will just pick it up she you compile and put it into the bundle.

Data txt files work when read in iPhone simulator, but do not work on iPhone device?

I have two text files (.txt) that are in the Documents directory of the Bundle for my project. The files load and work fine when I run the project on the iPhone Simulator in xCode, however the when I run the same project in xCode using my iPhone nothing gets loaded. I have checked and the files don't even exist in the file directory when the iPhone is selected to run the project.
Here is the code. Again this works fine and the file exists running under iPhone simulator in xCode, but the file does NOT exist when I run it using my iPhone as the device.
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [arrayPaths objectAtIndex:0];
NSString *path = [docDir stringByAppendingPathComponent:CURRENTPUZZLENUMBERFILE];
NSLog(#"Path = %#", path); // for debugging
bool fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
NSLog(#"File exists: %d", fileExists); // for debugging
Grab the file this way then you can copy it to your doc dir if you wish
NSString *filePath = [[NSBundle mainBundle] pathForResource:CURRENTPUZZLENUMBERFILE ofType:#"txt"];

Download created files from iPhone App's document folder on PC

I created some files which store some logging information in my iPhone App. They are stored in the App's document folder. I would like to download them onto my Mac. I'm able to see them in the xCode organizer but I'm not able to access these files. How can I achieve this?
First, set Application supports iTunes file sharing on on your project's settings plist. It could also be named UIFileSharingEnabled.
Then, for the code, save the file in NSDocumentDirectory like so:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Id its a local file in the app use its name. If not, alter for your needs.
NSString *fileName = #"someFile.png";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:fileName];
 
if (![fileManager fileExistsAtPath:documentDBFolderPath]) {
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
[self.window makeKeyAndVisible]; 
return YES;
}
All taken from iOS Dev Tips - File Sharing from App to iTunes is too easy
Using the Download button in the Organizer allows you to save a .xcappdata package to your Mac (Xcode 4.2, previous versions just save a folder). You can right-click and choose "Show Package Contents", a Finder window will open and you can find a copy of the Documents directory therein.

iPhone App Update. "createSymbolicLinkAtPath" released?

I am using the symbolic link with iPhoneApp.
NSString* js_path = [[NSBundle mainBundle] pathForResource:#"js" ofType:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if (js_path != nil) {
NSFileManager *fm = [NSFileManager defaultManager];
NSString* move_js_path = [NSString stringWithFormat:#"%#/js", [paths objectAtIndex:0]];
NSError *error;
if ([fm createSymbolicLinkAtPath:move_js_path withDestinationPath:js_path error:&error]) {
} else {}
}
I updated the application program. It becomes impossible to read the file afterwards.
However, the file was able to be read by reinstalling it after the application program had been deleted once.
Is there a problem in this code?
If anyones wondering about this, the reason is the application moves directory every time it's updated, the solution might be to use relative paths bundles are located at /var/mobile/Applications/[unique id that changes every update]/app.app whereas the documents directory is located at /var/mobile/Applications/[unique id that changes every update]/Documents so a symlink from Documents to the bundle will always work if it uses something like ../[bundlepath lastPathComponent]/Documents
ofc it's a good idea to build the relativeness from the directories you get at runtime rather than hard coding it, incase these relative paths change in the future.

Resources