How to create a TIFF on the iPad - ios

I am trying to create a TIFF image from a UIImage. I looked into Apple's docs but could not find any information.
Can anyone help me and explain how to create a TIFF image on an iPad?

It seems to me that ImageMagick is way overkill just to write tiffs. Why not build libtiff? iOS is supported from it, and is what most software packages use to write tiffs (including ImageMagick).
You can even use the libtiff.a file from the ImageMagick link above. Just install the lib and tiff headers into your project.
EDIT:
Here is a nice tutorial showing you how to write a tiff once you have installed libtiff. The second part of the tutorial shows you how to control the compression.

I feel like this answer is a little late, but in case someone else wants to know how to do this, I think you'll find the following will do the trick:
NSMutableData *mData = [NSMutableData dataWithCapacity:SOME_BIG_NUMBER];
CGImageDestinationRef myImageDest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)(mData), kUTTypeTIFF, 1, NULL);
CGImageDestinationAddImage(myImageDest,image.CGImage, NULL);
CGImageDestinationFinalize(myImageDest);
CFRelease(myImageDest);
The mData will then hold NSData encoding of a TIFF file which you can then store to the disk, upload to a server, whatever...
You might need to include MobileCoreServices and ImageIO frameworks...
Paul

ImageMagick has been compiled for iOS and allows for handling of TIFF images. The instructions can be found here:
Link
There is also a Sample Project that illustrates how to integrate this functionality into your application. It should be noted that including this library takes several steps - and the instructions are included in the link above.
SETTING UP A PROJECT FOR IMAGEMAGICK
First, download the latest version (from the first link above) with libs in the name. This includes pre-compiled versions of the needed frameworks. Unzip the contents of this file. Next, right-click Frameworks in your iOS projects and select the option to Add Files. Add each of the files with the .a extension. You should have something resembling this:
Next, you'll need to add the proper header search paths. Go to the Build Settings for your project and search for Header Search Paths. Select this and add a new search path that corresponds to where the include directory is (from the download). Don't add this just for debug or release, but for all. You should now have something that looks like this:
Now you should be able to include and use code from the ImageMagick framework.

Just use following code and you got the .tiff image. You have to add ImageIO and MobileCoreServices Frameworks into your project.
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/UTCoreTypes.h>
- (void)viewDidLoad {
[super viewDidLoad];
[self convertImageIntoTIFF];
}
-(void)convertImageIntoTIFF{
UIImage *img = [UIImage imageNamed:#"image.png"];
float compression = 1.0; // Lossless compression if available.
int orientation = 1; // Origin is at top, left.
CFStringRef myKeys[3];
CFTypeRef myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSLog(#"documentsDirectory %#", documentsDirectory);
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"image.tiff"];
[self writeCGImage:img.CGImage toURL:[NSURL fileURLWithPath:filePath] withType:kUTTypeTIFF andOptions:myOptions];
}
- (void) writeCGImage: (CGImageRef) image toURL: (NSURL*) url withType: (CFStringRef) imageType andOptions: (CFDictionaryRef) options
{
CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((CFURLRef)url, imageType, 1, nil);
CGImageDestinationAddImage(myImageDest, image, options);
CGImageDestinationFinalize(myImageDest);
CFRelease(myImageDest);
}
For More details, you can able to download this DemoCode.
Hope, this is what you're looking for. :)

Related

image uploaded rotated other way

let image_data = UIImageJPEGRepresentation(self.imagetoadd.image!,0.0)
The image in ios, am using swift 3 to do this is being uploaded rotated.How can I solve such thing?
JPEG images usually contain an EXIF dictionary, here are stored a lot information about how the image was taken, image rotation is one of it.
UIImage instances keeps these information (if the original image has it) as well inside a specific property called imageOrientation.
As far as I remember this information is ripped of by using the method UIImageJPEGRepresentation.
To create a correct data instance with the above information you must use Core Graphics methods, or normalize the rotation before sending the image.
To normalize the image something like that should be enough:
CGImageRef cgRef = imageToSave.CGImage;
UIImage * fixImage = [[UIImage alloc] initWithCGImage:cgRef scale:imageToSave.scale orientation:UIImageOrientationUp];
To keep the rotation information:
CFURLRef url = (__bridge_retained CFURLRef)[NSURL fileURLWithPath:path];//Save data path
NSDictionary * metadataDictionary = [self imageMetadataForPath:pathToOriginalImage];
CFMutableDictionaryRef metadataImage = (__bridge_retained CFMutableDictionaryRef) metadata;
CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypeJPEG, 1, NULL);
CGImageDestinationAddImage(destination, image, metadataImage);
if (!CGImageDestinationFinalize(destination)) {
DLog(#"Failed to write image to %#", path);
}
Where the -imageMetadataForPath:
- (NSDictionary*) imageMetadataForPath:(NSString*) imagePath{
NSURL *imageURL = [NSURL fileURLWithPath:imagePath];
CGImageSourceRef mySourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)imageURL, NULL);
NSDictionary * dict = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(mySourceRef,0,NULL));
CFRelease(mySourceRef);
return dict;
}
This is a copy and paste from a project of mine, you probably need to do a huge refactoring, also because it is using manual memory management in core foundation and you are using SWIFT. Of course by using this last set of instructions, the backend code must be prepared to deal with image orientation too.
If you want to know more about rotation, here is a link.

