从画廊android中的图像扫描条形码
Posted
技术标签:
【中文标题】从画廊android中的图像扫描条形码【英文标题】:Scan barcode from an image in gallery android 【发布时间】:2015-06-21 09:09:00 【问题描述】:我正在创建一个android项目,主要功能是扫描条形码。
我尝试将Zxing 库集成到我的项目中,并且工作正常。
但是,它似乎不支持从 android 设备库中的可用图像中扫描条形码。
我该怎么做?或与其他条形码库?
【问题讨论】:
【参考方案1】:您可以使用 ZXing 库中的此类 MultiFormatReader。
您必须在 BitMap 中获取图库图像并将其转换为:
Bitmap bMap = [...];
String contents = null;
int[] intArray = new int[bMap.getWidth()*bMap.getHeight()];
//copy pixel data from the Bitmap into the 'intArray' array
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
Result result = reader.decode(bitmap);
contents = result.getText();
更新1
要操作大图,请看:
https://developer.android.com/training/articles/memory.html
https://developer.android.com/training/displaying-bitmaps/manage-memory.html
您可以使用此属性android:largeHeap 来增加堆大小。
【讨论】:
@MítTơLớp,有用吗? 对不起,我的回复很慢。我试过你的代码,对于一些图片,它的工作很棒。但是其他一些图片,它在以下位置崩溃: int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];原因:java.lang.OutOfMemoryError 我该如何修复这些错误?请。 @MítTơLớp,我觉得有些图片太大了。崩溃时图片的大小是多少? 是的。它是 3264 x 2448。我在 Galaxy s3 上测试过。【参考方案2】:我有一个关于如何实现它的工作示例,如果您在 2016 年阅读,我就是这样做的:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
//initialize variables to make them global
private ImageButton Scan;
private static final int SELECT_PHOTO = 100;
//for easy manipulation of the result
public String barcode;
//call oncreate method
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//cast neccesary variables to their views
Scan = (ImageButton)findViewById(R.id.ScanBut);
//set a new custom listener
Scan.setOnClickListener(this);
//launch gallery via intent
Intent photoPic = new Intent(Intent.ACTION_PICK);
photoPic.setType("image/*");
startActivityForResult(photoPic, SELECT_PHOTO);
//do necessary coding for each ID
@Override
public void onClick(View v)
switch (v.getId())
case R.id.ScanBut:
//launch gallery via intent
Intent photoPic = new Intent(Intent.ACTION_PICK);
photoPic.setType("image/*");
startActivityForResult(photoPic, SELECT_PHOTO);
break;
//call the onactivity result method
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode)
case SELECT_PHOTO:
if (resultCode == RESULT_OK)
//doing some uri parsing
Uri selectedImage = imageReturnedIntent.getData();
InputStream imageStream = null;
try
//getting the image
imageStream = getContentResolver().openInputStream(selectedImage);
catch (FileNotFoundException e)
Toast.makeText(getApplicationContext(), "File not found", Toast.LENGTH_SHORT).show();
e.printStackTrace();
//decoding bitmap
Bitmap bMap = BitmapFactory.decodeStream(imageStream);
Scan.setImageURI(selectedImage);// To display selected image in image view
int[] intArray = new int[bMap.getWidth() * bMap.getHeight()];
// copy pixel data from the Bitmap into the 'intArray' array
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(),
bMap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(),
bMap.getHeight(), intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();// use this otherwise
// ChecksumException
try
Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
decodeHints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
Result result = reader.decode(bitmap, decodeHints);
//*I have created a global string variable by the name of barcode to easily manipulate data across the application*//
barcode = result.getText().toString();
//do something with the results for demo i created a popup dialog
if(barcode!=null)
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Scan Result");
builder.setIcon(R.mipmap.ic_launcher);
builder.setMessage("" + barcode);
AlertDialog alert1 = builder.create();
alert1.setButton(DialogInterface.BUTTON_POSITIVE, "Done", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
Intent i = new Intent (getBaseContext(),MainActivity.class);
startActivity(i);
);
alert1.setCanceledOnTouchOutside(false);
alert1.show();
else
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Scan Result");
builder.setIcon(R.mipmap.ic_launcher);
builder.setMessage("Nothing found try a different image or try again");
AlertDialog alert1 = builder.create();
alert1.setButton(DialogInterface.BUTTON_POSITIVE, "Done", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
Intent i = new Intent (getBaseContext(),MainActivity.class);
startActivity(i);
);
alert1.setCanceledOnTouchOutside(false);
alert1.show();
//the end of do something with the button statement.
catch (NotFoundException e)
Toast.makeText(getApplicationContext(), "Nothing Found", Toast.LENGTH_SHORT).show();
e.printStackTrace();
catch (ChecksumException e)
Toast.makeText(getApplicationContext(), "Something weird happen, i was probably tired to solve this issue", Toast.LENGTH_SHORT).show();
e.printStackTrace();
catch (FormatException e)
Toast.makeText(getApplicationContext(), "Wrong Barcode/QR format", Toast.LENGTH_SHORT).show();
e.printStackTrace();
catch (NullPointerException e)
Toast.makeText(getApplicationContext(), "Something weird happen, i was probably tired to solve this issue", Toast.LENGTH_SHORT).show();
e.printStackTrace();
【讨论】:
添加如何此代码回答问题将有助于未来的访问者。 @LucienMendela 谢谢。它工作..但它只扫描黑白png..如何扫描不同颜色的qr? 而且问题是相同的,它适用于大多数图像,但不适用于相同。为了验证生成的 QR 图像是否正确,我使用 在线工具 (qrlogo.kaarposoft.dk/qrdecode.html) 进行了检查,它能够成功解码。我有强烈的感觉,Zxing 在移动 SDK 方面缺少一些东西。【参考方案3】:我处于同一场景之间,它抛出 NotFoundException,official doc 说
在图像中未找到条形码时抛出。可能是 部分检测到但无法确认。
一级解决方案 在某种程度上,@Laurent 答案几乎适用于我拥有的每个样本,但很少失败。
下一级解决方案在@Lucien Mendela 建议的 reader.decode(..) 之前添加 decodeHints 就可以了。
Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); // Not required in my case
decodeHints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
但最后的事情对我有用
如果您的图片很大,您可能需要缩小尺寸。 它还需要一个 ~rectangle 形状(在我的例子中是 421*402)。参考 添加几个类似的问题:
Random com.google.zxing.NotFoundException during the reading valid QRCode您可以用来验证您拥有的图像的工具:
qrdecode(别忘了勾选“生成调试输出”以获取调试信息) Zxing Decoder online【讨论】:
【参考方案4】:首先,当然,从图库中读取图片(这可以在您的活动中): Help by
Intent pickIntent = new Intent(Intent.ACTION_PICK);
pickIntent.setDataAndType( android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(pickIntent, 111);
之后,只需获取活动结果上的图像 uri,ZXing 就会发挥作用:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode)
//the case is because you might be handling multiple request codes here
case 111:
if(data == null || data.getData()==null)
Log.e("TAG", "The uri is null, probably the user cancelled the image selection process using the back button.");
return;
Uri uri = data.getData();
try
InputStream inputStream = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null)
Log.e("TAG", "uri is not a bitmap," + uri.toString());
return;
int width = bitmap.getWidth(), height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
bitmap.recycle();
bitmap = null;
RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
BinaryBitmap bBitmap = new BinaryBitmap(new HybridBinarizer(source));
MultiFormatReader reader = new MultiFormatReader();
try
Result result = reader.decode(bBitmap);
Toast.makeText(this, "The content of the QR image is: " + result.getText(), Toast.LENGTH_SHORT).show();
catch (NotFoundException e)
Log.e("TAG", "decode exception", e);
catch (FileNotFoundException e)
Log.e("TAG", "can not open file" + uri.toString(), e);
break;
【讨论】:
以上是关于从画廊android中的图像扫描条形码的主要内容,如果未能解决你的问题,请参考以下文章
python 使用zbar,cv2和PIL / Pillow扫描图像中的条形码。
Android:如何将通过USB连接的外部条形码扫描仪设备集成到Android应用程序[关闭]
Zebra 设备-TC75x-Android 8.1-条形码扫描问题