diff --git a/app/src/main/rust/Cargo.lock b/app/src/main/rust/Cargo.lock index 904d6bcd4..46ced711b 100644 --- a/app/src/main/rust/Cargo.lock +++ b/app/src/main/rust/Cargo.lock @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" [[package]] name = "autocfg" @@ -694,9 +694,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "walkdir" diff --git a/app/src/main/rust/Cargo.toml b/app/src/main/rust/Cargo.toml index c88d36c01..2c1b0c7b0 100644 --- a/app/src/main/rust/Cargo.toml +++ b/app/src/main/rust/Cargo.toml @@ -17,8 +17,8 @@ android_logger = { default-features = false, version = "0.14" } serde_cbor = "0.11" serde = { version = "1.0", features = ["derive"] } anyhow = "1.0" +image = { default-features = false, version = "0.24" } bardecoder = "0.5" -image = "0.24" ndk = { version = "0.9", features = ["bitmap"] } [profile.release] diff --git a/app/src/main/rust/src/image.rs b/app/src/main/rust/src/image.rs new file mode 100644 index 000000000..9ad8744ee --- /dev/null +++ b/app/src/main/rust/src/image.rs @@ -0,0 +1 @@ +mod qr_code; diff --git a/app/src/main/rust/src/image/qr_code.rs b/app/src/main/rust/src/image/qr_code.rs new file mode 100644 index 000000000..87e0bbb28 --- /dev/null +++ b/app/src/main/rust/src/image/qr_code.rs @@ -0,0 +1,41 @@ +use crate::{get_bitmap_handle, jni_throwing}; +use anyhow::{anyhow, Result}; +use bardecoder::decode::Decode; +use bardecoder::default_builder; +use bardecoder::extract::QRExtractor; +use bardecoder::util::qr::{QRData, QRError}; +use image::ImageBuffer; +use jni::objects::JClass; +use jni::sys::{jboolean, jobject}; +use jni::JNIEnv; +use jni_fn::jni_fn; +use std::ptr::slice_from_raw_parts; + +#[allow(dead_code)] +struct Nothing {} + +impl Decode for Nothing { + fn decode(&self, result: Result) -> Result { + result.map(|_| String::new()) + } +} + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.image.ImageKt")] +pub fn hasQrCode(mut env: JNIEnv, _class: JClass, object: jobject) -> jboolean { + let handle = get_bitmap_handle(&mut env, object); + jni_throwing(&mut env, |_| { + let bitmap_info = handle.info()?; + let (width, height) = (bitmap_info.width(), bitmap_info.height()); + let ptr = handle.lock_pixels()? as *const u8; + let buffer = unsafe { &*slice_from_raw_parts(ptr, (width * height * 4) as usize) }; + let mut decoder = default_builder(); + decoder.qr(Box::new(QRExtractor {}), Box::new(Nothing {})); + let image = ImageBuffer::from_raw(width, height, buffer); + let result = image.map(|img| decoder.build().decode(&img)); + handle.unlock_pixels()?; + let vec = result.ok_or(anyhow!("Internal Error!"))?; + Ok(vec.iter().any(|i| i.is_ok()) as jboolean) + }) +} diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs index c768dd5ff..192f25976 100644 --- a/app/src/main/rust/src/lib.rs +++ b/app/src/main/rust/src/lib.rs @@ -1,22 +1,16 @@ +mod image; mod parser; use android_logger::Config; use anyhow::{anyhow, ensure, Result}; -use bardecoder::decode::Decode; -use bardecoder::default_builder; -use bardecoder::extract::QRExtractor; -use bardecoder::util::qr::{QRData, QRError}; -use image::ImageBuffer; -use jni::objects::{JByteBuffer, JClass}; +use jni::objects::JByteBuffer; use jni::sys::{jboolean, jint, jobject, JavaVM, JNI_VERSION_1_6}; use jni::JNIEnv; -use jni_fn::jni_fn; use log::LevelFilter; use ndk::bitmap::Bitmap; use serde::Serialize; use std::ffi::c_void; use std::io::Cursor; -use std::ptr::slice_from_raw_parts; use std::ptr::slice_from_raw_parts_mut; use std::str::from_utf8_unchecked; use tl::ParserOptions; @@ -151,35 +145,6 @@ fn get_bitmap_handle(env: &mut JNIEnv, bitmap: jobject) -> Bitmap { unsafe { Bitmap::from_jni(env.get_raw(), bitmap) } } -#[allow(dead_code)] -struct Nothing {} - -impl Decode for Nothing { - fn decode(&self, result: Result) -> Result { - result.map(|_| String::new()) - } -} - -#[no_mangle] -#[allow(non_snake_case)] -#[jni_fn("com.hippo.ehviewer.image.ImageKt")] -pub fn hasQrCode(mut env: JNIEnv, _class: JClass, object: jobject) -> jboolean { - let handle = get_bitmap_handle(&mut env, object); - jni_throwing(&mut env, |_| { - let bitmap_info = handle.info()?; - let (width, height) = (bitmap_info.width(), bitmap_info.height()); - let ptr = handle.lock_pixels()? as *const u8; - let buffer = unsafe { &*slice_from_raw_parts(ptr, (width * height * 4) as usize) }; - let mut decoder = default_builder(); - decoder.qr(Box::new(QRExtractor {}), Box::new(Nothing {})); - let image = ImageBuffer::from_raw(width, height, buffer); - let result = image.map(|img| decoder.build().decode(&img)); - handle.unlock_pixels()?; - let vec = result.ok_or(anyhow!("Internal Error!"))?; - Ok(vec.iter().any(|i| i.is_ok()) as jboolean) - }) -} - #[no_mangle] pub extern "system" fn JNI_OnLoad(_: JavaVM, _: *mut c_void) -> jint { android_logger::init_once(Config::default().with_max_level(LevelFilter::Debug));