Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.remobile.qrcodeLocalImage;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
Expand All @@ -22,8 +24,12 @@


public class RCTQRCodeLocalImage extends ReactContextBaseJavaModule {

private Context context;

public RCTQRCodeLocalImage(ReactApplicationContext reactContext) {
super(reactContext);
this.context = reactContext;
}

@Override
Expand All @@ -36,17 +42,27 @@ public void decode(String path, Callback callback) {
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先获取原大小
options.inJustDecodeBounds = false; // 获取新的大小
// 返回宽度高度为原图的1/4,节省内存,解决 OOM 异常
options.inSampleSize = 4;
// 附加上图片的Config参数,解析器或根据当前的参数配置进行对应的解析,这也可以有效减少加载的内存。
options.inPreferredConfig = Bitmap.Config.RGB_565;
// 由此产生的位图将分配它的像素,这样他们可以被净化系统需要回收的内存。
options.inPurgeable = true;

int sampleSize = (int) (options.outHeight / (float) 200);

if (sampleSize <= 0)
sampleSize = 1;
options.inSampleSize = sampleSize;
Bitmap scanBitmap = null;
if (path.startsWith("http://")||path.startsWith("https://")) {
scanBitmap = this.getbitmap(path);
} else if (path.startsWith("content://")) {
try {
InputStream inputStream = this.context.getContentResolver().openInputStream(Uri.parse(path));
if (inputStream != null) {
scanBitmap = BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
scanBitmap = null;
}
} else {
scanBitmap = BitmapFactory.decodeFile(path, options);
}
Expand Down
87 changes: 55 additions & 32 deletions ios/RCTQRCodeLocalImage/RCTQRCodeLocalImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,68 @@
#import <UIKit/UIKit.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
#import <Photos/Photos.h>
#import "RCTQRCodeLocalImage.h"

@implementation RCTQRCodeLocalImage
RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(decode:(NSString *)path callback:(RCTResponseSenderBlock)callback)
{
UIImage *srcImage;
- (void)loadImageWithPath:(NSString *)path callback:(void(^)(UIImage * _Nullable srcImage))callback {
if ([path hasPrefix:@"http://"] || [path hasPrefix:@"https://"]) {
srcImage = [UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString: path]]];
} else {
srcImage = [[UIImage alloc] initWithContentsOfFile:path];
}
if (nil==srcImage){
NSLog(@"PROBLEM! IMAGE NOT LOADED\n");
callback(@[RCTMakeError(@"IMAGE NOT LOADED!", nil, nil)]);
return;
}
NSLog(@"OK - IMAGE LOADED\n");
NSDictionary *detectorOptions = @{@"CIDetectorAccuracy": @"CIDetectorAccuracyHigh"};
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:detectorOptions];
CIImage *image = [CIImage imageWithCGImage:srcImage.CGImage];
NSArray *features = [detector featuresInImage:image];
if (0==features.count) {
NSLog(@"PROBLEM! Feature size is zero!\n");
callback(@[RCTMakeError(@"Feature size is zero!", nil, nil)]);
return;
}

CIQRCodeFeature *feature = [features firstObject];

NSString *result = feature.messageString;
NSLog(@"result: %@", result);

if (result) {
callback(@[[NSNull null], result]);
callback([UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString: path]]]);
} else if ([path hasPrefix:@"assets-library://"]) {
PHFetchResult *results = [PHAsset fetchAssetsWithALAssetURLs:@[[NSURL URLWithString:path]] options:nil];
PHAsset *asset = [results firstObject];
PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
imageOptions.networkAccessAllowed = YES;
imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;

[[PHImageManager defaultManager] requestImageDataForAsset:asset
options:imageOptions
resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if (imageData == nil) {
callback(nil);
} else {
callback([UIImage imageWithData:imageData]);
}
}];
} else {
callback(@[RCTMakeError(@"QR Parse failed!", nil, nil)]);
return;
callback([[UIImage alloc] initWithContentsOfFile:path]);
}
}

RCT_EXPORT_METHOD(decode:(NSString *)path callback:(RCTResponseSenderBlock)callback)
{
[self loadImageWithPath:path callback:^(UIImage * _Nullable srcImage) {
if (nil==srcImage){
NSLog(@"PROBLEM! IMAGE NOT LOADED\n");
callback(@[RCTMakeError(@"IMAGE NOT LOADED!", nil, nil)]);
return;
}
NSLog(@"OK - IMAGE LOADED\n");

NSDictionary *detectorOptions = @{@"CIDetectorAccuracy": @"CIDetectorAccuracyHigh"};
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:detectorOptions];
CIImage *image = [CIImage imageWithCGImage:srcImage.CGImage];
NSArray *features = [detector featuresInImage:image];
if (0==features.count) {
NSLog(@"PROBLEM! Feature size is zero!\n");
callback(@[RCTMakeError(@"Feature size is zero!", nil, nil)]);
return;
}

CIQRCodeFeature *feature = [features firstObject];

NSString *result = feature.messageString;
NSLog(@"result: %@", result);

if (result) {
callback(@[[NSNull null], result]);
} else {
callback(@[RCTMakeError(@"QR Parse failed!", nil, nil)]);
return;
}
}];
}
@end