How to check for a corrupted PDF in iOS?

I have a PDF file which I downloaded from a server, sometimes the users uploads a corrupted PDF and I need to check if my application can open such a file or not.
So is there a built-in way I could use to check for the PDF corruption ? If not is there a free lightweight PDF framework that I could use to view or checking the corruption ?
Note: Currently I am opening PDF files on a UIWebView.
I've found the solution using the CoreGraphics PDF drawing APIs.
Thanks for this answer.
NSString *path = [[NSBundle mainBundle] pathForResource:#"A_Corrupted_PDF" ofType:#"pdf"];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(provider);
if (document == nil) {
NSLog(#"The PDF is corrupted");
}
CGDataProviderRelease(provider);
CGPDFDocumentRelease(document);

Raw image data from camera like "645 PRO"

A time ago I already asked this question and I also got a good answer:
I've been searching this forum up and down but I couldn't find what I
really need. I want to get raw image data from the camera. Up till now
I tried to get the data out of the imageDataSampleBuffer from that
method
captureStillImageAsynchronouslyFromConnection:completionHandler: and
to write it to an NSData object, but that didn't work. Maybe I'm on
the wrong track or maybe I'm just doing it wrong. What I don't want is
for the image to be compressed in any way.
The easy way is to use jpegStillImageNSDataRepresentation: from
AVCaptureStillImageOutput, but like I said I don't want it to be
compressed.
Thanks!
Raw image data from camera
I thought I could work with this, but I finally noticed that I need to get raw image data more directly in a similar way as it is done in "645 PRO".
645 PRO: RAW Redux
The pictures on that site show that they get the raw data before any jpeg compression is done. That is what I want to do. My guess is that I need to transform imageDataSampleBuffer but I don't see a way to do it completely without compression.
"645 PRO" also saves its pictures in TIFF so I think it uses at least one additional library.
I don't want to make a photo app but I need the best quality I get to check for certain features in a picture.
Thanks!
Edit 1:
So after trying and searching in different directions for a while now I decided to give a status update.
The final goal of this project is to check for certain features in a picture which will happen with the help of opencv. But until the app is able to do it on the phone I'm trying to get mostly uncompressed pictures out of the phone to analyse them on the computer.
Therefore I want to save the "NSData instance containing the uncompressed BGRA bytes returned from the camera" I'm able to get with Brad Larson's code as bmp or TIFF file.
As I said in a comment I tried using opencv for this (it will be needed anyway). But the best I could do was turning it into a UIImage with a function from Computer Vision Talks.
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);
UIImage *testImag = [UIImage imageWithMat:frame andImageOrientation:UIImageOrientationUp];
//imageWithMat... being the function from Computer Vision Talks which I can post if someone wants to see it
ImageMagick - Approach
Another thing I tried was using ImageMagick as suggested in another post.
But I couldn't find a way to do it without using something like UIImagePNGRepresentationor UIImageJPEGRepresentation.
For now I'm trying to do something with libtiff using this tutorial.
Maybe someone has an idea or knows a much easier way to convert my buffer object into an uncompressed picture.
Thanks in advance again!
Edit 2:
I found something! And I must say I was very blind.
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"ocv%d.TIFF", picNum]];
const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];
const cv::string newPaths = (const cv::string)cPath;
cv::imwrite(newPaths, frame);
I just have to use the imwrite function from opencv. This way I get TIFF-files around 30 MB directly after the beyer-Polarisation!
Wow, that blog post was something special. A whole lot of words to just state that they get the sample buffer bytes that Apple hands you back from a still image. There's nothing particularly innovative about their approach, and I know a number of camera applications that do this.
You can get at the raw bytes returned from a photo taken with a AVCaptureStillImageOutput using code like the following:
[photoOutput captureStillImageAsynchronouslyFromConnection:[[photoOutput connections] objectAtIndex:0] completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(imageSampleBuffer);
CVPixelBufferLockBaseAddress(cameraFrame, 0);
GLubyte *rawImageBytes = CVPixelBufferGetBaseAddress(cameraFrame);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(cameraFrame);
NSData *dataForRawBytes = [NSData dataWithBytes:rawImageBytes length:bytesPerRow * CVPixelBufferGetHeight(cameraFrame)];
// Do whatever with your bytes
CVPixelBufferUnlockBaseAddress(cameraFrame, 0);
}];
This will give you an NSData instance containing the uncompressed BGRA bytes returned from the camera. You can save these to disk or do whatever you want with them. If you really need to process the bytes themselves, I'd avoid the overhead of the NSData creation and just work with the byte array from the pixel buffer.
I could solve it with OpenCV. Thanks to everyone who helped me.
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"ocv%d.BMP", picNum]];
const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];
const cv::string newPaths = (const cv::string)cPath;
cv::imwrite(newPaths, frame);
I just have to use the imwrite function from opencv. This way I get BMP-files around 24 MB directly after the bayer-filter!
While the core of the answer comes from Brad at iOS: Get pixel-by-pixel data from camera, a key element is completely unclear from Brad's reply. It's hidden in "once you have your capture session configured...".
You need to set the correct outputSettings for your AVCaptureStillImageOutput.
For example, setting kCVPixelBufferPixelFormatTypeKey to kCVPixelFormatType_420YpCbCr8BiPlanarFullRange will give you a YCbCr imageDataSampleBuffer in captureStillImageAsynchronouslyFromConnection:completionHandler:, which you can then manipulate to your heart's content.
as #Wildaker mentioned, for a specific code to work you have to be sure which pixel format the camera is sending you. The code from #thomketler will work if it's set for 32-bit RGBA format.
Here is a code for the YUV default from camera, using OpenCV:
cv::Mat convertImage(CMSampleBufferRef sampleBuffer)
{
CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(cameraFrame, 0);
int w = (int)CVPixelBufferGetWidth(cameraFrame);
int h = (int)CVPixelBufferGetHeight(cameraFrame);
void *baseAddress = CVPixelBufferGetBaseAddressOfPlane(cameraFrame, 0);
cv::Mat img_buffer(h+h/2, w, CV_8UC1, (uchar *)baseAddress);
cv::Mat cam_frame;
cv::cvtColor(img_buffer, cam_frame, cv::COLOR_YUV2BGR_NV21);
cam_frame = cam_frame.t();
//End processing
CVPixelBufferUnlockBaseAddress( cameraFrame, 0 );
return cam_frame;
}
cam_frame should have the full BGR frame. I hope that helps.

