diff --git a/entry/libs/arm64-v8a/libiconv.so b/entry/libs/arm64-v8a/libiconv.so new file mode 100644 index 0000000000000000000000000000000000000000..31c8e4f484d06bd7cabd795e69538b8f1a79c020 Binary files /dev/null and b/entry/libs/arm64-v8a/libiconv.so differ diff --git a/entry/libs/arm64-v8a/libzbarjni.so b/entry/libs/arm64-v8a/libzbarjni.so new file mode 100644 index 0000000000000000000000000000000000000000..9e0ce4930be93b35383f2448ff5a6795a63ccac6 Binary files /dev/null and b/entry/libs/arm64-v8a/libzbarjni.so differ diff --git a/entry/src/main/java/com/blikoon/qrcodescannerlibrary/slice/MainAbilitySlice.java b/entry/src/main/java/com/blikoon/qrcodescannerlibrary/slice/MainAbilitySlice.java index 3e9dd828bff1ded730b6e3c74663177fef2c2f63..ec5be5e919f2a16bed3462cea529994854297876 100644 --- a/entry/src/main/java/com/blikoon/qrcodescannerlibrary/slice/MainAbilitySlice.java +++ b/entry/src/main/java/com/blikoon/qrcodescannerlibrary/slice/MainAbilitySlice.java @@ -24,6 +24,7 @@ import ohos.agp.components.DirectionalLayout; import ohos.agp.components.LayoutScatter; import ohos.agp.components.Text; import ohos.agp.utils.LayoutAlignment; +import ohos.agp.window.dialog.BaseDialog; import ohos.agp.window.dialog.CommonDialog; import ohos.agp.window.service.DisplayAttributes; import ohos.agp.window.service.DisplayManager; @@ -37,6 +38,8 @@ import ohos.app.Context; public class MainAbilitySlice extends AbilitySlice { private Button button; + private boolean isFlag = true; + private CommonDialog dialog; @Override public void onStart(Intent intent) { @@ -52,7 +55,10 @@ public class MainAbilitySlice extends AbilitySlice { getUITaskDispatcher().asyncDispatch(new Runnable() { @Override public void run() { - show(getContext(),result); + if (isFlag){ + isFlag = false; + show(getContext(),result); + } } }); } @@ -65,7 +71,7 @@ public class MainAbilitySlice extends AbilitySlice { .parse(ResourceTable.Layout_dialog_picker, null, false); Text result = (Text) directionalLayout.findComponentById(ResourceTable.Id_tv_result); Text confirm = (Text) directionalLayout.findComponentById(ResourceTable.Id_tv_confirm); - CommonDialog dialog = new CommonDialog(context); + dialog = new CommonDialog(context); dialog.setContentCustomComponent(directionalLayout); dialog.setAutoClosable(true); dialog.setAutoClosable(true); @@ -76,6 +82,14 @@ public class MainAbilitySlice extends AbilitySlice { result.setText(text); confirm.setClickedListener(v -> { dialog.destroy(); + isFlag = true; + }); + dialog.setDestroyedListener(new CommonDialog.DestroyedListener() { + + @Override + public void onDestroy() { + isFlag = true; + } }); } diff --git a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/QrCodeAbility.java b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/QrCodeAbility.java index c56a7ac1686ac4f6d8203fa6883dbea1f30d4e1f..c4c02f9b67db0142bfbce5af645be9228c099c32 100644 --- a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/QrCodeAbility.java +++ b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/QrCodeAbility.java @@ -1,9 +1,30 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.blikoon.qrcodescanner; import com.blikoon.qrcodescanner.slice.QrCodeAbilitySlice; import ohos.aafwk.ability.Ability; import ohos.aafwk.content.Intent; +/** + * QrCodeAbilitySlice + * + * @author ljx + * @since 2021-04-14 + */ public class QrCodeAbility extends Ability { @Override diff --git a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/slice/QrCodeAbilitySlice.java b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/slice/QrCodeAbilitySlice.java index c53bcb66557d57194d4450b174493a0be79036b5..f65b17e2597c58bd1356b0c587396f0ac2b77da1 100644 --- a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/slice/QrCodeAbilitySlice.java +++ b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/slice/QrCodeAbilitySlice.java @@ -21,6 +21,9 @@ import com.blikoon.qrcodescanner.utils.QrUtils; import com.blikoon.qrcodescanner.utils.ScreenUtils; import com.blikoon.qrcodescanner.view.QrCodeFinderView; import com.google.zxing.Result; +import net.sourceforge.zbar.Config; +import net.sourceforge.zbar.ImageScanner; +import net.sourceforge.zbar.Symbol; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.ability.DataAbilityHelper; import ohos.aafwk.content.Intent; @@ -35,6 +38,7 @@ import ohos.agp.graphics.Surface; import ohos.agp.graphics.SurfaceOps; import ohos.agp.utils.Color; import ohos.agp.window.dialog.ToastDialog; +import ohos.agp.window.service.WindowManager; import ohos.eventhandler.EventHandler; import ohos.eventhandler.EventRunner; import ohos.global.resource.RawFileDescriptor; @@ -43,7 +47,7 @@ import ohos.media.camera.device.Camera; import ohos.media.camera.device.CameraConfig; import ohos.media.camera.device.CameraStateCallback; import ohos.media.camera.device.FrameConfig; -import ohos.media.camera.params.Metadata; +import ohos.media.common.BufferInfo; import ohos.media.common.Source; import ohos.media.image.Image; import ohos.media.image.ImageReceiver; @@ -56,8 +60,11 @@ import ohos.utils.IntentConstants; import ohos.utils.net.Uri; import java.io.FileDescriptor; +import java.nio.ByteBuffer; import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW; +import static ohos.media.camera.params.Metadata.FlashMode.FLASH_ALWAYS_OPEN; +import static ohos.media.camera.params.Metadata.FlashMode.FLASH_CLOSE; /** * QrCodeAbilitySlice @@ -66,33 +73,62 @@ import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVI * @since 2021-04-14 */ public class QrCodeAbilitySlice extends AbilitySlice { + + private ImageScanner scanner; private ImageReceiver imageReceiver; private CameraKit cameraKit; - private SurfaceProvider surfaceProvider; private Surface previewSurface; - private int VIDEO_WIDTH = 256; - private int VIDEO_HEIGHT = 256; + private Surface dataSurface; + private Camera mcamera; + + private EventHandler handler; + public static final int VIDEO_WIDTH = 640; + public static final int VIDEO_HEIGHT = 480; + private QrCodeFinderView mLaserView; - private Camera myCamera; - /** - * 相机属性 - */ - private CameraConfig.Builder cameraConfigBuilder; - /** - * 预览模板 - */ - private static FrameConfig.Builder frameConfigBuilder; private Player mPlayer; + private boolean isFlash = false; + private FrameConfig.Builder frameConfigBuilder; @Override public void onStart(Intent intent) { super.onStart(intent); + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(new Color(Color.getIntColor("#3F51B5")).getValue()); super.setUIContent(ResourceTable.Layout_ability_qr_code); + + handler = new EventHandler(EventRunner.getMainEventRunner()); + scanner = new ImageScanner(); + scanner.setConfig(0, Config.X_DENSITY, 3); + scanner.setConfig(0, Config.Y_DENSITY, 3); + + + //初始化UI和相机,实现视频帧的获取 + SurfaceProvider surfaceProvider = (SurfaceProvider) findComponentById(ResourceTable.Id_zbar_surfaceprovider); + surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceOps.Callback() { + @Override + public void surfaceCreated(SurfaceOps surfaceOps) { + previewSurface = surfaceOps.getSurface(); + openCamera(); + } + + @Override + public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) { + } + + @Override + public void surfaceDestroyed(SurfaceOps surfaceOps) { + } + }); + getWindow().setTransparent(true); + + + //注册编码器,实现视频帧的编码 + imageReceiver = ImageReceiver.create(VIDEO_WIDTH, VIDEO_HEIGHT, ImageFormat.YUV420_888, 10); + imageReceiver.setImageArrivalListener(new IImageArrivalListenerImpl()); + initPlayer(); initLayout(); - initImageReceiver(); - capture(); } private void initPlayer() { @@ -126,81 +162,24 @@ public class QrCodeAbilitySlice extends AbilitySlice { config.height = ScreenUtils.getDisplayWidthInPx(this); int px = ScreenUtils.getDisplayHeightInPX(this) - ScreenUtils.getDisplayWidthInPx(this); config.setMargins(0, px / 3, 0, 0); - surfaceProvider = new SurfaceProvider(this); - surfaceProvider.setLayoutConfig(config); +// surfaceProvider = new SurfaceProvider(this); +// surfaceProvider.setLayoutConfig(config); getWindow().setTransparent(true); - // 获取SurfaceOps对象 - SurfaceOps surfaceOps = surfaceProvider.getSurfaceOps().get(); - // 设置屏幕一直打开 - surfaceOps.setKeepScreenOn(true); - // 添加回调 - surfaceOps.addCallback(callback); - myLayout.addComponent(surfaceProvider); +// // 获取SurfaceOps对象 +// SurfaceOps surfaceOps = surfaceProvider.getSurfaceOps().get(); +// // 设置屏幕一直打开 +// surfaceOps.setKeepScreenOn(true); +// // 添加回调 +// surfaceOps.addCallback(callback); +// myLayout.addComponent(surfaceProvider); mLaserView = new QrCodeFinderView(this); config.width = ScreenUtils.getDisplayWidthInPx(this); config.height = ScreenUtils.getDisplayHeightInPX(this); - config.setMargins(0, 0, 0, 0); + config.setMargins(0, 100, 0, 0); mLaserView.setLayoutConfig(config); myLayout.addComponent(mLaserView); } - /** - * 创建ImageReceiver并配置监听器 - */ - private void initImageReceiver() { - imageReceiver = ImageReceiver.create(VIDEO_WIDTH, VIDEO_HEIGHT, ImageFormat.JPEG, 50); - IImageArrivalListenerImpl listener = new IImageArrivalListenerImpl(); - imageReceiver.setImageArrivalListener(listener); - } - - /** - * 闪光灯 - * - * @param des text - */ - public void setFlash(Text des) { - try { - isFlash = !isFlash; - // 获取预览配置模板 - FrameConfig.Builder frameConfigBuilder = myCamera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW); - // 配置预览Surface - frameConfigBuilder.addSurface(previewSurface); - if (isFlash) { - frameConfigBuilder.setFlashMode(Metadata.FlashMode.FLASH_ALWAYS_OPEN); - if (des != null) { - des.setText("Close Flash Light"); - } - } else { - frameConfigBuilder.setFlashMode(Metadata.FlashMode.FLASH_CLOSE); - if (des != null) { - des.setText("Open flash light"); - } - } - // 预览帧变焦值变更 - FrameConfig previewFrameConfig = frameConfigBuilder.build(); - - // 启动循环帧捕获 - myCamera.triggerLoopingCapture(previewFrameConfig); - } catch (Exception e) { - new ToastDialog(this).setText("该设备不支持闪光灯").show(); - } - } - - public void closeFlash() { - try { - FrameConfig.Builder frameConfigBuilder = myCamera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW); - frameConfigBuilder.addSurface(previewSurface); - int flashMode = frameConfigBuilder.getFlashMode(); - if (flashMode == Metadata.FlashMode.FLASH_ALWAYS_OPEN) { - frameConfigBuilder.setFlashMode(Metadata.FlashMode.FLASH_CLOSE); - FrameConfig previewFrameConfig = frameConfigBuilder.build(); - myCamera.triggerLoopingCapture(previewFrameConfig); - } - } catch (Exception e) { - System.out.println(e); - } - } - private void picture() { Intent intent = new Intent(); Operation operation = new Intent.OperationBuilder() @@ -246,9 +225,9 @@ public class QrCodeAbilitySlice extends AbilitySlice { mPlayer.prepare(); mPlayer.play(); closeFlash(); - if (myCamera != null) { - myCamera.release(); - myCamera = null; + if (mcamera != null) { + mcamera.release(); + mcamera = null; } terminate(); } catch (Exception e) { @@ -261,33 +240,99 @@ public class QrCodeAbilitySlice extends AbilitySlice { } } - public void capture() { - getUITaskDispatcher().delayDispatch(() -> { - try { - frameConfigBuilder = myCamera.getFrameConfigBuilder(Camera.FrameConfigType.FRAME_CONFIG_PICTURE); - frameConfigBuilder.addSurface(imageReceiver.getRecevingSurface()); - myCamera.triggerSingleCapture(frameConfigBuilder.build()); - } catch (Exception e) { + /** + * 闪光灯 + * + * @param des text + */ + public void setFlash(Text des) { + try { + isFlash = !isFlash; + if (isFlash) { + if (des != null) { + // 预览帧变焦值变更 + frameConfigBuilder.setFlashMode(FLASH_ALWAYS_OPEN); + des.setText("Close Flash Light"); + } + } else { + frameConfigBuilder.setFlashMode(FLASH_CLOSE); + if (des != null) { + des.setText("Open flash light"); + } } - }, 2000); + mcamera.triggerLoopingCapture(frameConfigBuilder.build()); + } catch (Exception e) { + new ToastDialog(this).setText("该设备不支持闪光灯").show(); + } } - private SurfaceOps.Callback callback = new SurfaceOps.Callback() { - - @Override - public void surfaceCreated(SurfaceOps surfaceOps) { - previewSurface = surfaceOps.getSurface(); - openCamera(); + public void closeFlash() { + try { + frameConfigBuilder.setFlashMode(FLASH_CLOSE); + mcamera.triggerLoopingCapture(frameConfigBuilder.build()); + } catch (Exception e) { + System.out.println(e); } + } - @Override - public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) { - } + @Override + public void onStop() { + } + private class IImageArrivalListenerImpl implements ImageReceiver.IImageArrivalListener { + //对监听事件的响应逻辑,实现对图像数据处理和到编码器的传输 @Override - public void surfaceDestroyed(SurfaceOps surfaceOps) { + public void onImageArrival(ImageReceiver imageReceiver) { + + Image mImage = imageReceiver.readNextImage(); + if (mImage != null) { + BufferInfo bufferInfo = new BufferInfo(); + ByteBuffer mBuffer; + byte[] YUV_DATA = new byte[VIDEO_HEIGHT * VIDEO_WIDTH * 3 / 2]; + int i; + //采集YUV格式数据 + mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_Y).getBuffer(); + for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT; i++) { + YUV_DATA[i] = mBuffer.get(i); + } + mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_V).getBuffer(); + for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT / 4; i++) { + YUV_DATA[(VIDEO_WIDTH * VIDEO_HEIGHT) + i * 2] = + mBuffer.get(i * 2); + } + mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_U).getBuffer(); + for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT / 4; i++) { + YUV_DATA[(VIDEO_WIDTH * VIDEO_HEIGHT) + i * 2 + 1] = mBuffer.get(i * 2); + } + bufferInfo.setInfo(0, VIDEO_WIDTH * VIDEO_HEIGHT * 3 / 2, mImage.getTimestamp(), 0); + net.sourceforge.zbar.Image barcode = new net.sourceforge.zbar.Image(mImage.getImageSize().width, mImage.getImageSize().height, "Y800"); + barcode.setData(YUV_DATA); + + + if (scanner.scanImage(barcode) != 0) { + for (Symbol sym : scanner.getResults()) { + handler.postSyncTask(new Runnable() { + @Override + public void run() { + + QrManager.getInstance().getResultCallback().onScanSuccess(sym.getData()); + mPlayer.prepare(); + mPlayer.play(); + closeFlash(); + if (mcamera != null) { + mcamera.release(); + mcamera = null; + } + terminate(); + } + }); + } + } + mImage.release(); + return; + } } - }; + } private void openCamera() { // 获取 CameraKit 对象 @@ -298,103 +343,63 @@ public class QrCodeAbilitySlice extends AbilitySlice { try { // 获取当前设备的逻辑相机列表cameraIds String[] cameraIds = cameraKit.getCameraIds(); - if (cameraIds.length <= 0) { - System.out.println("cameraIds size is 0"); - return; - } - // 创建相机对象,会调用cameraStateCallback中的回调方法 - cameraKit.createCamera(cameraIds[0], - new CameraStateCallbackImpl(), - new EventHandler(EventRunner.create("CameraCb"))); - } catch (Exception e) { + // 创建相机! + cameraKit.createCamera(cameraIds[0], new CameraStateCallbackImpl(), new EventHandler(EventRunner.create("CameraCb"))); + } catch (IllegalStateException e) { System.out.println("getCameraIds fail"); } } - private final class CameraStateCallbackImpl extends CameraStateCallback { + private final class CameraStateCallbackImpl extends CameraStateCallback { + //相机回调 @Override public void onCreated(Camera camera) { - myCamera = camera; - // 相机配置 - cameraConfigBuilder = camera.getCameraConfigBuilder(); - // 设置预览surface + mcamera = camera; + //相机创建时回调 + CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder(); + if (cameraConfigBuilder == null) { + return; + } + // 配置预览的 Surface cameraConfigBuilder.addSurface(previewSurface); - // 设置拍照surface - cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface()); + // 配置拍照的 Surface + dataSurface = imageReceiver.getRecevingSurface(); + cameraConfigBuilder.addSurface(dataSurface); + + frameConfigBuilder = mcamera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW); try { - // 相机设备配置, 触发onConfigured回调 + // 相机设备配置 camera.configure(cameraConfigBuilder.build()); - } catch (Exception e) { - // HiLog.error(LOG, "Argument Exception"); + } catch (IllegalArgumentException e) { + System.out.println("Argument Exception"); + } catch (IllegalStateException e) { + System.out.println("State Exception"); } } @Override public void onConfigured(Camera camera) { - // 获取预览模板 - frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW); - // 配置预览surface + // 配置预览 Surface frameConfigBuilder.addSurface(previewSurface); - // 设置放大倍数 - //frameConfigBuilder.setZoom(1.2f); - FrameConfig previewFrameConfig = frameConfigBuilder.build(); + // 配置拍照的 Surface + frameConfigBuilder.addSurface(dataSurface); try { - // 启动循环帧捕获,获取触发器id - camera.triggerLoopingCapture(previewFrameConfig); - } catch (Exception e) { - // HiLog.error(LOG, "Argument Exception"); + // 启动循环帧捕获 + mcamera.triggerLoopingCapture(frameConfigBuilder.build()); + } catch (IllegalArgumentException e) { + System.out.println("Argument Exception"); + } catch (IllegalStateException e) { + System.out.println("State Exception"); } } @Override public void onReleased(Camera camera) { // 释放相机设备 - try { - if (camera != null) { - // 释放相机设备 - camera.release(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - //监听器,当有数据进入ImageReceiver时触发 - private class IImageArrivalListenerImpl implements ImageReceiver.IImageArrivalListener { - - @Override - public void onImageArrival(ImageReceiver imageReceiver) { - try { - // 保存图片 - Image image = imageReceiver.readNextImage(); - if (image == null) { - capture(); - } else { - Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG); - byte[] bytes = new byte[component.remaining()]; - component.read(bytes); - ImageSource imageSource = ImageSource.create(bytes, null); - PixelMap bitmap = imageSource.createPixelmap(null); - int width = bitmap.getImageInfo().size.width; - int height = bitmap.getImageInfo().size.height; - - byte[] yuv420sp = QrUtils.getYUV420sp(width, height, bitmap); - Result result = QrUtils.decodeImage(yuv420sp, width, height); - if (null == result) { - capture(); - } else { - mPlayer.prepare(); - mPlayer.play(); - QrManager.getInstance().getResultCallback().onScanSuccess(result.getText()); - closeFlash(); - terminate(); - } - } - } catch (Exception e) { - e.printStackTrace(); - capture(); + if (mcamera != null) { + mcamera.release(); + mcamera = null; } } } @@ -406,6 +411,11 @@ public class QrCodeAbilitySlice extends AbilitySlice { @Override public void onForeground(Intent intent) { - super.onForeground(intent); + if (mcamera != null) { + mcamera.stopLoopingCapture(); + mcamera.release(); + mcamera = null; + } + QrCodeAbilitySlice.super.terminate(); } } diff --git a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/view/QrCodeFinderView.java b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/view/QrCodeFinderView.java index 82fc25fcd2393acf036794af45a62c3c1eb2a53e..458b1eb73aa982865f0263deb68cf8a79ae86419 100644 --- a/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/view/QrCodeFinderView.java +++ b/qrcodescanner/src/main/java/com/blikoon/qrcodescanner/view/QrCodeFinderView.java @@ -41,6 +41,7 @@ public final class QrCodeFinderView extends DependentLayout implements Component private int mFocusThick; private int mAngleThick; private int mAngleLength; + private AnimatorValue mValueAnimator; public QrCodeFinderView(Context context) { this(context, null); @@ -229,7 +230,7 @@ public final class QrCodeFinderView extends DependentLayout implements Component } private void initScanValueAnim() { - AnimatorValue mValueAnimator = new AnimatorValue(); + mValueAnimator = new AnimatorValue(); mValueAnimator.setDuration(1000); mValueAnimator.setLoopedCount(AnimatorValue.INFINITE); mValueAnimator.setCurveType(Animator.CurveType.DECELERATE); @@ -237,6 +238,9 @@ public final class QrCodeFinderView extends DependentLayout implements Component @Override public void onUpdate(AnimatorValue animatorValue, float v) { + if (height < 1){ + height = 700; + } height = (int) (height * v); invalidate(); } diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/Config.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/Config.java new file mode 100644 index 0000000000000000000000000000000000000000..8c5349a32a8b126298a4e6ce8780d876a93f44cd --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/Config.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Decoder configuration options. + */ +public class Config +{ + /** Enable symbology/feature. */ + public static final int ENABLE = 0; + /** Enable check digit when optional. */ + public static final int ADD_CHECK = 1; + /** Return check digit when present. */ + public static final int EMIT_CHECK = 2; + /** Enable full ASCII character set. */ + public static final int ASCII = 3; + + /** Minimum data length for valid decode. */ + public static final int MIN_LEN = 0x20; + /** Maximum data length for valid decode. */ + public static final int MAX_LEN = 0x21; + + /** Required video consistency frames. */ + public static final int UNCERTAINTY = 0x40; + + /** Enable scanner to collect position data. */ + public static final int POSITION = 0x80; + + /** Image scanner vertical scan density. */ + public static final int X_DENSITY = 0x100; + /** Image scanner horizontal scan density. */ + public static final int Y_DENSITY = 0x101; +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/Image.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/Image.java new file mode 100644 index 0000000000000000000000000000000000000000..dd79da9e928fd65482bcb71616228ee557030856 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/Image.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** stores image data samples along with associated format and size + * metadata. + */ +public class Image +{ + /** C pointer to a zbar_symbol_t. */ + private long peer; + private Object data; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + public Image () + { + peer = create(); + } + + public Image (int width, int height) + { + this(); + setSize(width, height); + } + + public Image (int width, int height, String format) + { + this(); + setSize(width, height); + setFormat(format); + } + + public Image (String format) + { + this(); + setFormat(format); + } + + Image (long peer) + { + this.peer = peer; + } + + /** Create an associated peer instance. */ + private native long create(); + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Destroy the associated peer instance. */ + private native void destroy(long peer); + + /** Image format conversion. + * @returns a @em new image with the sample data from the original + * image converted to the requested format fourcc. the original + * image is unaffected. + */ + public Image convert (String format) + { + long newpeer = convert(peer, format); + if(newpeer == 0) + return(null); + return(new Image(newpeer)); + } + + private native long convert(long peer, String format); + + /** Retrieve the image format fourcc. */ + public native String getFormat(); + + /** Specify the fourcc image format code for image sample data. */ + public native void setFormat(String format); + + /** Retrieve a "sequence" (page/frame) number associated with this + * image. + */ + public native int getSequence(); + + /** Associate a "sequence" (page/frame) number with this image. */ + public native void setSequence(int seq); + + /** Retrieve the width of the image. */ + public native int getWidth(); + + /** Retrieve the height of the image. */ + public native int getHeight(); + + /** Retrieve the size of the image. */ + public native int[] getSize(); + + /** Specify the pixel size of the image. */ + public native void setSize(int width, int height); + + /** Specify the pixel size of the image. */ + public native void setSize(int[] size); + + /** Retrieve the crop region of the image. */ + public native int[] getCrop(); + + /** Specify the crop region of the image. */ + public native void setCrop(int x, int y, int width, int height); + + /** Specify the crop region of the image. */ + public native void setCrop(int[] crop); + + /** Retrieve the image sample data. */ + public native byte[] getData(); + + /** Specify image sample data. */ + public native void setData(byte[] data); + + /** Specify image sample data. */ + public native void setData(int[] data); + + /** Retrieve the decoded results associated with this image. */ + public SymbolSet getSymbols () + { + return(new SymbolSet(getSymbols(peer))); + } + + private native long getSymbols(long peer); + +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/ImageScanner.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/ImageScanner.java new file mode 100644 index 0000000000000000000000000000000000000000..aa709586eb0a5ca63f404ae6b51f2b5a75cae377 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/ImageScanner.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Read barcodes from 2-D images. + */ +public class ImageScanner +{ + /** C pointer to a zbar_image_scanner_t. */ + private long peer; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + public ImageScanner () + { + peer = create(); + } + + /** Create an associated peer instance. */ + private native long create(); + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Destroy the associated peer instance. */ + private native void destroy(long peer); + + /** Set config for indicated symbology (0 for all) to specified value. + */ + public native void setConfig(int symbology, int config, int value) + throws IllegalArgumentException; + + /** Parse configuration string and apply to image scanner. */ + public native void parseConfig(String config); + + /** Enable or disable the inter-image result cache (default disabled). + * Mostly useful for scanning video frames, the cache filters duplicate + * results from consecutive images, while adding some consistency + * checking and hysteresis to the results. Invoking this method also + * clears the cache. + */ + public native void enableCache(boolean enable); + + /** Retrieve decode results for last scanned image. + * @returns the SymbolSet result container + */ + public SymbolSet getResults () + { + return(new SymbolSet(getResults(peer))); + } + + private native long getResults(long peer); + + /** Scan for symbols in provided Image. + * The image format must currently be "Y800" or "GRAY". + * @returns the number of symbols successfully decoded from the image. + */ + public native int scanImage(Image image); +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/Modifier.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/Modifier.java new file mode 100644 index 0000000000000000000000000000000000000000..ab4bcbe0dd06b754ddeeaaa90d8b3135c4d943b4 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/Modifier.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Decoder symbology modifiers. + */ +public class Modifier +{ + /** barcode tagged as GS1 (EAN.UCC) reserved + * (eg, FNC1 before first data character). + * data may be parsed as a sequence of GS1 AIs + */ + public static final int GS1 = 0; + + /** barcode tagged as AIM reserved + * (eg, FNC1 after first character or digit pair) + */ + public static final int AIM = 1; +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/Orientation.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/Orientation.java new file mode 100644 index 0000000000000000000000000000000000000000..a86f9bf036d1a8b04016b9eea7d7cdd6804a8a32 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/Orientation.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Decoded symbol coarse orientation. + */ +public class Orientation +{ + /** Unable to determine orientation. */ + public static final int UNKNOWN = -1; + /** Upright, read left to right. */ + public static final int UP = 0; + /** sideways, read top to bottom */ + public static final int RIGHT = 1; + /** upside-down, read right to left */ + public static final int DOWN = 2; + /** sideways, read bottom to top */ + public static final int LEFT = 3; +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/Symbol.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/Symbol.java new file mode 100644 index 0000000000000000000000000000000000000000..e59ab073a23bbc69cd845e08c5cc845a211ddf73 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/Symbol.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Immutable container for decoded result symbols associated with an image + * or a composite symbol. + */ +public class Symbol +{ + /** No symbol decoded. */ + public static final int NONE = 0; + /** Symbol detected but not decoded. */ + public static final int PARTIAL = 1; + + /** EAN-8. */ + public static final int EAN8 = 8; + /** UPC-E. */ + public static final int UPCE = 9; + /** ISBN-10 (from EAN-13). */ + public static final int ISBN10 = 10; + /** UPC-A. */ + public static final int UPCA = 12; + /** EAN-13. */ + public static final int EAN13 = 13; + /** ISBN-13 (from EAN-13). */ + public static final int ISBN13 = 14; + /** Interleaved 2 of 5. */ + public static final int I25 = 25; + /** DataBar (RSS-14). */ + public static final int DATABAR = 34; + /** DataBar Expanded. */ + public static final int DATABAR_EXP = 35; + /** Codabar. */ + public static final int CODABAR = 38; + /** Code 39. */ + public static final int CODE39 = 39; + /** PDF417. */ + public static final int PDF417 = 57; + /** QR Code. */ + public static final int QRCODE = 64; + /** Code 93. */ + public static final int CODE93 = 93; + /** Code 128. */ + public static final int CODE128 = 128; + + /** C pointer to a zbar_symbol_t. */ + private long peer; + + /** Cached attributes. */ + private int type; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + /** Symbols are only created by other package methods. */ + Symbol (long peer) + { + this.peer = peer; + } + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Release the associated peer instance. */ + private native void destroy(long peer); + + /** Retrieve type of decoded symbol. */ + public int getType () + { + if(type == 0) + type = getType(peer); + return(type); + } + + private native int getType(long peer); + + /** Retrieve symbology boolean configs settings used during decode. */ + public native int getConfigMask(); + + /** Retrieve symbology characteristics detected during decode. */ + public native int getModifierMask(); + + /** Retrieve data decoded from symbol as a String. */ + public native String getData(); + + /** Retrieve raw data bytes decoded from symbol. */ + public native byte[] getDataBytes(); + + /** Retrieve a symbol confidence metric. Quality is an unscaled, + * relative quantity: larger values are better than smaller + * values, where "large" and "small" are application dependent. + */ + public native int getQuality(); + + /** Retrieve current cache count. When the cache is enabled for + * the image_scanner this provides inter-frame reliability and + * redundancy information for video streams. + * @returns < 0 if symbol is still uncertain + * @returns 0 if symbol is newly verified + * @returns > 0 for duplicate symbols + */ + public native int getCount(); + + /** Retrieve an approximate, axis-aligned bounding box for the + * symbol. + */ + public int[] getBounds () + { + int n = getLocationSize(peer); + if(n <= 0) + return(null); + + int[] bounds = new int[4]; + int xmin = Integer.MAX_VALUE; + int xmax = Integer.MIN_VALUE; + int ymin = Integer.MAX_VALUE; + int ymax = Integer.MIN_VALUE; + + for(int i = 0; i < n; i++) { + int x = getLocationX(peer, i); + if(xmin > x) xmin = x; + if(xmax < x) xmax = x; + + int y = getLocationY(peer, i); + if(ymin > y) ymin = y; + if(ymax < y) ymax = y; + } + bounds[0] = xmin; + bounds[1] = ymin; + bounds[2] = xmax - xmin; + bounds[3] = ymax - ymin; + return(bounds); + } + + private native int getLocationSize(long peer); + private native int getLocationX(long peer, int idx); + private native int getLocationY(long peer, int idx); + + public int[] getLocationPoint (int idx) + { + int[] p = new int[2]; + p[0] = getLocationX(peer, idx); + p[1] = getLocationY(peer, idx); + return(p); + } + + /** Retrieve general axis-aligned, orientation of decoded + * symbol. + */ + public native int getOrientation(); + + /** Retrieve components of a composite result. */ + public SymbolSet getComponents () + { + return(new SymbolSet(getComponents(peer))); + } + + private native long getComponents(long peer); + + native long next(); +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolIterator.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..8d29eaf23dcb14c0528186ebb66281688e262725 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolIterator.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Iterator over a SymbolSet. + */ +public class SymbolIterator + implements java.util.Iterator +{ + /** Next symbol to be returned by the iterator. */ + private Symbol current; + + /** SymbolIterators are only created by internal interface methods. */ + SymbolIterator (Symbol first) + { + current = first; + } + + /** Returns true if the iteration has more elements. */ + public boolean hasNext () + { + return(current != null); + } + + /** Retrieves the next element in the iteration. */ + public Symbol next () + { + if(current == null) + throw(new java.util.NoSuchElementException + ("access past end of SymbolIterator")); + + Symbol result = current; + long sym = current.next(); + if(sym != 0) + current = new Symbol(sym); + else + current = null; + return(result); + } + + /** Raises UnsupportedOperationException. */ + public void remove () + { + throw(new UnsupportedOperationException + ("SymbolIterator is immutable")); + } +} diff --git a/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolSet.java b/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolSet.java new file mode 100644 index 0000000000000000000000000000000000000000..ab6893a021c6b4fd72b0c0e73544b1caa1f6aa41 --- /dev/null +++ b/qrcodescanner/src/main/java/net/sourceforge/zbar/SymbolSet.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2011 Jeff Brown + * Copyright 2021 Institute of Software Chinese Academy of Sciences, ISRC + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sourceforge.zbar; + +/** Immutable container for decoded result symbols associated with an image + * or a composite symbol. + */ +public class SymbolSet + extends java.util.AbstractCollection +{ + /** C pointer to a zbar_symbol_set_t. */ + private long peer; + + static + { + System.loadLibrary("zbarjni"); + init(); + } + private static native void init(); + + /** SymbolSets are only created by other package methods. */ + SymbolSet (long peer) + { + this.peer = peer; + } + + protected void finalize () + { + destroy(); + } + + /** Clean up native data associated with an instance. */ + public synchronized void destroy () + { + if(peer != 0) { + destroy(peer); + peer = 0; + } + } + + /** Release the associated peer instance. */ + private native void destroy(long peer); + + /** Retrieve an iterator over the Symbol elements in this collection. */ + public java.util.Iterator iterator () + { + long sym = firstSymbol(peer); + if(sym == 0) + return(new SymbolIterator(null)); + + return(new SymbolIterator(new Symbol(sym))); + } + + /** Retrieve the number of elements in the collection. */ + public native int size(); + + /** Retrieve C pointer to first symbol in the set. */ + private native long firstSymbol(long peer); +} diff --git a/qrcodescanner/src/main/resources/base/layout/ability_qr_code.xml b/qrcodescanner/src/main/resources/base/layout/ability_qr_code.xml index a1ae538ac727ad8379c2b1723502e778e89df597..93783733c34e608bef92e683349f93cea3e29424 100644 --- a/qrcodescanner/src/main/resources/base/layout/ability_qr_code.xml +++ b/qrcodescanner/src/main/resources/base/layout/ability_qr_code.xml @@ -1,61 +1,67 @@ + ohos:orientation="vertical"> - + - + - - + + - + - + - - + + + + \ No newline at end of file