【问题标题】:Scan barcode from an image in gallery android从画廊android中的图像扫描条形码
【发布时间】:2015-06-21 09:09:00
【问题描述】:

我正在创建一个android项目,主要功能是扫描条形码。

我尝试将Zxing 库集成到我的项目中,并且工作正常。

但是,它似乎不支持从 android 设备库中的可用图像中扫描条形码。

我该怎么做?或与其他条形码库?

【问题讨论】:

    标签: android qr-code barcode-scanner image-gallery


    【解决方案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)。

    参考 添加几个类似的问题:

    您可以用来验证您拥有的图像的工具:

    【讨论】:

      【解决方案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;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-16
        相关资源
        最近更新 更多