aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt6
-rw-r--r--Dockerfile.android19
-rw-r--r--README.md10
-rw-r--r--cmake/FindZBar0.cmake38
-rw-r--r--external/CMakeLists.txt7
m---------external/quirc0
-rw-r--r--src/CMakeLists.txt16
-rw-r--r--src/QR-Code-scanner/CMakeLists.txt23
-rw-r--r--src/QR-Code-scanner/Decoder.cpp71
-rw-r--r--src/QR-Code-scanner/Decoder.h21
-rw-r--r--src/QR-Code-scanner/QrCodeScanner.cpp3
-rw-r--r--src/QR-Code-scanner/QrCodeScanner.h3
-rw-r--r--src/QR-Code-scanner/QrScanThread.cpp55
-rw-r--r--src/QR-Code-scanner/QrScanThread.h13
15 files changed, 139 insertions, 149 deletions
diff --git a/.gitmodules b/.gitmodules
index ac11bb78..ac846a03 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,6 @@
path = monero
url = https://github.com/monero-project/monero
ignore = all
+[submodule "external/quirc"]
+ path = external/quirc
+ url = https://github.com/dlbeer/quirc/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 05324ca6..97c7608f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,12 +131,8 @@ message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
-# Zbar (for QR scanner)
if(WITH_SCANNER)
add_definitions(-DWITH_SCANNER)
- find_package(ZBar0 REQUIRED)
- message(STATUS "libzbar: include dir at ${ZBAR_INCLUDE_DIR}")
- message(STATUS "libzbar: libraries at ${ZBAR_LIBRARIES}")
endif()
# Sodium
@@ -563,6 +559,6 @@ if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
endif()
endif()
+add_subdirectory(external)
add_subdirectory(translations)
-
add_subdirectory(src)
diff --git a/Dockerfile.android b/Dockerfile.android
index b529978e..b0a3d3c9 100644
--- a/Dockerfile.android
+++ b/Dockerfile.android
@@ -151,25 +151,6 @@ RUN set -ex \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
-RUN git clone https://github.com/ZBar/ZBar.git --depth 1 \
- && cd ZBar \
- && git reset --hard 854a5d97059e395807091ac4d80c53f7968abb8f \
- && sed -i 's/SHARED/STATIC/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CPP_FEATURES := exceptions rtti features\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS := -Wno-multichar\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -D_ANDROID\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DLIBDIR="\\".\\""\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DBUILDING_LIBICONV\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DBUILDING_LIBCHARSET\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DIN_LIBRARY\n\0/' android/jni/Android.mk \
- && sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -fno-stack-protector\n\0/' android/jni/Android.mk \
- && echo "APP_ABI := arm64-v8a \nAPP_STL := c++_shared \nTARGET_PLATFORM := ${ANDROID_API} \nTARGET_ARCH_ABI := arm64-v8a \nAPP_CFLAGS += -target aarch64-none-linux-android -fexceptions -fstack-protector-strong -fno-limit-debug-info -mfloat-abi=softfp -fno-builtin-memmove -fno-omit-frame-pointer -fno-stack-protector\n" \
- >> android/jni/Application.mk \
- && cd android \
- && CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ${ANDROID_NDK_ROOT}/ndk-build ICONV_SRC=${WORKDIR}/libiconv-${ICONV_VERSION} -B V=1 NDK_APPLICATION_MK=jni/Application.mk \
- && cp obj/local/arm64-v8a/lib* ${PREFIX}/lib \
- && cp -r ../include/* ${PREFIX}/include
-
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
&& cd libgpg-error \
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
diff --git a/README.md b/README.md
index 1158ea67..dd52e630 100644
--- a/README.md
+++ b/README.md
@@ -217,13 +217,13 @@ The following instructions will fetch Qt from your distribution's repositories i
- For Ubuntu
- `sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
+ `sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
- For Gentoo
The *qml* USE flag must be enabled.
- `emerge dev-qt/qtmultimedia:5 media-gfx/zbar`
+ `emerge dev-qt/qtmultimedia:5`
3. Clone repository
@@ -290,12 +290,6 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt
```
- Optional : To build the flag `WITH_SCANNER`
-
- ```
- pacman -S mingw-w64-x86_64-zbar
- ```
-
You find more details about those dependencies in the [Monero documentation](https://github.com/monero-project/monero). Note that that there is no more need to compile Boost from source; like everything else, you can install it now with a MSYS2 package.
4. Install Qt5
diff --git a/cmake/FindZBar0.cmake b/cmake/FindZBar0.cmake
deleted file mode 100644
index f97b2378..00000000
--- a/cmake/FindZBar0.cmake
+++ /dev/null
@@ -1,38 +0,0 @@
-# from http://code.google.com/p/low-cost-vision-2012/source/browse/CMakeModules/FindZBar0.cmake?name=2-helium-1&r=d61f248bd5565b3c086bf4769a04bfd98f7079df
-# - Try to find ZBar
-# This will define
-#
-# ZBAR_FOUND -
-# ZBAR_LIBRARY_DIR -
-# ZBAR_INCLUDE_DIR -
-# ZBAR_LIBRARIES -
-#
-
-find_package(PkgConfig)
-if(PkgConfig_FOUND)
- pkg_check_modules(PC_ZBAR QUIET zbar)
- if(PC_ZBAR_FOUND)
- set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
- find_library(ZBAR_LIBRARIES NAMES zbar HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS})
- find_path(ZBAR_INCLUDE_DIR Decoder.h HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS} PATH_SUFFIXES zbar)
- endif()
-endif()
-
-if(NOT ZBAR_LIBRARIES AND ANDROID)
- find_library(ZBARJNI_LIBRARY NAMES zbarjni)
- find_library(ICONV_LIBRARY NAMES iconv)
- if(ZBARJNI_LIBRARY AND ICONV_LIBRARY)
- set(ZBAR_LIBRARIES ${ZBARJNI_LIBRARY} ${ICONV_LIBRARY})
- endif()
-endif()
-
-if(NOT ZBAR_INCLUDE_DIR)
- find_path(ZBAR_H_PATH zbar.h)
- if(ZBAR_H_PATH)
- set(ZBAR_INCLUDE_DIR "${ZBAR_H_PATH}/zbar")
- endif()
-endif()
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(ZBAR DEFAULT_MSG ZBAR_LIBRARIES ZBAR_INCLUDE_DIR)
-message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
new file mode 100644
index 00000000..c99cd900
--- /dev/null
+++ b/external/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(quirc STATIC
+ quirc/lib/decode.c
+ quirc/lib/identify.c
+ quirc/lib/quirc.c
+ quirc/lib/version_db.c
+)
+target_include_directories(quirc PUBLIC quirc/lib)
diff --git a/external/quirc b/external/quirc
new file mode 160000
+Subproject 7e7ab596e4d0988faf1c12ae89c354b114181c4
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e38c7dde..a4c3a15b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -55,13 +55,6 @@ if(ENABLE_PASS_STRENGTH_METER)
)
endif()
-if(WITH_SCANNER)
- file(GLOB QR_CODE_FILES
- "QR-Code-scanner/*.h"
- "QR-Code-scanner/*.cpp"
- )
-endif()
-
set(EXECUTABLE_FLAG)
if(MINGW)
set(EXECUTABLE_FLAG WIN32)
@@ -84,7 +77,6 @@ endif()
set(monero_wallet_gui_sources
${SOURCE_FILES}
${PASS_STRENGTH_FILES}
- ${QR_CODE_FILES}
${RESOURCES}
)
@@ -128,7 +120,6 @@ target_include_directories(monero-wallet-gui PUBLIC
${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
- ${ZBAR_INCLUDE_DIR}
)
target_compile_definitions(monero-wallet-gui
@@ -159,6 +150,7 @@ target_link_libraries(monero-wallet-gui
${EXTRA_LIBRARIES}
${ICU_LIBRARIES}
openpgp
+ qrdecoder
translations
)
@@ -171,16 +163,14 @@ if(X11_FOUND)
endif()
if(WITH_SCANNER)
- if(NOT ANDROID)
+ target_link_libraries(monero-wallet-gui qrscanner)
+ if(LINUX AND NOT ANDROID)
target_link_libraries(monero-wallet-gui
- ${ZBAR_LIBRARIES}
jpeg
v4l2
v4lconvert
rt
)
- else()
- target_link_libraries(monero-wallet-gui ${ZBAR_LIBRARIES})
endif()
endif()
diff --git a/src/QR-Code-scanner/CMakeLists.txt b/src/QR-Code-scanner/CMakeLists.txt
index 9ca31c61..15e288df 100644
--- a/src/QR-Code-scanner/CMakeLists.txt
+++ b/src/QR-Code-scanner/CMakeLists.txt
@@ -1,4 +1,21 @@
-file(GLOB_RECURSE SRC_SOURCES *.cpp)
-file(GLOB_RECURSE SRC_HEADERS *.h)
-
+add_library(qrdecoder STATIC
+ Decoder.cpp
+)
+target_link_libraries(qrdecoder
+ PUBLIC
+ Qt5::Gui
+ PRIVATE
+ quirc
+)
+if(WITH_SCANNER)
+ add_library(qrscanner
+ QrCodeScanner.cpp
+ QrScanThread.cpp
+ )
+ target_link_libraries(qrscanner
+ PUBLIC
+ Qt5::Multimedia
+ qrdecoder
+ )
+endif()
diff --git a/src/QR-Code-scanner/Decoder.cpp b/src/QR-Code-scanner/Decoder.cpp
new file mode 100644
index 00000000..a814969b
--- /dev/null
+++ b/src/QR-Code-scanner/Decoder.cpp
@@ -0,0 +1,71 @@
+#include "Decoder.h"
+
+#include <limits>
+
+#include "quirc.h"
+
+QrDecoder::QrDecoder()
+ : m_qr(quirc_new())
+{
+ if (m_qr == nullptr)
+ {
+ throw std::runtime_error("QUIRC: failed to allocate memory");
+ }
+}
+
+QrDecoder::~QrDecoder()
+{
+ quirc_destroy(m_qr);
+}
+
+std::vector<std::string> QrDecoder::decode(const QImage &image)
+{
+ if (image.format() == QImage::Format_Grayscale8)
+ {
+ return decodeGrayscale8(image);
+ }
+ return decodeGrayscale8(image.convertToFormat(QImage::Format_Grayscale8));
+}
+
+std::vector<std::string> QrDecoder::decodeGrayscale8(const QImage &image)
+{
+ if (quirc_resize(m_qr, image.width(), image.height()) < 0)
+ {
+ throw std::runtime_error("QUIRC: failed to allocate video memory");
+ }
+
+ uint8_t *rawImage = quirc_begin(m_qr, nullptr, nullptr);
+ if (rawImage == nullptr)
+ {
+ throw std::runtime_error("QUIRC: failed to get image buffer");
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+ std::copy(image.constBits(), image.constBits() + image.sizeInBytes(), rawImage);
+#else
+ std::copy(image.constBits(), image.constBits() + image.byteCount(), rawImage);
+#endif
+ quirc_end(m_qr);
+
+ const int count = quirc_count(m_qr);
+ if (count < 0)
+ {
+ throw std::runtime_error("QUIRC: failed to get the number of recognized QR-codes");
+ }
+
+ std::vector<std::string> result;
+ result.reserve(static_cast<size_t>(count));
+ for (int index = 0; index < count; ++index)
+ {
+ quirc_code code;
+ quirc_extract(m_qr, index, &code);
+
+ quirc_data data;
+ const quirc_decode_error_t err = quirc_decode(&code, &data);
+ if (err == QUIRC_SUCCESS)
+ {
+ result.emplace_back(&data.payload[0], &data.payload[data.payload_len]);
+ }
+ }
+
+ return result;
+}
diff --git a/src/QR-Code-scanner/Decoder.h b/src/QR-Code-scanner/Decoder.h
new file mode 100644
index 00000000..e25c3936
--- /dev/null
+++ b/src/QR-Code-scanner/Decoder.h
@@ -0,0 +1,21 @@
+#include <QImage>
+
+struct quirc;
+
+class QrDecoder
+{
+public:
+ QrDecoder(const QrDecoder &) = delete;
+ QrDecoder &operator=(const QrDecoder &) = delete;
+
+ QrDecoder();
+ ~QrDecoder();
+
+ std::vector<std::string> decode(const QImage &image);
+
+private:
+ std::vector<std::string> decodeGrayscale8(const QImage &image);
+
+private:
+ quirc *m_qr;
+};
diff --git a/src/QR-Code-scanner/QrCodeScanner.cpp b/src/QR-Code-scanner/QrCodeScanner.cpp
index 55e396fe..2e8bde9f 100644
--- a/src/QR-Code-scanner/QrCodeScanner.cpp
+++ b/src/QR-Code-scanner/QrCodeScanner.cpp
@@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "QrCodeScanner.h"
-#include <WalletManager.h>
#include <QVideoProbe>
#include <QCamera>
@@ -40,7 +39,7 @@ QrCodeScanner::QrCodeScanner(QObject *parent)
m_probe = new QVideoProbe(this);
m_thread = new QrScanThread(this);
m_thread->start();
- QObject::connect(m_thread, SIGNAL(decoded(int, QString)), this, SIGNAL(decoded(int, QString)));
+ QObject::connect(m_thread, SIGNAL(decoded(QString)), this, SIGNAL(decoded(QString)));
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
}
diff --git a/src/QR-Code-scanner/QrCodeScanner.h b/src/QR-Code-scanner/QrCodeScanner.h
index 9420693d..10cf7766 100644
--- a/src/QR-Code-scanner/QrCodeScanner.h
+++ b/src/QR-Code-scanner/QrCodeScanner.h
@@ -56,8 +56,7 @@ public Q_SLOTS:
Q_SIGNALS:
void enabledChanged();
- void decoded(int type, const QString &data);
- void decode(int type, const QString &data);
+ void decoded(const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:
diff --git a/src/QR-Code-scanner/QrScanThread.cpp b/src/QR-Code-scanner/QrScanThread.cpp
index 15f4c030..6421321e 100644
--- a/src/QR-Code-scanner/QrScanThread.cpp
+++ b/src/QR-Code-scanner/QrScanThread.cpp
@@ -38,62 +38,15 @@ QrScanThread::QrScanThread(QObject *parent)
: QThread(parent)
,m_running(true)
{
- m_scanner.set_handler(*this);
}
-void QrScanThread::image_callback(zbar::Image &image)
-{
- qDebug() << "image_callback : Found Code ! " ;
- for(zbar::Image::SymbolIterator sym = image.symbol_begin();
- sym != image.symbol_end();
- ++sym)
- if(!sym->get_count()) {
- QString data = QString::fromStdString(sym->get_data());
- emit decoded(sym->get_type(), data);
- }
-}
-
-void QrScanThread::processZImage(zbar::Image &image)
-{
- m_scanner.recycle_image(image);
- zbar::Image tmp = image.convert(*(long*)"Y800");
- m_scanner.scan(tmp);
- image.set_symbols(tmp.get_symbols());
-}
-
-bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
-{
- switch( qimg.format() ){
- case QImage::Format_RGB32 :
- case QImage::Format_ARGB32 :
- case QImage::Format_ARGB32_Premultiplied :
- break;
- default :
- emit notifyError(QString("Invalid QImage Format !"));
- return false;
- }
- unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
- dst.set_size(width, height);
- dst.set_format("BGR4");
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
- unsigned long datalen = qimg.sizeInBytes();
-#else
- unsigned long datalen = qimg.byteCount();
-#endif
- dst.set_data(qimg.bits(), datalen);
- if((width * 4 != bpl) || (width * height * 4 > datalen)){
- emit notifyError(QString("QImage to Zbar::Image failed !"));
- return false;
- }
- return true;
-}
void QrScanThread::processQImage(const QImage &qimg)
{
try {
- m_image = QSharedPointer<zbar::Image>(new zbar::Image());
- if( ! zimageFromQImage(qimg, *m_image) )
- return;
- processZImage(*m_image);
+ for (const std::string &code : m_decoder.decode(qimg))
+ {
+ emit decoded(QString::fromStdString(code));
+ }
}
catch(std::exception &e) {
qDebug() << "ERROR: " << e.what();
diff --git a/src/QR-Code-scanner/QrScanThread.h b/src/QR-Code-scanner/QrScanThread.h
index b6daa29f..7dfffc55 100644
--- a/src/QR-Code-scanner/QrScanThread.h
+++ b/src/QR-Code-scanner/QrScanThread.h
@@ -35,9 +35,10 @@
#include <QEvent>
#include <QVideoFrame>
#include <QCamera>
-#include <zbar.h>
-class QrScanThread : public QThread, public zbar::Image::Handler
+#include "Decoder.h"
+
+class QrScanThread : public QThread
{
Q_OBJECT
@@ -47,20 +48,16 @@ public:
virtual void stop();
Q_SIGNALS:
- void decoded(int type, const QString &data);
+ void decoded(const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:
virtual void run();
void processVideoFrame(const QVideoFrame &);
void processQImage(const QImage &);
- void processZImage(zbar::Image &image);
- virtual void image_callback(zbar::Image &image);
- bool zimageFromQImage(const QImage&, zbar::Image &);
private:
- zbar::ImageScanner m_scanner;
- QSharedPointer<zbar::Image> m_image;
+ QrDecoder m_decoder;
bool m_running;
QMutex m_mutex;
QWaitCondition m_waitCondition;