Делаем фото при сканировании QR-кода

У меня есть приложение, в которое встроен zxing. Я пытался сохранить фотографию при сканировании QR-кода. Шон Оуэн рекомендовал следующее:

«Приложение получает непрерывный поток кадров с камеры для анализа. Вы можете сохранить любой из них, перехватив их в обратном вызове предварительного просмотра».

Насколько мне известно, единственные экземпляры обратного вызова предварительного просмотра находятся в действии CameraManager.java (https://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/camera/CameraManager.java).

Особенно:

public synchronized void requestPreviewFrame(Handler handler, int message) {
Camera theCamera = camera;
if (theCamera != null && previewing) {
  previewCallback.setHandler(handler, message);
  theCamera.setOneShotPreviewCallback(previewCallback);
}}

Поскольку это выполняется в каждом кадре, у меня нет метода сохранения (предпочтительно в виде даты байта) любого конкретного кадра. Я бы предположил, что есть точка, в которой что-то передается обратно в класс CaptureActivity.java (ссылка внизу), однако я сам ничего не нашел.

Любой, кто использовал Zxing, знает, что после сканирования на экране данных сканирования отображается призрачное изображение, если есть возможность взломать эту часть кода и преобразовать и/или сохранить эти данные в виде байтового кода, что также может быть полезно .

Любая помощь или другие идеи будут очень признательны. На запросы о любой дополнительной информации ответят быстро. Спасибо.

Полный код доступен в этой папке: https://code.google.com/p/zxing/source/browse/trunk#trunk%2Fandroid%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fandroid

Обновлять:

На данный момент следующие разделы кода кажутся возможными местами для сохранения байтовых данных, оба находятся в классе DecodeHandler.java.

private void decode(byte[] data, int width, int height) {
long start = System.currentTimeMillis();
Result rawResult = null;
PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
if (source != null) {
  BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

  //here?

  try {
    rawResult = multiFormatReader.decodeWithState(bitmap);
  } catch (ReaderException re) {
    // continue
  } finally {
    multiFormatReader.reset();
  }
}

Handler handler = activity.getHandler();
if (rawResult != null) {
  // Don't log the barcode contents for security.
  long end = System.currentTimeMillis();
  Log.d(TAG, "Found barcode in " + (end - start) + " ms");
  if (handler != null) {
    Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
    Bundle bundle = new Bundle();
    Bitmap grayscaleBitmap = toBitmap(source, source.renderCroppedGreyscaleBitmap());

    //I believe this bitmap is the one shown on screen after a scan has been performed

    bundle.putParcelable(DecodeThread.BARCODE_BITMAP, grayscaleBitmap);
    message.setData(bundle);
    message.sendToTarget();
  }
} else {
  if (handler != null) {
    Message message = Message.obtain(handler, R.id.decode_failed);
    message.sendToTarget();
  }
}}


  private static Bitmap toBitmap(LuminanceSource source, int[] pixels) {
int width = source.getWidth();
int height = source.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

//saving the bitmnap at this point or slightly sooner, before grey scaling could work.

return bitmap;}

Обновление: запрошенный код найден в PreviewCallback.java.

public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
Handler thePreviewHandler = previewHandler;
if (cameraResolution != null && thePreviewHandler != null) {
  Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
      cameraResolution.y, data);
  message.sendToTarget();
  previewHandler = null;
} else {
  Log.d(TAG, "Got preview callback, but no handler or resolution available");
}

person Community    schedule 03.08.2013    source источник


Ответы (1)


Данные обратного вызова предварительного просмотра имеют формат NV21. Поэтому, если вы хотите сохранить его, вы можете использовать такой код:

YuvImage im = new YuvImage(byteArray, ImageFormat.NV21, width,
                        height, null);
            Rect r = new Rect(0, 0, width, height);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            im.compressToJpeg(r, 50, baos);

            try {
                  FileOutputStream output = new FileOutputStream("/sdcard/test_jpg.jpg");
                  output.write(baos.toByteArray());
                  output.flush();
                  output.close();
            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            }

Точка сохранения — это когда ZXing может успешно декодировать byte[] и вернуть строку содержимого.

person yushulx    schedule 03.08.2013
comment
Правильно ли я думаю, что я должен сохранять данные в этом методе: public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) { Rect rect = getFramingRectInPreview(); if (rect == null) { return null; } // Go ahead and assume it's YUV rather than die. return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height(), false); } - person ; 03.08.2013
comment
Данные byte[] взяты из обратного вызова предварительного просмотра, следуйте им и найдите подходящую точку для их сохранения. вы также можете выполнить поиск по ключевому слову декодировать - person yushulx; 03.08.2013
comment
Я обновил исходный пост некоторыми возможными точками сохранения, однако они, похоже, не подпадают под необходимый критерий для сохранения с помощью вашего метода. Мысли и отзывы приветствуются. - person ; 03.08.2013
comment
можете ли вы найти onPreviewFrame (байт [] данные, камера камеры), в котором вы получаете данные из предварительного просмотра камеры? - person yushulx; 04.08.2013
comment
Код «работает», однако изображение повреждено, я полагаю, это потому, что он пытается сохранить изображение в каждом кадре, а не только в одном кадре. - person ; 09.08.2013
comment
Я задал новый вопрос, чтобы уточнить этот вопрос, любая помощь будет принята с благодарностью. Спасибо. stackoverflow.com/questions/18149620/ - person ; 09.08.2013