[FEATURE] added size(bytes) and mime type for returned images

This commit is contained in:
Ivan Pusic 2016-06-20 12:33:05 +02:00
parent d93e918450
commit cb79b4adc6
7 changed files with 92 additions and 53 deletions

View File

@ -105,8 +105,8 @@
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />

View File

@ -6,7 +6,9 @@ import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
@ -88,6 +90,16 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity
}
}
public static int byteSizeOf(Bitmap bitmap) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return bitmap.getAllocationByteCount();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
return bitmap.getByteCount();
} else {
return bitmap.getRowBytes() * bitmap.getHeight();
}
}
private WritableMap getImage(Uri uri, boolean resolvePath) {
WritableMap image = new WritableNativeMap();
String path = uri.getPath();
@ -97,12 +109,20 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
image.putString("path", "file://" + path);
image.putInt("width", options.outWidth);
image.putInt("height", options.outHeight);
image.putString("mime", options.outMimeType);
if (bitmap != null) {
image.putInt("size", byteSizeOf(bitmap));
bitmap.recycle();
} else {
image.putInt("size", 0);
}
return image;
}

View File

@ -64,14 +64,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
@ -80,8 +72,17 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
@ -98,12 +99,17 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.26.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />

View File

@ -36,6 +36,7 @@ export default class App extends Component {
height: 300,
cropping: cropit
}).then(image => {
console.log('received image', image);
this.setState({
image: {uri: image.path, width: image.width, height: image.height},
images: null
@ -50,6 +51,7 @@ export default class App extends Component {
this.setState({
image: null,
images: images.map(i => {
console.log('received image', i);
return {uri: i.path, width: i.width, height: i.height};
})
});

View File

@ -1,21 +1,21 @@
PODS:
- QBImagePickerController (3.4.0)
- React (0.26.1):
- React/Core (= 0.26.1)
- react-native-image-crop-picker (0.2.6):
- React (0.27.2):
- React/Core (= 0.27.2)
- react-native-image-crop-picker (0.3.1):
- QBImagePickerController (= 3.4.0)
- React (>= 0.26.1)
- RSKImageCropper (= 1.5.1)
- UIImage-Resize (~> 1.0)
- React/Core (0.26.1)
- React/RCTImage (0.26.1):
- React/Core (0.27.2)
- React/RCTImage (0.27.2):
- React/Core
- React/RCTNetwork
- React/RCTNetwork (0.26.1):
- React/RCTNetwork (0.27.2):
- React/Core
- React/RCTText (0.26.1):
- React/RCTText (0.27.2):
- React/Core
- React/RCTWebSocket (0.26.1):
- React/RCTWebSocket (0.27.2):
- React/Core
- RSKImageCropper (1.5.1)
- UIImage-Resize (1.0.1)
@ -36,8 +36,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
React: 9a7eb5f6e7146734fb50ab17f515087d302d5cca
react-native-image-crop-picker: 74b2f62969408d309d510bb5b5ea1c86b894a678
React: ed545be51aeb5c3988abb0b17bf174b87aac1a17
react-native-image-crop-picker: 25000b16a716be2b298998c2d959cf8d7565d24a
RSKImageCropper: edd65fedb3734332818deb139906d6b7f54b8a44
UIImage-Resize: fa776860f10e6900bbaf53a73e494bdceaaccc77

View File

@ -6,7 +6,7 @@
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "15.0.2",
"react-native": "^0.26.1"
"react": "^15.1.0",
"react-native": "^0.27.2"
}
}

View File

@ -29,21 +29,21 @@ RCT_EXPORT_MODULE();
@"height": @200
};
}
return self;
}
RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
self.resolve = resolve;
self.reject = reject;
self.options = [NSMutableDictionary dictionaryWithDictionary:self.defaultOptions];
for (NSString *key in options.keyEnumerator) {
[self.options setValue:options[key] forKey:key];
}
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
// init picker
@ -54,7 +54,7 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
imagePickerController.maximumNumberOfSelection = [[self.options objectForKey:@"maxFiles"] intValue];
imagePickerController.showsNumberOfSelectedAssets = YES;
imagePickerController.mediaType = QBImagePickerMediaTypeImage;
UIViewController *root = [[[[UIApplication sharedApplication] delegate]
window] rootViewController];
[root presentViewController:imagePickerController
@ -67,67 +67,76 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
- (void)qb_imagePickerController:
(QBImagePickerController *)imagePickerController
didFinishPickingAssets:(NSArray *)assets {
PHImageManager *manager = [PHImageManager defaultManager];
if ([[[self options] objectForKey:@"multiple"] boolValue]) {
NSMutableArray *images = [[NSMutableArray alloc] init];
PHImageRequestOptions* options = [[PHImageRequestOptions alloc] init];
options.synchronous = YES;
for (PHAsset *asset in assets) {
[manager
requestImageDataForAsset:asset
options:options
resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
NSString *filePath = [self persistFile:imageData];
UIImage *image = [UIImage imageWithData:imageData];
NSData *data = UIImageJPEGRepresentation(image, 1);
NSString *filePath = [self persistFile:data];
if (filePath == nil) {
self.reject(ERROR_CANNOT_SAVE_IMAGE_KEY, ERROR_CANNOT_SAVE_IMAGE_MSG, nil);
return;
}
[images addObject:@{
@"path": filePath,
@"width": @(asset.pixelWidth),
@"height": @(asset.pixelHeight)
@"height": @(asset.pixelHeight),
@"mime": @"image/jpeg",
@"size": [NSNumber numberWithUnsignedInteger:data.length]
}];
}];
}
self.resolve(images);
[imagePickerController dismissViewControllerAnimated:YES completion:nil];
} else {
PHAsset *asset = [assets objectAtIndex:0];
[manager
requestImageDataForAsset:asset
options:nil
resultHandler:^(NSData *imageData, NSString *dataUTI,
UIImageOrientation orientation,
NSDictionary *info) {
if ([[[self options] objectForKey:@"cropping"] boolValue]) {
UIImage *image = [UIImage imageWithData:imageData];
RSKImageCropViewController *imageCropVC = [[RSKImageCropViewController alloc] initWithImage:image cropMode:RSKImageCropModeCustom];
imageCropVC.avoidEmptySpaceAroundImage = YES;
imageCropVC.dataSource = self;
imageCropVC.delegate = self;
UIViewController *root = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[imagePickerController dismissViewControllerAnimated:YES completion:nil];
[root presentViewController:imageCropVC animated:YES completion:nil];
} else {
NSString *filePath = [self persistFile:imageData];
UIImage *image = [UIImage imageWithData:imageData];
NSData *data = UIImageJPEGRepresentation(image, 1);
NSString *filePath = [self persistFile:data];
if (filePath == nil) {
self.reject(ERROR_CANNOT_SAVE_IMAGE_KEY, ERROR_CANNOT_SAVE_IMAGE_MSG, nil);
return;
}
self.resolve(@{
@"path": filePath,
@"width": @(asset.pixelWidth),
@"height": @(asset.pixelHeight)
@"height": @(asset.pixelHeight),
@"mime": @"image/jpeg",
@"size": [NSNumber numberWithUnsignedInteger:data.length]
});
[imagePickerController dismissViewControllerAnimated:YES completion:nil];
}
@ -148,14 +157,14 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
CGSize maskSize = CGSizeMake(
[[self.options objectForKey:@"width"] intValue],
[[self.options objectForKey:@"height"] intValue]);
CGFloat viewWidth = CGRectGetWidth(controller.view.frame);
CGFloat viewHeight = CGRectGetHeight(controller.view.frame);
CGRect maskRect = CGRectMake((viewWidth - maskSize.width) * 0.5f,
(viewHeight - maskSize.height) * 0.5f,
maskSize.width, maskSize.height);
return maskRect;
}
@ -165,7 +174,7 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
CGRect rect = controller.maskRect;
CGFloat viewWidth = CGRectGetWidth(controller.view.frame);
CGFloat viewHeight = CGRectGetHeight(controller.view.frame);
if (rect.size.width > viewWidth) {
float scaleFactor = viewWidth / rect.size.width;
rect.size.width *= scaleFactor;
@ -179,7 +188,7 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
rect.origin.x = viewWidth / 2 * 0.5f;
rect.origin.y = 0;
}
return rect;
}
@ -212,25 +221,27 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
- (void)imageCropViewController:(RSKImageCropViewController *)controller
didCropImage:(UIImage *)croppedImage
usingCropRect:(CGRect)cropRect {
// we have correct rect, but not correct dimensions
// so resize image
CGSize resizedImageSize = CGSizeMake([[[self options] objectForKey:@"width"] intValue], [[[self options] objectForKey:@"height"] intValue]);
UIImage *resizedImage = [croppedImage resizedImageToFitInSize:resizedImageSize scaleIfSmaller:YES];
NSData *data = UIImageJPEGRepresentation(resizedImage, 1);
NSString *filePath = [self persistFile:data];
if (filePath == nil) {
self.reject(ERROR_CANNOT_SAVE_IMAGE_KEY, ERROR_CANNOT_SAVE_IMAGE_MSG, nil);
return;
}
NSDictionary *image = @{
@"path": filePath,
@"width": @(resizedImage.size.width),
@"height": @(resizedImage.size.height)
@"height": @(resizedImage.size.height),
@"mime": @"image/jpeg",
@"size": [NSNumber numberWithUnsignedInteger:data.length]
};
self.resolve(image);
[controller dismissViewControllerAnimated:YES completion:nil];
}
@ -241,13 +252,13 @@ RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options
// create temp file
NSString *filePath = [NSTemporaryDirectory() stringByAppendingString:[[NSUUID UUID] UUIDString]];
filePath = [filePath stringByAppendingString:@".jpg"];
// save cropped file
BOOL status = [data writeToFile:filePath atomically:YES];
if (!status) {
return nil;
}
return filePath;
}