2011-03-03 2 views
9

현재 내 코드에서 작업의 새로운 기능 : 내가 사진 라이브러리에서 JPG 또는 PNG를 선택아이폰 OS : 다중/폼 데이터 사용을 NSData로 변환, 사진 라이브러리에서 GIF를 선택

(표준 ImagePicker 방법을 사용하여)를 사용하여 다음 이미지를 사용하여 해당 이미지를 NSData로 변환합니다.

self.myImageData = UIImageJPEGRepresentation(myImage, 0.9); 

그런 다음 multipart/form-data를 사용하여 서버에 게시합니다.

원래 GIF 데이터를 유지하면서 (라이브러리에 들어가는 애니메이션 GIF가 여전히 애니메이션으로 돌아 오도록) GIF에 대해 동일한 작업을 수행하려고합니다. didFinishPickingMediaWithInfo에서

, 나는

self.myGIFURL = [info objectForKey:UIImagePickerControllerReferenceURL]. 

여기 그 날을 얻을 수있는 것의 한 예이다 사용하여 원래 GIF의 URL을 얻을 수 있어요 :

자산 라이브러리 : // 자산/asset.GIF? ID = 1000000034 & 내선 = GIF

여기, 내가있는 NSData로이 GIF를 밀어 지금 시도한 두 가지 방법 때마다 나는 myIma geData는 (null)을 보여줍니다.

나는 initWithContentsOfURL을 사용하려했습니다

NSString *stringFromURL = [NSString stringWithFormat:@"%@", myGIFURL]; 
NSData *dataFromGIFURL = [[NSData alloc] initWithContentsOfFile: stringFromURL]; 
self.myImageData = dataFromGIFURL; 
[dataFromGIFURL release]; 

어떤 제안 :

NSData *dataFromGIFURL = [[NSData alloc] initWithContentsOfURL: myGIFURL]; 
self.myImageData = dataFromGIFURL; 
[dataFromGIFURL release]; 

가 그럼 난 initWithContentsOfFile에 대한 문자열로 NSURL 변환 시도

? 감사.

답변

13

iOS 4.1까지 UIImagePickerControllerReferenceURL 키가 표시되지 않습니다. 따라서 4.0에서 iOS에만 등장한 AssetsLibrary 프레임 워크를 사용하는 것이 좋다는 질문에 내포되어 있습니다. 이 경우, 다음과 같은 사용할 수 있습니다 다음, : 당신이 지정한 URL에 자산을 찾아 그것을 물어

- (void)imagePickerController:(UIImagePickerController *)picker 
     didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
    [library assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] 
     resultBlock:^(ALAsset *asset) 
     { 
      ALAssetRepresentation *representation = [asset defaultRepresentation]; 

      NSLog(@"size of asset in bytes: %d", [representation size]); 

      unsigned char bytes[4]; 
      [representation getBytes:bytes fromOffset:0 length:4 error:nil]; 
      NSLog(@"first four bytes: %02x (%c) %02x (%c) %02x (%c) %02x (%c)", 
           bytes[0], bytes[0], 
           bytes[1], bytes[1], 
           bytes[2], bytes[2], 
           bytes[3], bytes[3]); 

      [library autorelease]; 
     } 
     failureBlock:^(NSError *error) 
     { 
      NSLog(@"couldn't get asset: %@", error); 

      [library autorelease]; 
     } 
    ]; 
} 

그래서, 당신은 ALAssetsLibrary를 작성 (// URL 방식은 자산 라이브러리를 이해) 자산을 얻으면 기본 표현을 가져와이를 사용하여 바이트를 제공합니다. 디스크상의 실제 바이트가 될 것이고, 라이브러리에있는 자산의 기본 표현은 디스크상의 형태 일 것입니다.

2011-03-03 23 :

예를 들어, 화상 피커 I 구글 이미지에서 랜덤 잡고 특정 GIF를 선택하는 단계는 나에게 출력을 제공에서 그 방법 대리자까지 유선 : 17 : 37.451 IPTest [1199 : 307] 바이트 저작물의 크기 : 174,960

2011-03-03 23 : 17 : 37.459 IPTest [1199 : 307] 제 4 바이트 47 (G) (49) (I) 46 (F) 38 (8)

이것이 바로 표준 GIF 헤더의 시작입니다. PNG 또는 JPG를 선택하면 PNG 및 JPG 헤더의 처음 4 바이트를 인식 할 수 있습니다.

EDIT : 생각을 끝내려면 ALAssetRepresentation을 사용하여 파일을 적절하게 malloc 된 C 배열로 읽은 다음 NSData + (id) dataWithBytes : length :를 사용하는 것이 좋습니다 , + dataWithBytesNoCopy : length : freeWhenDone :) NSData에 랩핑합니다.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) { 
    guard let imageURL = info[UIImagePickerControllerReferenceURL] as? URL else { return } 
    guard let asset = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil).lastObject else { return } 

    if picker.sourceType == .photoLibrary || picker.sourceType == .savedPhotosAlbum { 
     let options = PHImageRequestOptions() 
     options.isSynchronous = true 
     options.isNetworkAccessAllowed = false 
     options.deliveryMode = .highQualityFormat 
     PHImageManager.default().requestImageData(for: asset, options: options) { data, uti, orientation, info in 
      guard let info = info else { return } 

      if let error = info[PHImageErrorKey] as? Error { 
       log.error("Cannot fetch data for GIF image: \(error)") 
       return 
      } 

      if let isInCould = info[PHImageResultIsInCloudKey] as? Bool, isInCould { 
       log.error("Cannot fetch data from cloud. Option for network access not set.") 
       return 
      } 

      // do something with data (it is a Data object) 
     } 
    } else { 
     // do something with media taken via camera 
    } 
} 
+0

와우 :

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSURL * refUrl = [info objectForKey:UIImagePickerControllerReferenceURL]; if (refUrl) { PHAsset * asset = [[PHAsset fetchAssetsWithALAssetURLs:@[refUrl] options:nil] lastObject]; if (asset) { PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; options.synchronous = YES; options.networkAccessAllowed = NO; options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) { NSNumber * isError = [info objectForKey:PHImageErrorKey]; NSNumber * isCloud = [info objectForKey:PHImageResultIsInCloudKey]; if ([isError boolValue] || [isCloud boolValue] || ! imageData) { // fail } else { // success, data is in imageData } }]; } } } 

+0

그것은 일했다! "분명히 할 수있다 ..."이후의 부분은 잠깐 나를 데려 갔다. (나는 이것에 처음이에요.) –

+0

오, 미안 해요! 방금 바이트를 얻는 것을 처리했지만 질문의 NSData 부분에 응답하는 것을 잊어 버리고 뭔가를 집어 넣기 위해 돌아왔다. 나는 더 많은 치료를 받아야했다. 자산 표현에 의해 주어진 크기의 블록을 malloc 할 것이고, 자산 표현을 작성한 후 NSData로 랩핑하여 freeWhenDone을 ​​통해 메모리의 소유권을 양도합니다. 또한 올바른 스토리지를 사용하여 NSMutableData를 만든 다음 자산 표시를 가져 와서 mutableBytes 속성에 쓸 수 있습니다. 하지만 당신이 지금 이걸 알아 냈다고 확신합니다 ... – Tommy

6

다음은 새로운 사진 프레임 워크를 사용하는 버전입니다. 철저한 응답에 감사드립니다. 그것으로 파고 나를 위해 어떻게 작동하는지보십시오.
3

여기 스위프트 3를 사용하여 엘리의 버전입니다 :