2012-10-31 6 views
6

Ich versuche, JPEG-Bilder in der Benutzergalerie (Kamera-Rolle) zu lesen und zu schreiben, ohne dass iOS sie erneut komprimiert. UIImage scheint hier der Flaschenhals zu sein. Die einzige Methode zum Speichern in der Benutzergalerie, die ich gefunden habe, ist UIImageWriteToSavedPhotosAlbum(). Gibt es einen Weg dahin?Speichern/Abrufen von JPEG aus der Benutzergalerie ohne erneute Komprimierung

Vorerst meine Routine sieht wie folgt aus

-Fragen UIImagePickerController für ein Foto. Und wenn es didFinishPickingMediaWithInfo, tun:

NSData *imgdata = [NSData dataWithData:UIImageJPEGRepresentation([info objectForKey:@"UIImagePickerControllerOriginalImage"], 1)]; 
[imgdata writeToFile:filePath atomically:NO]; 

-Prozess JPEG verlustlos auf dem Datenträger.

-Dann speichern zurück:

UIImageWriteToSavedPhotosAlbum([UIImage imageWithContentsOfFile:[self getImagePath]], self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 

Hier eine kleine Animation, was Abbau sieht aus wie nach 3 Durchgängen Qualität:

JPEG quality degradation

Es wird offensichtlich jedes Mal, wenn ich dies tun schlimmer , aber ich konnte den Bildaufnahmeteil nicht automatisieren, um ihn vollständig auf 50/100/1000 Zyklen zu testen.

Antwort

10

UIImage decodiert die Bilddaten, so kann es, würde zuerst das Bild dekodieren

UIImageWriteToSavedPhotosAlbum([UIImage imageWithContentsOfFile:[NSData dataWithContentsOfFile:[self getImagePath]]], self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 

so bearbeitet und angezeigt werden, und als es durch das Verfahren UIImageWriteToSavedPhotosAlbum kodieren zurück.

Stattdessen sollten Sie ALAssetsLibrary/writeImageDataToSavedPhotosAlbum:metadata:completionBlock:, so etwas wie folgt verwenden:

ALAssetsLibrary *assetLib = [[[ALAssetsLibrary alloc] init] autorelease]; 
[assetLib writeImageDataToSavedPhotosAlbum:[self getImagePath] metadata:nil completionBlock:nil]; 

Sie auch Metadaten und den Abschluss Block auf den Aufruf passieren kann.

EDIT:

für das Bild bekommen:

[info objectForKey:@"UIImagePickerControllerOriginalImage"] enthält das entschlüsselte UIImage von UIImagePickerController ausgewählt. Sie sollten stattdessen

NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL]; 

verwenden Mit der assetURL Sie jetzt die ALAsset für sie mit der ALAssetsLibrary/assetForURL:resultBlock:failureBlock: Methode erhalten kann:

ALAssetsLibrary *assetLib = [[[ALAssetsLibrary alloc] init] autorelease]; 
[assetLib assetForURL:assetURL resultBlock:resultBlock failureBlock:failureBlock]; 

Sie können nun die unverändert NSData dieses Bildes erhalten:

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset){ 
    ALAssetRepresentation *assetRep = [asset defaultRepresentation]; 
    long long imageDataSize = [assetRepresentation size]; 
    uint8_t* imageDataBytes = malloc(imageDataSize); 
    [assetRepresentation getBytes:imageDataBytes fromOffset:0 length:imageDataSize error:nil]; 
    NSData *imageData = [NSData dataWithBytesNoCopy:imageDataBytes length:imageDataSize freeWhenDone:YES]; // you could for instance read data in smaller buffers and append them to your file instead of reading it all at once 
    // save it 
    [imgdata writeToFile:filePath atomically:NO]; 
}; 
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror){ 
    NSLog(@"Cannot get image - %@",[myerror localizedDescription]); 
    // 
}; 

Ich habe möglicherweise einige Fehler im Code gemacht, aber die Schritte sind wie oben aufgeführt. Wenn etwas nicht richtig funktioniert, oder wenn Sie dies ein wenig effizienter machen möchten, gibt es viele Beispiele für Dinge wie das Lesen NSData von einem ALAsset auf Stackoverflow oder anderen Websites.

+0

Ja, danke, ich habe diesen Trick mit AssetsLibrary bereits herausgefunden. Ich hoffe, Ihre Antwort wird anderen helfen. – Kai