Saving in NSDocumentDirectory uniquely - iphone

Hi Im really having a hard time saving in my NSDocumentDirectory.Im using AGImagePickerby the way. Yes I was able to save this in NSDocumentDirectory. But how to save them uniquely ( in terms of their own then converting their names into oneSlotImages) or save them with their unique IDs then load them back. Sorry Im kinda new to this UIImagePickerControllerMediaURL thing., I think that would be my solution to my other problem for not overlaping them when saving. How to save this using their unique ID, or UIImagePickerControllerMediaURL.
for (int i = 0; i < info.count; i++) {
NSLog(#"%#", [info objectAtIndex:i]);
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask ,YES );
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"oneSlotImages%d.png", i]];
ALAssetRepresentation *rep = [[info objectAtIndex: i] defaultRepresentation];
UIImage *image = [UIImage imageWithCGImage:[rep fullResolutionImage]];
//----resize the images
image = [self imageByScalingAndCroppingForSize:image toSize:CGSizeMake(256,256*image.size.height/image.size.width)];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:YES];
Thanks for the help. Much Appreciated.

You could always keep a list of used names and do something like this
int i = 1;
while([listOfUsedNames containsObject:nextAvailableTile]) {
nextAvailableTitle = [kDefaultImageName stringByAppendingFormat:#" %d", i];
i++;
}
// found an unused name

The URL for each image is unique right? So we can make use of this. Convert the URL into MD5 string (which form a unique identifier for each image). And save with that name (like "MD5string.png").
Why can't we use this?
Hope this helps you.
For converting to MD5, please create a file named NSString+MD5.h and put the code
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#interface NSString(MD5)
- (NSString *)MD5;
#end
in it.
Then in the NSString+MD5.m,
#import "NSString+MD5.h"
#implementation NSString(MD5)
- (NSString*)MD5
{
const char *ptr = [self UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(ptr, strlen(ptr), md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
#end
Import the NSString+MD5.h class where ever you want to use the MD5 function with normal NSString object.
In you code if you have the UIImagePickerControllerMediaURL string, since it is unique for every file you can convert in to MD5 String like
NSString *imgURL = [NSString stringWithString: UIImagePickerControllerMediaURL];
NSString *MD5String = [imgURL MD5];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", MD5String]];
Use that path to save your image file.
On Loading,
Convert the UIImagePickerControllerMediaURL into MD5 and check in the Documents directory for the file
// In this the UIImagePickerControllerMediaURL is the URL of media file to load
NSString *imgURL = [NSString stringWithString: UIImagePickerControllerMediaURL];
NSString *MD5String = [imgURL MD5];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", MD5String]];
Then do the checking with the fileExistsAtPath method of NSFileManager and if exists then load the file from the path. Thats it.
Note: For this you want to keep the UIImagePickerControllerMediaURL of the images you saved in documents directory locally somewhere in your app (In DB or NSUserDefaults) for make use of then at the time of loading.

Try this:
NSMutableString *imageName = [[[NSMutableString alloc] initWithCapacity:0] autorelease];
CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
if (theUUID) {
[imageName appendString:NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID))];
CFRelease(theUUID);
}
[imageName appendString:#".png"];

Related

Convert captured image in to a separate png file, and insert that png file name as a string in to sqlite data base and retrieve it

In my iPhone app I need to capture a picture and save it in to the sqlite database.
NSString *insertQuery = [NSString stringWithFormat:#"INSERT INTO ProfileTable (NAME, MOBILE, EMAIL, ProfilePICTURE) VALUES(?, ?, ?, ?)"];
const char *insert = [insertQuery UTF8String];
if(sqlite3_prepare_v2(contactsDB, insert, -1, &insertStatement, NULL) != SQLITE_OK) {
NSLog(#"Error while creating insert Statement");
}
else
{
sqlite3_bind_text(insertStatement, 1, [name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insertStatement, 2, [mobile UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(insertStatement, 2, [email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_blob(insertStatement, 4, [profilePic bytes], [contactImage length], NULL);
}
}
// Same Query for insert statement also
I saved that file in the form of blob type but that cause to occupy huge memory and causes to memory warnings.
So i have an idea that.
I want to save the captured image as a png file for suppose "image1.png" and insert that title "image1.png" as a varchar type and the retrieve that file having that name when we want to display.
any help how to do this
Get the document directory (or other directory that you might want to store the images):
/**
Returns the URL to the application's Documents directory.
*/
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
Store image as png:
NSURL *documentsDirURL = [self applicationDocumentsDirectory];
NSURL *fileURL = [documentsDirURL URLByAppendingPathComponent:#"some-image-name.png"];
NSData* data = UIImagePNGRepresentation(image);
[data writeToURL:fileURL atomically:YES];
NSString *filePath = [fileURL path];
// now save your filePath as string to sqlite
Note, you'll have to fill in details, such as where the appropriate directory is in the filesystem, a naming convention, generating filenames unless they exist already etc.
EDIT:
Here's some help with serial naming of the images. There are a lot of different solutions.
Create an entry in the NSUserDefaults with the key #"lastImageNumber". When you need a new image name:
NSInteger imageNumber = [[NSUserDefaults standardUserDefaults] integerForKey:#"lastImageNumber"] + 1;
NSString *imageName = [NSString stringWithFormat:#"image%05d.png",imageNumber];
// save the new imageNumber in the `NSUserDefaults`
[[NSUserDefaults standardUserDefaults] setInteger:imageNum ForKey:#"lastImageNumber"];
Add int counter in appDelegate.h file
Also add In application didFinishLaunchingWithOptions method:
counter = 0;
if(![[NSUserDefaults standardUserDefaults] integerForKey:#"ImageNumber"])
{
[[NSUserDefaults standardUserDefaults] setInteger:counter ForKey:#"ImageNumber"]
}
else
{
counter = [[NSUserDefaults standardUserDefaults] integerForKey:#"ImageNumber"];
}
Also add this method in appDelegate.h file
+ (NSString *) applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
Now when ever adding captured image in database firstly add int Doc Directory like this:
appDelegate = (appDelegate *)[[UIApplication sharedApplication] delegate];
NSString *strDocDirPath = [appDelegate applicationDocumentsDirectory];
NSString *fileName = [NSString stringWithFormat:#"Image%03d.png",appDelegate.counter];
strDocDirPath = [strDocDirPath stringByAppendingPathComponent:fileName];
NSData* imgdata = UIImagePNGRepresentation(yourCapturedImage);
[imgdata writeToFile:strDocDirPath atomically:YES];
appDelegate.counter ++;
[[NSUserDefaults standardUserDefaults] setInteger:appDelegate.counter ForKey:#"ImageNumber"];
//add in database with fileName
Retrieve like this:
appDelegate = (appDelegate *)[[UIApplication sharedApplication] delegate];
NSString *strDocDirPath = [appDelegate applicationDocumentsDirectory];
strDocDirPath = [strDocDirPath stringByAppendingPathComponent:#"Image001.png"]; //use your database image name here
UIImage *img = [[UIImage alloc]initWithContentsOfFile:strDocDirPath];
Every time you can Create a Random String and Rename that image Which you capture to Randomly generated string.
NSString *letters = #"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity:6];
for (int i=0; i<6; i++)
{
[randomString appendFormat: #"%C", [letters characterAtIndex: arc4random() % [letters length]]];
}
NSString *fileName = [NSString stringWithFormat:#"%#.png",randomString];
Hope this will Help.

Property 'jsonData' not found on object of type 'MapViewController *'

I am trying to draw the route on the graphic layer of my app application and i do not know is this the right approach to do it, or is there another way to do it? Where i am trying to use NSArray with ArgGIS to draw out the map am i have problem with it.
*edit I tried to change the NSArray back to a JSON string and try to draw it using ArcGIS with a JSON string
This is what i have done:
NSArray *BusRoute=[jsonResult objectForKey:#"BusRoute"];
int i;
int count = [BusRoute count];
for (i = 0; i < count; i++)
{
NSDictionary *dic = [BusRoute objectAtIndex: i];
NSString *Duration = [dic valueForKey:#"Duration"];
//---PATH---
NSArray *PATH = [dic valueForKey:#"PATH"];
NSLog(#"PATH = %#", PATH);
self.path = PATH;
}
NSError *writeError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:path options:NSJSONWritingPrettyPrinted error:&writeError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"JSON Output: %#", jsonString);
if (self.jsonString) {
// symbolize the returned route graphic
self.jsonString.routeGraphic.symbol = [self routeSymbol];
// add the route graphic to the graphic's layer
[self._graphicsLayer addGraphic:self.jsonString.routeGraphic];
// tell the graphics layer to redraw
[self._graphicsLayer dataChanged];
}
*Output for JSON string
JSON Output: [
[
"38909,35576;38872,35589;38861,35593;38848,35597;38697,35650;38695,35651;38695,35651;38609,35681;38583,35689;38553,35697;38508,35700;38476...;29560,40043"
]
]
This is a portion of the path that i have to draw on the map:
PATH = (( "38909,35576;38872,35589;38861,35593;38848,35597;38697,35650;38695,35651;38695,35651;38609,35681;38583,35689;38553,35697;38508,35700;38476,35696;38476,35696;....))
for this line self.jsonData.routeGraphic.symbol = [self routeSymbol]; i am getting an error Property 'Property 'jsonData' not found on object of type 'MapViewController *'
what should i do to solve? pls help
*How can i draw the line of the path using the NSArray and using ArcGIS?
routeGraphic property does not have any association with NSArray Class. NSArray is the Collection.
Your code is a little strange.
what is routeGrphic???
Are not you forgotten the like code below?
YourObject *object = [path objectAtIndex:index];
object.routeGraphic.symbol = [self routeSymbol];

locate byte in pdf file and read line

I try to read pdf file. I want to use this function
databuffer = [file readDataOfLength : 7] but i want read all the byte in the line .
It mean I use seekToFileOffset to find the byte but I want read the line.
NSMutableArray *nameArray = [[NSMutableArray alloc] initWithObjects:nil];
NSMutableArray *nameArrayDict = [[NSMutableArray alloc] initWithObjects:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:#"testpdf" ofType:#"pdf"];
NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:nil];
int var=[[nameArray objectAtIndex:[nameArray count]-2] intValue];
NSFileHandle *file;
NSData *databuffer;
file = [NSFileHandle fileHandleForReadingAtPath: appFile];
int i=0;
while (file!=nil ) {
[file seekToFileOffset: var+i];
databuffer = [file readDataOfLength : 7];
NSString* aStr;
aStr = [[NSString alloc] initWithData: databuffer encoding:NSASCIIStringEncoding];
NSLog(#"%#",aStr);
i=i+[databuffer length];
}
now i try your solution but i can't show nothing!!!
CGPDFPageRef page = CGPDFDocumentGetPage (myDocument, 1);// 2
CGPDFDictionaryRef d;
d = CGPDFPageGetDictionary(page);
CGPDFScannerRef myScanner;
CGPDFOperatorTableRef myTable;
myTable = CGPDFOperatorTableCreate();
CGPDFContentStreamRef myContentStream = CGPDFContentStreamCreateWithPage (page);// 3
myScanner = CGPDFScannerCreate (myContentStream, myTable, NULL);// 4
CGPDFScannerScan (myScanner);// 5
CGPDFOperatorTableSetCallback(myTable, "BT", &op_BT);//Begin text object
CGPDFOperatorTableSetCallback(myTable, "ET", &op_ET);//End text object
CGPDFOperatorTableSetCallback (myTable, "MP", &op_MP);
CGPDFOperatorTableSetCallback (myTable, "DP", &op_DP);
CGPDFOperatorTableSetCallback (myTable, "BMC", &op_BMC);
CGPDFOperatorTableSetCallback (myTable, "BDC", &op_BDC);
CGPDFOperatorTableSetCallback (myTable, "EMC", &op_EMC);
I recommend not to parse your pdf in a way you like to do it.
Try to use CGPDFScanner (docs here)
As JeremyP says: lot's of zlib compressed stuff is in a PDF file. Do search for end of lines.
Use CGPDFScanner to extract font maps, images, etc.
But is not that easy. I can tell you. :)

EXC_BAD_ACCESS when using string declared in header file

I've declared a string in my header file like so:
#property (nonatomic, retain) NSString *resultOfHash;
I call my getHash method like so:
NSString *hash = [self getHash];
My getHash method is:
-(NSString *) getHash
{
//Get username form Keychain
KeychainItemWrapper *keyChain = [[KeychainItemWrapper alloc] initWithIdentifier:KeyChainName accessGroup:nil];
username = [keyChain objectForKey:(__bridge id)kSecAttrAccount];
//get token from NSUserDefauls
NSString *token = [[NSUserDefaults standardUserDefaults]objectForKey:#"Token"];
NSString *toHash = [[username stringByAppendingString:HashExtra] stringByAppendingString:token];
const char *s = [toHash cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
CC_SHA512(keyData.bytes, keyData.length, digest);
NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
//convert to string
resultOfHash = [out description];
//App crashed out above
// get rid of unwanted characters
resultOfHash = [resultOfHash stringByReplacingOccurrencesOfString:#" " withString:#""];
resultOfHash = [resultOfHash stringByReplacingOccurrencesOfString:#"<" withString:#""];
resultOfHash = [resultOfHash stringByReplacingOccurrencesOfString:#">" withString:#""];
//log to make sure it works
NSLog(#"hash is: %#", resultOfHash);
return resultOfHash;
}
My code crashes out at the line: ResultOfHash = [out description]; but I'm not sure why.
When I use a local variable the conversion works fine but then I cannot return the local variable from the getHash method. Example:
Replace ResultOfHash = [out description];
with
NSString *local = [out description];
return local;
and the conversion works fine and when I debug line by line, the debugger will go to my closing bracket on my method and then produce the EXC_BAD_ACCESS error.
I've tried running NSZombie but that didn't find anything at all.
Any help in trying to sort this out would be greatly appreciated.
Have a look at the answer in this question. Try converting to NSString using
[NSString *local = [[[NSString alloc] initWithData:out encoding:NSASCIIStringEncoding];
I haven't tested this code with this encoding, but it's similar to something I already use.
Update -
I corrected an error in the code above. I somehow left the method signiture out in a distracted copy and paste.
I think the problem is here:
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
CC_SHA512(keyData.bytes, keyData.length, digest);
NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
You are using CC_SHA512, but only allocate array of size CC_SHA1_DIGEST_LENGTH, which is smaller and will lead to the buffer overrunning.
To correct this, you should use CC_SHA512_DIGEST_LENGTH instead.
It's crashing because out is unretained. You should add retain:
resultOfHash = [[out description] retain];
or use retained property:
self.resultOfHash = [out description];
Check this, it should be work.
You probably need to use an NSMutableString.

Problem with CGImageDestination and file naming

I am capturing images from the camera, using AVCapture as I have need of speed and the standard kit stuff is way too slow.
I have problem whereby the file that is being output (an animated GIF) is having it's file name mangles by the CGImageDestination functions...
When I output the NSURL (cast to a CFURLRef) to the log I get the path/filename I intended:
2011-09-04 20:40:25.914 Mover[3558:707] Path as string:.../Documents/91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif
However, once the file is created and saved it actually lists the filename as this:
2011-09-04 20:40:25.960 Mover[3558:707] file: .91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif-TtNT
See the difference? the period at the start and the 4 character suffix?
Whats really wierd is that it doesn't always do it, about 40% of the time it works OK. However it's preventing the code working further down the line where I'm listing them with previews in a table view.
Does anyone know why and how to stop it doing this?
Here's the code:
- (void)exportAnimatedGif{
NSString *guidPath = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *tmpPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:guidPath];
NSString *path = [tmpPath stringByAppendingPathExtension:#"gif"];
NSLog(#"Path as string:%#", path);
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], kUTTypeGIF, [captureArray count], NULL);
NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:testDisplay3.displayValue] forKey:(NSString *)kCGImagePropertyGIFDelayTime]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2], (NSString *)kCGImagePropertyGIFLoopCount,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFDelayTime,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFUnclampedDelayTime,
nil]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
for (int ii = 0; ii < [captureArray count]; ii++)
{
UIImage *tmpImg = [[UIImage alloc] init];
tmpImg = [captureArray objectAtIndex:ii];
CGImageDestinationAddImage(destination, tmpImg.CGImage, (CFDictionaryRef)frameProperties);
}
CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);
CGImageDestinationFinalize(destination);
CFRelease(destination);
//TEST OUTPUT GENERATED FILES
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] error:nil];
for (int xx = 0; xx < [contents count]; xx++)
{
NSLog(#"file: %#", [contents objectAtIndex:xx]);
}
//END TEST CODE
[captureArray removeAllObjects];
}
AFAIK this is a temporary file that CGImageDestinationFinalize makes, the reason you see them is that CGImageDestinationFinalize failed. I think that if you check the file sizes you'll see that the ones with mangled names have a file size of 0.
I started check for succes after I got these files :)
bool success = CGImageDestinationFinalize(destination);
CFRelease(destination);
if (success) {
NSLog(#"animated GIF file created at %#", path);
} else {
NSLog(#"failed to create gif at %#", path);
}