2013-03-06 21 views
19

muszę konwertować UIImage do NSData ale bez użycia UIImagePngRepresentation lub UIImageJpegRepresentation dla obrazów z photolib mogę używać assetlib sposób jak wspomniano tutaj Using ALAssetsLibrary and ALAsset take out Image as NSData, ale dla przechwyconego obrazu, assset url nie ma stąd w tym przypadku muszę przekonwertować UIImage bezpośrednio na bajty z danymi exif, jak mogę to zrobić? proszę pomócKonwersja UIImage do NSData bez użycia UIImagePngrepresentation lub UIImageJpegRepresentation

+0

Dlaczego? Wieloplatformowe powody? To jedyny powód, dla którego mogę myśleć ...cóż, jeśli tak jest, to spróbuj użyć LodePNG http://lodev.org/lodepng/ – borrrden

+2

Używając reprezentacji png i jpeg uiimage, rozmiar obrazu jest różny, również jakość obrazu dla jpeg jest zmniejszona nawet przy 1.0 jakości kompresji. Potrzebuję sposobu na bezpośrednią konwersję UIImage na bajty. –

+0

Oczywiście rozmiar obrazu jest różny ... taka jest natura kompresji. W przeciwnym razie wszystkie obrazy miałyby ogromny rozmiar pliku (wxhx4 bajty). Również twój rozmiar będzie się różnić w zależności od wymiarów pliku. Myślę, że musisz opisać swój problem znacznie lepiej niż obecnie. – borrrden

Odpowiedz

17

H Bastan,

oparciu o swój komentarz:

... Chcę zapisać przechwycony przez kamerę obraz zwrot urządzenia poprzez UIImagepicker metody delegata w katalogu publikacji ...

wygląda na to, prawdziwy celem jest zapisanie obrazu z danymi EXIF ​​do katalogu dokumentów, a nie otrzymanie obiektu UII jako obiektu NSData z danymi EXIF. W tym przypadku, można wykonać następujące czynności w realizacji imagePickerController:didFinishPickingMediaWithInfo:

// Get your image. 
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage]; 

// Get your metadata (includes the EXIF data). 
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata]; 

// Create your file URL. 
NSFileManager *defaultManager = [NSFileManager defaultManager]; 
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory 
             inDomains:NSUserDomainMask] lastObject]; 
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"]; 

// Set your compression quuality (0.0 to 1.0). 
NSMutableDictionary *mutableMetadata = [metadata mutableCopy]; 
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality]; 

// Create an image destination. 
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL); 
if (imageDestination == NULL) { 

    // Handle failure. 
    NSLog(@"Error -> failed to create image destination."); 
    return; 
} 

// Add your image to the destination. 
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata); 

// Finalize the destination. 
if (CGImageDestinationFinalize(imageDestination) == NO) { 

    // Handle failure. 
    NSLog(@"Error -> failed to finalize the image."); 
} 

CFRelease(imageDestination); 

Z moich testów czas realizacji był mniej więcej taki sam lub szybciej niż robi:

NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0); 
[data writeToURL:outputURL atomically:YES]; 

... i dostać się do zachowaj dane EXIF!

Można również wysyła ją do kolejki tła, jeśli chcesz, aby upewnić się, że interfejs użytkownika pozostaje wrażliwy:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 

    // Do the image saving here... 
}); 

Ważna uwaga: Trzeba dodać ImageIO.framework i tym MobileCoreServices.framework zbudować docelowego fazy i importować je w klasie, gdzie robisz zapisywanie obrazu:

#import <ImageIO/ImageIO.h> 
#import <MobileCoreServices/MobileCoreServices.h> 

Dodatkowe noty Rozumiem, że w tym przypadku nie generujemy straty generacji przy zapisywaniu obrazu zaproponowanego w przykładzie. Używamy właściwości CGImage UIImage i jako dokumentacji stwierdza:

bazowego danych obrazowych Quartz

+0

Dzięki temu naprawdę pomocne, W ten sposób, jeśli donot ustawić jakość kompresji, które zostaną zapisane z oryginalnej kompresji obrazu qaulity n, to w porządku ze mną, również rozmiar danych obrazu pozostaje taki sam jak fotolib, a zatem jest to doskonały sposób, aby to zrobić dzięki. –

+0

sry komentarze dotyczyły rozwiązania poniżej :) Nie próbowałem twojego – hasan83

+0

Utknąłem już od jakiegoś czasu. ale dzięki twojemu rozwiązaniu mogę iść do przodu. Dziękuję – Asbar

0

Możesz spróbować czegoś takiego. Nie jestem pewien, czy jest to najlepsza metoda. Ale wart strzał. Okrywać URL obrazu jest dostępny, można spróbować initWithContentsOfUrl

NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"]; 
+0

cześć dzięki, ale używam uiimagepicker do przechwytywanie obrazu, tutaj tylko zwraca uiimage n nie URL do obrazu, stąd powyższa metoda nie byłaby przydatna –

21

miałem podobny problem, ale ze względów bezpieczeństwa nie chciałem napisać dane do domyślny system plików sugerowany przez Wesa. Chciałem też móc dodać metadane do mojego obrazu. Moje rozwiązanie było następująco:

- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype 
{ 
    NSMutableData *imageData = [NSMutableData data]; 
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL); 
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL); 

    if (imageDestination == NULL) 
    { 
     NSLog(@"Failed to create image destination"); 
     imageData = nil; 
    } 
    else 
    { 
     CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata); 

     if (CGImageDestinationFinalize(imageDestination) == NO) 
     { 
      NSLog(@"Failed to finalise"); 
      imageData = nil; 
     } 
     CFRelease(imageDestination); 
    } 

    CFRelease(uti); 

    return imageData; 
} 

Aby go użyć, należy wykonać następujące czynności:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; 
    NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata]; 
    NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg! 

    // you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to. 

    // convert to NSData 
    NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType]; 

    // ... 
} 
+0

Czas przeprowadzania egzaminu jest o ok. 5% lepszy niż w przypadku UIImageJpegRepresentation. ale używa w przybliżeniu tej samej pamięci. ale przynajmniej rezerwuje tę pamięć na bardzo mały czas. – hasan83