2012-10-31 20 views
6

Tôi đang cố tìm cách đọc và ghi ảnh JPEG vào thư viện người dùng (cuộn ảnh) mà không cần nén lại chúng. UIImage có vẻ là nút cổ chai ở đây. Phương pháp duy nhất để lưu vào thư viện người dùng mà tôi đã tìm thấy là UIImageWriteToSavedPhotosAlbum(). Có cách nào để giái quyết vấn đề này không?Lưu/nhận ảnh JPEG từ thư viện người dùng mà không cần nén lại

Còn bây giờ thói quen của tôi trông như thế này

-Ask UIImagePickerController cho một bức ảnh. Và khi nó thực hiệnFinishPickingMediaWithInfo, hãy làm:

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

–Trình xử lý JPEG không mất trên đĩa.

-Sau đó lưu nó lại:

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

Đây là một hình ảnh động nhỏ của những gì suy thoái chất lượng trông giống như sau 3 đèo:

JPEG quality degradation

Nó rõ ràng trở nên tệ hơn mỗi khi tôi làm điều này , nhưng tôi không thể tự động hóa phần chọn hình ảnh để kiểm tra đầy đủ cho chu kỳ 50/100/1000.

Trả lời

10

UIImage giải mã dữ liệu hình ảnh để nó có thể được chỉnh sửa và hiển thị, vì vậy

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

đầu tiên sẽ giải mã hình ảnh, và hơn mã hóa nó trở lại theo phương pháp UIImageWriteToSavedPhotosAlbum.

Thay vào đó, bạn nên sử dụng ALAssetsLibrary/writeImageDataToSavedPhotosAlbum:metadata:completionBlock:, một cái gì đó như thế này:

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

Bạn cũng có thể vượt qua siêu dữ liệu và khối hoàn thành cuộc gọi.

EDIT:

Để nhận được hình ảnh:

[info objectForKey:@"UIImagePickerControllerOriginalImage"] chứa giải mã UIImage chọn từ UIImagePickerController. thay vào đó bạn nên sử dụng

NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL]; 

Sử dụng assetURL bây giờ bạn có thể nhận được ALAsset cho nó bằng cách sử dụng ALAssetsLibrary/assetForURL:resultBlock:failureBlock: phương pháp:

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

Bây giờ bạn có thể nhận được NSData không thay đổi gì của hình ảnh đó:

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]); 
    // 
}; 

Tôi có thể đã thực hiện một số lỗi trong mã, nhưng các bước được liệt kê ở trên. Trong trường hợp một cái gì đó không hoạt động đúng, hoặc nếu bạn muốn thực hiện điều này hiệu quả hơn một chút, có rất nhiều ví dụ về việc thực hiện các công việc như đọc NSData từ số ALAsset trên stackoverflow hoặc các trang web khác.

+0

Vâng, cảm ơn, tôi đã tìm hiểu về mẹo đó với AssetsLibrary. Tôi hy vọng câu trả lời của bạn sẽ hữu ích cho người khác. – Kai