library for iOS to split huge binary files by certain sizes?

I am looking for the library for splitting (divide) a binary file into multiple files.
If there is 20MB size of file named "test.m4v" in iOS temporary folder (NSTemporaryDirectory()),
I would like to split that to
test.m4v.000 (7MB)
test.m4v.001 (7MB)
test.m4v.002 (6MB)
Something like that (It doesn't have to be '7MB', could be 5MB like that)
like command line split command., I don't think we can call this command inside iOS app.
Is there iOS (free/paid) library to do that? I might need to just low level access and write it, but I am too lazy to do that ;)
This should work assuming the file isn't so large that it freaks out at dataWithContentsOfFile:filename. iOS might do caching in the background, but I don't know.
-(NSUInteger)splitFile:(NSString *)filename chunkSize:(NSUInteger)chunkSize {
NSUInteger chunksWritten;
NSFileManager *fm = [[[NSFileManager alloc] init] autorelease];
NSData *fileData = [NSData dataWithContentsOfFile:filename];
NSString *newFileName;
NSRange dataRange;
for (chunksWritten = 0; chunksWritten * chunkSize < [fileData length]; chunksWritten++) {
newFileName = [filename stringByAppendingPathExtension:[NSString stringWithFormat:#"%03d", chunksWritten]];
dataRange = NSMakeRange(chunksWritten * chunkSize, MIN(chunkSize, [fileData length] - chunksWritten * chunkSize));
if (![fm createFileAtPath:newFileName contents:[fileData subdataWithRange:dataRange] attributes:nil]) {
NSLog(#"Error writing chunk #%d", chunksWritten);
break;
}
}
return chunksWritten;
}
The error checking obviously needs to be more robust.

iPhone Unzip code

Really stuck on trying to write code to unzip a file or directory on the iPhone.
Below is some sample code that I'm using to try and unzip a simple text file.
It unzips the file but its corrupt.
(void)loadView {
NSString *DOCUMENTS_FOLDER = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *path = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"sample.zip"];
NSString *unzipeddest = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"test.txt"];
gzFile file = gzopen([path UTF8String], "rb");
FILE *dest = fopen([unzipeddest UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength = gzread(file, buffer, CHUNK);
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
else{
}
fclose(dest);
gzclose(file);
}
I wanted an easy solution and didn't find one I liked here, so I modified a library to do what I wanted. You may find SSZipArchive useful. (It can also create zip files by the way.)
Usage:
NSString *path = #"path_to_your_zip_file";
NSString *destination = #"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];
Has "sample.zip" really been created with gZip? The .zip extension usually is used for archives created by WinZip. Those can also be decompressed using zLib, but you'd have to parse the header and use other routines.
To check, have a look at the first two bytes of the file. If it is 'PK', it's WinZip, if it's 0x1F8B, it's gZip.
Because this is iPhone specific, have a look at this iPhone SDK forum discussion where miniZip is mentioned. It seems this can handle WinZip files.
But if it's really a WinZip file, you should have a look at the WinZip specification and try to parse the file yourself. It basically should be parsing some header values, seeking the compressed stream position and using zLib routines to decompress it.
This code worked well for me for gzip:
the database was prepared like this:
gzip foo.db
the key was looping over the gzread(). The example above only reads the first CHUNK bytes.
#import <zlib.h>
#define CHUNK 16384
NSLog(#"testing unzip of database");
start = [NSDate date];
NSString *zippedDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"foo.db.gz"];
NSString *unzippedDBPath = [documentsDirectory stringByAppendingPathComponent:#"foo2.db"];
gzFile file = gzopen([zippedDBPath UTF8String], "rb");
FILE *dest = fopen([unzippedDBPath UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength;
while (uncompressedLength = gzread(file, buffer, CHUNK) ) {
// got data out of our file
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
}
fclose(dest);
gzclose(file);
NSLog(#"Finished unzipping database");
Incidentally, I can unzip 33MB into 130MB in 77 seconds or about 1.7 MB uncompressed/second.
This code will unzip any .zip file into your app document directory and get file from app resources.
self.fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"document directory path:%#",paths);
self.documentDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/abc", self.documentDirectory];
NSLog(#"file path is:%#",filePath);
NSString *fileContent = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.zip"];
NSData *unzipData = [NSData dataWithContentsOfFile:fileContent];
[self.fileManager createFileAtPath:filePath contents:unzipData attributes:nil];
// here we go, unzipping code
ZipArchive *zipArchive = [[ZipArchive alloc] init];
if ([zipArchive UnzipOpenFile:filePath])
{
if ([zipArchive UnzipFileTo:self.documentDirectory overWrite:NO])
{
NSLog(#"Archive unzip success");
[self.fileManager removeItemAtPath:filePath error:NULL];
}
else
{
NSLog(#"Failure to unzip archive");
}
}
else
{
NSLog(#"Failure to open archive");
}
[zipArchive release];
It's really hard to unzip any arbitrary zip file. It's a complex file format, and there are potentially many different compression routines that could have been used internally to the file. Info-ZIP has some freely licencable code to do it (http://www.info-zip.org/UnZip.html) that can be made to work on the iPhone with some hacking, but the API is frankly horrible - it involves passing command-line arguments to a fake 'main' that simulates the running of UnZIP (to be fair that's because their code was never designed to be used like this in the first place, the library functionality was bolted on afterwards).
If you have any control of where the files you're trying to unzip are coming from, I highly recommend using another compression system instead of ZIP. It's flexibility and ubiquity make it great for passing archives of files around in person-to-person, but it's very awkward to automate.
zlib isn't meant to open .zip files, but you are in luck: zlib's contrib directory includes minizip, which is able to use zlib to open .zip files.
It may not be bundled in the SDK, but you can probably use the bundled version of zlib use it. Grab a copy of the zlib source and look in contrib/minizip.
I haven't used the iPhone, but you may want to look at GZIP, which is a very portable open source zip library available for many platforms.
I had some luck testing this on the iPhone simulator:
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *saveLocation =
[documentsDirectory stringByAppendingString:#"myfile.zip"];
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:saveLocation]) {
[fileManager removeItemAtPath:saveLocation error:nil];
}
NSURLRequest *theRequest =
[NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://example.com/myfile.zip"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSData *received =
[NSURLConnection sendSynchronousRequest:theRequest
returningResponse:nil error:nil];
if ([received writeToFile:saveLocation atomically:TRUE]) {
NSString *cmd =
[NSString stringWithFormat:#"unzip \"%#\" -d\"%#\"",
saveLocation, documentsDirectory];
// Here comes the magic...
system([cmd UTF8String]);
}
It looks easier than fiddling about with zlib...

Resources