diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5094610 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +# CMake 最低版本号要求 +cmake_minimum_required (VERSION 2.8) + +# 设置VCPKG_ROOT所在的位置 + + +set(CMAKE_CONFIGURATION_TYPES "Debug;Release") + +message($ENV{PATH}) + +if(WIN32) + if(${CMAKE_GENERATOR_PLATFORM} STREQUAL "x64") + set(platform x64) + else() + set(platform x86) + endif() + + # 设置VCPKG_ROOT所在的位置 + set(CMAKE_TOOLCHAIN_FILE "$ENV{Vcpkg_BuildSystemPath}/vcpkg.cmake") + set(VCPKG_TARGET_TRIPLET "${platform}-windows-static-md") + message(${VCPKG_TARGET_TRIPLET}) +endif() +# 项目信息 +project(huagaotwain) + +add_subdirectory(huagao) +add_subdirectory(device) +add_subdirectory(ImageProcess) +add_subdirectory(gpdf) +add_subdirectory(Tirdparty) +add_subdirectory(ui) \ No newline at end of file diff --git a/ImageProcess/.gitignore b/ImageProcess/.gitignore new file mode 100644 index 0000000..cdda12b --- /dev/null +++ b/ImageProcess/.gitignore @@ -0,0 +1,22 @@ +################################################################################ +# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 +################################################################################ + +/.vs +/opencv +/imageprocess.pro.user +/debug +/release +/Win32/Debug +/.qmake.stash +/Makefile.Release +/Makefile.Debug +/Makefile +/imageprocess.vcxproj.filters +/imageprocess.vcxproj +/imageprocess.sln +/ImageMatQueue.cpp +/ImageMatQueue.h +/gpdf +/ImageApplyColorCorrect.cpp.autosave +/imageprocess.vcxproj.user diff --git a/ImageProcess/CMakeLists.txt b/ImageProcess/CMakeLists.txt new file mode 100644 index 0000000..70e4bc0 --- /dev/null +++ b/ImageProcess/CMakeLists.txt @@ -0,0 +1,12 @@ +project(gimgproc) + +file(GLOB IMGPROC_HEADS ${PROJECT_SOURCE_DIR}/*.h) +aux_source_directory(${PROJECT_SOURCE_DIR} IMGPROC_SRCS) + +find_package(OpenCV) + +add_library(${PROJECT_NAME} ${IMGPROC_SRCS} ${IMGPROC_HEADS}) +target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/Tirdparty/3rdparty/nick) +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS} gpdf hg::zxing hg::zbar) \ No newline at end of file diff --git a/ImageProcess/IMulti.cpp b/ImageProcess/IMulti.cpp new file mode 100644 index 0000000..442cf4c --- /dev/null +++ b/ImageProcess/IMulti.cpp @@ -0,0 +1,10 @@ +#include "IMulti.h" + +IMulti::IMulti(void) +{ +} + +IMulti::~IMulti(void) +{ +} + diff --git a/ImageProcess/IMulti.h b/ImageProcess/IMulti.h new file mode 100644 index 0000000..df7ef35 --- /dev/null +++ b/ImageProcess/IMulti.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include +#include "imgprocdefs.h" + +class IMulti +{ +public: + IMulti(void); + virtual ~IMulti(void); + virtual std::vector apply(cv::Mat& pDib) = 0; +}; diff --git a/ImageProcess/ImageApply.cpp b/ImageProcess/ImageApply.cpp new file mode 100644 index 0000000..80f5fbf --- /dev/null +++ b/ImageProcess/ImageApply.cpp @@ -0,0 +1,9 @@ +#include "ImageApply.h" + +CImageApply::CImageApply(void) +{ +} + +CImageApply::~CImageApply(void) +{ +} diff --git a/ImageProcess/ImageApply.h b/ImageProcess/ImageApply.h new file mode 100644 index 0000000..3894eb2 --- /dev/null +++ b/ImageProcess/ImageApply.h @@ -0,0 +1,27 @@ +#ifndef IMAGE_APPLY_H +#define IMAGE_APPLY_H + +//#define LOG + +#include +#include +#include + +#if defined(LOG) +#include "Device/filetools.h" +#endif + +class CImageApply +{ +public: + CImageApply(void); + virtual ~CImageApply(void); + + virtual void apply(cv::Mat& pDib,int side) = 0; + + virtual void apply(std::vector& mats, bool isTwoSide) = 0; +}; + +typedef std::shared_ptr ImageApplyPtr; + +#endif //!IMAGE_APPLY_H diff --git a/ImageProcess/ImageApplyAdjustColors.cpp b/ImageProcess/ImageApplyAdjustColors.cpp new file mode 100644 index 0000000..3e6cd5a --- /dev/null +++ b/ImageProcess/ImageApplyAdjustColors.cpp @@ -0,0 +1,90 @@ +#include "ImageApplyAdjustColors.h" + +CImageApplyAdjustColors::CImageApplyAdjustColors(void) + : m_brightness(0) + , m_contrast(0) + , m_gamma(1.0f) + , lut(1, 256, CV_8UC1) +{ + update_lutData(); +} + +CImageApplyAdjustColors::CImageApplyAdjustColors(int brightness, int contrast, float gamma) + : lut(1, 256, CV_8UC1) +{ + setAdjustColors(brightness, contrast, gamma); +} + +CImageApplyAdjustColors::~CImageApplyAdjustColors(void) +{ + +} + +void CImageApplyAdjustColors::apply(cv::Mat& pDib,int side) +{ + (void)side; + if (pDib.empty()) return; + + if (m_brightness != 0 || m_contrast != 0 || m_gamma < 0.999999f || m_gamma > 1.000001f) + cv::LUT(pDib, lut, pDib); +} + +void CImageApplyAdjustColors::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if(!var.empty()) + apply(var, 0); + i++; + } +} + +void CImageApplyAdjustColors::setAdjustColors(int brightness, int contrast, float gamma) +{ + m_brightness = cv::max(-255, cv::min(brightness, 255)); + m_contrast = cv::max(-127, cv::min(contrast, 127)); + m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f)); + update_lutData(); +} + +void CImageApplyAdjustColors::setBrightness(int brightness) +{ + m_brightness = cv::max(-255, cv::min(brightness, 255)); + update_lutData(); +} + +void CImageApplyAdjustColors::setContrast(int contrast) +{ + m_contrast = cv::max(-127, cv::min(contrast, 127)); + update_lutData(); +} + +void CImageApplyAdjustColors::setGamma(float gamma) +{ + m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f)); + update_lutData(); +} + +void CImageApplyAdjustColors::update_lutData() +{ + unsigned char* ptr = lut.data; + + uchar buffer[256]; + for (int i = 0; i < 256; i++) + { + //update brightness + ptr[i] = static_cast(cv::max(0, cv::min(i + m_brightness, 255))); + + //update contrast + if (ptr[i] < 128) + ptr[i] = static_cast(cv::max(0, cv::min(ptr[i] - m_contrast, 127))); + else + ptr[i] = static_cast(cv::max(127, cv::min(ptr[i] + m_contrast, 255))); + } + float g = 1.0f / m_gamma; + for (int i = 0; i < 256; i++) + ptr[i] = static_cast(cv::min(255, static_cast(cv::pow(static_cast(ptr[i]) / 255.0f, g) * 255.0f + 0.5f))); +} diff --git a/ImageProcess/ImageApplyAdjustColors.h b/ImageProcess/ImageApplyAdjustColors.h new file mode 100644 index 0000000..83ea595 --- /dev/null +++ b/ImageProcess/ImageApplyAdjustColors.h @@ -0,0 +1,53 @@ +#ifndef IMAGE_APPLY_ADJUST_COLOR_H +#define IMAGE_APPLY_ADJUST_COLOR_H + +#include "ImageApply.h" + +class CImageApplyAdjustColors : public CImageApply +{ +public: + + CImageApplyAdjustColors(void); + + /* + * brightness [in]: ȵڣȡֵΧ[-255, 255] + * constrast [in]: ԱȶȵڣȡֵΧ[-128 127] + * gamma [in]: ٤ڣȡֵΧ[0.1, 5.0] + */ + CImageApplyAdjustColors(int brightness, int contrast, float gamma); + + virtual ~CImageApplyAdjustColors(void); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + void setAdjustColors(int brightness, int contrast, float gamma); + + int getContrast() { return m_contrast; } + + int getBrightness() { return m_brightness; } + + double getGamma() { return m_gamma; } + + void setBrightness(int brightness); + + void setContrast(int contrast); + + void setGamma(float gamma); + +private: + + void update_lutData(); + +private: + + int m_brightness; + int m_contrast; + float m_gamma; + cv::Mat lut; +}; + +#endif // !IMAGE_APPLY_ADJUST_COLOR_H + + diff --git a/ImageProcess/ImageApplyAutoContrast.cpp b/ImageProcess/ImageApplyAutoContrast.cpp new file mode 100644 index 0000000..4cd0d5f --- /dev/null +++ b/ImageProcess/ImageApplyAutoContrast.cpp @@ -0,0 +1,43 @@ +#include "ImageApplyAutoContrast.h" +#include +using namespace std; +using namespace cv; + +CImageApplyAutoContrast::CImageApplyAutoContrast() +{ +} + +CImageApplyAutoContrast::~CImageApplyAutoContrast() +{ +} + +void CImageApplyAutoContrast::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.empty()) return; + + if(pDib.channels() == 1) + cv::equalizeHist(pDib,pDib); + else + { + std::vector mats(3); + cv::split(pDib,mats); + for(size_t i = 0; i < mats.size(); i++) + if(!mats[i].empty()) + cv::equalizeHist(mats[i], mats[i]); + cv::merge(mats,pDib); + } +} + +void CImageApplyAutoContrast::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyAutoContrast.h b/ImageProcess/ImageApplyAutoContrast.h new file mode 100644 index 0000000..d8abf05 --- /dev/null +++ b/ImageProcess/ImageApplyAutoContrast.h @@ -0,0 +1,32 @@ +/* + * ==================================================== + + * ܣԶɫУʵԭΪֱͼ⻯ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_AUTO_CONTRAST_H +#define IMAGE_APPLY_AUTO_CONTRAST_H + +#include "ImageApply.h" + +class CImageApplyAutoContrast : public CImageApply +{ +public: + + CImageApplyAutoContrast(); + + virtual ~CImageApplyAutoContrast(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); +private: + +}; +#endif // !IMAGE_APPLY_AUTO_CONTRAST_H diff --git a/ImageProcess/ImageApplyAutoCrop.cpp b/ImageProcess/ImageApplyAutoCrop.cpp new file mode 100644 index 0000000..97c068f --- /dev/null +++ b/ImageProcess/ImageApplyAutoCrop.cpp @@ -0,0 +1,229 @@ +#include "ImageApplyAutoCrop.h" +#include "ImageProcess_Public.h" + +CImageApplyAutoCrop::CImageApplyAutoCrop() + : m_isCrop(false) + , m_isDesaskew(false) + , m_isFillBlank(false) + , m_isConvexHull(true) + , m_isFillColor(false) + , m_threshold(40) + , m_noise(2) + , m_indent(5) +{ +} + +CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, double threshold, int noise, int indent) + : m_isCrop(isCrop) + , m_isDesaskew(isDesaskew) + , m_isFillBlank(isFillBlank) + , m_isConvexHull(isConvex) + , m_isFillColor(isFillColor) + , m_threshold(threshold) + , m_noise(noise) + , m_indent(indent) + , m_fixedSize(fixedSize) +{ +} + +CImageApplyAutoCrop::~CImageApplyAutoCrop() +{ +} + +void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.empty()) return; + if (!m_isCrop && !m_isDesaskew && !m_isFillBlank && m_fixedSize.empty()) return; + + cv::Mat src = pDib; + cv::Mat thre; + cv::Mat dst; + hg::threshold_Mat(src, thre, m_threshold); + + if (m_noise > 0) + { + cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise, m_noise)); + cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element); + } + std::vector hierarchy; + std::vector> contours; + + hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); + m_maxContour = hg::getMaxContour(contours, hierarchy); + + if (m_maxContour.size() == 0) + { + thre.release(); +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply"); +#endif // LOG + return; + } + thre.release(); + dst.release(); + + cv::RotatedRect rect = hg::getBoundingRect(m_maxContour); + cv::Rect boudingRect = cv::boundingRect(m_maxContour); + boudingRect.x -= 1; + boudingRect.y -= 1; + boudingRect.width += 2; + boudingRect.height += 2; + + if (m_isDesaskew && rect.angle != 0) + { + cv::Point2f srcTri[4]; + cv::Point2f dstTri[3]; + rect.points(srcTri); + + dstTri[0] = cv::Point2f(0, rect.size.height - 1); + dstTri[1] = cv::Point2f(0, 0); + dstTri[2] = cv::Point2f(rect.size.width - 1, 0); + cv::Mat warp_mat; + warp_mat = cv::getAffineTransform(srcTri, dstTri); + //cv::warpAffine(src, dst, warp_mat, rect.size,cv::INTER_LANCZOS4); + cv::warpAffine(src, dst, warp_mat, rect.size); + } + else + dst = src(boudingRect & cv::Rect(0, 0, src.cols, src.rows)); + + m_maxContour.clear(); + m_maxContour.push_back(cv::Point(-1, dst.rows)); + m_maxContour.push_back(cv::Point(-1, -1)); + m_maxContour.push_back(cv::Point(dst.cols, -1)); + m_maxContour.push_back(cv::Point(dst.cols, dst.rows)); + + if (m_isFillBlank) + { + cv::Mat thre_dst; + hg::threshold_Mat(dst, thre_dst, m_threshold); + + if (m_indent > 0) + { + std::vector rectEdge{ cv::Point(0, 0) ,cv::Point(thre_dst.cols - 1, 0), + cv::Point(thre_dst.cols - 1, thre_dst.rows - 1), cv::Point(0, thre_dst.rows - 1) }; + std::vector> rectEdges{ rectEdge }; + cv::drawContours(thre_dst, rectEdges, 0, cv::Scalar::all(0)); + cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(m_indent, m_indent)); + cv::erode(thre_dst, thre_dst, element, cv::Point(-1, -1), 1); + } + hierarchy.clear(); + contours.clear(); + m_maxContour.clear(); + + hg::findContours(thre_dst, contours, hierarchy, cv::RETR_EXTERNAL); + if (m_isConvexHull) + { + m_maxContour = hg::getMaxContour(contours, hierarchy); + hg::convexHull(m_maxContour, m_maxContour); + contours.clear(); + contours.push_back(m_maxContour); + } + + contours.push_back(std::vector()); + contours[contours.size() - 1].push_back(cv::Point(-1, dst.rows - 1)); + contours[contours.size() - 1].push_back(cv::Point(-1, -1)); + contours[contours.size() - 1].push_back(cv::Point(dst.cols, -1)); + contours[contours.size() - 1].push_back(cv::Point(dst.cols, dst.rows)); + + hg::fillPolys(dst, contours, m_isFillColor ? getBackGroudColor(pDib, rect.size.area()) : cv::Scalar(255, 255, 255)); + } + + pDib.release(); + if (/*(m_isCrop && side == 0) || (side == 1 && m_fixedSize.width * m_fixedSize.height == 0)*/ m_isCrop) + pDib = dst.clone(); + else + { + pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0)); + + cv::Rect roi; + roi.x = dst.cols > pDib.cols ? (dst.cols - pDib.cols) / 2 : 0; + roi.width = cv::min(pDib.cols, dst.cols); + roi.y = dst.rows > pDib.rows ? (dst.rows - pDib.rows) / 2 : 0; + roi.height = cv::min(pDib.rows, dst.rows); + cv::Rect rect((pDib.cols - roi.width) / 2, (pDib.rows - roi.height) / 2, roi.width, roi.height); + + for (cv::Point& p : m_maxContour) + p += roi.tl(); + dst(roi).copyTo(pDib(rect)); + } +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8"); +#endif // LOG +} + +void CImageApplyAutoCrop::apply(std::vector& mats, bool isTwoSide) +{ + if (mats.empty()) return; + if (!mats[0].empty()) { + apply(mats[0], 0); + } + + if (isTwoSide && mats.size() > 1) + { + cv::Size dSize = m_fixedSize; + if (!mats[0].empty()) + m_fixedSize = mats[0].size(); + if (!mats[1].empty()) { + apply(mats[1], 1); + } + + if (!mats[0].empty()) + m_fixedSize = dSize; + } +} + +cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int total) +{ + if (image.channels() == 3) + { + cv::Mat image_bgr[3]; + cv::split(image, image_bgr); + + uchar bgr[3]; + for (size_t i = 0; i < 3; i++) + bgr[i] = getBackGroudChannelMean(image_bgr[i], total); + return cv::Scalar(bgr[0], bgr[1], bgr[2]); + } + else + return cv::Scalar::all(getBackGroudChannelMean(image, total)); +} + +uchar CImageApplyAutoCrop::getBackGroudChannelMean(const cv::Mat& gray, int total) +{ + cv::Mat image_clone; + cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25); + + int threnshold = total / 32; + int channels[] = { 0 }; + int nHistSize[] = { 256 }; + float range[] = { 0, 256 }; + const float* fHistRanges[] = { range }; + cv::Mat hist; + cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false); + + int hist_array[256]; + for (int i = 0; i < 256; i++) + hist_array[i] = hist.at(i, 0); + + int length = 1; + const int length_max = 255 - m_threshold; + while (length < length_max) + { + for (size_t i = m_threshold + 1; i < 256 - length; i++) + { + int count = 0; + uint pixSum = 0; + for (size_t j = 0; j < length; j++) + { + count += hist_array[j + i]; + pixSum += hist_array[j + i] * (i + j); + } + + if (count >= threnshold) + return pixSum / count; + } + length++; + } + return 255; +} diff --git a/ImageProcess/ImageApplyAutoCrop.h b/ImageProcess/ImageApplyAutoCrop.h new file mode 100644 index 0000000..f02f187 --- /dev/null +++ b/ImageProcess/ImageApplyAutoCrop.h @@ -0,0 +1,83 @@ +#ifndef IMAGE_APPLY_AUTO_CROP_H +#define IMAGE_APPLY_AUTO_CROP_H + +#include "ImageApply.h" + +class CImageApplyAutoCrop : public CImageApply +{ +public: + CImageApplyAutoCrop(); + + /* + * isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剪 + * isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏 + * isFillBlank [in]:黑底填充使能,true为填充,false为不填充 + * fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像素 + * isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true + * isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false + * threshold [in]:二值化阈值,取值范围(0, 255),默认40 + * noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默认40 + * indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5 + */ + CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, bool isFillColor = false, double threshold = 40, int noise = 40, int indent = 5); + + virtual ~CImageApplyAutoCrop(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + bool isAutoCrop() { return m_isCrop; } + + bool isFillBlank() { return m_isFillBlank; } + + bool isDesaskew() { return m_isDesaskew; } + + bool isConvexHull() { return m_isConvexHull; } + + double threshold() { return m_threshold; } + + int noise() { return m_noise; } + + int indent() { return m_indent; } + + cv::Size fixedSize() { return m_fixedSize; } + + const std::vector& maxContour() { return m_maxContour; } + + void setAutoCrop(bool enabled) { m_isCrop = enabled; } + + void setFillBlank(bool enabled) { m_isFillBlank = enabled; } + + void setDesaskew(bool enabled) { m_isDesaskew = enabled; } + + void setConvexHull(bool convex) { m_isConvexHull = convex; } + + void setThreshold(double value) { m_threshold = value; } + + void setNoise(int value) { m_noise = value; } + + void setIndent(int value) { m_indent = value; } + + void setFixedSize(cv::Size size) { m_fixedSize = size; } + +private: + cv::Scalar getBackGroudColor(const cv::Mat& image, int total); + + uchar getBackGroudChannelMean(const cv::Mat& gray, int total); + +private: + bool m_isCrop; + bool m_isDesaskew; + bool m_isFillBlank; + bool m_isConvexHull; + bool m_isFillColor; + + double m_threshold; + int m_noise; + int m_indent; + cv::Size m_fixedSize; + std::vector m_maxContour; +}; + +#endif // !IMAGE_APPLY_AUTO_CROP_H diff --git a/ImageProcess/ImageApplyBWBinaray.cpp b/ImageProcess/ImageApplyBWBinaray.cpp new file mode 100644 index 0000000..7995a25 --- /dev/null +++ b/ImageProcess/ImageApplyBWBinaray.cpp @@ -0,0 +1,164 @@ +#include "ImageApplyBWBinaray.h" + +CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant) + : m_threshold(threshold) + , m_type(type) + , m_blockSize(blockSize) + , m_constant(constant) + , m_table(new uchar[256]) +{ + memset(m_table, 255, 256); + memset(m_table, 0, static_cast(m_threshold)); +} + +CImageApplyBWBinaray::CImageApplyBWBinaray() + : m_threshold(120) + , m_type(ThresholdType::THRESH_BINARY) + , m_blockSize(25) + , m_constant(5) + , m_table(new uchar[256]) +{ + memset(m_table, 255, 256); + memset(m_table, 0, static_cast(m_threshold)); +} + +CImageApplyBWBinaray::~CImageApplyBWBinaray(void) +{ + delete[] m_table; +} + +void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.empty()) return; + + if (pDib.channels() == 3) + cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY); + + //20.12.29 ޸IJΪ51 10 30 235 + //20.12.30 ޸IJΪ51 20 30 235 + // ޸IJΪ17 20 110 235 + cv::Mat integ; + int blockSize = 17;//ߴ + int threshold = 20; + int low = 110; + int up = 235; + int halfSize = blockSize / 2; + int square_blockSize = blockSize * blockSize; + switch (m_type) + { + case ThresholdType::THRESH_BINARY: + cv::integral(pDib, integ, CV_32S); + + for (int j = halfSize; j < integ.rows - halfSize - 1; j++) + { + uchar* data = pDib.ptr(j); + int* idata1 = integ.ptr(j - halfSize); + int* idata2 = integ.ptr(j + halfSize + 1); + for (int i = halfSize; i < integ.cols - halfSize - 1; i++) + { + if (data[i] < low) + data[i] = 0; + else if (data[i] > up) + data[i] = 255; + else + data[i] = data[i] < ((idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / square_blockSize - threshold) ? 0 : 255; + } + } + + cv::threshold(pDib(cv::Rect(0, 0, halfSize, pDib.rows)), pDib(cv::Rect(0, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY); + cv::threshold(pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY); + cv::threshold(pDib(cv::Rect(0, 0, pDib.cols, halfSize)), pDib(cv::Rect(0, 0, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY); + cv::threshold(pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY); + break; + case ThresholdType::THRESH_OTSU: + cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU); + break; + case ThresholdType::ADAPTIVE_GAUSSIAN: + cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant); + break; + case ThresholdType::ADAPTIVE_MEAN: + cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant); + break; + case ThresholdType::ERROR_DIFFUSION: + errorDiffuse(pDib); + break; + default: + break; + } +} + +void CImageApplyBWBinaray::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} + +void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image) +{ + if (image.rows < 3 || image.cols < 3) + { + cv::threshold(image, image, m_threshold, 255, CV_THRESH_BINARY); + return; + } + + cv::Mat dst; + image.convertTo(dst, CV_16S); + + size_t rows = static_cast(image.rows) - 1; + size_t cols = static_cast(image.cols) - 1; + + short** pixels_dst = new short* [static_cast(image.rows)]; + for (int i = 0; i < image.rows; i++) + pixels_dst[i] = reinterpret_cast(dst.data + i * static_cast(dst.step)); + + short error; + for (size_t y = 0; y < rows; y++) + for (size_t x = 1; x < cols; x++) + { + short dstPix = pixels_dst[y][x]; + if (dstPix >= m_threshold) + { + pixels_dst[y][x] = 255; + error = dstPix - 255; + } + else + { + pixels_dst[y][x] = 0; + error = dstPix; + } + + pixels_dst[y][x + 1] += error * 1 / 16; + pixels_dst[y + 1][x - 1] += error * 1 / 16; + pixels_dst[y + 1][x] += error * 1 / 16; + pixels_dst[y + 1][x + 1] += error * 1 / 16; + } + image.release(); + dst.convertTo(image, CV_8U); + + rows++; + uchar* ptr = image.data; + size_t step = image.step; + size_t offset; + for (size_t y = 0; y < rows; y++) + { + offset = y * step; + ptr[offset] = m_table[ptr[offset]]; + offset += cols; + ptr[offset] = m_table[ptr[offset]]; + } + + cols++; + ptr = image.data + step * (rows - 1); + for (size_t x = 0; x < cols; x++) + ptr[x] = m_table[ptr[x]]; + + delete[] pixels_dst; +} \ No newline at end of file diff --git a/ImageProcess/ImageApplyBWBinaray.h b/ImageProcess/ImageApplyBWBinaray.h new file mode 100644 index 0000000..d52675a --- /dev/null +++ b/ImageProcess/ImageApplyBWBinaray.h @@ -0,0 +1,86 @@ +/* + * ==================================================== + + * 功能:二值化处理 + * 作者:刘丁维 + * 生成时间:2020/4/21 + * 最近修改时间:2020/5/28 v1.1 修改传统二值化算法,改用自定义局部自适应阈值算法 + 2020/5/29 v1.2 在传统二值化之前添加增强锐化效果,二值化之后增加除噪效果 + 2020/6/19 v1.3 编写自定义自适应阈值二值化;取消锐化处理;保留除噪效果 + 2020/12/21 v1.3.1 调整自适应阈值上下限 + 2020/12/21 v1.3.2 调整blockSize,从原来的51调整到25 + * 版本号:v1.3.2 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_BW_BINARAY_H +#define IMAGE_APPLY_BW_BINARAY_H + +#include "ImageApply.h" + +class CImageApplyBWBinaray:public CImageApply +{ +public: + + enum class ThresholdType + { + THRESH_BINARY = 0, //传统二值化 + THRESH_OTSU, //大津阈值 + + ADAPTIVE_GAUSSIAN, //高斯局部自适应阈值 + ADAPTIVE_MEAN, //均值局部自适应阈值 + + ERROR_DIFFUSION //错误扩散 + }; + + /* + * type [in]:二值化模式 + * threshold [in]:阈值,当选择THRESH_OTSU时无效 + * blockSize [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,表示局部观察块的宽度 + * constant [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,与blockSize形成比例关系,作为局部筛选阈值 + */ + CImageApplyBWBinaray(ThresholdType type, int threshold = 120, int blockSize = 25, int constant = 5); + + CImageApplyBWBinaray(); + + virtual ~CImageApplyBWBinaray(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + double getThreshold() { return m_threshold; } + + ThresholdType getThresholdType() { return m_type; } + + int getBlockSize() { return m_blockSize; } + + double getConstant() { return m_constant; } + + void setThreshold(double value) { m_threshold = value; } + + void setThresholdType(ThresholdType type) { m_type = type; } + + void setBlockSize(int value) { m_blockSize = value; } + + void setConstant(double value) { m_constant = value; } + +private: + + void errorDiffuse(cv::Mat& image); + +private: + double m_threshold; + + ThresholdType m_type; + + int m_blockSize; + + double m_constant; + + uchar* m_table; +}; + +#endif //!IMAGE_APPLY_BW_BINARAY_H + diff --git a/ImageProcess/ImageApplyBarCodeRecognition.cpp b/ImageProcess/ImageApplyBarCodeRecognition.cpp new file mode 100644 index 0000000..fbb4d43 --- /dev/null +++ b/ImageProcess/ImageApplyBarCodeRecognition.cpp @@ -0,0 +1,355 @@ +#include "ImageApplyBarCodeRecognition.h" +#ifndef _NOT_USE +#include +#include "zxing/BinaryBitmap.h" +#include "zxing/DecodeHints.h" +#include "zxing/common/GlobalHistogramBinarizer.h" +#include "zxing/LuminanceSource.h" +#include "zxing/MultiFormatReader.h" +#include "zxing/Result.h" +#include "zxing/multi/GenericMultipleBarcodeReader.h" +#include "zbar.h" + +class ImageWrapper : public zxing::LuminanceSource +{ +public: + ImageWrapper(const cv::Mat& sourceImage) + : LuminanceSource(sourceImage.cols, sourceImage.rows) + , m_image(sourceImage) {} + + virtual ~ImageWrapper() = default; + + // Callers take ownership of the returned memory and must call delete [] on it themselves. + zxing::ArrayRef getRow(int y, zxing::ArrayRef row) const + { + int width = getWidth(); + + if (row->size() != width) + row.reset(zxing::ArrayRef(width)); + + for (int x = 0; x < width; ++x) + row[x] = m_image.at(y, x); + + return row; + } + + zxing::ArrayRef getMatrix() const + { + int width = m_image.cols; + int height = m_image.rows; + char* matrix = new char[width * height]; + char* m = matrix; + + for (int y = 0; y < height; ++y) + { + zxing::ArrayRef tmpRow; + tmpRow = getRow(y, zxing::ArrayRef(width)); +#if __cplusplus > 199711L + memcpy(m, tmpRow->values().data(), width); +#else + memcpy(m, &tmpRow->values()[0], width); +#endif + m += width * sizeof(unsigned char); + + //delete tmpRow; + } + + zxing::ArrayRef arr = zxing::ArrayRef(matrix, width * height); + + if (matrix) delete[] matrix; + + return arr; + } +private: + cv::Mat m_image; +}; + +static std::string WstringToString(const std::wstring& wstr) +{ + std::string str; + std::mbstate_t state = {}; + const wchar_t* data = wstr.data(); + size_t len = std::wcsrtombs(nullptr, &data, 0, &state); + if (static_cast(-1) != len) + { + std::unique_ptr buff(new char[len + 1]); + len = std::wcsrtombs(buff.get(), &data, len, &state); + + if (static_cast(-1) != len) + str.assign(buff.get(), len); + } + return str; +} + +int CImageApplyBarCodeRecognition::recognize_ZXing(const cv::Mat& image, BarCodeInfo& result) +{ + zxing::Ref res; + auto ciw = new ImageWrapper(image); + zxing::Ref imageRef(ciw); + zxing::GlobalHistogramBinarizer* binz = new zxing::GlobalHistogramBinarizer(imageRef); + + zxing::Ref< zxing::Binarizer > bz(binz); + zxing::BinaryBitmap* bb = new zxing::BinaryBitmap(bz); + + zxing::Ref< zxing::BinaryBitmap > ref(bb); + zxing::MultiFormatReader decoder_; + try + { + res = decoder_.decode(ref, static_cast(static_cast( + zxing::DecodeHints::QR_CODE_HINT | + zxing::DecodeHints::AZTEC_HINT | + zxing::DecodeHints::CODABAR_HINT | + zxing::DecodeHints::CODE_39_HINT | + zxing::DecodeHints::CODE_93_HINT | + zxing::DecodeHints::CODE_128_HINT | + zxing::DecodeHints::DATA_MATRIX_HINT | + zxing::DecodeHints::EAN_8_HINT | + zxing::DecodeHints::EAN_13_HINT | + zxing::DecodeHints::ITF_HINT | + zxing::DecodeHints::MAXICODE_HINT | + zxing::DecodeHints::PDF_417_HINT | + zxing::DecodeHints::QR_CODE_HINT | + zxing::DecodeHints::RSS_14_HINT | + zxing::DecodeHints::RSS_EXPANDED_HINT | + zxing::DecodeHints::UPC_A_HINT | + zxing::DecodeHints::UPC_E_HINT | + zxing::DecodeHints::UPC_EAN_EXTENSION_HINT))); + result.barCodeText = res->getText()->getText(); + result.barCodeLength = result.barCodeText.length(); + if (!result.barCodeText.empty()) + { + result.barCodeType = -1; + switch (res->getBarcodeFormat()) + { + case zxing::BarcodeFormat::NONE: + result.barCodeType = -1; + break; + case zxing::BarcodeFormat::AZTEC: + break; + case zxing::BarcodeFormat::CODABAR: + result.barCodeType = BarCodeType::CodaBar; + break; + case zxing::BarcodeFormat::CODE_39: + break; + case zxing::BarcodeFormat::CODE_93: + result.barCodeType = BarCodeType::Code93; + break; + case zxing::BarcodeFormat::CODE_128: + result.barCodeType = BarCodeType::Code128; + break; + case zxing::BarcodeFormat::DATA_MATRIX: + break; + case zxing::BarcodeFormat::EAN_8: + result.barCodeType = BarCodeType::Ean8; + break; + case zxing::BarcodeFormat::EAN_13: + result.barCodeType = BarCodeType::Ean13; + break; + case zxing::BarcodeFormat::ITF: + break; + case zxing::BarcodeFormat::MAXICODE: + result.barCodeType = BarCodeType::MaxiCode; + break; + case zxing::BarcodeFormat::PDF_417: + result.barCodeType = BarCodeType::Pdf417; + break; + case zxing::BarcodeFormat::QR_CODE: + result.barCodeType = BarCodeType::QrCode; + break; + case zxing::BarcodeFormat::RSS_14: + break; + case zxing::BarcodeFormat::RSS_EXPANDED: + break; + case zxing::BarcodeFormat::UPC_A: + break; + case zxing::BarcodeFormat::UPC_EAN_EXTENSION: + break; + default: + result.barCodeType = -1; + } + } + } + catch (zxing::Exception& e) + { + std::cout << e.what() << std::endl; + return -1; + } + + return 0; +} + +int CImageApplyBarCodeRecognition::recognize_Zbar(const cv::Mat& image, BarCodeInfo& result) +{ + zbar::ImageScanner scanner; + zbar::Image img(image.cols, image.rows, "Y800", reinterpret_cast(image.data), image.total()); + + scanner.scan(img); + for (zbar::Image::SymbolIterator symbol = img.symbol_begin(); symbol != img.symbol_end(); ++symbol) + { + result.barCodeText = symbol->get_data(); + result.barCodeLength = result.barCodeText.length(); + if (!result.barCodeText.empty()) + { + result.barCodeType = -1; + switch (symbol->get_type()) + { + case zbar::zbar_symbol_type_t::ZBAR_NONE: + result.barCodeType = -1; + break; + case zbar::zbar_symbol_type_t::ZBAR_PARTIAL: + break; + case zbar::zbar_symbol_type_t::ZBAR_EAN8: + result.barCodeType = BarCodeType::Ean8; + break; + case zbar::zbar_symbol_type_t::ZBAR_UPCE: + break; + case zbar::zbar_symbol_type_t::ZBAR_ISBN10: + break; + case zbar::zbar_symbol_type_t::ZBAR_UPCA: + break; + case zbar::zbar_symbol_type_t::ZBAR_EAN13: + result.barCodeType = BarCodeType::Ean13; + break; + case zbar::zbar_symbol_type_t::ZBAR_ISBN13: + break; + case zbar::zbar_symbol_type_t::ZBAR_I25: + break; + case zbar::zbar_symbol_type_t::ZBAR_CODE39: + break; + case zbar::zbar_symbol_type_t::ZBAR_PDF417: + result.barCodeType = BarCodeType::Pdf417; + break; + case zbar::zbar_symbol_type_t::ZBAR_QRCODE: + result.barCodeType = BarCodeType::QrCode; + break; + case zbar::zbar_symbol_type_t::ZBAR_CODE128: + result.barCodeType = BarCodeType::Code128; + break; + case zbar::zbar_symbol_type_t::ZBAR_SYMBOL: + break; + case zbar::zbar_symbol_type_t::ZBAR_ADDON2: + break; + case zbar::zbar_symbol_type_t::ZBAR_ADDON5: + break; + case zbar::zbar_symbol_type_t::ZBAR_ADDON: + break; + default: + result.barCodeType = -1; + } + } + break; + } + + return 0; +} + +void CImageApplyBarCodeRecognition::decode(cv::Mat& image, CImageApplyBarCodeRecognition::BarCodeInfo& result) +{ + if (image.empty()) return; + + cv::Mat temp; + if (image.channels() == 3) + { + cv::cvtColor(image, temp, cv::COLOR_BGR2GRAY); + cv::threshold(temp, temp, 127, 255, cv::THRESH_OTSU); + } + else + cv::threshold(image, temp, 127, 255, cv::THRESH_OTSU); + + //cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(m_direction == Direction::Horizontal ? 1 : 5, m_direction == Direction::Horizontal ? 5 : 1)); + //cv::morphologyEx(temp, temp, cv::MORPH_ERODE, element); + + recognize_Zbar(temp, result); + if (result.barCodeText.empty()) + recognize_ZXing(temp, result); +} + +CImageApplyBarCodeRecognition::CImageApplyBarCodeRecognition() + : m_mode(RecognizeMode::Single) + , m_direction(Direction::Horizontal) +{ +} + +CImageApplyBarCodeRecognition::CImageApplyBarCodeRecognition(RecognizeMode mode, Direction dir) + : m_mode(mode) + , m_direction(dir) +{ + +} + +CImageApplyBarCodeRecognition::~CImageApplyBarCodeRecognition() +{ + +} + +void CImageApplyBarCodeRecognition::apply(cv::Mat& pDib, int side) +{ + (void)side; + m_result = BarCodeInfo(); + + cv::Mat temp = pDib.clone(); + decode(temp, m_result); + if (!m_result.barCodeText.empty()) return; + + cv::transpose(pDib, temp); + cv::flip(temp, temp, 0); + decode(temp, m_result); + if (!m_result.barCodeText.empty()) return; + + cv::flip(pDib, temp, 0); + cv::flip(temp, temp, 1); + decode(temp, m_result); + if (!m_result.barCodeText.empty()) return; + + cv::transpose(pDib, temp); + cv::flip(temp, temp, 1); + decode(temp, m_result); +} + +void findContours1(const cv::Mat& src, std::vector>& contours, std::vector& hierarchy, int retr, int method, cv::Point offset) +{ + CvMat c_image = cvMat(src); + cv::MemStorage storage(cvCreateMemStorage()); + CvSeq* _ccontours = nullptr; + cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, cvPoint(offset)); + + if (!_ccontours) + { + contours.clear(); + return; + } + cv::Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); + size_t total = all_contours.size(); + contours.resize(total); + + cv::SeqIterator it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq* c = *it; + reinterpret_cast(c)->color = static_cast(i); + int count = c->total; + int* data = new int[static_cast(count * 2)]; + cvCvtSeqToArray(c, data); + for (int j = 0; j < count; j++) + { + contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1])); + } + delete[] data; + } + + hierarchy.resize(total); + it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq* c = *it; + int h_next = c->h_next ? reinterpret_cast(c->h_next)->color : -1; + int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; + int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; + int v_prev = c->v_prev ? reinterpret_cast(c->v_prev)->color : -1; + hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev); + } + + storage.release(); +} + +#endif //_NOT_USE \ No newline at end of file diff --git a/ImageProcess/ImageApplyBarCodeRecognition.h b/ImageProcess/ImageApplyBarCodeRecognition.h new file mode 100644 index 0000000..96f1e56 --- /dev/null +++ b/ImageProcess/ImageApplyBarCodeRecognition.h @@ -0,0 +1,84 @@ +#ifndef IMAGE_APPLY_BAR_CODE_RECOGNITION_H +#define IMAGE_APPLY_BAR_CODE_RECOGNITION_H + +#include "ImageApply.h" + +class CImageApplyBarCodeRecognition : public CImageApply +{ +public: + enum class RecognizeMode + { + Single = 0, + Multi + }; + + enum class Direction + { + Horizontal, + Vertical + }; + + enum BarCodeType + { + ThreeOfNine = 0, + ThreeOfFiveInterleaved = 1, + ThreeOfFiveNonInterleaved = 2, + Code93 = 3, + Code128 = 4, + Ucc128 = 5, + CodaBar = 6, + Upca = 7, + Upce = 8, + Ean8 = 9, + Ean13 = 10, + Postnet = 11, + Pdf417 = 12, + TwoOfFiveIndustrial = 13, + TwoOfFiveMatrix = 14, + TwoOfFiveDatalogic = 15, + TwoOfFiveIata = 16, + ThreeOfNineFullAscii = 17, + CodaBarWithStartStop = 18, + MaxiCode = 19, + QrCode = 20 + }; + + typedef struct BarCode_Info + { + int barCodeType; + int barCodeLength; + std::string barCodeText; + int barCodeX; + int barCodeY; + int barCodeRotation; + int barCdeConfidence; + }BarCodeInfo; + +public: + CImageApplyBarCodeRecognition(); + + CImageApplyBarCodeRecognition(RecognizeMode mode, Direction dir); + + virtual ~CImageApplyBarCodeRecognition(void); + + virtual void apply(cv::Mat& pDib, int side); + + inline BarCodeInfo result() { return m_result; } + + inline std::vector results() { return m_vector_result; } + +private: + int recognize_ZXing(const cv::Mat& image, BarCodeInfo& result); + int recognize_Zbar(const cv::Mat& image, BarCodeInfo& result); + void decode(cv::Mat& image, BarCodeInfo& result); + virtual void apply(std::vector& mats, bool isTwoSide) {} +private: + RecognizeMode m_mode; + Direction m_direction; + + BarCodeInfo m_result; + std::vector m_vector_result; +}; + +#endif // IMAGE_APPLY_BAR_CODE_RECOGNITION_H + diff --git a/ImageProcess/ImageApplyChannel.cpp b/ImageProcess/ImageApplyChannel.cpp new file mode 100644 index 0000000..6cb0117 --- /dev/null +++ b/ImageProcess/ImageApplyChannel.cpp @@ -0,0 +1,127 @@ +#include "ImageApplyChannel.h" +#include "ImageApplyAdjustColors.h" + +CImageApplyChannel::CImageApplyChannel() + : m_channel(Invalid) + , colors(new CImageApplyAdjustColors(0, 30, 1.0)) +{ +} + +CImageApplyChannel::CImageApplyChannel(Channel channel) + : m_channel(channel) + , colors(new CImageApplyAdjustColors(0, 30, 1.0)) +{ +} + +CImageApplyChannel::~CImageApplyChannel() +{ + if (colors != nullptr) delete colors; +} + +void CImageApplyChannel::apply(cv::Mat& pDib,int side) +{ + (void)side; + if (pDib.empty()) return; + + cv::Mat dst(pDib.rows, pDib.cols, CV_8UC1); + switch (m_channel) + { + case Red: + cv::extractChannel(pDib, dst, 2); + colors->apply(pDib, side); + break; + case Green: + cv::extractChannel(pDib, dst, 1); + break; + case Blue: + cv::extractChannel(pDib, dst, 0); + break; + case All: + colourless(pDib, dst, 80); + break; + case Except_Red: + except_channel(pDib, dst, 2); + break; + case Except_Green: + except_channel(pDib, dst, 1); + break; + case Except_Blue: + except_channel(pDib, dst, 0); + break; + default: + break; + } + pDib.release(); + pDib = dst; +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyChannel apply"); +#endif // LOG +} + +void CImageApplyChannel::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} + +void CImageApplyChannel::except_channel(const cv::Mat & src, cv::Mat & dst, int channel) +{ + int rows = static_cast(src.total()); + cv::Mat src_temp(rows, 3, CV_8UC1, src.data); + cv::Mat dst_temp(rows, 1, CV_8UC1, dst.data); + + cv::Mat temp1, temp2; + switch (channel) + { + case 0: + temp1 = src_temp(cv::Rect(1, 0, 1, rows)); + temp2 = src_temp(cv::Rect(2, 0, 1, rows)); + cv::addWeighted(temp1, 0.587, temp2, 0.299, 0, dst_temp); + break; + case 1: + temp1 = src_temp(cv::Rect(0, 0, 1, rows)); + temp2 = src_temp(cv::Rect(2, 0, 1, rows)); + cv::addWeighted(temp1, 0.114, temp2, 0.299, 0, dst_temp); + break; + case 2: + temp1 = src_temp(cv::Rect(0, 0, 1, rows)); + temp2 = src_temp(cv::Rect(1, 0, 1, rows)); + cv::addWeighted(temp1, 0.114, temp2, 0.587, 0, dst_temp); + break; + default: + break; + } +} + +void CImageApplyChannel::colourless(const cv::Mat &src, cv::Mat &dst, uchar threshold) +{ + if (src.channels() != 3) + { + dst = src; + return; + } + + cv::Mat hsv; + cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV_FULL); + cv::Mat mv_hsv[3]; + cv::split(hsv, mv_hsv); + size_t total = mv_hsv[1].total(); + uchar* ptr_s = mv_hsv[1].data; + uchar* ptr_v = mv_hsv[2].data; + for (size_t i = 0; i < total; i++) + if (ptr_s[i] > threshold) + { + ptr_s[i] = 0; + ptr_v[i] = 255; + } + cv::merge(mv_hsv, 3, hsv); + cv::cvtColor(hsv, hsv, cv::COLOR_HSV2BGR_FULL); + cv::cvtColor(hsv, dst, cv::COLOR_BGR2GRAY); +} diff --git a/ImageProcess/ImageApplyChannel.h b/ImageProcess/ImageApplyChannel.h new file mode 100644 index 0000000..3937221 --- /dev/null +++ b/ImageProcess/ImageApplyChannel.h @@ -0,0 +1,47 @@ +#ifndef IMAGE_APPLY_CHANNEL_H +#define IMAGE_APPLY_CHANNEL_H + +#include "ImageApply.h" + +class CImageApplyAdjustColors; +class CImageApplyChannel : public CImageApply +{ +public: + + typedef enum channel + { + Red, //ɫͨ + Green, //ɫͨ + Blue, //ɫͨ + All, //ȥHSVɫʽṹУS80ɫ + Invalid, //Ч + Except_Red, //ɫͨ + Except_Green, //ɫͨ + Except_Blue //ɫͨ + }Channel; + +public: + + CImageApplyChannel(); + + CImageApplyChannel(Channel channel); + + virtual ~CImageApplyChannel(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + +private: + + void except_channel(const cv::Mat& src, cv::Mat& dst, int channel); + + void colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold = 80); + +private: + + Channel m_channel; + CImageApplyAdjustColors* colors; +}; + +#endif // !IMAGE_APPLY_CHANNEL_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyColorRecognition.cpp b/ImageProcess/ImageApplyColorRecognition.cpp new file mode 100644 index 0000000..d85896b --- /dev/null +++ b/ImageProcess/ImageApplyColorRecognition.cpp @@ -0,0 +1,126 @@ +#include "ImageApplyColorRecognition.h" +#include "ImageApplyHeaders.h" + +static CImageApplyBWBinaray m_bw; +static CImageApplyAdjustColors m_ac(0, 50, 1.0f); + +/// +/// ͼǷDzɫǰ߼ԺɫؽжϣںɫΪɫΪDzɫ +/// +/// ͼ +/// trueΪɫfalseΪDzɫ +bool isColor(const cv::Mat& image) +{ + if (image.channels() != 3) return false; + + cv::Mat pDib_resize; + cv::resize(image, pDib_resize, cv::Size(image.cols / 9, image.rows / 9), 0, 0, cv::INTER_AREA); + + cv::Mat hsv; + cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL); + std::vector hsv_channels; + cv::split(hsv, hsv_channels); + + cv::Mat range_h1, range_h2, range_s, range_v; + cv::inRange(hsv_channels[0], 0, 85, range_h1); + cv::inRange(hsv_channels[0], 170, 255, range_h2); + cv::inRange(hsv_channels[1], 60, 255, range_s); + cv::inRange(hsv_channels[2], 100, 255, range_v); + + cv::Mat thre = (range_h1 | range_h2) & range_s & range_v; + return (cv::sum(thre)[0] / 255)> 4; +} + +bool isGray(const cv::Mat& image) +{ + if (image.channels() == 3) return true; + + cv::Mat image_clone; + cv::resize(image, image_clone, cv::Size(), 0.25, 0.25); + int channels[] = { 0 }; + int histsize[] = { 256 }; + float range[] = { 0, 256 }; + const float* histRanges[] = { range }; + cv::Mat hist; + cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, histsize, histRanges, true, false); + + float pixel_count0 = hist.at(0, 0); + float pixel_count255 = hist.at(255, 0); + float total = image_clone.total(); + + return ((pixel_count0 + pixel_count255) / total) > 0.95; +} + +CImageApplyColorRecognition::CImageApplyColorRecognition(ColorRecognitionMode mode) + : m_mode(mode) +{ +} + +CImageApplyColorRecognition::~CImageApplyColorRecognition(void) +{ +} + +void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side) +{ + //жǷҪжDzɫ + if (m_mode == AllColor || m_mode == Color_Gray || m_mode == Color_Mono) + { + //Dzɫֱ˳ + if (isColor(pDib)) + { + m_result = Color; + return; + } + } + + if (pDib.channels() == 3) + cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY); + + if (m_mode == Color_Gray) + { + m_result = Gray; + return; + } + + if (m_mode == Color_Mono) + { + m_bw.apply(pDib, side); + m_result = Mono; + return; + } + + if (isGray(pDib)) + m_result = Gray; + else + { + m_bw.apply(pDib, side); + m_result = Mono; + } +} + +void CImageApplyColorRecognition::apply(std::vector& mats, bool isTwoSide) +{ + m_results.clear(); + if (mats.empty()) return; + + if (!mats[0].empty()) + apply(mats[0], 0); + + m_results.push_back(m_result); + + if (isTwoSide && mats.size() > 1) + if (!mats[1].empty()) + apply(mats[1], 1); + + m_results.push_back(m_result); +} + +CImageApplyColorRecognition::ColorType CImageApplyColorRecognition::getResult() +{ + return m_result; +} + +std::vector CImageApplyColorRecognition::getResults() +{ + return m_results; +} diff --git a/ImageProcess/ImageApplyColorRecognition.h b/ImageProcess/ImageApplyColorRecognition.h new file mode 100644 index 0000000..f006122 --- /dev/null +++ b/ImageProcess/ImageApplyColorRecognition.h @@ -0,0 +1,66 @@ +/* + * ==================================================== + + * ܣɫʶ𣬽ʶᡰҶȡ24λͼתΪ256ɫ8λͼ ʶΪڰסͼתΪֵ8λͼ + * ߣά + * ʱ䣺2020/7/17 + * ޸ʱ䣺2020/12/15 + * 汾ţv1.0 2020/7/17 + * v1.1 2020/12/15 ԣжϺɫأںɫΪɫΪҶȣɾֱתͼ + * v1.2 2020/12/16 ɫģʽֻ֣ӽʽӿ + * ==================================================== + */ + +#ifndef IMAGE_APPLY_COLOR_RECOGNITION_H +#define IMAGE_APPLY_COLOR_RECOGNITION_H + +#include "ImageApply.h" + +class CImageApplyColorRecognition : public CImageApply +{ +public : + + //ɫʶģʽ + enum ColorRecognitionMode + { + AllColor, //ȫɫģʽ ʶܻDzɫҶȡڰ + Color_Gray, //ɫҶģʽ ʶֻDzɫ߻Ҷ + Color_Mono, //ɫڰģʽ ʶֻDzɫߺڰ + Gray_Mono //ҶȺڰģʽ ʶֻǻҶȻߺڰ + }; + + //ɫ + enum ColorType + { + Color, //ɫ + Gray, //Ҷ + Mono //ڰ + }; +public: + CImageApplyColorRecognition(ColorRecognitionMode mode = AllColor); + + virtual ~CImageApplyColorRecognition(void); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + /// + /// ȡͼƬɫ͡void apply(cv::Mat&, int)ӿʹ + /// + /// ɫ + ColorType getResult(); + + /// + /// ȡͼƬɫ͡void apply(std::vector&, int)ӿʹ + /// + /// ɫ + std::vector getResults(); + +private: + ColorType m_result; + std::vector m_results; + ColorRecognitionMode m_mode; +}; + +#endif // !IMAGE_APPLY_CONCATENATION_H diff --git a/ImageProcess/ImageApplyConcatenation.cpp b/ImageProcess/ImageApplyConcatenation.cpp new file mode 100644 index 0000000..8b1b62e --- /dev/null +++ b/ImageProcess/ImageApplyConcatenation.cpp @@ -0,0 +1,107 @@ +#include "ImageApplyConcatenation.h" + +CImageApplyConcatenation::CImageApplyConcatenation() + : m_direction(autoDirection) + , m_BG_color(255, 255, 255) +{ +} + +CImageApplyConcatenation::CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& background) + : m_direction(dir) + , m_BG_color(background) +{ +} + +CImageApplyConcatenation::~CImageApplyConcatenation(void) +{ +} + +void CImageApplyConcatenation::apply(cv::Mat& pDib, int side) +{ + (void)pDib; + (void)side; +} + +void CImageApplyConcatenation::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + if (mats.size() < 2) + { + mats.clear(); + return; + } + + ConcatMode direction; + if (m_direction == ConcatMode::autoDirection) + direction = (mats[0].cols > mats[0].rows) ? ConcatMode::vertical : ConcatMode::horizontal; + else + direction = m_direction; + cv::Mat dst = concat(mats[0], mats[1], direction); + mats.clear(); + mats.push_back(dst); +} + +cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMode direction) +{ + cv::Mat dst; + if (direction == horizontal) + { +#if 0 + int top, bottom; + if (front.rows > back.rows) + { + top = (front.rows - back.rows) / 2; + bottom = front.rows - back.rows - top; + cv::copyMakeBorder(back, back, top, bottom, 0, 0, cv::BORDER_CONSTANT); + } + else if (front.rows < back.rows) + { + top = (back.rows - front.rows) / 2; + bottom = back.rows - front.rows - top; + cv::copyMakeBorder(front, front, top, bottom, 0, 0, cv::BORDER_CONSTANT); + } + cv::hconcat(front, back, dst); +#else + int width = cv::max(front.cols, back.cols) * 2; + int height = cv::max(front.rows, back.rows); + if (front.channels() != back.channels()) + cv::cvtColor(front.channels() > back.channels() ? back : front, front.channels() > back.channels() ? back : front, cv::COLOR_GRAY2BGR); + dst = cv::Mat(height, width, front.type(), m_BG_color); + front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows))); + int offset = front.cols; + front.release(); + back.copyTo(dst(cv::Rect(offset, 0, back.cols, back.rows))); + back.release(); +#endif + } + else if (direction == vertical) + { +#if 0 + int left, right; + if (front.cols > back.cols) + { + left = (front.cols - back.cols) / 2; + right = front.cols - back.cols - left; + cv::copyMakeBorder(back, back, 0, 0, left, right, cv::BORDER_CONSTANT); + } + else if (front.cols < back.cols) + { + left = (back.cols - front.cols) / 2; + right = back.cols - front.cols - left; + cv::copyMakeBorder(front, front, 0, 0, left, right, cv::BORDER_CONSTANT); + } + cv::vconcat(front, back, dst); +#else + int width = cv::max(front.cols, back.cols); + int height = cv::max(front.rows, back.rows) * 2; + + dst = cv::Mat(height, width, front.type(), m_BG_color); + front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows))); + int offset = front.rows; + front.release(); + back.copyTo(dst(cv::Rect(0, offset, back.cols, back.rows))); + back.release(); +#endif + } + return dst; +} diff --git a/ImageProcess/ImageApplyConcatenation.h b/ImageProcess/ImageApplyConcatenation.h new file mode 100644 index 0000000..c4ec540 --- /dev/null +++ b/ImageProcess/ImageApplyConcatenation.h @@ -0,0 +1,61 @@ +/* + * ==================================================== + + * ܣƴӣ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/29 + * 汾ţv1.0 2020/4/21 + * 汾ţv1.1 2020/4/29 : 1m_BG_colorӿڣͼƬ2Żڴ + * ==================================================== + */ + +#ifndef IMAGE_APPLY_CONCATENATION_H +#define IMAGE_APPLY_CONCATENATION_H + +#include "ImageApply.h" + + class CImageApplyConcatenation : public CImageApply +{ +public: + //۷ + enum ConcatMode + { + horizontal = 0, //ƴ + vertical, //ƴ + autoDirection + + }; +public: + CImageApplyConcatenation(); //Ĭm_direction = autoDirection; + + /* + * dir [in]:ƴӷ + * backgroud [in]:ɫĬΪɫ + * */ + CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& backgroud = cv::Scalar(0, 0, 0)); + + virtual ~CImageApplyConcatenation(void); + + virtual void apply(std::vector& mats, bool isTwoSide); + + inline ConcatMode getConcatDirection() { return m_direction; } + + inline void setFildDirection(ConcatMode dir) { m_direction = dir; } + + inline cv::Scalar getBackGroundColor() const { return m_BG_color; } + + inline void setBackGroundColor(const cv::Scalar& color) { m_BG_color = color; } + +private: + + virtual void apply(cv::Mat& pDib, int side); + + cv::Mat concat(cv::Mat& front, cv::Mat& back, ConcatMode direction = autoDirection); + +private: + ConcatMode m_direction; + cv::Scalar m_BG_color; +}; + +#endif // !IMAGE_APPLY_CONCATENATION_H diff --git a/ImageProcess/ImageApplyCrop.cpp b/ImageProcess/ImageApplyCrop.cpp new file mode 100644 index 0000000..a95e63b --- /dev/null +++ b/ImageProcess/ImageApplyCrop.cpp @@ -0,0 +1,52 @@ +#include "ImageApplyCrop.h" + +CImageApplyCrop::CImageApplyCrop(void) +{ +} + + +CImageApplyCrop::~CImageApplyCrop(void) +{ +} + +void CImageApplyCrop::apply(cv::Mat& pDib,int side) +{ +#ifdef LOG + FileTools::write_log("imgprc.txt", "enter CImageApplyCrop apply"); +#endif // LOG + + if (pDib.empty()) + { +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply"); +#endif // LOG + return; + } + + if (m_roi.x < 0 || m_roi.y < 0 || m_roi.br().x >= pDib.cols || m_roi.br().y >= pDib.rows || m_roi.width == 0 || m_roi.height == 0) + { +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply"); +#endif // LOG + return; + } + + pDib = pDib(m_roi).clone(); +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply"); +#endif // LOG +} + +void CImageApplyCrop::apply(std::vector& mats, bool isTwoSide) +{ + if (mats.empty()) return; + + if (!mats[0].empty()) { + apply(mats[0], 0); + } + + if (isTwoSide && mats.size() > 1) { + if (!mats[1].empty()) + apply(mats[1], 1); + } +} diff --git a/ImageProcess/ImageApplyCrop.h b/ImageProcess/ImageApplyCrop.h new file mode 100644 index 0000000..3d178b5 --- /dev/null +++ b/ImageProcess/ImageApplyCrop.h @@ -0,0 +1,28 @@ +#ifndef IMAGE_APPLY_CROP_H +#define IMAGE_APPLY_CROP_H + +#include "imageapply.h" + +class CImageApplyCrop : public CImageApply +{ + +public: + + CImageApplyCrop(void); + + virtual ~CImageApplyCrop(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + cv::Rect getROI() { return m_roi; } + + void setROI(const cv::Rect& rect) { m_roi = rect; } + +private: + + cv::Rect m_roi; +}; + +#endif // !IMAGE_APPLY_CROP_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyCustomCrop.cpp b/ImageProcess/ImageApplyCustomCrop.cpp new file mode 100644 index 0000000..9875e38 --- /dev/null +++ b/ImageProcess/ImageApplyCustomCrop.cpp @@ -0,0 +1,32 @@ +#include "ImageApplyCustomCrop.h" + +CImageApplyCustomCrop::CImageApplyCustomCrop(const cv::Rect &rect) + : m_rect(rect) +{ + +} + +CImageApplyCustomCrop::~CImageApplyCustomCrop() +{ + +} + +void CImageApplyCustomCrop::apply(cv::Mat &pDib, int side) +{ + (void)side; + if(pDib.empty()) return; + pDib = pDib(cv::Rect(0, 0, pDib.cols, pDib.rows) & m_rect).clone(); +} + +void CImageApplyCustomCrop::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyCustomCrop.h b/ImageProcess/ImageApplyCustomCrop.h new file mode 100644 index 0000000..3993a51 --- /dev/null +++ b/ImageProcess/ImageApplyCustomCrop.h @@ -0,0 +1,40 @@ +/* + * ==================================================== + + * ܣԶü + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_CUSTOM_CROP_H +#define IMAGE_APPLY_CUSTOM_CROP_H + +#include "ImageApply.h" + +class CImageApplyCustomCrop : public CImageApply +{ +public: + + /* + * rect [in]:ü + * */ + CImageApplyCustomCrop(const cv::Rect& rect); + + virtual~ CImageApplyCustomCrop(void); + + inline cv::Rect getROI() const { return m_rect; } + + inline void setROI(const cv::Rect& roi) { m_rect = roi; } + + virtual void apply(cv::Mat &pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); +private: + cv::Rect m_rect; +}; + +#endif // IMAGE_APPLY_CUSTOM_CROP_H diff --git a/ImageProcess/ImageApplyCustomGamma.cpp b/ImageProcess/ImageApplyCustomGamma.cpp new file mode 100644 index 0000000..8132682 --- /dev/null +++ b/ImageProcess/ImageApplyCustomGamma.cpp @@ -0,0 +1,63 @@ +#include "ImageApplyCustomGamma.h" + +CImageApplyCustomGamma::CImageApplyCustomGamma(unsigned char* table,int length) + : emptyPtr(false) +{ + if(table==nullptr) + emptyPtr = true; + + init_gamma_table(); + setLUT(table,length == 256 ? 1 : 3); +} + +CImageApplyCustomGamma::~CImageApplyCustomGamma() +{ +} + +void CImageApplyCustomGamma::setLUT(const unsigned char* table, int byteCount) +{ + if (emptyPtr) + return; + + if (byteCount == 1) + memcpy(m_table_bit8, table, 256); + else if (byteCount == 3) + memcpy(m_table_bit24, table, 768); +} + +void CImageApplyCustomGamma::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (emptyPtr) + return; + int numOfChannels = pDib.channels(); + cv::Mat mat_table(1, 256, CV_8UC(numOfChannels), (numOfChannels == 3) ? m_table_bit24 : m_table_bit8); + cv::LUT(pDib, mat_table, pDib); +} + +void CImageApplyCustomGamma::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} + +void CImageApplyCustomGamma::setTableData(const unsigned char* data, int length) +{ + setLUT(data, length == 256 ? 1 : 3); +} + +void CImageApplyCustomGamma::init_gamma_table() +{ + for (size_t i = 0; i < 256; ++i) + { + m_table_bit8[i] = static_cast(i); + m_table_bit24[i * 3] = m_table_bit24[i * 3 + 1] = m_table_bit24[i * 3 + 2] = static_cast(i); + } +} diff --git a/ImageProcess/ImageApplyCustomGamma.h b/ImageProcess/ImageApplyCustomGamma.h new file mode 100644 index 0000000..0e0613b --- /dev/null +++ b/ImageProcess/ImageApplyCustomGamma.h @@ -0,0 +1,44 @@ +/* + * ==================================================== + + * ܣԶ٤УԭΪϣֵ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_CUSTOM_CAMMA_H +#define IMAGE_APPLY_CUSTOM_CAMMA_H + +#include "ImageApply.h" + +class CImageApplyCustomGamma : public CImageApply +{ +public: + /* + * table [in]:Զֵ + * length [in]:ijȣҶȱ256ɫ768 + * */ + CImageApplyCustomGamma(unsigned char* table,int length); + + virtual ~CImageApplyCustomGamma(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + void setTableData(const unsigned char* data, int length); +private: + void init_gamma_table(); + void setLUT(const unsigned char* table, int byteCount); + bool emptyPtr; +private: + unsigned char m_table_bit8[256]; + + unsigned char m_table_bit24[768]; +}; + +#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H diff --git a/ImageProcess/ImageApplyCvtColor.cpp b/ImageProcess/ImageApplyCvtColor.cpp new file mode 100644 index 0000000..d69979a --- /dev/null +++ b/ImageProcess/ImageApplyCvtColor.cpp @@ -0,0 +1,57 @@ +#include "ImageApplyCvtColor.h" + +CImageApplyCvtColor::CImageApplyCvtColor(ConversionCodes type) + : m_code(type) +{ +} + +CImageApplyCvtColor::~CImageApplyCvtColor() +{ +} + +void CImageApplyCvtColor::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.channels() == 1) return; + if (m_code > 3) + cv::cvtColor(pDib, pDib, static_cast(m_code)); + else + { + cv::Mat gray(pDib.size(), CV_8UC1); + if (m_code == BGR_MAX) + { + for (size_t y = 0, rows = pDib.rows; y < rows; y++) + { + uchar* ptr_y = pDib.ptr(y); + uchar* gray_y = gray.ptr(y); + for (size_t x = 0, cols = pDib.cols; x < cols; x++) + gray_y[x] = cv::max(ptr_y[x * 3], cv::max(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2])); + } + } + else if (m_code == BGR_MIN) + { + for (size_t y = 0, rows = pDib.rows; y < rows; y++) + { + uchar* ptr_y = pDib.ptr(y); + uchar* gray_y = gray.ptr(y); + for (size_t x = 0, cols = pDib.cols; x < cols; x++) + gray_y[x] = cv::min(ptr_y[x * 3], cv::min(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2])); + } + } + pDib.release(); + pDib = gray; + } +} + +void CImageApplyCvtColor::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyCvtColor.h b/ImageProcess/ImageApplyCvtColor.h new file mode 100644 index 0000000..2fc3034 --- /dev/null +++ b/ImageProcess/ImageApplyCvtColor.h @@ -0,0 +1,52 @@ +/* + * ==================================================== + + * 1|?����o��?2����??? + * ����??��o��????? + * ����3������??��o2020/6/19 + * ��??��DT??����??��ov1.0 2020/6/19 + v1.1 2020/6/20 ����?��BGR��aHSV,����?��BGR_MAX��?����?��BGR_MIN + * ��?��?o?��ov1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_CONVERT_COLOR_H +#define IMAGE_APPLY_CONVERT_COLOR_H + +#include "ImageApply.h" + +class CImageApplyCvtColor : public CImageApply +{ +public: + + //��a???�꨺? + enum ConversionCodes + { + BGR_MAX = 1, //BGR��?�䨮?�̡�?��aGRAY + BGR_MIN = 2, //BGR��?D??�̡�?��aGRAY + BGR2GRAY = 6, //BGR��aGRAY + BGR2HSV = 40 //BGR��aHSV + }; + + /* + * type [in]:��?2����a???�꨺?��???��?BGR��aGray + * */ + CImageApplyCvtColor(ConversionCodes type = BGR2GRAY); + + virtual ~CImageApplyCvtColor(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + inline ConversionCodes getConversionCode() { return m_code; } + + inline void setConversionCode(ConversionCodes code) { m_code = code; } + +private: + ConversionCodes m_code; + +}; + +#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H diff --git a/ImageProcess/ImageApplyDetachNoise.cpp b/ImageProcess/ImageApplyDetachNoise.cpp new file mode 100644 index 0000000..d32951b --- /dev/null +++ b/ImageProcess/ImageApplyDetachNoise.cpp @@ -0,0 +1,42 @@ +#include "ImageApplyDetachNoise.h" +#include "ImageProcess_Public.h" + +CImageApplyDetachNoise::CImageApplyDetachNoise(int noise) + : m_noise(noise) +{ +} + +CImageApplyDetachNoise::~CImageApplyDetachNoise(void) +{ +} + +void CImageApplyDetachNoise::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.empty()||pDib.channels() != 1) + return; + + cv::Mat mask; + cv::threshold(pDib, mask, 127, 255, cv::THRESH_BINARY_INV); + + std::vector> contours; + std::vector h; + hg::findContours(mask, contours, h); + + for (const std::vector& contour : contours) + if (contourArea(contour) < m_noise) + fillConvexPoly(pDib, contour, cv::Scalar(255)); +} + +void CImageApplyDetachNoise::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyDetachNoise.h b/ImageProcess/ImageApplyDetachNoise.h new file mode 100644 index 0000000..c795b8e --- /dev/null +++ b/ImageProcess/ImageApplyDetachNoise.h @@ -0,0 +1,38 @@ +/* + * ==================================================== + + * ܣ룬3*3ڵص㣬ҪԺڰͼ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 v1.0 + 2020/5/29 v1.1 ӽӿڣʹСֵɵ + * 汾ţv1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_DETACH_NOISE_H +#define IMAGE_APPLY_DETACH_NOISE_H + +#include "ImageApply.h" + +class CImageApplyDetachNoise : public CImageApply +{ +public: + CImageApplyDetachNoise(int noise = 1); + + inline int getNoise() { return m_noise; } + + inline void setNoise(int noise) { m_noise = noise; } + + virtual ~CImageApplyDetachNoise(void); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + +private: + int m_noise; +}; +#endif // !IMAGE_APPLY_DETACH_NOISE_H + diff --git a/ImageProcess/ImageApplyDiscardBlank.cpp b/ImageProcess/ImageApplyDiscardBlank.cpp new file mode 100644 index 0000000..6d03ac1 --- /dev/null +++ b/ImageProcess/ImageApplyDiscardBlank.cpp @@ -0,0 +1,202 @@ +#include "ImageApplyDiscardBlank.h" +#include "ImageProcess_Public.h" +CImageApplyDiscardBlank::CImageApplyDiscardBlank(int blockSize, int devTh) + : m_res(false) + , m_dSize(blockSize) + , m_devTh(devTh) +{ +} +CImageApplyDiscardBlank::CImageApplyDiscardBlank() + : m_res(false) + , m_dSize(200) + , m_devTh(15, 15, 15, 15) +{ +} + +CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void) +{ +} + +int CImageApplyDiscardBlank::processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector& maxContour, + double scale, double thresh, int blobAreaSize) +{ + cv::Mat gray; + int blockCount = 0; + if (image.channels() == 3) + if (scale != 1.0f) + { + cv::Size ResImgSiz = cv::Size(image.cols * scale, image.rows * scale); + resize(image, gray, cv::Size(), scale, scale, 0); + cvtColor(gray, gray, CV_BGR2GRAY); + } + else + cvtColor(image, gray, CV_BGR2GRAY); + else + if (scale != 1.0f) + resize(image, gray, cv::Size(), scale, scale, 0); + else + gray = image; + + cv::Mat threshold_img; + threshold(gray, threshold_img, thresh, 255.0, CV_THRESH_BINARY); + std::vector> contours; + std::vector h1; + hg::findContours(threshold_img, contours, h1, CV_CHAIN_APPROX_SIMPLE); + threshold_img.release(); + + if (contours.size() == 0) + return blockCount; + + std::vector list_com; + for (int i = 0; i < contours.size(); i++) + { + double area = cv::contourArea(contours[i]); + if (area > blobAreaSize) + { + blockCount++; + for (int j = 0; j < contours[i].size(); j++) + list_com.push_back(contours[i][j]); + } + } + + if (list_com.size() == 0) + return blockCount; + + rotatedRect = cv::minAreaRect(list_com); + rotatedRect.center.x /= (float)scale; + rotatedRect.center.y /= (float)scale; + rotatedRect.size.width /= (float)scale; + rotatedRect.size.height /= (float)scale; + + if (rotatedRect.angle < -45.0f) + { + rotatedRect.angle += 90.0f; + float l_temp = rotatedRect.size.width; + rotatedRect.size.width = rotatedRect.size.height; + rotatedRect.size.height = l_temp; + } + + std::vector hull(list_com.size()); + cv::convexHull(list_com, hull); + + for (int i = 0; i < hull.size(); i++) + { + cv::Point temp = list_com[hull[i]]; + int x = (int)(temp.x / scale); + int y = (int)(temp.y / scale); + maxContour.push_back(cv::Point(x, y)); + } + + return blockCount; +} + + bool CImageApplyDiscardBlank::scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2) +{ + for (int i = 0; i < 3; i++) + if (val1[i] > val2[i]) + return false; + return true; +} + +void CImageApplyDiscardBlank::setIntensity(int val) +{ + val = cv::max(cv::min(100, val), 2); + m_devTh = cv::Scalar::all(val); +} + +cv::Mat CImageApplyDiscardBlank::getRoiMat(const cv::Mat& image) +{ + int gap = 100; + cv::RotatedRect rect; + std::vector contour; + double scale = 0.25; + double thresh = 50; + int blobSize = 200; + processRectR(image, rect, contour, scale, thresh, blobSize); + cv::Rect rect2 = rect.boundingRect(); + cv::Rect inRect = rect2 & cv::Rect(0, 0, image.cols, image.rows); + gap = cv::max(inRect.width - rect.size.width, inRect.height - rect.size.height) + 20; + inRect = cv::Rect(inRect.x + gap, inRect.y + gap, inRect.width - gap * 2, inRect.height - gap * 2); + + if (inRect.width <= 0 || inRect.height <= 0) + return cv::Mat(); + return image(inRect); +} + +void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side) +{ + + if (pDib.empty()) + { + return; + } + + cv::Scalar mean; + cv::Scalar dev; + cv::Mat image = getRoiMat(pDib); + cv::Rect rect; + cv::Rect imRect(0, 0, image.cols, image.rows); + for(int i = 0; i < image.cols; i+= m_dSize) + for(int j = 0; j < image.rows; j+= m_dSize) + { + rect = cv::Rect(i, j, m_dSize, m_dSize) & imRect; + if(rect != cv::Rect()) + { + cv::meanStdDev (image(rect) , mean, dev); + if(!scalar_LE(dev, m_devTh)) + { + m_res = false; +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply"); +#endif // LOG + return; + } + } + } + m_res = true; + if (m_res) + pDib.release(); +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply"); +#endif // LOG +} + +void CImageApplyDiscardBlank::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} + +bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, int blockSize, int devTh) +{ + if (pDib.empty()) + return true; + + cv::Scalar mean; + cv::Scalar dev; + cv::Scalar s_devTh = cv::Scalar::all(devTh); + cv::Mat image = getRoiMat(pDib); + if (image.empty()) + return false; + cv::Rect rect; + cv::Rect imRect(0, 0, image.cols, image.rows); + for (int i = 0; i < image.cols; i += blockSize) + for (int j = 0; j < image.rows; j += blockSize) + { + rect = cv::Rect(i, j, blockSize, blockSize) & imRect; + if (rect != cv::Rect()) + { + cv::meanStdDev(image(rect), mean, dev); + if (!scalar_LE(dev, s_devTh)) + return false; + } + } + return true; +} diff --git a/ImageProcess/ImageApplyDiscardBlank.h b/ImageProcess/ImageApplyDiscardBlank.h new file mode 100644 index 0000000..2fad470 --- /dev/null +++ b/ImageProcess/ImageApplyDiscardBlank.h @@ -0,0 +1,56 @@ +/* + * ==================================================== + + * ܣհҳʶ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 v1.0 + 2020/8/12 v1.1 setIntensitysetMinAreaȡisNormalʶλsetIntensity÷Χ[2, 20][1, 100] + * 汾ţv1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_DISCARD_BLANK_H +#define IMAGE_APPLY_DISCARD_BLANK_H + +#include "ImageApply.h" + +class CImageApplyDiscardBlank : public CImageApply +{ +public: + CImageApplyDiscardBlank(int blockSize, int devTh); + + /* + * isnormal [in]:true׼ģʽfalseΪƱݸдֽģʽ + * */ + CImageApplyDiscardBlank(); + + virtual ~CImageApplyDiscardBlank(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + void setIntensity(int val); + + void setMinArea(int val) { m_dSize = val; } + + static bool apply(const cv::Mat& pDib, int blockSize = 200, int devTh = 15); + +private: + + static int processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector& maxContour, + double scale, double thresh, int blobAreaSize); + + static bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2); + + static cv::Mat getRoiMat(const cv::Mat& pDib); +private: + bool m_res; + bool m_isNormalDiscard; + int m_dSize; + cv::Scalar m_devTh; +}; + +#endif // !IMAGE_APPLY_DISCARD_BLANK_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyDogEarDetection.cpp b/ImageProcess/ImageApplyDogEarDetection.cpp new file mode 100644 index 0000000..40ef3a7 --- /dev/null +++ b/ImageProcess/ImageApplyDogEarDetection.cpp @@ -0,0 +1,67 @@ +#include "ImageApplyDogEarDetection.h" +#include "ImageProcess_Public.h" + +CImageApplyDogEarDetection::CImageApplyDogEarDetection() + : m_threshold(40) + , m_zoom(1.0) + , m_distance(50) + , m_result(false) +{ + +} + +CImageApplyDogEarDetection::CImageApplyDogEarDetection(double threshlod, double zoom, double distance) + : m_threshold(threshlod) + , m_zoom(zoom) + , m_distance(distance) + , m_result(false) +{ + +} + +CImageApplyDogEarDetection::~CImageApplyDogEarDetection() +{ + +} + +void CImageApplyDogEarDetection::apply(cv::Mat &pDib, int side) +{ + m_result = false; + (void)side; + if (pDib.empty()) return; + cv::Mat src; + if (m_zoom != 1.0) + cv::resize(pDib, src, cv::Size(), m_zoom, m_zoom, cv::INTER_NEAREST); + else + src = pDib; + + cv::Mat thre; + hg::threshold_Mat(src, thre, m_threshold); + std::vector hierarchy; + std::vector> contours; + hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); + + std::vector maxContour = hg::getMaxContour(contours, hierarchy); + if (maxContour.size() == 0) + { + m_result = true; + return; + } + hg::convexHull(maxContour, maxContour); + cv::RotatedRect rect = hg::getBoundingRect(maxContour); + cv::Point2f vertexes[4]; + rect.points(vertexes); + + for (int i = 0; i < 4; i++) + if ((-cv::pointPolygonTest(maxContour, vertexes[i], true)) > (m_distance * m_zoom)) + { + m_result = true; + return; + } +} + +void CImageApplyDogEarDetection::apply(std::vector &mats, bool isTwoSide) +{ + (void)mats; + (void)isTwoSide; +} diff --git a/ImageProcess/ImageApplyDogEarDetection.h b/ImageProcess/ImageApplyDogEarDetection.h new file mode 100644 index 0000000..a05f313 --- /dev/null +++ b/ImageProcess/ImageApplyDogEarDetection.h @@ -0,0 +1,56 @@ +/* + * ==================================================== + + * 功能:折角检测。检测原理:计算纸张的理论四角顶点,到实际轮廓最小距离。当任意顶点到轮廓最小距离超过阈值,则判定为折角 + * 作者:刘丁维 + * 生成时间:2020/10/30 + * 最近修改时间:2020/10/30 + * 版本号:v1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_DOGEAR_DETECTION_H +#define IMAGE_APPLY_DOGEAR_DETECTION_H + +#include "ImageApply.h" + +class CImageApplyDogEarDetection :public CImageApply +{ +public: + + /// + /// 折角检测默认构造函数,threshold = 40, zoom = 1.0, distance = 50 + /// + CImageApplyDogEarDetection(); + + /// + /// 折角检测构造函数 + /// + /// 二值化阈值 + /// 原图缩放比例,对于大尺寸图像而言通过zoom缩小图像可减少计算量。默认值1.0(不缩放) + /// 理论顶点到实际轮廓最小距离的阈值,大于该阈值则判定为折角,默认值50(像素) + CImageApplyDogEarDetection(double threshlod, double zoom = 1.0, double distance = 50); + + virtual ~CImageApplyDogEarDetection(void); + + /// + /// 获取检测结果。该函数须在调用apply之后使用。 + /// + /// true为折角,false为不折角 + inline bool getResult() { return m_result; } + + virtual void apply(cv::Mat& pDib, int side); + +private: + virtual void apply(std::vector& mats, bool isTwoSide); + +private: + double m_threshold; + double m_zoom; + double m_distance; + + bool m_result; +}; + +#endif // IMAGE_APPLY_DOGEAR_DETECTION_H diff --git a/ImageProcess/ImageApplyFilter.cpp b/ImageProcess/ImageApplyFilter.cpp new file mode 100644 index 0000000..dbdab6e --- /dev/null +++ b/ImageProcess/ImageApplyFilter.cpp @@ -0,0 +1,62 @@ +#include "ImageApplyFilter.h" + +CImageApplyFilter::CImageApplyFilter(FilterMode type) + : m_type(type) +{ + m_kSize = (m_type == FilterMode::Sharpen || m_type == FilterMode::AverBlur) ? 5 : 9; +} + +CImageApplyFilter::~CImageApplyFilter() +{ +} + +void CImageApplyFilter::apply(cv::Mat & pDib, int side) +{ +#ifdef LOG + FileTools::write_log("imgprc.txt", "enter CImageApplySharpen apply"); +#endif // LOG + + switch (m_type) + { + case FilterMode::Sharpen: + case FilterMode::Sharpen_More: + sharpen(pDib, m_kSize); + break; + case FilterMode::AverBlur: + case FilterMode::AverBlur_More: + averblur(pDib, static_cast(m_kSize)); + break; + } + +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplySharpen apply"); +#endif // LOG +} + +void CImageApplyFilter::apply(std::vector& mats, bool isTwoSide) +{ + if (mats.empty()) return; + + if (!mats[0].empty()) + apply(mats[0], 0); + + if (isTwoSide && mats.size() > 1) + { + if (!mats[1].empty()) + apply(mats[1], 1); + } +} + +void CImageApplyFilter::averblur(cv::Mat& src, int kSize) +{ + cv::blur(src, src, cv::Size(kSize, kSize)); +} + +void CImageApplyFilter::sharpen(cv::Mat& src, float kSize) +{ + float other = (1.0f - kSize) / 4; + float kernel_data[] = { 0, other, 0, other, kSize, other, 0, other, 0 }; + cv::Mat kernel(3, 3, CV_32FC1, kernel_data); + + cv::filter2D(src, src, src.depth(), kernel); +} \ No newline at end of file diff --git a/ImageProcess/ImageApplyFilter.h b/ImageProcess/ImageApplyFilter.h new file mode 100644 index 0000000..9f7e807 --- /dev/null +++ b/ImageProcess/ImageApplyFilter.h @@ -0,0 +1,49 @@ +/* + * ==================================================== + + * ܣ˾Ŀǰ񻯡ǿ񻯡ģͼǿģ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + + +#ifndef IMAGE_APPLY_FILTER_H +#define IMAGE_APPLY_FILTER_H + +#include "ImageApply.h" + +class CImageApplyFilter : public CImageApply +{ +public: + enum FilterMode + { + None, + Sharpen, + Sharpen_More, + AverBlur, + AverBlur_More + }; + + /* + * sharpentype [in]:˾ģʽ + */ + CImageApplyFilter(FilterMode type); + + virtual ~CImageApplyFilter(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); +private: + void averblur(cv::Mat& src, int kSize); + void sharpen(cv::Mat& src, float kSize); +private: + int m_type; + float m_kSize; +}; + +#endif // !IMAGE_APPLY_SHARPEN_H diff --git a/ImageProcess/ImageApplyHSVCorrect.cpp b/ImageProcess/ImageApplyHSVCorrect.cpp new file mode 100644 index 0000000..4b558a8 --- /dev/null +++ b/ImageProcess/ImageApplyHSVCorrect.cpp @@ -0,0 +1,144 @@ +#include "ImageApplyHSVCorrect.h" +#include + +CImageApplyHSVCorrect::CImageApplyHSVCorrect() + : m_table(new uint[256 * 256 * 256]) +{ + initLUT(); +} + +CImageApplyHSVCorrect::CImageApplyHSVCorrect(CorrectOption mode) + : m_table(new uint[256 * 256 * 256]) +{ + initLUT(); + switch (mode) + { + case CImageApplyHSVCorrect::Red_Removal: + set_HSV_value(std::pair(0, 63), std::pair(20, 255), std::pair(160, 255), 0x00FFFFFF); + set_HSV_value(std::pair(191, 255), std::pair(20, 255), std::pair(160, 255), 0x00FFFFFF); + break; + default: + break; + } +} + +CImageApplyHSVCorrect::~CImageApplyHSVCorrect() +{ + delete [] m_table; +} + +void CImageApplyHSVCorrect::apply(cv::Mat &pDib, int side) +{ + (void)side; + if (pDib.empty() || pDib.channels() != 3) return; + + uchar* src = pDib.data; + cv::Mat z = cv::Mat::zeros(pDib.size(), CV_8UC3); + uchar* dst = z.data; + + int total = pDib.total(); +#pragma omp parallel for + for (int i = 0; i < total; i++) + { + int offset = i * 3; + int index = *reinterpret_cast(src + offset) & 0x00ffffff; + uint color = m_table[index]; + *reinterpret_cast(dst + offset) |= color; + } + pDib = z; +} + +void CImageApplyHSVCorrect::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} + +void CImageApplyHSVCorrect::initLUT() +{ +#if 0 + uchar h, s, v; +#endif + for (uint b = 0; b < 256; b++) + for (uint g = 0; g < 256; g++) + for (uint r = 0; r < 256; r++) + { +#if 0 + RGB_2_HSV_full(r, g, b, h, s, v); + + uint index = b | (g << 8) | (r << 16); + if (h < 12 || h > 245) + m_table[index] = index & 0x00ffffff; + else + m_table[index] = (v | (v << 8) | (v << 16)) & 0x00ffffff; +#else + m_table[b | (g << 8) | (r << 16)] = b | (g << 8) | (r << 16); +#endif + } +} + +void CImageApplyHSVCorrect::set_single(const uint src_b, const uint src_g, const uint src_r, + const uint dst_b, const uint dst_g, const uint dst_r) +{ + m_table[src_b | (src_g << 8) | (src_r << 16)] = dst_b | (dst_g << 8) | (dst_r << 16); +} + +void CImageApplyHSVCorrect::set_HSV_value(const std::pair& range_h, + const std::pair& range_s, + const std::pair& range_v, + uint bgr) +{ + uchar h, s, v; + for (int b = 0; b < 256; b++) + for (int g = 0; g < 256; g++) + for (int r = 0; r < 256; r++) + { + RGB_2_HSV_full(r, g, b, h, s, v); + if (contained(h, range_h) && contained(s, range_s) && contained(v, range_v)) + m_table[(b | (g << 8) | (r << 16)) & 0x00ffffff] = bgr & 0x00ffffff; + } +} + +void CImageApplyHSVCorrect::set_table(const uint* table) +{ + memcpy(m_table, table, 256 * 256 * 256); +} + +bool CImageApplyHSVCorrect::contained(uchar value, const std::pair &range) +{ + return value >= range.first && value <= range.second; +} + +void CImageApplyHSVCorrect::RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v) +{ + int minn = cv::min(r, cv::min(g, b)); + int maxx = cv::max(r, cv::max(g, b)); + v = static_cast(maxx); //V + + int delta = maxx - minn; + float _h; + if (maxx == 0) + { + h = s = v = 0; + return; + } + else + s = static_cast(delta * 255 / maxx); + + if (r == maxx) + _h = static_cast(g - b) / static_cast(delta); + else if (g == maxx) + _h = 2 + static_cast(b - r) / static_cast(delta); + else + _h = 4 + static_cast(r - g) / static_cast(delta); + + float __h = _h * 42.6666666667f; + h = (__h >= 0) ? static_cast(__h) : static_cast(__h + 256); +} diff --git a/ImageProcess/ImageApplyHSVCorrect.h b/ImageProcess/ImageApplyHSVCorrect.h new file mode 100644 index 0000000..8816d13 --- /dev/null +++ b/ImageProcess/ImageApplyHSVCorrect.h @@ -0,0 +1,87 @@ +/* + * ==================================================== + + * ܣɫͼɫУLUTʵ֣ԤBGRֵHVSBGRԭͼвֵУ + * ߣά + * ʱ䣺2020/3/21 + * ޸ʱ䣺v1.0 2020/3/21 + v1.1 2020/6/15 ЧHSVȡֵΧ + * 汾ţv1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_COLOR_CORRECT_H +#define IMAGE_APPLY_COLOR_CORRECT_H + +#include "ImageApply.h" + +class CImageApplyHSVCorrect : public CImageApply +{ +public: + enum CorrectOption + { + Red_Removal //ɫɫH:[0, 85][170, 255],S:[10, 255],V:[120,255] + }; +public: + + CImageApplyHSVCorrect(); + + /* + * mode [in]:Ԥɫģʽ + */ + CImageApplyHSVCorrect(CorrectOption mode); + + virtual ~CImageApplyHSVCorrect(); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + /* + * ܣʼֵRGBRڸλBڵλ32λݽֵһ¡ + Χ[00x00FFFFFF]ڹ캯лĬϵøú + */ + void initLUT(); + + /* + * ܣֵָRGBֵΪĿֵ + = src_b | (src_g << 8) | (src_r << 16) + ֵ = dst_b | (dst_g << 8) | (dst_r << 16) + * src_b:[in] ԭֵBͨ + * src_g:[in] ԭֵGͨ + * src_r:[in] ԭֵRͨ + * dst_b:[in] ĿֵBֵͨ + * dst_g:[in] ĿֵGֵͨ + * dst_r:[in] ĿֵRֵͨ + */ + void set_single(const uint src_b, const uint src_g, const uint src_r, + const uint dst_b, const uint dst_g, const uint dst_r); + /* + * ܣHSVɫʿռɫʷΧ÷ΧӦBGRΪ0x00FFFFFF(Ĭϰɫ + * range_h:[in] HΧȡֵΧ[0, 255] + * range_s:[in] SΧȡֵΧ[0, 255] + * range_v:[in] VΧȡֵΧ[0, 255] + * bgr:[in] uintʾBGRֵBڵλRڸλ + */ + void set_HSV_value(const std::pair& range_h, + const std::pair& range_s, + const std::pair& range_v, + uint bgr = 0x00FFFFFF); + + /* + * ܣⲿֵĬϳΪ 256 * 256 * 256 * sizeof(uint + * table:[in] ָ + */ + void set_table(const uint* table); + +private: + static bool contained(uchar value, const std::pair& range); + + static void RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v); + +private: + uint* m_table; +}; + +#endif diff --git a/ImageProcess/ImageApplyHeaders.h b/ImageProcess/ImageApplyHeaders.h new file mode 100644 index 0000000..9fbe375 --- /dev/null +++ b/ImageProcess/ImageApplyHeaders.h @@ -0,0 +1,29 @@ +#ifndef IMAGE_APPLY_HEADER_H +#define IMAGE_APPLY_HEADER_H + +#include "ImageApply.h" +#include "ImageApplyAdjustColors.h" +#include "ImageApplyAutoCrop.h" +#include "ImageApplyBWBinaray.h" +#include "ImageApplyChannel.h" +#include "ImageApplyCrop.h" +#include "ImageApplyDiscardBlank.h" +#include "ImageApplyOutHole.h" +#include "ImageApplyDogEarDetection.h" +#include "ImageApplyResize.h" +#include "ImageApplyRotation.h" +#include "ImageApplySharpen.h" +#include "ImageApplyConcatenation.h" +#include "ImageApplyHSVCorrect.h" +#include "ImageApplyDetachNoise.h" +#include "ImageApplyColorRecognition.h" +#include "ImageApplyCustomCrop.h" +#include "ImageApplyCustomGamma.h" +#include "ImageApplyRefuseInflow.h" +#include "ImageApplyTextureRemoval.h" +#include "ImageApplyFilter.h" +#include "ImageApplySplit.h" +#include "ImageApplyAutoContrast.h" +#include "ImageMulti.h" +#include "ImageMultiOutputRed.h" +#endif diff --git a/ImageProcess/ImageApplyMarkCrop.cpp b/ImageProcess/ImageApplyMarkCrop.cpp new file mode 100644 index 0000000..53b68c9 --- /dev/null +++ b/ImageProcess/ImageApplyMarkCrop.cpp @@ -0,0 +1,315 @@ +#include "ImageApplyMarkCrop.h" +#include "ImageProcess_Public.h" + +#define RE 2 +//#define DRAW + +#ifdef NOT_USE + + + +CImageApplyMarkCrop::CImageApplyMarkCrop(CImageApplyMarkCrop::DeviceModel device, bool isCropped, double threshold, int noise, CImageApplyMarkCrop::DPI dpi, DirectionMethod direction) + : m_device(device) + , m_b_isCropped(isCropped) + , m_threshold(120) + , m_noise(noise) + , m_dpi(dpi) + , m_range(30, 55) + , m_direction(direction) +{ + +} + +int CImageApplyMarkCrop::apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle) +{ + if (src.empty()) return -1; + + cv::Mat src_resize; + if (m_device == DeviceModel::G400) + cv::resize(src, src_resize, cv::Size(src.cols / RE, src.rows / RE)); + else + cv::resize(src, src_resize, cv::Size(src.cols / 3, src.rows / RE)); + cv::Mat scale_mat; + cv::Mat thre(src_resize.size(), CV_8UC1); + hg::threshold_Mat(src_resize, thre, m_threshold); + +#ifdef DRAW + cv::imwrite("thre.bmp", thre); +#endif + std::vector hierarchy; + std::vector> contours; + + hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); + std::vector maxContour = hg::getMaxContour(contours, hierarchy); + + float scale = m_device == DeviceModel::G300 ? 3 : RE; + + if (maxContour.size() == 0) + { + thre.release(); + return -1; + } + + //thre.release(); + //dst.release(); + + cv::RotatedRect rect = hg::getBoundingRect(maxContour); + + cv::Point2f vertex[4]; + rect.points(vertex); + + std::vector> marks; + std::vector rrects; + + hg::threshold_Mat(src_resize, thre, m_threshold); + cv::bitwise_not(thre, thre); + contours.clear(); + hierarchy.clear(); + hg::findContours(thre, contours, hierarchy, cv::RETR_LIST); + findMarks(contours, rect, cv::Range(m_range.start / RE, m_range.end / RE), marks, rrects); + + if (marks.size() < 3) return -2; + +#ifdef DRAW + for (int i = 0; i < marks.size(); i++) + cv::circle(thre, marks[i][0], 30, cv::Scalar(255)); + cv::imwrite("contour.bmp", thre); +#endif + + maxContour.clear(); + for (const std::vector& mark : marks) + for (const cv::Point& p : mark) + maxContour.push_back(p); + + if (rrects.size() == 3) + { + double distance1 = hg::distanceP2P(rrects[0].center, rrects[1].center); + double distance2 = hg::distanceP2P(rrects[1].center, rrects[2].center); + double distance3 = hg::distanceP2P(rrects[2].center, rrects[0].center); + + if (distance1 > distance2 && distance1 > distance3) + maxContour.push_back(((rrects[0].center + rrects[1].center) / 2 * 3 - rrects[2].center) / 2); + else if (distance2 > distance1 && distance2 > distance3) + maxContour.push_back(((rrects[1].center + rrects[2].center) / 2 * 3 - rrects[0].center) / 2); + else + maxContour.push_back(((rrects[2].center + rrects[0].center) / 2 * 3 - rrects[1].center) / 2); + } + + for (cv::Point& item : maxContour) + item *= scale; + + rect = hg::getBoundingRect(maxContour); + rect.points(vertex); + + cv::Point2f focus; + Orientation ori; + + for (size_t i = 0; i < rrects.size(); i++) + for (size_t j = i + 1; j < rrects.size(); j++) + if (rrects[i].size.area() < rrects[j].size.area()) + { + cv::RotatedRect rect_remp = rrects[j]; + rrects[j] = rrects[i]; + rrects[i] = rect_remp; + } + + for (cv::RotatedRect& item : rrects) + item.center *= scale; + + if (m_direction == DirectionMethod::Multilateral) + { + if (rrects.size() < 4) return -3; + + for (int i = 0; i < 5; i++) + focus += rrects[i].center; + focus /= 5; + + float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]); + float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]); + float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]); + float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]); + + float dis_min = cv::min(dis_top, cv::min(dis_bottom, cv::min(dis_left, dis_right))); + if (dis_top == dis_min) + ori = Top_RB; + else if (dis_bottom == dis_min) + ori = Bottom_LT; + else if (dis_left == dis_min) + ori = Left_RT; + else + ori = Right_LB; + } + else if (m_direction == DirectionMethod::Trilateral_7Net) + { + for (int i = 0; i < 3; i++) + focus += rrects[i].center; + focus /= 3; + + float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]); + float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]); + float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]); + float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]); + + float dis_min_lr = cv::min(dis_left, dis_right); + float dis_min_tb = cv::min(dis_top, dis_bottom); + if (dis_min_lr == dis_right && dis_min_tb == dis_bottom) + ori = Bottom_LT; + else if (dis_min_lr == dis_left && dis_min_tb == dis_top) + ori = Top_RB; + else if (dis_min_lr == dis_right && dis_min_tb == dis_top) + ori = Right_LB; + else + ori = Left_RT; + } + + cv::Point2f srcTri[4]; + cv::Point2f dstTri[3]; + rect.points(srcTri); + + if (m_device == DeviceModel::G300) + for (cv::Point2f& p : srcTri) + p.y = p.y * RE / m_device; + + cv::Size temp_size; + float width = rect.size.width; + float height = hg::distanceP2P(srcTri[0], srcTri[1]); + if (markOri == Default || markOri == ori) + { + dstTri[0] = cv::Point2f(0, height - 1); + dstTri[1] = cv::Point2f(0, 0); + dstTri[2] = cv::Point2f(width - 1, 0); + temp_size.width = width; + temp_size.height = height; + angle = 0; + } + else if (markOri - ori == -3 || markOri - ori == 1) + { + dstTri[0] = cv::Point2f(0, 0); + dstTri[1] = cv::Point2f(height - 1, 0); + dstTri[2] = cv::Point2f(height - 1, width - 1); + temp_size.width = height; + temp_size.height = width; + angle = -90; + } + else if (markOri - ori == -2 || markOri - ori == 2) + { + dstTri[0] = cv::Point2f(width - 1, 0); + dstTri[1] = cv::Point2f(width - 1, height - 1); + dstTri[2] = cv::Point2f(0, height - 1); + temp_size.width = width; + temp_size.height = height; + angle = 180; + } + else if (markOri - ori == -1 || markOri - ori == 3) + { + dstTri[0] = cv::Point2f(height - 1, width - 1); + dstTri[1] = cv::Point2f(0, width - 1); + dstTri[2] = cv::Point2f(0, 0); + temp_size.width = height; + temp_size.height = width; + angle = 90; + } + + if (m_b_isCropped) + { + cv::Mat warp_mat; + warp_mat = cv::getAffineTransform(srcTri, dstTri); + cv::warpAffine(src, dst, warp_mat, temp_size); + } + else + { + if (angle == 0) + dst = src.clone(); + else if (angle == 90) + { + cv::transpose(src, dst); + cv::flip(dst, dst, 0); + } + else if (angle == -90) + { + cv::transpose(src, dst); + cv::flip(dst, dst, 1); + } + else + { + cv::flip(src, dst, 0); + cv::flip(dst, dst, 1); + } + } + + //Ҫж + if (barCode) + { + //cv::imwrite("dst.bmp", dst); + if (dst.cols < 600 || dst.rows < 400) + return -4; + if (!isContainBarCode(dst(cv::Rect(0, 0, 600, 400)))) + return -5; + } + + return 0; + +#ifdef DRAW + cv::imwrite("dst.bmp", dst); +#endif +} + +void CImageApplyMarkCrop::findMarks(const std::vector>& contours, const cv::RotatedRect& region, + const cv::Range& range, std::vector>& marks, std::vector& rrect) +{ + cv::RotatedRect region_outside = region; + cv::RotatedRect region_inside = region; + region_inside.size = cv::Size2f(region.size.width * 0.9, region.size.height * 0.9); + + cv::Point2f outside[4], inside[4]; + region_outside.points(outside); + region_inside.points(inside); + + std::vector v_outside, v_inside; + for (size_t i = 0; i < 4; i++) + { + v_outside.push_back(cv::Point(outside[i].x, outside[i].y)); + v_inside.push_back(cv::Point(inside[i].x, inside[i].y)); + } + for (size_t i = 0, length = contours.size(); i < length; i++) + { + std::vector contour = contours[i]; + cv::RotatedRect rect = cv::minAreaRect(contour); + double area = cv::contourArea(contour); + + if (rect.size.width < range.start || rect.size.height < range.start || rect.size.width > range.end || rect.size.height > range.end) + continue; + if (rect.size.width * rect.size.height < 40 / RE) + continue; + + if (cv::pointPolygonTest(v_outside, rect.center, true) > 0 && cv::pointPolygonTest(v_inside, rect.center, true) < 0) + { + marks.push_back(contour); + rrect.push_back(rect); + } + } +} + +bool CImageApplyMarkCrop::isContainBarCode(const cv::Mat& image) +{ + cv::Mat thre; + hg::threshold_Mat(image, thre, 127); + cv::bitwise_not(thre, thre); + + cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(20, 1)); + cv::morphologyEx(thre, thre, cv::MorphTypes::MORPH_DILATE, element); + //cv::imwrite("barCode.bmp", thre); + + std::vector hierarchy; + std::vector> contours; + hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); + + for (size_t i = 0; i < contours.size(); i++) + { + cv::Rect rect = cv::boundingRect(contours[i]); + if (rect.width > 250 && rect.height > 50) + return true; + } + return false; +} +#endif // \ No newline at end of file diff --git a/ImageProcess/ImageApplyMarkCrop.h b/ImageProcess/ImageApplyMarkCrop.h new file mode 100644 index 0000000..6907c17 --- /dev/null +++ b/ImageProcess/ImageApplyMarkCrop.h @@ -0,0 +1,116 @@ +/* + * ==================================================== + + * ���ܣ�Mark�㶨λ�ü���ʶ���Ծ��е�mark�㣬���о�ƫ�ü����ù��ܲ�����ȫ����ʹ�ã���Ϊ���ܻ�ʶ��ʧ�ܣ�Ȼ����Ҫ�����ô�ͳ�ü���ƫ���в��䡣 + * ���ߣ�����ά + * ����ʱ�䣺2020/5/22 + * ����޸�ʱ�䣺2020/5/22 v1.0 + 2020/7/29 v1.1 �Ż�Mark��ʶ���Լ��ĸ巽���ж� + 2020/7/30 v1.1.1 �Ż�Mark��ʶ���Լ��ĸ巽���ж� + 2020/8/3 v1.2 ������죬������Mark��ʶ���ĸ巽��ԭ���ķ�ʽ����Ϊ���ʶ���ĸ巽�� + 2020/8/12 v1.3 ������죬�����������ж��㷨�������ж��Ծ��Ƿ�Ϊָ���Ծ���������ֻ�Ǵ���ʶ���Ƿ������룬��������׼ȷʶ�� + apply�ӿ�����barCode�����������Ƿ������ж����빦�� + 2020/8/12 v1.4 ������죬���Ӳü��ӿڣ��ɽ��вü��벻�ü�����ѡ�� + * �汾�ţ�v1.4 + + * ==================================================== + */ + +#ifndef IMAGEMARKCROPAPPLY_H +#define IMAGEMARKCROPAPPLY_H + +#include "ImageApply.h" + +class CImageApplyMarkCrop +{ +public: + + //ʶ���ĸ巽��ʽ + enum DirectionMethod + { + Trilateral_7Net, //���߶�λ�ĸ巽������������� + Multilateral //��߶�λ�ĸ巽�� + }; + + enum DPI : ushort + { + DPI_200 = 200, + DPI_300 = 300 + }; + + enum DeviceModel + { + G400 = 2, + G300 = 3 + }; + + enum Orientation + { + Default = 0, + Left_RT, //����ĸ巽��ʶ��ʱ����Ϊ����7��3markʶ��ʱ��ȱ��������Ϊ�� + Top_RB, //����ĸ巽��ʶ��ʱ����Ϊ����7��3markʶ��ʱ��ȱ��������Ϊ�� + Right_LB, //����ĸ巽��ʶ��ʱ����Ϊ����7��3markʶ��ʱ��ȱ��������Ϊ�� + Bottom_LT //����ĸ巽��ʶ��ʱ����Ϊ����7��3markʶ��ʱ��ȱ��������Ϊ�� + }; + +public: + CImageApplyMarkCrop(DeviceModel device, bool isCropped = true, double threshold = 20, int noise = 40, DPI dpi = DPI::DPI_200, DirectionMethod direction = DirectionMethod::Multilateral); + + /* + * src [in]: ԭͼ + * dst [out]:�����ɹ�ʱ�����صĽ��ͼ�� + * markOri [in]: �ĸ巽���ж���ʽ + * barCode [in]: �Ƿ��ж������룬�ù���ֻ���Trilateral_7Netģʽ + * angle [out]:�����ĸ巽��ƫת�Ƕȡ���0��90��180��270������� + * ����ֵ�� 0���ɹ��� + -1��ԭͼΪ�գ������޷��ҵ�ͼƬ����������ͼ�ᱨ�ô��󣩣� + -2��markС��3�� + -3��ѡ��Multilateralģʽʱ��mark��С��4�� + -4��ʶ��������ʱ��Ŀ��ͼ���С���޷����������� + -5���������� + */ + int apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle); + + inline DeviceModel getDeviceModel() { return m_device; } + + inline void setDeviceModel(DeviceModel device) { m_device = device; } + + inline bool isCropped() { return m_b_isCropped; } + + inline void setCropped(bool cropped) { m_b_isCropped = cropped; } + + inline double getThreshold() { return m_threshold; } + + inline void setThreshold(double threshold) { m_threshold = threshold; } + + inline int getNoise() { return m_noise; } + + inline void setNoise(int noise) { m_noise = noise; } + + inline DPI getDPI() { return m_dpi; } + + inline void setDPI(DPI dpi) { m_dpi = dpi; } + + inline const cv::Range getSizeRange() { return m_range; } + + inline void setSizeRange(const cv::Range& range) { m_range = range; } + + inline void setSizeRange(int low, int up) { m_range = cv::Range(low, up); } + +private: + + void findMarks(const std::vector>& contours, const cv::RotatedRect& region, const cv::Range& range, + std::vector>& marks, std::vector& rrect); + + bool isContainBarCode(const cv::Mat& image); +private: + DeviceModel m_device; + bool m_b_isCropped; + double m_threshold; + int m_noise; + DPI m_dpi; + cv::Range m_range; + DirectionMethod m_direction; +}; + +#endif // IMAGEMARKCROPAPPLY_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyOutHole.cpp b/ImageProcess/ImageApplyOutHole.cpp new file mode 100644 index 0000000..c9945e6 --- /dev/null +++ b/ImageProcess/ImageApplyOutHole.cpp @@ -0,0 +1,257 @@ +#include "ImageApplyOutHole.h" +#include "ImageProcess_Public.h" + +#ifdef LOG +#include "Device/filetools.h" +#endif // LOG + +CImageOutHole::CImageOutHole(void) + : CImageApply() + , m_borderSize(200) + , m_edgeScale(0.1f) + , m_threshold(50) +{ +} + +CImageOutHole::CImageOutHole(float borderSize, float edgeScale, double threshold) + : CImageApply() + , m_borderSize(borderSize) + , m_edgeScale(edgeScale) + , m_threshold(threshold) +{ +} + +CImageOutHole::~CImageOutHole(void) +{ +} + +void CImageOutHole::apply(cv::Mat& pDib, int side) +{ + (void)pDib; + (void)side; +} + +void CImageOutHole::apply(std::vector& mats, bool isTwoSide) +{ +#ifdef LOG + FileTools::write_log("imgprc.txt", "enter ImageOutHole apply"); +#endif // LOG + + if (mats.size() < 2) + { +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); +#endif // LOG + return; + } + + if (mats[0].empty() || mats[1].empty()) + { +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); +#endif // LOG + return; + } + + //ֵͼ + cv::Mat front = mats[0]; + cv::Mat back = mats[1]; + cv::Mat front_thre, back_thre; + hg::threshold_Mat(front, front_thre, m_threshold); + hg::threshold_Mat(back, back_thre, m_threshold); + + //ֵͼˮƽת + cv::flip(back_thre, back_thre, 1); //1:Horizontal + + //ͼѰ + std::vector> contours_front, contours_back; + std::vector b1_front, b1_back; + hg::findContours(front_thre.clone(), contours_front, b1_front, cv::RETR_EXTERNAL); + hg::findContours(back_thre.clone(), contours_back, b1_back, cv::RETR_EXTERNAL); + + //ȡͼ + std::vector maxContour_front = hg::getMaxContour(contours_front, b1_front); + std::vector maxContour_back = hg::getMaxContour(contours_back, b1_back); + + cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //ȡСӾ + cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //ȡСӾ + + //ȡͼص + cv::Rect roi_front, roi_back; + cv::RotatedRect mask_rotatedRect; + getRoi(rrect_front, rrect_back, cv::Size(front.cols, front.rows), roi_front, roi_back, mask_rotatedRect); + + cv::Mat roiMat_front(front_thre, roi_front); //ֵͼнȡص + cv::Mat roiMat_back(back_thre, roi_back); //ڷֵͼнȡص + + //ֵͼ㣬ο0طΪ255 + cv::Mat mask; + bitwise_or(roiMat_front, roiMat_back, mask); //㣬ֵͼص + + //ֵͼصͼɫȡͣȡ + std::vector> contours_mask; + std::vector b1_mask; + bitwise_not(mask, mask); //ɫ + + cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(15, 15)); + dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //㷨׶ͨ + + //Ϊ˱׶׹ᴩֽߣΪֽȷп׶ΪͼΣ뱳ճ + polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), 15); //ֽžαԵ + + hg::findContours(mask.clone(), contours_mask, b1_mask, cv::RETR_TREE); //ȡصͼ + + //˷ǿ׶ͨ + std::vector> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize); + for (size_t i = 0; i < hole_contours.size(); i++) + cv::drawContours(mask, hole_contours, static_cast(i), cv::Scalar(127), 2); + + for (size_t i = 0; i < hole_contours.size(); i++) + { + cv::Scalar color = getBackGroudColor(front(roi_front), hole_contours[i]); + cv::Mat temp = front(roi_front); + std::vector> contourss_temp; + contourss_temp.push_back(hole_contours[i]); + hg::fillPolys(temp, contourss_temp, color); + } + + if (isTwoSide) + { + int width_ = roi_back.width; + roi_back.x = back.cols - roi_back.width - roi_back.x; //Ϊ֮ǰͼתROIҲҪӦת + for (size_t i = 0; i < hole_contours.size(); i++) + { + std::vector hole_contour; + for (size_t j = 0; j < hole_contours[i].size(); j++) + hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y)); + + cv::Scalar color = getBackGroudColor(back(roi_back), hole_contour); + cv::Mat temp = back(roi_back); + + std::vector> contours_temp; + contours_temp.push_back(hole_contour); + hg::fillPolys(temp, contours_temp, color); + } + } +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); +#endif // LOG +} + +void CImageOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, + cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect) +{ + cv::Size size(static_cast(rrect_front.size.width + rrect_back.size.width) / 2, static_cast(rrect_front.size.height + rrect_back.size.height) / 2); + float angle = (rrect_front.angle + rrect_back.angle) / 2; + + rrect_front.size = rrect_back.size = size; + rrect_front.angle = rrect_back.angle = angle; + + roi_front = rrect_front.boundingRect(); + roi_back = rrect_back.boundingRect(); + + if (roi_front.width != roi_back.width || roi_front.height != roi_back.height) + { + roi_front.height = roi_back.height; + roi_front.width = roi_back.width; + } + + cv::Point offset(0, 0); + int top = std::min(roi_front.y, roi_back.y); + if (top < 0) + { + roi_front.y -= top; + roi_back.y -= top; + roi_front.height += top; + roi_back.height += top; + offset.y += top; + } + + int left = std::min(roi_front.x, roi_back.x); + if (left < 0) + { + roi_front.x -= left; + roi_back.x -= left; + roi_front.width += left; + roi_back.width += left; + offset.x += left; + } + + int right = std::max(roi_front.x + roi_front.width, roi_back.x + roi_back.width); + if (right >= srcSize.width) + { + roi_front.width -= (right - srcSize.width + 1); + roi_back.width -= (right - srcSize.width + 1); + } + + int bottom = std::max(roi_front.y + roi_front.height, roi_back.y + roi_back.height); + if (bottom >= srcSize.height) + { + roi_front.height -= (bottom - srcSize.height + 1); + roi_back.height -= (bottom - srcSize.height + 1); + } + + mask_rotatedRect.center = cv::Point((roi_front.width + offset.x) / 2, (roi_front.height + offset.y) / 2); + mask_rotatedRect.size = size; + mask_rotatedRect.angle = angle; +} + +std::vector> CImageOutHole::filterPoly(std::vector>& contours, const std::vector& m, + cv::RotatedRect roi, float edgeScale, float areaThreshold) +{ + edgeScale = std::min(0.49f, std::max(edgeScale, 0.0f)); + cv::RotatedRect roi2(roi.center, cv::Size(static_cast(roi.size.width * (1 - edgeScale * 2)), + static_cast(roi.size.height * (1 - edgeScale * 2))), roi.angle); + + std::vector vertices_roi1 = hg::getVertices(roi); + std::vector vertices_roi2 = hg::getVertices(roi2); + + std::vector> hole_contours; + for (size_t i = 0, length = contours.size(); i < length; i++) + { + if (m[i][2] != -1) continue; + + cv::RotatedRect rrect = hg::getBoundingRect(contours[i]); + if (rrect.size.width > areaThreshold || rrect.size.height > areaThreshold) continue; + + bool enabled = true; + for (size_t j = 0, count = contours[i].size(); j < count; j++) + { + cv::Point p(contours[i][j]); + double temp1 = pointPolygonTest(vertices_roi1, p, false); //жǷֽ 1ڣ0ϣ-1 + double temp2 = pointPolygonTest(vertices_roi2, p, false); //жǷڱԵ 1ڣ0ϣ-1 + //ֽ⣬߱ԵڣΪǿ׶ + if (temp1 < 0 || temp2 > 0) + { + enabled = false; + break; + } + } + + if (enabled) + hole_contours.push_back(contours[i]); + } + return hole_contours; +} + +cv::Scalar CImageOutHole::getBackGroudColor(const cv::Mat &image, const std::vector pixelPoints) +{ + if (pixelPoints.empty()) return cv::Scalar(255, 255, 255); + + int channels = image.channels(); + + int temp[3] = { 0 }; + for (size_t i = 0, length = pixelPoints.size(); i < length; ++i) + { + int x = cv::min(cv::max(0, pixelPoints[i].x), image.cols - 1); + int y = cv::min(cv::max(0, pixelPoints[i].y), image.rows - 1); + + const unsigned char* ptr = image.ptr(y, x); + for (int j = 0; j < channels; ++j) + temp[j] += ptr[j]; + } + + return cv::Scalar(temp[0] / static_cast(pixelPoints.size()), + temp[1] / static_cast(pixelPoints.size()), + temp[2] / static_cast(pixelPoints.size())); +} diff --git a/ImageProcess/ImageApplyOutHole.h b/ImageProcess/ImageApplyOutHole.h new file mode 100644 index 0000000..9ed49b3 --- /dev/null +++ b/ImageProcess/ImageApplyOutHole.h @@ -0,0 +1,49 @@ +#ifndef IMAGE_APPLY_OUT_HOLE_H +#define IMAGE_APPLY_OUT_HOLE_H + +#include "ImageApply.h" + +class CImageOutHole : public CImageApply +{ + +public: + + CImageOutHole(); + + CImageOutHole(float borderSize, float edgeScale, double threshold); + + ~CImageOutHole(void); + + virtual void apply(std::vector& mats, bool isTwoSide); + + float getBorderSize() { return m_borderSize; } + + float getEdgeScale() { return m_edgeScale; } + + double getThreshold() { return m_threshold; } + + void setBorderSize(float size) { m_borderSize = size; } + + void setEdgeScale(float scale) { m_edgeScale = scale; } + + void setThreshold(double threshold) { m_threshold = (std::min)((std::max)(threshold, 1.0), 254.0); } + +private: + + virtual void apply(cv::Mat& pDib, int side); + + void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, cv::Rect& roi_front, + cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect); + + std::vector > filterPoly(std::vector>& contours, const std::vector &m, cv::RotatedRect roi, + float edgeScale, float areaThreshold); + + cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector pixelPoints); + +private: + float m_borderSize; + float m_edgeScale; + double m_threshold; +}; + +#endif // !IMAGE_APPLY_OUT_HOLE_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyRefuseInflow.cpp b/ImageProcess/ImageApplyRefuseInflow.cpp new file mode 100644 index 0000000..6b801c3 --- /dev/null +++ b/ImageProcess/ImageApplyRefuseInflow.cpp @@ -0,0 +1,57 @@ +#include "ImageApplyRefuseInflow.h" + +CImageApplyRefuseInflow::CImageApplyRefuseInflow() +{ +} + +CImageApplyRefuseInflow::~CImageApplyRefuseInflow() +{ +} + +void CImageApplyRefuseInflow::apply(cv::Mat& pDib, int side) +{ + (void)side; + static unsigned char table_contrast[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255 }; + static cv::Mat mat_table(1, 256, CV_8UC1, table_contrast); + cv::LUT(pDib, mat_table, pDib); +} + +void CImageApplyRefuseInflow::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyRefuseInflow.h b/ImageProcess/ImageApplyRefuseInflow.h new file mode 100644 index 0000000..0f58e54 --- /dev/null +++ b/ImageProcess/ImageApplyRefuseInflow.h @@ -0,0 +1,29 @@ +/* + * ==================================================== + + * ܣ͸ԭΪ˲ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_REFUSE_INFLOW_H +#define IMAGE_APPLY_REFUSE_INFLOW_H + +#include "ImageApply.h" + +class CImageApplyRefuseInflow : public CImageApply +{ +public: + CImageApplyRefuseInflow(); + + virtual ~CImageApplyRefuseInflow(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); +}; +#endif // !IMAGE_APPLY_REFUSE_INFLOW_H diff --git a/ImageProcess/ImageApplyResize.cpp b/ImageProcess/ImageApplyResize.cpp new file mode 100644 index 0000000..3405eaa --- /dev/null +++ b/ImageProcess/ImageApplyResize.cpp @@ -0,0 +1,47 @@ +#include "ImageApplyResize.h" + +CImageApplyResize::CImageApplyResize() + : m_fx(1.0) + , m_fy(1.0) + , m_type(ResizeType::RATIO) +{ +} + +CImageApplyResize::CImageApplyResize(ResizeType type, const cv::Size& size, double fx, double fy) + : m_type(type) + , m_dSize(size) + , m_fx(fx) + , m_fy(fy) +{ +} + + +CImageApplyResize::~CImageApplyResize(void) +{ +} + + +void CImageApplyResize::apply(cv::Mat& pDib,int side) +{ + (void)side; + if (pDib.empty()) return; + + if (m_type == ResizeType::RATIO) + cv::resize(pDib, pDib, cv::Size(0, 0), m_fx, m_fy); + else + cv::resize(pDib, pDib, m_dSize); +} + +void CImageApplyResize::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyResize.h b/ImageProcess/ImageApplyResize.h new file mode 100644 index 0000000..c4dad8b --- /dev/null +++ b/ImageProcess/ImageApplyResize.h @@ -0,0 +1,57 @@ +#ifndef IMAGE_APPLY_RESIZE_H +#define IMAGE_APPLY_RESIZE_H + +#include "imageapply.h" + +class CImageApplyResize : public CImageApply +{ +public: + + enum class ResizeType + { + RATIO, + DSIZE + }; + +public: + CImageApplyResize(); + + /* + * type [in]: + * size [in]:Ŀߴ磬typeΪDSIZEʱЧ + * fx [in]:ĿtypeΪRATIOʱЧ + * fy [in]:ĿtypeΪRATIOʱЧ + */ + CImageApplyResize(ResizeType type, const cv::Size& size, double fx, double fy); + + virtual ~CImageApplyResize(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + + double getFX() { return m_fx; } + + double getFY() { return m_fy; } + + cv::Size getDSize() { return m_dSize; } + + ResizeType getType() { return m_type; } + + void setFX(double value) { m_fx = value; } + + void setFY(double value) { m_fy = value; } + + void setDSize(const cv::Size& size) { m_dSize = size; } + + void setType(ResizeType type) { m_type = type; } + +private: + double m_fx; + double m_fy; + cv::Size m_dSize; + ResizeType m_type; +}; + +#endif // !IMAGE_APPLY_RESIZE_H \ No newline at end of file diff --git a/ImageProcess/ImageApplyRotation.cpp b/ImageProcess/ImageApplyRotation.cpp new file mode 100644 index 0000000..b7dc359 --- /dev/null +++ b/ImageProcess/ImageApplyRotation.cpp @@ -0,0 +1,131 @@ +#include "ImageApplyRotation.h" +//#define USE_TESSERCAT + +#ifdef USE_TESSERCAT +//#define HG_GPDF_API_BUILD +#include "hg_gpdf.h" +#endif + +CImageApplyRotation::CImageApplyRotation(RotationType rotation, bool isBackTransposed, int dpi, const char* tessdataPath) + : m_rotation(rotation) + , m_backTranspose(isBackTransposed) + , m_dpi(dpi) + , osd(nullptr) +{ + if (rotation == RotationType::AutoTextOrientation) + { +#ifdef USE_TESSERCAT + osd = new HG_OCR(); + reinterpret_cast(osd)->init(tessdataPath, HG_OCR::RECOGNITION_OSD); +#endif + } +} + +CImageApplyRotation::~CImageApplyRotation() +{ +#ifdef USE_TESSERCAT + if (osd) delete reinterpret_cast(osd); +#endif +} + +void CImageApplyRotation::apply(cv::Mat & pDib, int side) +{ +#ifdef LOG + FileTools::write_log("imgprc.txt", "enter CImageApplyRotation apply"); +#endif // LOG + if (pDib.empty()) + { +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply"); +#endif // LOG + return; + } + + if (m_rotation == RotationType::AutoTextOrientation) //�Զ��ı�����ʶ�� + { +#ifdef USE_TESSERCAT + if (osd) + { + cv::Mat temp; + if (m_dpi != 200) + { + double scale = 200 / static_cast(m_dpi); + int new_w = static_cast(pDib.cols * scale) / 4 * 4; + int new_h = pDib.rows * scale; + cv::resize(pDib, temp, cv::Size(new_w, new_h)); + } + else + temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone(); + + if (temp.channels() == 3) + cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY); + cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU); + + HG_OCR* ptr_osd = reinterpret_cast(osd); + int orientation = ptr_osd->orientation(temp.data, temp.cols, temp.rows, temp.channels(), 200); + + switch (orientation) + { + case 90: + cv::transpose(pDib, pDib); + cv::flip(pDib, pDib, 0); + break; + case 180: + cv::flip(pDib, pDib, 0); + cv::flip(pDib, pDib, 1); + break; + case 270: + cv::transpose(pDib, pDib); + cv::flip(pDib, pDib, 1); + break; + default: + break; + } + } +#endif + } + else if (m_backTranspose && side == 1) //������ת180 + { + if (m_rotation != RotationType::Rotate_180) //��ת180�� + { + if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90�� -90�� + { + transpose(pDib, pDib); + flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 1 : 0); + } + else + { + flip(pDib, pDib, 0); + flip(pDib, pDib, 1); + } + } + } + else //zh + { + if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90�� -90�� + { + transpose(pDib, pDib); + flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1); + } + else if (m_rotation == RotationType::Rotate_180) + { + flip(pDib, pDib, 0); + flip(pDib, pDib, 1); + } + } +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply"); +#endif // LOG +} + +void CImageApplyRotation::apply(std::vector& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) { + if (!var.empty()) { + apply(var, i); + i++; + } + } +} diff --git a/ImageProcess/ImageApplyRotation.h b/ImageProcess/ImageApplyRotation.h new file mode 100644 index 0000000..2c70631 --- /dev/null +++ b/ImageProcess/ImageApplyRotation.h @@ -0,0 +1,68 @@ +/* + * ==================================================== + + * ܣתͼ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺v1.0 2020/4/21 + v1.1 2020/8/12 ޸ĸ巽Զʶ±BUG + * 汾ţv1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_ROTATION_H +#define IMAGE_APPLY_ROTATION_H + +#include "ImageApply.h" + +class CImageApplyRotation : public CImageApply +{ +public: + enum class RotationType + { + Invalid, //Ч + Rotate_90_clockwise, //˳ʱ90 + Rotate_180, //180 + Rotate_90_anti_clockwise, //ʱ90㣬270 + + AutoTextOrientation //Զĸ巽ʶת + }; + +public: + + /* + * rotation [in]:ת + * isBackTransposed [in]:trueΪ180ת֮Ȼ + * dpi [in]:ǰͼDPIòrotationΪAutoTextOrientationʱЧʶĸ巽ʱĬϽͼ任Ϊ200DPIʶ + * tessadataPath [in]:ѵļ·òrotationΪAutoTextOrientationʱЧ + */ + CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr); + + virtual ~CImageApplyRotation(); + + virtual void apply(cv::Mat & pDib, int side) override; + + virtual void apply(std::vector& mats, bool isTwoSide); + + bool isBackTransposed() { return m_backTranspose; } + + int getDPI() { return m_dpi; } + + RotationType getRotationType() { return m_rotation; } + + void setBackTransposed(bool enabled) { m_backTranspose = enabled; } + + void setDPI(int dpi) { m_dpi = dpi; } + + void setRotationType(RotationType type) { m_rotation = type; } + +private: + RotationType m_rotation; + bool m_backTranspose; + int m_dpi; + + void* osd; +}; + +#endif // !IMAGE_APPLY_ROTATION_H diff --git a/ImageProcess/ImageApplySharpen.cpp b/ImageProcess/ImageApplySharpen.cpp new file mode 100644 index 0000000..22876ff --- /dev/null +++ b/ImageProcess/ImageApplySharpen.cpp @@ -0,0 +1,61 @@ +#include "ImageApplySharpen.h" +using namespace cv; +CImageApplySharpen::CImageApplySharpen(int sharpentype) +{ + sharpenType = sharpentype; + kSize = (sharpentype == FilterMethod::Sharpen || sharpentype == FilterMethod::AverBlur) ? 5 : 9; +} + +CImageApplySharpen::~CImageApplySharpen() +{ +} + +void CImageApplySharpen::apply(cv::Mat & pDib, int side) +{ +#ifdef LOG + FileTools::write_log("imgprc.txt", "enter CImageApplySharpen apply"); +#endif // LOG + + switch (sharpenType) + { + case CImageApplySharpen::Sharpen: + case CImageApplySharpen::Sharpen_More: + sharpen(pDib, kSize); + break; + case CImageApplySharpen::AverBlur: + case CImageApplySharpen::AverBlur_More: + averblur(pDib, static_cast(kSize)); + break; + } + +#ifdef LOG + FileTools::write_log("imgprc.txt", "exit CImageApplySharpen apply"); +#endif // LOG +} + +void CImageApplySharpen::apply(std::vector& mats, bool isTwoSide) +{ + if (mats.empty()) return; + + if (!mats[0].empty()) + apply(mats[0], 0); + + if (isTwoSide && mats.size() > 1) { + if (!mats[1].empty()) + apply(mats[1], 1); + } +} + +void CImageApplySharpen::averblur(Mat& src, int kSize) +{ + blur(src, src, Size(kSize, kSize)); +} + +void CImageApplySharpen::sharpen(Mat& src, float kSize) +{ + float other = (1.0f - kSize) / 4; + float kernel_data[] = { 0, other, 0, other, kSize, other, 0, other, 0 }; + Mat kernel(3, 3, CV_32FC1, kernel_data); + + filter2D(src, src, src.depth(), kernel); +} diff --git a/ImageProcess/ImageApplySharpen.h b/ImageProcess/ImageApplySharpen.h new file mode 100644 index 0000000..9401b9e --- /dev/null +++ b/ImageProcess/ImageApplySharpen.h @@ -0,0 +1,32 @@ +#ifndef IMAGE_APPLY_SHARPEN_H +#define IMAGE_APPLY_SHARPEN_H + +#include "ImageApply.h" + +class CImageApplySharpen : + public CImageApply +{ +public: + enum FilterMethod + { + None, + Sharpen, + Sharpen_More, + AverBlur, + AverBlur_More + }; + CImageApplySharpen(int sharpentype); + virtual ~CImageApplySharpen(); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); +private: + void averblur(cv::Mat& src, int kSize); + void sharpen(cv::Mat& src, float kSize); +private: + int sharpenType; + float kSize; +}; + +#endif // !IMAGE_APPLY_SHARPEN_H diff --git a/ImageProcess/ImageApplySplit.cpp b/ImageProcess/ImageApplySplit.cpp new file mode 100644 index 0000000..4092342 --- /dev/null +++ b/ImageProcess/ImageApplySplit.cpp @@ -0,0 +1,110 @@ +#include "ImageApplySplit.h" +#include + +#define BPP(type,index) +CImageApplySplit::CImageApplySplit(int multitype,bool split, bool ismulti_filter_red,int colormode) : + m_bmulti_filter_red(ismulti_filter_red) + , m_split(split) + , m_multitype(multitype) + , m_colormode(colormode) +{ +} + +CImageApplySplit::~CImageApplySplit(void) +{ +} + +std::vector CImageApplySplit::SplitMats(std::vector& mats, bool isTwoSide) +{ + std::vector rets; + for (size_t i = 0; i < mats.size(); i++) + { + if (mats[i].empty()) + continue; + int bpp = getBpp(i); + if(m_split)// + { + std::vector retmats = apply(mats[i]); + if (bpp != -1) { + } + else {// + if (m_colormode == 0) bpp = 1;//bw + else if (m_colormode == 1) bpp = 8; + else bpp = 24; + } + + for (size_t j = 0; j < retmats.size(); j++) + { + if (!retmats[j].empty()) { + MatEx matex(retmats[j], bpp); + rets.push_back(matex); + } + } + } + else{ + MatEx matex(mats[i], bpp); + rets.push_back(matex); + } + } + return rets; +} + +std::vector CImageApplySplit::apply(cv::Mat& pDib) +{ + if (pDib.empty()) + return std::vector(); + std::vector retMats; + int heigth = pDib.rows; + int width = pDib.cols; + if (heigth > width) + { + cv::Mat matF = pDib(cv::Rect(0, 0, width, (int)(0.5 * heigth))); + cv::Mat matB = pDib(cv::Rect(0, (int)(0.5 * heigth), width, (int)(0.5 * heigth))); + retMats.push_back(matF); + retMats.push_back(matB); + } + else + { + cv::Mat matF = pDib(cv::Rect(0, 0, (int)(width*0.5), heigth)); + cv::Mat matB = pDib(cv::Rect((int)(width*0.5), 0, (int)(width * 0.5), heigth)); + retMats.push_back(matF); + retMats.push_back(matB); + } + return retMats; +} + +int CImageApplySplit::getBpp(int matIndex) +{ + int ret = -1; + if (m_bmulti_filter_red) { + ret = matIndex == 0 ? 24 : 8; + } + else + { + if (m_multitype == -1) + return ret; + switch (m_multitype) + { + case 0://all + if (matIndex == 0) ret = 24; + else if (matIndex == 1) ret = 8; + else ret = 1; + break; + case 1://clolr +gray + if (matIndex == 0) ret = 24; + else ret = 8; + break; + case 2://color+bw + if (matIndex == 0) ret = 24; + else ret = 1; + break; + case 3://gray+bw + if (matIndex == 0) ret = 8; + else ret = 1; + break; + default: + break; + } + } + return ret; +} diff --git a/ImageProcess/ImageApplySplit.h b/ImageProcess/ImageApplySplit.h new file mode 100644 index 0000000..6ae342a --- /dev/null +++ b/ImageProcess/ImageApplySplit.h @@ -0,0 +1,36 @@ +/* + * ==================================================== + + * ܣͼ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ +#include "IMulti.h" +#ifndef IMAGE_APPLY_SPLIT_H +#define IMAGE_APPLY_SPLIT_H +#include "MatEx.h" +#include +#include "imgprocdefs.h" + +class CImageApplySplit :public IMulti +{ +public: + CImageApplySplit(int multitype=-1,bool split=false,bool ismulti_filter_red=false,int colormode=1);//Ĭϲ Ҷ + + ~CImageApplySplit(void); + std::vector SplitMats(std::vector& mats, bool isTwoSide); +private: + std::vector apply(cv::Mat& pDib); + int getBpp(int matIndex); +private://field + bool m_bmulti_filter_red; + int m_multitype; + int m_colormode; + bool m_split; +}; + +#endif // !IMAGE_APPLY_SPLIT_H diff --git a/ImageProcess/ImageApplyTextureRemoval.cpp b/ImageProcess/ImageApplyTextureRemoval.cpp new file mode 100644 index 0000000..5c42622 --- /dev/null +++ b/ImageProcess/ImageApplyTextureRemoval.cpp @@ -0,0 +1,172 @@ +#include "ImageApplyTextureRemoval.h" + +//Խ +void zero_to_center(cv::Mat& image, int colToCut, int rowToCut) +{ + cv::Mat q1(image, cv::Rect(0, 0, colToCut, rowToCut)); + cv::Mat q2(image, cv::Rect(colToCut, 0, colToCut, rowToCut)); + cv::Mat q3(image, cv::Rect(0, rowToCut, colToCut, rowToCut)); + cv::Mat q4(image, cv::Rect(colToCut, rowToCut, colToCut, rowToCut)); + + //ڶ޺͵޽н + cv::Mat tmpImg; + q1.copyTo(tmpImg); + q4.copyTo(q1); + tmpImg.copyTo(q4); + + //һ޺͵޽н + q2.copyTo(tmpImg); + q3.copyTo(q2); + tmpImg.copyTo(q3); +} + +// +cv::Mat create_spectrum(cv::Mat* matArray, double scale = 1.5) +{ + cv::Mat dst; + cv::magnitude(matArray[0], matArray[1], dst); +#if 1 + cv::divide(dst, dst.cols * dst.rows, dst, scale); + //imshow("Ƶ", dst); +#else + dst += Scalar::all(1); + log(dst, dst); + normalize(dst, dst, 1, 0, CV_MINMAX); +#endif + +#if 0 + imshow("Ƶ", dst); +#endif + return dst; +} + +//Ҷ任 +void inverseFourierTransform(const cv::Mat& src, cv::Mat& dst) +{ + cv::Mat complexIDFT; + cv::Mat matArray[2]; + cv::idft(src, complexIDFT); + cv::split(complexIDFT, matArray); + cv::magnitude(matArray[0], matArray[1], dst); + cv::normalize(dst, dst, 0, 1, CV_MINMAX); +} + +//ݲ˲ +cv::Mat createFilter(const cv::Mat& spectrum, int dilateSize, int erodeSize) +{ + cv::Mat temp; + spectrum.convertTo(temp, CV_8UC1, 255); + cv::threshold(temp, temp, 0, 255, CV_THRESH_OTSU); + //imshow("ֵ", temp); + + cv::Mat element1 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(dilateSize, dilateSize)); + cv::Mat element2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(erodeSize, erodeSize)); + cv::dilate(temp, temp, element1); + cv::erode(temp, temp, element2); + cv::floodFill(temp, cv::Point(temp.cols / 2, temp.rows / 2), cv::Scalar(0)); //ˮ + cv::medianBlur(~temp, temp, 3); //ֵ˲ + //temp = ~temp; + //cv::imshow("ֵ", temp); + + //ݲ˲ + cv::Mat filter; + temp.convertTo(filter, CV_32FC1); + cv::normalize(filter, filter, 1, 0.01, CV_MINMAX); + std::vector mv; + mv.push_back(filter); + mv.push_back(filter); + cv::merge(mv, filter); + + return filter; +} + +void CImageApplyTextureRemoval::textureRemovalGray(cv::Mat& img) +{ + //õDFTѳߴ磨2ָԼټ + cv::Mat paddedImg; + int m = cv::getOptimalDFTSize(img.rows); + int n = cv::getOptimalDFTSize(img.cols); + + //ͼ¶˺Ҷ + cv::copyMakeBorder(img, paddedImg, 0, m - img.rows, 0, n - img.cols, + cv::BORDER_CONSTANT, cv::Scalar::all(0)); + + //ͼһĶά飨ͨMatDFT + cv::Mat matArray[] = { cv::Mat_(paddedImg), cv::Mat::zeros(paddedImg.size(), CV_32F) }; + cv::Mat complexInput, complexOutput; + cv::merge(matArray, 2, complexInput); + cv::dft(complexInput, complexOutput); + cv::split(complexOutput, matArray); //ףҶף + + //˲ + //ʵ鲿Ƶͼķʽλ + //Ƶͼģ˲ + zero_to_center(matArray[0], complexOutput.cols / 2, complexOutput.rows / 2); + zero_to_center(matArray[1], complexOutput.cols / 2, complexOutput.rows / 2); + cv::Mat spectrum = create_spectrum(matArray); + + //˲ + cv::Mat filter = createFilter(spectrum, m_dilateSize, m_erodeSize); + cv::merge(matArray, 2, complexOutput); + cv::multiply(complexOutput, filter, filter); + + //IDFTõ˲ + cv::Size imgSize = img.size(); + inverseFourierTransform(filter, img); + img = img(cv::Rect(cv::Point(0, 0), imgSize)); + img *= 255; + img.convertTo(img, CV_8UC1); +} + +CImageApplyTextureRemoval::CImageApplyTextureRemoval() + : CImageApply() + , m_dilateSize(5) + , m_erodeSize(3) +{ + +} + +CImageApplyTextureRemoval::CImageApplyTextureRemoval(int dilateSize, int erodeSize) + : CImageApply() + , m_dilateSize(dilateSize) + , m_erodeSize(erodeSize) +{ + +} + +CImageApplyTextureRemoval::~CImageApplyTextureRemoval() +{ + +} + +void CImageApplyTextureRemoval::apply(cv::Mat &pDib, int side) +{ + (void)side; + + if (pDib.channels() == 1) + textureRemovalGray(pDib); + else + { + std::vector rgb(3); + cv::split(pDib, rgb); + for (cv::Mat& var : rgb) + textureRemovalGray(var); + cv::merge(rgb, pDib); + } + + pDib *= 1.15; +} + +void CImageApplyTextureRemoval::apply(std::vector &mats, bool isTwoSide) +{ + (void)isTwoSide; + + int i = 0; + for (cv::Mat& var : mats) { + if (i != 0 && isTwoSide == false) + break; + if (!var.empty()) + apply(var, 0); + i++; + } +} diff --git a/ImageProcess/ImageApplyTextureRemoval.h b/ImageProcess/ImageApplyTextureRemoval.h new file mode 100644 index 0000000..30ceaa7 --- /dev/null +++ b/ImageProcess/ImageApplyTextureRemoval.h @@ -0,0 +1,50 @@ +/* + * ==================================================== + + * ܣȥ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_TEXTURE_REMOVAL_H +#define IMAGE_APPLY_TEXTURE_REMOVAL_H + +#include "ImageApply.h" + +class CImageApplyTextureRemoval : public CImageApply +{ +public: + CImageApplyTextureRemoval(void); + + /* + * dilateSize [in]: + * erodeSize [in]:ʴ + */ + CImageApplyTextureRemoval(int dilateSize, int erodeSize); + + virtual ~CImageApplyTextureRemoval(void); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + int getDilateSize() {return m_dilateSize;} + + int getErodeSize() {return m_erodeSize;} + + void setDilateSize(int size) {m_dilateSize = size;} + + void setErodeSize(int size) {m_erodeSize = size;} +private: + void textureRemovalGray(cv::Mat& img); + +private: + int m_dilateSize; + int m_erodeSize; +}; + +#endif diff --git a/ImageProcess/ImageApplyUVMerge.cpp b/ImageProcess/ImageApplyUVMerge.cpp new file mode 100644 index 0000000..d7bc668 --- /dev/null +++ b/ImageProcess/ImageApplyUVMerge.cpp @@ -0,0 +1,186 @@ +#include "ImageApplyUVMerge.h" +#include "ImageProcess_Public.h" +using namespace cv; +#define SCA 50 + +CImageApplyUVMerge::CImageApplyUVMerge(): lut(1, 256, CV_8UC1) +{ +} + +CImageApplyUVMerge::~CImageApplyUVMerge() +{ +} + +void CImageApplyUVMerge::update_lutData(int contrast) +{ + unsigned char* ptr = lut.data; + int m_contrast = cv::max(-127, cv::min(contrast, 127)); + for (int i = 0; i < 256; i++) + { + //update contrast + if (i < 128) + ptr[i] = static_cast(cv::max(0, cv::min(i - m_contrast, 127))); + else + ptr[i] = static_cast(cv::max(127, cv::min(i + m_contrast, 255))); + } +} + +void CImageApplyUVMerge::Apply(cv::Mat& image, const cv::Mat& uv, int dpi, int thresh) +{ + update_lutData(12); + cv::LUT(uv, lut, uv); + Mat uv_resize; + cv::resize(uv, uv_resize, cv::Size(uv.cols * SCA / dpi, uv.rows * SCA / dpi)); + if (uv_resize.channels() == 3) + cv::cvtColor(uv_resize, uv_resize, cv::COLOR_BGR2GRAY); + cv::threshold(uv_resize, uv_resize, 0, 255, THRESH_OTSU); + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1500 / dpi, 1500 / dpi)); + cv::dilate(uv_resize, uv_resize, element); + std::vector> contours; + std::vector hierarchy; + hg::findContours(uv_resize, contours, hierarchy, cv::RETR_EXTERNAL); + + std::map map_color; + for (int i = 0; i < contours.size(); i++) + { + cv::Rect roi = cv::boundingRect(contours[i]); + roi.x *= dpi / SCA; + roi.y *= dpi / SCA; + roi.width *= dpi / SCA; + roi.height *= dpi / SCA; + + purgeQR_kernal(image, roi, map_color, dpi, thresh); + } +} + +cv::Mat CImageApplyUVMerge::Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle) +{ + if (uvRoi.size.width == 0) return cv::Mat(); + + cv::RotatedRect uvRoi_clone = uvRoi; + cv::Mat dst = cv::Mat::zeros(image.rows > image.cols ? image.rows : (image.rows * 2), image.cols > image.rows ? image.cols : (image.cols * 2), image.type()); + image.copyTo(dst(cv::Rect(0, 0, image.cols, image.rows))); + + cv::Mat dst_uv = dst(cv::Rect(image.rows > image.cols ? image.cols : 0, image.rows > image.cols ? 0 : image.rows, image.cols, image.rows)); + if (isDesaskew) + { + cv::Point2f srcTri[4]; + cv::Point2f dstTri[3]; + uvRoi_clone.points(srcTri); + + + if (angle == 90) + { + dstTri[0] = cv::Point2f(0, 0); + dstTri[1] = cv::Point2f(dst_uv.cols - 1, 0); + dstTri[2] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1); + } + else if (angle == 180) + { + dstTri[0] = cv::Point2f(dst_uv.cols - 1, 0); + dstTri[1] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1); + dstTri[2] = cv::Point2f(0, dst_uv.rows - 1); + } + else if (angle == 270) + { + dstTri[0] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1); + dstTri[1] = cv::Point2f(0, dst_uv.rows - 1); + dstTri[2] = cv::Point2f(0, 0); + } + else + { + dstTri[0] = cv::Point2f(0, dst_uv.rows - 1); + dstTri[1] = cv::Point2f(0, 0); + dstTri[2] = cv::Point2f(dst_uv.cols - 1, 0); + } + + cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri); + if (uv.channels() == 1 && dst_uv.channels() == 3) + { + cv::Mat uv_temp; + cv::warpAffine(uv, uv_temp, warp_mat, dst_uv.size()); + cv::cvtColor(uv_temp, dst_uv, cv::COLOR_GRAY2BGR); + } + else + cv::warpAffine(uv, dst_uv, warp_mat, dst_uv.size()); + } + else + { + cv::Rect uvBoundingRect = uvRoi_clone.boundingRect(); + + cv::Rect roi_dst_right; + roi_dst_right.x = dst_uv.cols > uvBoundingRect.width ? (dst_uv.cols - uvBoundingRect.width) / 2 : 0; + roi_dst_right.width = cv::min(dst_uv.cols, uvBoundingRect.width); + roi_dst_right.y = dst_uv.rows > uvBoundingRect.height ? (dst_uv.rows - uvBoundingRect.height) / 2 : 0; + roi_dst_right.height = cv::min(dst_uv.rows, uvBoundingRect.height); + + cv::Rect roi_uv_BoundingRect((uvBoundingRect.width - roi_dst_right.width) / 2, + (uvBoundingRect.height - roi_dst_right.height) / 2, roi_dst_right.width, roi_dst_right.height); + + Mat uvCrop = (uv(uvBoundingRect))(roi_uv_BoundingRect); + if (uvCrop.channels() == 1 && dst_uv.channels() == 3) + cv::cvtColor(uvCrop, uvCrop, cv::COLOR_GRAY2BGR); + uvCrop.copyTo(dst_uv(roi_dst_right)); + } + return dst; +} + + +void CImageApplyUVMerge::purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map map_color, int dpi, int threshold) +{ + cv::Mat image_roi = image(roi); + cv::Mat mask; + cv::cvtColor(image_roi, mask, cv::COLOR_BGR2GRAY); + cv::threshold(mask, mask, 127, 255, cv::THRESH_OTSU); + cv::Mat image_resize; + cv::resize(image, image_resize, cv::Size(image.cols, 800)); + + for (int i = 0, cols = image_roi.cols, rows = image_roi.rows; i < cols; i++) + { + cv::Scalar color_fill; + if (map_color.find(i + roi.x) == map_color.end()) + { + color_fill = getColor(image_resize, roi.x + i, threshold); + map_color[i + roi.x] = color_fill; + } + else + color_fill = map_color[i + roi.x]; + + for (int j = 0; j < rows; j++) + { + if (*mask.ptr(j, i)) + { + uchar* color = image_roi.ptr(j, i); + color[0] = color_fill[0]; + color[1] = color_fill[1]; + color[2] = color_fill[2]; + } + } + } +} + +cv::Scalar CImageApplyUVMerge::getColor(const cv::Mat& image, int col, int threshold) +{ + cv::Scalar color(0, 0, 0); + int num = 0; + + for (int i = 0, length = image.rows; i < length; i++) + { + const uchar* ptr = image.ptr(i, col); + int gray = (ptr[0] * 30 + ptr[1] * 59 + ptr[2] * 11) / 100; + if (gray > threshold) + { + color[0] += ptr[0]; + color[1] += ptr[1]; + color[2] += ptr[2]; + num++; + } + } + + if (num) + color /= num; + else + color[0] = color[1] = color[2] = 255; + + return color; +} diff --git a/ImageProcess/ImageApplyUVMerge.h b/ImageProcess/ImageApplyUVMerge.h new file mode 100644 index 0000000..757b1eb --- /dev/null +++ b/ImageProcess/ImageApplyUVMerge.h @@ -0,0 +1,33 @@ +/* + * ==================================================== + + * ¹¦ÄÜ£ºUVͼÓëԭͼºÏ²¢¡£¸ù¾Ýԭͼ¾ÀÆ«¡¢²Ã¼ôÒÔ¼°ÐýתÇé¿ö£¬UV¸´ÖÆԭͼµÄ´¦Àí£¬²¢ÇÒÓëԭͼƴ½ÓΪһÕÅͼ¡£ + ¸Ã¹¦ÄÜÓÃÓÚUVÒ»Ìå»úÖС£ + * ×÷ÕߣºÁõ¶¡Î¬ + * Éú³Éʱ¼ä£º2020/7/20 + * ×î½üÐÞ¸Äʱ¼ä£º2020/7/20 + * °æ±¾ºÅ£ºv1.0 2020/7/20 + * ==================================================== + */ + +#ifndef IMAGE_APPLY_UV_MERGE_H +#define IMAGE_APPLY_UV_MERGE_H + +#include "ImageApply.h" + +class CImageApplyUVMerge +{ +public: + CImageApplyUVMerge(); + ~CImageApplyUVMerge(); + void Apply(cv::Mat& image, const cv::Mat& uv, int dpi = 200, int thresh = 100); + + static cv::Mat Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle); +private: + void purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map map_color, int dpi, int threshold); + cv::Scalar getColor(const cv::Mat& image, int col, int threshold); + void update_lutData(int contrast); + cv::Mat lut; +}; + +#endif // !IMAGE_APPLY_UV_MERGE_H \ No newline at end of file diff --git a/ImageProcess/ImageMulti.cpp b/ImageProcess/ImageMulti.cpp new file mode 100644 index 0000000..422f707 --- /dev/null +++ b/ImageProcess/ImageMulti.cpp @@ -0,0 +1,72 @@ +#include "ImageMulti.h" + +IMageMulti::IMageMulti(int multiType,int thre) +{ + m_multiType = multiType; + m_thre = thre; +} + +IMageMulti::~IMageMulti(void) +{ +} + +std::vector IMageMulti::apply(cv::Mat& pDib) +{ + std::vector retMats; + if (pDib.empty()) + return retMats; + retMats.push_back(pDib); + switch (m_multiType) + { + case ALL: + { + if (pDib.channels() == 3){ + cv::Mat dst; + cv::cvtColor(pDib, dst,cv::COLOR_BGR2GRAY); + retMats.push_back(dst); + } + cv::Mat dstThre; + cv::cvtColor(pDib, dstThre,cv::COLOR_BGR2GRAY); + //cv::threshold(dstThre, dstThre, m_thre, 255, cv::THRESH_BINARY); + cv::adaptiveThreshold(dstThre,dstThre,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5); + if (!dstThre.empty()) + { + retMats.push_back(dstThre); + } + } + break; + case COLORGRAY: + { + if (pDib.channels() == 3) { + cv::Mat dstGray; + cv::cvtColor(pDib, dstGray, cv::COLOR_BGR2GRAY); + retMats.push_back(dstGray); + } + } + break; + case COLORBW: + { + if (pDib.channels() == 3) { + cv::Mat dstGray; + cv::cvtColor(pDib, dstGray, cv::COLOR_BGR2GRAY); + cv::Mat dstBW; + cv::adaptiveThreshold(dstGray,dstBW,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5); + retMats.push_back(dstBW); + } + } + break; + case GRAYBW://pDib should be GreyImage(channels() == 1) + { + cv::Mat dstBW; + cv::adaptiveThreshold(pDib,dstBW,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5); + if (!dstBW.empty()) + { + retMats.push_back(dstBW); + } + } + break; + default: + break; + } + return retMats; +} diff --git a/ImageProcess/ImageMulti.h b/ImageProcess/ImageMulti.h new file mode 100644 index 0000000..0a79195 --- /dev/null +++ b/ImageProcess/ImageMulti.h @@ -0,0 +1,26 @@ +#ifndef IMAGE_MULTI_H +#define IMAGE_MULTI_H +#include "IMulti.h" + +class IMageMulti + :public IMulti +{ +public: + enum MultiOutput + { + NONE=-1, + ALL, + COLORGRAY, + COLORBW, + GRAYBW + }; +public: + IMageMulti(int multiType = 0,int thre = 128); + virtual ~IMageMulti(void); + virtual std::vector apply(cv::Mat& pDib); +private: + int m_multiType; + int m_thre; +}; + +#endif // !IMAGE_MULTI_H \ No newline at end of file diff --git a/ImageProcess/ImageMultiOutputRed.cpp b/ImageProcess/ImageMultiOutputRed.cpp new file mode 100644 index 0000000..5cc08d2 --- /dev/null +++ b/ImageProcess/ImageMultiOutputRed.cpp @@ -0,0 +1,63 @@ +#include "ImageMultiOutputRed.h" +#include + +using namespace std; + +ImageMultiOutputRed::ImageMultiOutputRed(short channelIndex) +{ + m_channelIndex = channelIndex; +} + +ImageMultiOutputRed::~ImageMultiOutputRed(void) +{ +} + +std::vector ImageMultiOutputRed::apply(cv::Mat& pDib) +{ + std::vector retMats; + if (pDib.empty()) + return retMats; + retMats.push_back(pDib); + cv::Mat mat = FilterColor(pDib, m_channelIndex); + if (!mat.empty()) + retMats.push_back(mat); + return retMats; +} + +cv::Mat ImageMultiOutputRed::FilterColor(cv::Mat image, short channel) +{ + cv::Mat dstImage(image.rows, image.cols, CV_8UC1); + int channels = image.channels(); + if (channel > channels - 1) + { + return cv::Mat(); + } + if ((channel == 3) && (channels != 4) && (channels != 8)) + { + return cv::Mat(); + } + if (channels <= 4) + { + int srcOffset = image.step - image.cols * channels; + int dstOffset = dstImage.step - dstImage.cols; + unsigned char *src = image.data; + unsigned char *dst = dstImage.data; + src += channel; + + for (int y = 0; y < image.rows; y++) + { + for (int x = 0; x < image.cols; x++, src += channels, dst++) + { + unsigned short pix = *src; + if (pix >= 130) + { + pix = 255; + } + *dst = pix; + } + src += srcOffset; + dst += dstOffset; + } + } + return dstImage; +} diff --git a/ImageProcess/ImageMultiOutputRed.h b/ImageProcess/ImageMultiOutputRed.h new file mode 100644 index 0000000..a7ed28c --- /dev/null +++ b/ImageProcess/ImageMultiOutputRed.h @@ -0,0 +1,17 @@ +#ifndef IMAGE_MULTI_OUTPUT_RED_H +#define IMAGE_MULTI_OUTPUT_RED_H +#include "IMulti.h" + +class ImageMultiOutputRed + :public IMulti +{ +public: + ImageMultiOutputRed(short channelIndex); + virtual ~ImageMultiOutputRed(void); + virtual std::vector apply(cv::Mat& pDib) override; + +private: + short m_channelIndex; + cv::Mat FilterColor(cv::Mat image, short channel); +}; +#endif //!IMAGE_MULTI_OUTPUT_RED_H diff --git a/ImageProcess/ImageProcess_Public.cpp b/ImageProcess/ImageProcess_Public.cpp new file mode 100644 index 0000000..27d5aaf --- /dev/null +++ b/ImageProcess/ImageProcess_Public.cpp @@ -0,0 +1,328 @@ +#include "ImageProcess_Public.h" + +namespace hg +{ + void convexHull(const std::vector& src, std::vector& dst, bool clockwise) + { + CvMemStorage* storage = cvCreateMemStorage(); // + CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage + + // + for (const cv::Point& item : src) + { + CvPoint p; + p.x = item.x; + p.y = item.y; + cvSeqPush(ptseq, &p); + } + + //hullstorage + CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0); + + //dst + dst.clear(); + for (int i = 0, hullCount = hull->total; i < hullCount; i++) + dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i)); + + //storage + cvReleaseMemStorage(&storage); + } + +#define R_COLOR 255 + void fillConvexHull(cv::Mat& image, const std::vector& points) + { + uint index_top = 0; + uint index_bottom = 0; + for (size_t i = 0, length = points.size(); i < length; i++) + { + if (points[i].y < points[index_top].y) + index_top = i; + if (points[i].y > points[index_bottom].y) + index_bottom = i; + } + + std::vector edge_left; + uint temp = index_top; + while (temp != index_bottom) + { + edge_left.push_back(points[temp]); + temp = (temp + points.size() - 1) % points.size(); + } + edge_left.push_back(points[index_bottom]); + + std::vector edge_right; + temp = index_top; + while (temp != index_bottom) + { + edge_right.push_back(points[temp]); + temp = (temp + points.size() + 1) % points.size(); + } + edge_right.push_back(points[index_bottom]); + + std::vector left_edge_x; + std::vector left_edge_y; + for (size_t i = 0, length = edge_left.size() - 1; i < length; i++) + { + int y_top = edge_left[i].y; + int x_top = edge_left[i].x; + int y_bottom = edge_left[i + 1].y; + int x_bottom = edge_left[i + 1].x; + for (int y = y_top; y < y_bottom; y++) + if (y >= 0 && y_top != y_bottom && y < image.rows) + { + left_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top)); + left_edge_y.push_back(y); + } + } + size_t step = image.step; + unsigned char* ptr; + ptr = image.data + static_cast(left_edge_y[0]) * step; + for (size_t i = 0, length = left_edge_x.size(); i < length; i++) + { + int pix = left_edge_x[i]; + if (pix < image.cols - 1 && pix > 0) + memset(ptr + i * step, R_COLOR, static_cast((pix + 1) * image.channels())); + } + + std::vector right_edge_x; + std::vector right_edge_y; + for (size_t i = 0, length = edge_right.size() - 1; i < length; i++) + { + int y_top = edge_right[i].y; + int x_top = edge_right[i].x; + int y_bottom = edge_right[i + 1].y; + int x_bottom = edge_right[i + 1].x; + for (int y = y_top; y < y_bottom; y++) + if (y_top != y_bottom && y < image.rows && y >= 0) + { + right_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top)); + right_edge_y.push_back(y); + } + } + + ptr = image.data + static_cast(right_edge_y[0]) * step; + for (size_t i = 0, length = right_edge_x.size(); i < length; i++) + { + int pix = right_edge_x[i]; + if (pix < image.cols - 1 && pix > 0) + memset(ptr + i * step + pix * image.channels(), R_COLOR, step - static_cast(pix * image.channels())); + } + + if (edge_left[0].y > 0) + memset(image.data, R_COLOR, static_cast(edge_left[0].y) * step); + + if (edge_left.back().y < image.rows - 1) + memset(image.data + static_cast(edge_left.back().y) * step, R_COLOR, + static_cast(image.rows - edge_left.back().y) * step); + } + + void fillPolys(cv::Mat& image, const std::vector>& contours, const cv::Scalar& color) + { + if (contours.empty()) return; + + size_t count = contours.size(); + cv::Point** pointss = new cv::Point*[count]; + int* npts = new int[count]; + + for (size_t i = 0; i < count; i++) + { + size_t length = contours[i].size(); + npts[i] = length; + pointss[i] = new cv::Point[length]; + for (size_t j = 0; j < length; j++) + pointss[i][j] = contours[i][j]; + } + cv::fillPoly(image, const_cast(pointss), npts, count, color); + + for (size_t i = 0; i < count; i++) + delete[] pointss[i]; + + delete[] pointss; + delete[] npts; + } + + void findContours(const cv::Mat& src, std::vector>& contours, std::vector& hierarchy, int retr, int method, cv::Point offset) + { + CvMat c_image; + CV_DbgAssert(src.dims <= 2); + c_image = cvMat(src.rows, src.dims == 1 ? 1 : src.cols, src.type(), src.data); + c_image.step = int(src.step[0]); + c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG); + cv::MemStorage storage(cvCreateMemStorage()); + CvSeq* _ccontours = nullptr; + cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x,offset.y }); + + if (!_ccontours) + { + contours.clear(); + return; + } + cv::Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); + size_t total = all_contours.size(); + contours.resize(total); + + cv::SeqIterator it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq* c = *it; + reinterpret_cast(c)->color = static_cast(i); + int count = c->total; + int* data = new int[static_cast(count * 2)]; + cvCvtSeqToArray(c, data); + for (int j = 0; j < count; j++) + { + contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1])); + } + delete[] data; + } + + hierarchy.resize(total); + it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq* c = *it; + int h_next = c->h_next ? reinterpret_cast(c->h_next)->color : -1; + int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; + int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; + int v_prev = c->v_prev ? reinterpret_cast(c->v_prev)->color : -1; + hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev); + } + + storage.release(); + } + + cv::RotatedRect getBoundingRect(const std::vector& contour) + { + if (contour.empty()) return {}; + + cv::RotatedRect rect = minAreaRect(contour); + if (rect.angle < -45) + { + rect.angle += 90; + float temp = rect.size.width; + rect.size.width = rect.size.height; + rect.size.height = temp; + } + + return rect; + } + + std::vector getMaxContour(const std::vector>& contours, const std::vector& hierarchy) + { + std::vector maxContour; + if (contours.size() < 1) return {}; + + for (size_t i = 0, length = hierarchy.size(); i < length; i++) + if (hierarchy[i][3] == -1) + for (const auto &item : contours[i]) + maxContour.push_back(item); + + return maxContour; + } + + std::vector getVertices(const cv::RotatedRect& rect) + { + cv::Point2f box[4]; + rect.points(box); + std::vector points; + for (int i = 0; i < 4; i++) + points.push_back(cv::Point(box[i])); + + return points; + } + + void polyIndent(std::vector& points, const cv::Point& center, int indent) + { + static cv::Point zero(0, 0); + for (cv::Point& item : points) + { +#if 0 + cv::Point vec = item - center; + if (vec != zero) + { + int length = vec.x * vec.x + vec.y * vec.y; + float x = cv::sqrt(static_cast(vec.x * vec.x / length)) * indent; + float y = cv::sqrt(static_cast(vec.y * vec.y / length)) * indent; + + if (vec.x < 0) x *= -1.0f; + if (vec.y < 0) y *= -1.0f; + + item.x -= static_cast(x); + item.y -= static_cast(y); + } +#else + if (item.x > center.x) + item.x -= indent; + else + item.x += indent; + + if (item.y > center.y) + item.y -= indent; + else + item.y += indent; +#endif + } + } + + cv::Mat transforColor(const cv::Mat& src) + { + if (src.channels() == 1) return src.clone(); + + std::vector channels(3); + cv::split(src, channels); + + cv::Mat temp, dst; + bitwise_or(channels[0], channels[1], temp); + bitwise_or(channels[2], temp, dst); + temp.release(); + + for (cv::Mat& index : channels) + index.release(); + return dst; + } + + void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre) + { + if (src.channels() == 3) + { +#ifdef USE_ONENCL + if (cl_res.context) + transforColor_threshold_opencl(src, dst, static_cast(thre)); + else +#endif + { + cv::Mat gray = transforColor(src); + cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY); + gray.release(); + } + } + else + cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY); + } + + cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat) + { + double src_data[3] = { static_cast(p.x), static_cast(p.y), 1 }; + cv::Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1 + + cv::Mat dst = warp_mat * src; + double* ptr = reinterpret_cast(dst.data); + return cv::Point(static_cast(ptr[0]), static_cast(ptr[1])); + } + + int distanceP2P(const cv::Point& p1, const cv::Point& p2) + { + return cv::sqrt(cv::pow(p1.x - p2.x, 2) + cv::pow(p1.y - p2.y, 2)); + } + + float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2) + { + //ֱ߷ + int A = 0, B = 0, C = 0; + A = l1.y - l2.y; + B = l2.x - l1.x; + C = l1.x * l2.y - l1.y * l2.x; + //㵽ֱ߾빫ʽ + return ((float)abs(A * p.x + B * p.y + C)) / ((float)sqrtf(A * A + B * B)); + } +} \ No newline at end of file diff --git a/ImageProcess/ImageProcess_Public.h b/ImageProcess/ImageProcess_Public.h new file mode 100644 index 0000000..94c7b8a --- /dev/null +++ b/ImageProcess/ImageProcess_Public.h @@ -0,0 +1,123 @@ +/* + * ==================================================== + + * ܣͼ㷨ֹܻܿImageProcess෴ʹ + * ߣά + * ʱ䣺2020/4/21 + * ޸ʱ䣺2020/4/21 + * 汾ţv1.0 + + * ==================================================== + */ + +#ifndef IMAGE_PROCESS_PUBLIC_H +#define IMAGE_PROCESS_PUBLIC_H + +#include "opencv2/opencv.hpp" +#include + +namespace hg +{ + /* + * ܣԴ㼯͹㼯 + * src: Դ㼯 + * dst: Ŀ㼯 + * clockwise: trueΪ˳ʱfalseΪʱ + */ + void convexHull(const std::vector& src, std::vector& dst, bool clockwise = false); + + /* + * ܣ͹ΣĬɫΪɫ + * image: ͼ + * points: ͹㼯ʱ + */ + void fillConvexHull(cv::Mat& image, const std::vector& points); + + /* + * ܣ䰼 + * image: ͼ + * contours: 㼯ʱ + * color: ɫ + */ + void fillPolys(cv::Mat& image, const std::vector>& contours, const cv::Scalar& color); + + /* + * ܣȡͨ + * src: Դͼ + * contours: + * hierarchy: ϵcontoursӦretrѡͬб仯 + * retr: ʽĬΪʽ + * method: 㷨ѡĬΪͨ + * offset: ʼ㣬ĬΪ0,0 + */ + void findContours(const cv::Mat& src, std::vector>& contours, std::vector& hierarchy, + int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0)); + + cv::RotatedRect getBoundingRect(const std::vector& contour); + + /* + * : ȡС͹ + * contours: ÿɵ㼯ɣ + * hierarchy: У֮ĹϵcontoursӦ + * ֵ: ͹㼯 + */ + std::vector getMaxContour(const std::vector>& contours, const std::vector& hierarchy); + + /* + * : ȡС͹ + * contours: ÿɵ㼯ɣ + * hierarchy: У֮ĹϵcontoursӦ + * ֵ: ͹㼯 + */ + std::vector getVertices(const cv::RotatedRect& rect); + + /* + * : + * points: 㼯 + * center: Χcenter + * indent: + */ + void polyIndent(std::vector& points, const cv::Point& center, int indent); + + /* + * : ֵܹɫͻҶͼsrcΪɫͼʱҶͼȡֵͨ + * src: Դͼ + * dst: Ŀͼ + * thre: ֵ + */ + void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre); + + /* + * : ɫתҶȣҶͼȡֵͨ + * src: Դͼ + * ֵ: Ҷͼ + */ + cv::Mat transforColor(const cv::Mat& src); + + /* + * : ȡķ任 + * p: ԭ + * warp_mat: 任ϵ + * ֵ: 任ĵ + */ + cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat); + + /* + * : 㵽 + * p1: 1 + * p2: 2 + * ֵ: 㵽 + */ + int distanceP2P(const cv::Point& p1, const cv::Point& p2); + + /* + * : 㵽ֱ߾ + * p: + * l1: ֱ߶˵1 + * l2: ֱ߶˵2 + * ֵ: 㵽ֱ߾ + */ + float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2); +} + +#endif // !IMAGE_PROCESS_C_H diff --git a/ImageProcess/MatEx.h b/ImageProcess/MatEx.h new file mode 100644 index 0000000..4175e2c --- /dev/null +++ b/ImageProcess/MatEx.h @@ -0,0 +1,22 @@ +#pragma once +#include + +class MatEx { +public: + MatEx() : + mat(cv::Mat()) + , Bpp(-1) { + + }; + + MatEx(cv::Mat mat, int bpp) : + mat(cv::Mat()) + , Bpp(bpp) + { + this->mat = mat.clone(); + this->Bpp = bpp; + } +public: + int Bpp; + cv::Mat mat; +}; \ No newline at end of file diff --git a/ImageProcess/imageprocess.pro b/ImageProcess/imageprocess.pro new file mode 100644 index 0000000..6ff9f2e --- /dev/null +++ b/ImageProcess/imageprocess.pro @@ -0,0 +1,141 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-12-29T09:49:19 +# +#------------------------------------------------- + +QT += core + +TARGET = gimgproc +TEMPLATE = lib + +DEFINES += GIMGPROC_LIBRARY + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +INCLUDEPATH += $$PWD/../Tirdparty/3rdparty/nick +DEPENDPATH += $$PWD/../Tirdparty/3rdparty/nick + + INCLUDEPATH += $$PWD/../gpdf + DEPENDPATH += $$PWD/../gpdf + +win32 { + DEFINES += _WIN32 + + INCLUDEPATH += $$PWD/../Tirdparty/3party/3rdparty/win/hgOCR/include + DEPENDPATH += $$PWD/../Tirdparty/3rdparty/win/hgOCR/include + INCLUDEPATH += $$PWD/../Tirdparty/3rdparty/win/opencv/include + DEPENDPATH += $$PWD/../Tirdparty/3rdparty/win/opencv/include + LIBS += -L$$PWD/../Tirdparty/3rdparty/win/hgOCR/x86/lib + INCLUDEPATH += $$PWD/include + + contains(QT_ARCH, i386) { + CONFIG(release, debug|release) { + DESTDIR += ../bin/x86/release + LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346 + LIBS += -L$$PWD/../bin/x86/release -lhg_gpdf + LIBS += -L$$PWD/lib/release -lzxing -lzbar + LIBS += -lwinmm + } + CONFIG(debug, debug|release) { + DESTDIR += ../bin/x86/debug + LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346d + LIBS += -L$$PWD/../bin/x86/debug -lhg_gpdf + LIBS += -L$$PWD/lib/debug -lzxing -lzbar + LIBS += -lwinmm + } + } else { + CONFIG(release, debug|release) { + DESTDIR += ../bin/x64/release + LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346 + LIBS += -L$$PWD/../bin/x64/release -lhg_gpdf + } + CONFIG(debug, debug|release) { + DESTDIR += ../bin/x64/debug + LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346d + LIBS += -L$$PWD/../bin/x64/debug -lhg_gpdf + } + } +} + +else:unix:!macx: { + LIBS += -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs #linux系统上面需安装opencv3.4.6库 + CONFIG(debug, debug|release) { + DESTDIR += ../bin/x86/debug + LIBS += -L$$PWD/../bin/x86/debug -lhg_gpdf + } + CONFIG(release, debug|release) { + DESTDIR += ../bin/x86/release + LIBS += -L$$PWD/../bin/x86/release -lhg_gpdf + } +} + +SOURCES += \ + ImageApply.cpp \ + IMulti.cpp\ + ImageApplyAdjustColors.cpp \ + ImageApplyAutoContrast.cpp \ + ImageApplyAutoCrop.cpp \ + ImageApplyBWBinaray.cpp \ + ImageApplyBarCodeRecognition.cpp \ + ImageApplyChannel.cpp \ + ImageApplyConcatenation.cpp \ + ImageApplyCustomCrop.cpp \ + ImageApplyCustomGamma.cpp \ + ImageApplyDetachNoise.cpp \ + ImageApplyDiscardBlank.cpp \ + ImageApplyFilter.cpp \ + ImageApplyHSVCorrect.cpp \ + ImageApplyOutHole.cpp \ + ImageApplyRefuseInflow.cpp \ + ImageApplyResize.cpp \ + ImageApplyRotation.cpp \ + ImageApplySplit.cpp \ + ImageApplyTextureRemoval.cpp \ + ImageMulti.cpp \ + ImageMultiOutputRed.cpp \ + ImageProcess_Public.cpp + +HEADERS += \ + ImageApply.h \ + IMulti.h\ + ImageApplyAdjustColors.h \ + ImageApplyAutoContrast.h \ + ImageApplyAutoCrop.h \ + ImageApplyBWBinaray.h \ + ImageApplyBarCodeRecognition.h \ + ImageApplyChannel.h \ + ImageApplyConcatenation.h \ + ImageApplyCustomCrop.h \ + ImageApplyCustomGamma.h \ + ImageApplyDetachNoise.h \ + ImageApplyDiscardBlank.h \ + ImageApplyFilter.h \ + ImageApplyHSVCorrect.h \ + ImageApplyHeaders.h \ + ImageApplyOutHole.h \ + ImageApplyRefuseInflow.h \ + ImageApplyResize.h \ + ImageApplyRotation.h \ + ImageApplySplit.h \ + ImageApplyTextureRemoval.h \ + ImageMulti.h \ + ImageMultiOutputRed.h \ + ImageProcess_Public.h \ + imgprocdefs.h + + +#VERSION = 1.0.0.0 +QMAKE_TARGET_PRODUCT = "gimgproc" +QMAKE_TARGET_COMPANY = "huagaoscan" +QMAKE_TARGET_DESCRIPTION = "文件描述" +QMAKE_TARGET_COPYRIGHT = "版权" diff --git a/ImageProcess/imgprocdefs.h b/ImageProcess/imgprocdefs.h new file mode 100644 index 0000000..b099957 --- /dev/null +++ b/ImageProcess/imgprocdefs.h @@ -0,0 +1,23 @@ +#ifndef IMAGE_PROCESS_DEFINES_H +#define IMAGE_PROCESS_DEFINES_H + +#define _DIRECT_BUILD + +#if defined(_MSC_VER) +# define HT_DECL_EXPORT __declspec(dllexport) +# define HT_DECL_IMPORT __declspec(dllimport) +#elif defined(__linux__) || defined(__linux) +# define HT_DECL_EXPORT __attribute__((visibility("default"))) +# define HT_DECL_IMPORT __attribute__((visibility("default"))) +# define HT_DECL_HIDDEN __attribute__((visibility("hidden"))) +#endif + +#if defined(GIMGPROC_LIBRARY_BUILD) +#define GIMGPROC_LIBRARY_API HT_DECL_EXPORT +#elif defined(_DIRECT_BUILD) +#define GIMGPROC_LIBRARY_API +#else +#define GIMGPROC_LIBRARY_API HT_DECL_IMPORT +#endif + +#endif // !IMAGE_PROCESS_DEFINES_H diff --git a/ImageProcess/include/bigint/BigInteger.hh b/ImageProcess/include/bigint/BigInteger.hh new file mode 100644 index 0000000..cf6e910 --- /dev/null +++ b/ImageProcess/include/bigint/BigInteger.hh @@ -0,0 +1,215 @@ +#ifndef BIGINTEGER_H +#define BIGINTEGER_H + +#include "BigUnsigned.hh" + +/* A BigInteger object represents a signed integer of size limited only by + * available memory. BigUnsigneds support most mathematical operators and can + * be converted to and from most primitive integer types. + * + * A BigInteger is just an aggregate of a BigUnsigned and a sign. (It is no + * longer derived from BigUnsigned because that led to harmful implicit + * conversions.) */ +class BigInteger { + +public: + typedef BigUnsigned::Blk Blk; + typedef BigUnsigned::Index Index; + typedef BigUnsigned::CmpRes CmpRes; + static const CmpRes + less = BigUnsigned::less , + equal = BigUnsigned::equal , + greater = BigUnsigned::greater; + // Enumeration for the sign of a BigInteger. + enum Sign { negative = -1, zero = 0, positive = 1 }; + +protected: + Sign sign; + BigUnsigned mag; + +public: + // Constructs zero. + BigInteger() : sign(zero), mag() {} + + // Copy constructor + BigInteger(const BigInteger &x) : sign(x.sign), mag(x.mag) {}; + + // Assignment operator + void operator=(const BigInteger &x); + + // Constructor that copies from a given array of blocks with a sign. + BigInteger(const Blk *b, Index blen, Sign s); + + // Nonnegative constructor that copies from a given array of blocks. + BigInteger(const Blk *b, Index blen) : mag(b, blen) { + sign = mag.isZero() ? zero : positive; + } + + // Constructor from a BigUnsigned and a sign + BigInteger(const BigUnsigned &x, Sign s); + + // Nonnegative constructor from a BigUnsigned + BigInteger(const BigUnsigned &x) : mag(x) { + sign = mag.isZero() ? zero : positive; + } + + // Constructors from primitive integer types + BigInteger(unsigned long x); + BigInteger( long x); + BigInteger(unsigned int x); + BigInteger( int x); + BigInteger(unsigned short x); + BigInteger( short x); + + /* Converters to primitive integer types + * The implicit conversion operators caused trouble, so these are now + * named. */ + unsigned long toUnsignedLong () const; + long toLong () const; + unsigned int toUnsignedInt () const; + int toInt () const; + unsigned short toUnsignedShort() const; + short toShort () const; +protected: + // Helper + template X convertToUnsignedPrimitive() const; + template X convertToSignedPrimitive() const; +public: + + // ACCESSORS + Sign getSign() const { return sign; } + /* The client can't do any harm by holding a read-only reference to the + * magnitude. */ + const BigUnsigned &getMagnitude() const { return mag; } + + // Some accessors that go through to the magnitude + Index getLength() const { return mag.getLength(); } + Index getCapacity() const { return mag.getCapacity(); } + Blk getBlock(Index i) const { return mag.getBlock(i); } + bool isZero() const { return sign == zero; } // A bit special + + // COMPARISONS + + // Compares this to x like Perl's <=> + CmpRes compareTo(const BigInteger &x) const; + + // Ordinary comparison operators + bool operator ==(const BigInteger &x) const { + return sign == x.sign && mag == x.mag; + } + bool operator !=(const BigInteger &x) const { return !operator ==(x); }; + bool operator < (const BigInteger &x) const { return compareTo(x) == less ; } + bool operator <=(const BigInteger &x) const { return compareTo(x) != greater; } + bool operator >=(const BigInteger &x) const { return compareTo(x) != less ; } + bool operator > (const BigInteger &x) const { return compareTo(x) == greater; } + + // OPERATORS -- See the discussion in BigUnsigned.hh. + void add (const BigInteger &a, const BigInteger &b); + void subtract(const BigInteger &a, const BigInteger &b); + void multiply(const BigInteger &a, const BigInteger &b); + /* See the comment on BigUnsigned::divideWithRemainder. Semantics + * differ from those of primitive integers when negatives and/or zeros + * are involved. */ + void divideWithRemainder(const BigInteger &b, BigInteger &q); + void negate(const BigInteger &a); + + /* Bitwise operators are not provided for BigIntegers. Use + * getMagnitude to get the magnitude and operate on that instead. */ + + BigInteger operator +(const BigInteger &x) const; + BigInteger operator -(const BigInteger &x) const; + BigInteger operator *(const BigInteger &x) const; + BigInteger operator /(const BigInteger &x) const; + BigInteger operator %(const BigInteger &x) const; + BigInteger operator -() const; + + void operator +=(const BigInteger &x); + void operator -=(const BigInteger &x); + void operator *=(const BigInteger &x); + void operator /=(const BigInteger &x); + void operator %=(const BigInteger &x); + void flipSign(); + + // INCREMENT/DECREMENT OPERATORS + void operator ++( ); + void operator ++(int); + void operator --( ); + void operator --(int); +}; + +// NORMAL OPERATORS +/* These create an object to hold the result and invoke + * the appropriate put-here operation on it, passing + * this and x. The new object is then returned. */ +inline BigInteger BigInteger::operator +(const BigInteger &x) const { + BigInteger ans; + ans.add(*this, x); + return ans; +} +inline BigInteger BigInteger::operator -(const BigInteger &x) const { + BigInteger ans; + ans.subtract(*this, x); + return ans; +} +inline BigInteger BigInteger::operator *(const BigInteger &x) const { + BigInteger ans; + ans.multiply(*this, x); + return ans; +} +inline BigInteger BigInteger::operator /(const BigInteger &x) const { + if (x.isZero()) throw "BigInteger::operator /: division by zero"; + BigInteger q, r; + r = *this; + r.divideWithRemainder(x, q); + return q; +} +inline BigInteger BigInteger::operator %(const BigInteger &x) const { + if (x.isZero()) throw "BigInteger::operator %: division by zero"; + BigInteger q, r; + r = *this; + r.divideWithRemainder(x, q); + return r; +} +inline BigInteger BigInteger::operator -() const { + BigInteger ans; + ans.negate(*this); + return ans; +} + +/* + * ASSIGNMENT OPERATORS + * + * Now the responsibility for making a temporary copy if necessary + * belongs to the put-here operations. See Assignment Operators in + * BigUnsigned.hh. + */ +inline void BigInteger::operator +=(const BigInteger &x) { + add(*this, x); +} +inline void BigInteger::operator -=(const BigInteger &x) { + subtract(*this, x); +} +inline void BigInteger::operator *=(const BigInteger &x) { + multiply(*this, x); +} +inline void BigInteger::operator /=(const BigInteger &x) { + if (x.isZero()) throw "BigInteger::operator /=: division by zero"; + /* The following technique is slightly faster than copying *this first + * when x is large. */ + BigInteger q; + divideWithRemainder(x, q); + // *this contains the remainder, but we overwrite it with the quotient. + *this = q; +} +inline void BigInteger::operator %=(const BigInteger &x) { + if (x.isZero()) throw "BigInteger::operator %=: division by zero"; + BigInteger q; + // Mods *this by x. Don't care about quotient left in q. + divideWithRemainder(x, q); +} +// This one is trivial +inline void BigInteger::flipSign() { + sign = Sign(-sign); +} + +#endif diff --git a/ImageProcess/include/bigint/BigIntegerAlgorithms.hh b/ImageProcess/include/bigint/BigIntegerAlgorithms.hh new file mode 100644 index 0000000..b1dd943 --- /dev/null +++ b/ImageProcess/include/bigint/BigIntegerAlgorithms.hh @@ -0,0 +1,25 @@ +#ifndef BIGINTEGERALGORITHMS_H +#define BIGINTEGERALGORITHMS_H + +#include "BigInteger.hh" + +/* Some mathematical algorithms for big integers. + * This code is new and, as such, experimental. */ + +// Returns the greatest common divisor of a and b. +BigUnsigned gcd(BigUnsigned a, BigUnsigned b); + +/* Extended Euclidean algorithm. + * Given m and n, finds gcd g and numbers r, s such that r*m + s*n == g. */ +void extendedEuclidean(BigInteger m, BigInteger n, + BigInteger &g, BigInteger &r, BigInteger &s); + +/* Returns the multiplicative inverse of x modulo n, or throws an exception if + * they have a common factor. */ +BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n); + +// Returns (base ^ exponent) % modulus. +BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent, + const BigUnsigned &modulus); + +#endif diff --git a/ImageProcess/include/bigint/BigIntegerLibrary.hh b/ImageProcess/include/bigint/BigIntegerLibrary.hh new file mode 100644 index 0000000..2a0ebee --- /dev/null +++ b/ImageProcess/include/bigint/BigIntegerLibrary.hh @@ -0,0 +1,8 @@ +// This header file includes all of the library header files. + +#include "NumberlikeArray.hh" +#include "BigUnsigned.hh" +#include "BigInteger.hh" +#include "BigIntegerAlgorithms.hh" +#include "BigUnsignedInABase.hh" +#include "BigIntegerUtils.hh" diff --git a/ImageProcess/include/bigint/BigIntegerUtils.hh b/ImageProcess/include/bigint/BigIntegerUtils.hh new file mode 100644 index 0000000..c815b5d --- /dev/null +++ b/ImageProcess/include/bigint/BigIntegerUtils.hh @@ -0,0 +1,72 @@ +#ifndef BIGINTEGERUTILS_H +#define BIGINTEGERUTILS_H + +#include "BigInteger.hh" +#include +#include + +/* This file provides: + * - Convenient std::string <-> BigUnsigned/BigInteger conversion routines + * - std::ostream << operators for BigUnsigned/BigInteger */ + +// std::string conversion routines. Base 10 only. +std::string bigUnsignedToString(const BigUnsigned &x); +std::string bigIntegerToString(const BigInteger &x); +BigUnsigned stringToBigUnsigned(const std::string &s); +BigInteger stringToBigInteger(const std::string &s); + +// Creates a BigInteger from data such as `char's; read below for details. +template +BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign); + +// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'. +std::ostream &operator <<(std::ostream &os, const BigUnsigned &x); + +// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'. +// My somewhat arbitrary policy: a negative sign comes before a base indicator (like -0xFF). +std::ostream &operator <<(std::ostream &os, const BigInteger &x); + +// BEGIN TEMPLATE DEFINITIONS. + +/* + * Converts binary data to a BigInteger. + * Pass an array `data', its length, and the desired sign. + * + * Elements of `data' may be of any type `T' that has the following + * two properties (this includes almost all integral types): + * + * (1) `sizeof(T)' correctly gives the amount of binary data in one + * value of `T' and is a factor of `sizeof(Blk)'. + * + * (2) When a value of `T' is casted to a `Blk', the low bytes of + * the result contain the desired binary data. + */ +template +BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign) { + // really ceiling(numBytes / sizeof(BigInteger::Blk)) + unsigned int pieceSizeInBits = 8 * sizeof(T); + unsigned int piecesPerBlock = sizeof(BigInteger::Blk) / sizeof(T); + unsigned int numBlocks = (length + piecesPerBlock - 1) / piecesPerBlock; + + // Allocate our block array + BigInteger::Blk *blocks = new BigInteger::Blk[numBlocks]; + + BigInteger::Index blockNum, pieceNum, pieceNumHere; + + // Convert + for (blockNum = 0, pieceNum = 0; blockNum < numBlocks; blockNum++) { + BigInteger::Blk curBlock = 0; + for (pieceNumHere = 0; pieceNumHere < piecesPerBlock && pieceNum < length; + pieceNumHere++, pieceNum++) + curBlock |= (BigInteger::Blk(data[pieceNum]) << (pieceSizeInBits * pieceNumHere)); + blocks[blockNum] = curBlock; + } + + // Create the BigInteger. + BigInteger x(blocks, numBlocks, sign); + + delete [] blocks; + return x; +} + +#endif diff --git a/ImageProcess/include/bigint/BigUnsigned.hh b/ImageProcess/include/bigint/BigUnsigned.hh new file mode 100644 index 0000000..9228753 --- /dev/null +++ b/ImageProcess/include/bigint/BigUnsigned.hh @@ -0,0 +1,418 @@ +#ifndef BIGUNSIGNED_H +#define BIGUNSIGNED_H + +#include "NumberlikeArray.hh" + +/* A BigUnsigned object represents a nonnegative integer of size limited only by + * available memory. BigUnsigneds support most mathematical operators and can + * be converted to and from most primitive integer types. + * + * The number is stored as a NumberlikeArray of unsigned longs as if it were + * written in base 256^sizeof(unsigned long). The least significant block is + * first, and the length is such that the most significant block is nonzero. */ +class BigUnsigned : protected NumberlikeArray { + +public: + // Enumeration for the result of a comparison. + enum CmpRes { less = -1, equal = 0, greater = 1 }; + + // BigUnsigneds are built with a Blk type of unsigned long. + typedef unsigned long Blk; + + typedef NumberlikeArray::Index Index; + using NumberlikeArray::N; + +protected: + // Creates a BigUnsigned with a capacity; for internal use. + BigUnsigned(int, Index c) : NumberlikeArray(0, c) {} + + // Decreases len to eliminate any leading zero blocks. + void zapLeadingZeros() { + while (len > 0 && blk[len - 1] == 0) + len--; + } + +public: + // Constructs zero. + BigUnsigned() : NumberlikeArray() {} + + // Copy constructor + BigUnsigned(const BigUnsigned &x) : NumberlikeArray(x) {} + + // Assignment operator + void operator=(const BigUnsigned &x) { + NumberlikeArray::operator =(x); + } + + // Constructor that copies from a given array of blocks. + BigUnsigned(const Blk *b, Index blen) : NumberlikeArray(b, blen) { + // Eliminate any leading zeros we may have been passed. + zapLeadingZeros(); + } + + // Destructor. NumberlikeArray does the delete for us. + ~BigUnsigned() {} + + // Constructors from primitive integer types + BigUnsigned(unsigned long x); + BigUnsigned( long x); + BigUnsigned(unsigned int x); + BigUnsigned( int x); + BigUnsigned(unsigned short x); + BigUnsigned( short x); +protected: + // Helpers + template void initFromPrimitive (X x); + template void initFromSignedPrimitive(X x); +public: + + /* Converters to primitive integer types + * The implicit conversion operators caused trouble, so these are now + * named. */ + unsigned long toUnsignedLong () const; + long toLong () const; + unsigned int toUnsignedInt () const; + int toInt () const; + unsigned short toUnsignedShort() const; + short toShort () const; +protected: + // Helpers + template X convertToSignedPrimitive() const; + template X convertToPrimitive () const; +public: + + // BIT/BLOCK ACCESSORS + + // Expose these from NumberlikeArray directly. + using NumberlikeArray::getCapacity; + using NumberlikeArray::getLength; + + /* Returns the requested block, or 0 if it is beyond the length (as if + * the number had 0s infinitely to the left). */ + Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; } + /* Sets the requested block. The number grows or shrinks as necessary. */ + void setBlock(Index i, Blk newBlock); + + // The number is zero if and only if the canonical length is zero. + bool isZero() const { return NumberlikeArray::isEmpty(); } + + /* Returns the length of the number in bits, i.e., zero if the number + * is zero and otherwise one more than the largest value of bi for + * which getBit(bi) returns true. */ + Index bitLength() const; + /* Get the state of bit bi, which has value 2^bi. Bits beyond the + * number's length are considered to be 0. */ + bool getBit(Index bi) const { + return (getBlock(bi / N) & (Blk(1) << (bi % N))) != 0; + } + /* Sets the state of bit bi to newBit. The number grows or shrinks as + * necessary. */ + void setBit(Index bi, bool newBit); + + // COMPARISONS + + // Compares this to x like Perl's <=> + CmpRes compareTo(const BigUnsigned &x) const; + + // Ordinary comparison operators + bool operator ==(const BigUnsigned &x) const { + return NumberlikeArray::operator ==(x); + } + bool operator !=(const BigUnsigned &x) const { + return NumberlikeArray::operator !=(x); + } + bool operator < (const BigUnsigned &x) const { return compareTo(x) == less ; } + bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; } + bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less ; } + bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; } + + /* + * BigUnsigned and BigInteger both provide three kinds of operators. + * Here ``big-integer'' refers to BigInteger or BigUnsigned. + * + * (1) Overloaded ``return-by-value'' operators: + * +, -, *, /, %, unary -, &, |, ^, <<, >>. + * Big-integer code using these operators looks identical to code using + * the primitive integer types. These operators take one or two + * big-integer inputs and return a big-integer result, which can then + * be assigned to a BigInteger variable or used in an expression. + * Example: + * BigInteger a(1), b = 1; + * BigInteger c = a + b; + * + * (2) Overloaded assignment operators: + * +=, -=, *=, /=, %=, flipSign, &=, |=, ^=, <<=, >>=, ++, --. + * Again, these are used on big integers just like on ints. They take + * one writable big integer that both provides an operand and receives a + * result. Most also take a second read-only operand. + * Example: + * BigInteger a(1), b(1); + * a += b; + * + * (3) Copy-less operations: `add', `subtract', etc. + * These named methods take operands as arguments and store the result + * in the receiver (*this), avoiding unnecessary copies and allocations. + * `divideWithRemainder' is special: it both takes the dividend from and + * stores the remainder into the receiver, and it takes a separate + * object in which to store the quotient. NOTE: If you are wondering + * why these don't return a value, you probably mean to use the + * overloaded return-by-value operators instead. + * + * Examples: + * BigInteger a(43), b(7), c, d; + * + * c = a + b; // Now c == 50. + * c.add(a, b); // Same effect but without the two copies. + * + * c.divideWithRemainder(b, d); + * // 50 / 7; now d == 7 (quotient) and c == 1 (remainder). + * + * // ``Aliased'' calls now do the right thing using a temporary + * // copy, but see note on `divideWithRemainder'. + * a.add(a, b); + */ + + // COPY-LESS OPERATIONS + + // These 8: Arguments are read-only operands, result is saved in *this. + void add(const BigUnsigned &a, const BigUnsigned &b); + void subtract(const BigUnsigned &a, const BigUnsigned &b); + void multiply(const BigUnsigned &a, const BigUnsigned &b); + void bitAnd(const BigUnsigned &a, const BigUnsigned &b); + void bitOr(const BigUnsigned &a, const BigUnsigned &b); + void bitXor(const BigUnsigned &a, const BigUnsigned &b); + /* Negative shift amounts translate to opposite-direction shifts, + * except for -2^(8*sizeof(int)-1) which is unimplemented. */ + void bitShiftLeft(const BigUnsigned &a, int b); + void bitShiftRight(const BigUnsigned &a, int b); + + /* `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'. + * / and % use semantics similar to Knuth's, which differ from the + * primitive integer semantics under division by zero. See the + * implementation in BigUnsigned.cc for details. + * `a.divideWithRemainder(b, a)' throws an exception: it doesn't make + * sense to write quotient and remainder into the same variable. */ + void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q); + + /* `divide' and `modulo' are no longer offered. Use + * `divideWithRemainder' instead. */ + + // OVERLOADED RETURN-BY-VALUE OPERATORS + BigUnsigned operator +(const BigUnsigned &x) const; + BigUnsigned operator -(const BigUnsigned &x) const; + BigUnsigned operator *(const BigUnsigned &x) const; + BigUnsigned operator /(const BigUnsigned &x) const; + BigUnsigned operator %(const BigUnsigned &x) const; + /* OK, maybe unary minus could succeed in one case, but it really + * shouldn't be used, so it isn't provided. */ + BigUnsigned operator &(const BigUnsigned &x) const; + BigUnsigned operator |(const BigUnsigned &x) const; + BigUnsigned operator ^(const BigUnsigned &x) const; + BigUnsigned operator <<(int b) const; + BigUnsigned operator >>(int b) const; + + // OVERLOADED ASSIGNMENT OPERATORS + void operator +=(const BigUnsigned &x); + void operator -=(const BigUnsigned &x); + void operator *=(const BigUnsigned &x); + void operator /=(const BigUnsigned &x); + void operator %=(const BigUnsigned &x); + void operator &=(const BigUnsigned &x); + void operator |=(const BigUnsigned &x); + void operator ^=(const BigUnsigned &x); + void operator <<=(int b); + void operator >>=(int b); + + /* INCREMENT/DECREMENT OPERATORS + * To discourage messy coding, these do not return *this, so prefix + * and postfix behave the same. */ + void operator ++( ); + void operator ++(int); + void operator --( ); + void operator --(int); + + // Helper function that needs access to BigUnsigned internals + friend Blk getShiftedBlock(const BigUnsigned &num, Index x, + unsigned int y); + + // See BigInteger.cc. + template + friend X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a); +}; + +/* Implementing the return-by-value and assignment operators in terms of the + * copy-less operations. The copy-less operations are responsible for making + * any necessary temporary copies to work around aliasing. */ + +inline BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const { + BigUnsigned ans; + ans.add(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const { + BigUnsigned ans; + ans.subtract(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const { + BigUnsigned ans; + ans.multiply(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const { + if (x.isZero()) throw "BigUnsigned::operator /: division by zero"; + BigUnsigned q, r; + r = *this; + r.divideWithRemainder(x, q); + return q; +} +inline BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const { + if (x.isZero()) throw "BigUnsigned::operator %: division by zero"; + BigUnsigned q, r; + r = *this; + r.divideWithRemainder(x, q); + return r; +} +inline BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const { + BigUnsigned ans; + ans.bitAnd(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const { + BigUnsigned ans; + ans.bitOr(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const { + BigUnsigned ans; + ans.bitXor(*this, x); + return ans; +} +inline BigUnsigned BigUnsigned::operator <<(int b) const { + BigUnsigned ans; + ans.bitShiftLeft(*this, b); + return ans; +} +inline BigUnsigned BigUnsigned::operator >>(int b) const { + BigUnsigned ans; + ans.bitShiftRight(*this, b); + return ans; +} + +inline void BigUnsigned::operator +=(const BigUnsigned &x) { + add(*this, x); +} +inline void BigUnsigned::operator -=(const BigUnsigned &x) { + subtract(*this, x); +} +inline void BigUnsigned::operator *=(const BigUnsigned &x) { + multiply(*this, x); +} +inline void BigUnsigned::operator /=(const BigUnsigned &x) { + if (x.isZero()) throw "BigUnsigned::operator /=: division by zero"; + /* The following technique is slightly faster than copying *this first + * when x is large. */ + BigUnsigned q; + divideWithRemainder(x, q); + // *this contains the remainder, but we overwrite it with the quotient. + *this = q; +} +inline void BigUnsigned::operator %=(const BigUnsigned &x) { + if (x.isZero()) throw "BigUnsigned::operator %=: division by zero"; + BigUnsigned q; + // Mods *this by x. Don't care about quotient left in q. + divideWithRemainder(x, q); +} +inline void BigUnsigned::operator &=(const BigUnsigned &x) { + bitAnd(*this, x); +} +inline void BigUnsigned::operator |=(const BigUnsigned &x) { + bitOr(*this, x); +} +inline void BigUnsigned::operator ^=(const BigUnsigned &x) { + bitXor(*this, x); +} +inline void BigUnsigned::operator <<=(int b) { + bitShiftLeft(*this, b); +} +inline void BigUnsigned::operator >>=(int b) { + bitShiftRight(*this, b); +} + +/* Templates for conversions of BigUnsigned to and from primitive integers. + * BigInteger.cc needs to instantiate convertToPrimitive, and the uses in + * BigUnsigned.cc didn't do the trick; I think g++ inlined convertToPrimitive + * instead of generating linkable instantiations. So for consistency, I put + * all the templates here. */ + +// CONSTRUCTION FROM PRIMITIVE INTEGERS + +/* Initialize this BigUnsigned from the given primitive integer. The same + * pattern works for all primitive integer types, so I put it into a template to + * reduce code duplication. (Don't worry: this is protected and we instantiate + * it only with primitive integer types.) Type X could be signed, but x is + * known to be nonnegative. */ +template +void BigUnsigned::initFromPrimitive(X x) { + if (x == 0) + ; // NumberlikeArray already initialized us to zero. + else { + // Create a single block. blk is NULL; no need to delete it. + cap = 1; + blk = new Blk[1]; + len = 1; + blk[0] = Blk(x); + } +} + +/* Ditto, but first check that x is nonnegative. I could have put the check in + * initFromPrimitive and let the compiler optimize it out for unsigned-type + * instantiations, but I wanted to avoid the warning stupidly issued by g++ for + * a condition that is constant in *any* instantiation, even if not in all. */ +template +void BigUnsigned::initFromSignedPrimitive(X x) { + if (x < 0) + throw "BigUnsigned constructor: " + "Cannot construct a BigUnsigned from a negative number"; + else + initFromPrimitive(x); +} + +// CONVERSION TO PRIMITIVE INTEGERS + +/* Template with the same idea as initFromPrimitive. This might be slightly + * slower than the previous version with the masks, but it's much shorter and + * clearer, which is the library's stated goal. */ +template +X BigUnsigned::convertToPrimitive() const { + if (len == 0) + // The number is zero; return zero. + return 0; + else if (len == 1) { + // The single block might fit in an X. Try the conversion. + X x = X(blk[0]); + // Make sure the result accurately represents the block. + if (Blk(x) == blk[0]) + // Successful conversion. + return x; + // Otherwise fall through. + } + throw "BigUnsigned::to: " + "Value is too big to fit in the requested type"; +} + +/* Wrap the above in an x >= 0 test to make sure we got a nonnegative result, + * not a negative one that happened to convert back into the correct nonnegative + * one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again, + * separated to avoid a g++ warning. */ +template +X BigUnsigned::convertToSignedPrimitive() const { + X x = convertToPrimitive(); + if (x >= 0) + return x; + else + throw "BigUnsigned::to(Primitive): " + "Value is too big to fit in the requested type"; +} + +#endif diff --git a/ImageProcess/include/bigint/BigUnsignedInABase.hh b/ImageProcess/include/bigint/BigUnsignedInABase.hh new file mode 100644 index 0000000..0ea89c6 --- /dev/null +++ b/ImageProcess/include/bigint/BigUnsignedInABase.hh @@ -0,0 +1,122 @@ +#ifndef BIGUNSIGNEDINABASE_H +#define BIGUNSIGNEDINABASE_H + +#include "NumberlikeArray.hh" +#include "BigUnsigned.hh" +#include + +/* + * A BigUnsignedInABase object represents a nonnegative integer of size limited + * only by available memory, represented in a user-specified base that can fit + * in an `unsigned short' (most can, and this saves memory). + * + * BigUnsignedInABase is intended as an intermediary class with little + * functionality of its own. BigUnsignedInABase objects can be constructed + * from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.) + * and `std::string's (by switching digit values for appropriate characters). + * + * BigUnsignedInABase is similar to BigUnsigned. Note the following: + * + * (1) They represent the number in exactly the same way, except that + * BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses + * ``blocks'' (or Blk). + * + * (2) Both use the management features of NumberlikeArray. (In fact, my desire + * to add a BigUnsignedInABase class without duplicating a lot of code led me to + * introduce NumberlikeArray.) + * + * (3) The only arithmetic operation supported by BigUnsignedInABase is an + * equality test. Use BigUnsigned for arithmetic. + */ + +class BigUnsignedInABase : protected NumberlikeArray { + +public: + // The digits of a BigUnsignedInABase are unsigned shorts. + typedef unsigned short Digit; + // That's also the type of a base. + typedef Digit Base; + +protected: + // The base in which this BigUnsignedInABase is expressed + Base base; + + // Creates a BigUnsignedInABase with a capacity; for internal use. + BigUnsignedInABase(int, Index c) : NumberlikeArray(0, c) {} + + // Decreases len to eliminate any leading zero digits. + void zapLeadingZeros() { + while (len > 0 && blk[len - 1] == 0) + len--; + } + +public: + // Constructs zero in base 2. + BigUnsignedInABase() : NumberlikeArray(), base(2) {} + + // Copy constructor + BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray(x), base(x.base) {} + + // Assignment operator + void operator =(const BigUnsignedInABase &x) { + NumberlikeArray::operator =(x); + base = x.base; + } + + // Constructor that copies from a given array of digits. + BigUnsignedInABase(const Digit *d, Index l, Base base); + + // Destructor. NumberlikeArray does the delete for us. + ~BigUnsignedInABase() {} + + // LINKS TO BIGUNSIGNED + BigUnsignedInABase(const BigUnsigned &x, Base base); + operator BigUnsigned() const; + + /* LINKS TO STRINGS + * + * These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to + * represent digits of 0 through 35. When parsing strings, lowercase is + * also accepted. + * + * All string representations are big-endian (big-place-value digits + * first). (Computer scientists have adopted zero-based counting; why + * can't they tolerate little-endian numbers?) + * + * No string representation has a ``base indicator'' like ``0x''. + * + * An exception is made for zero: it is converted to ``0'' and not the + * empty string. + * + * If you want different conventions, write your own routines to go + * between BigUnsignedInABase and strings. It's not hard. + */ + operator std::string() const; + BigUnsignedInABase(const std::string &s, Base base); + +public: + + // ACCESSORS + Base getBase() const { return base; } + + // Expose these from NumberlikeArray directly. + using NumberlikeArray::getCapacity; + using NumberlikeArray::getLength; + + /* Returns the requested digit, or 0 if it is beyond the length (as if + * the number had 0s infinitely to the left). */ + Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; } + + // The number is zero if and only if the canonical length is zero. + bool isZero() const { return NumberlikeArray::isEmpty(); } + + /* Equality test. For the purposes of this test, two BigUnsignedInABase + * values must have the same base to be equal. */ + bool operator ==(const BigUnsignedInABase &x) const { + return base == x.base && NumberlikeArray::operator ==(x); + } + bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); } + +}; + +#endif diff --git a/ImageProcess/include/bigint/NumberlikeArray.hh b/ImageProcess/include/bigint/NumberlikeArray.hh new file mode 100644 index 0000000..53c8e5b --- /dev/null +++ b/ImageProcess/include/bigint/NumberlikeArray.hh @@ -0,0 +1,177 @@ +#ifndef NUMBERLIKEARRAY_H +#define NUMBERLIKEARRAY_H + +// Make sure we have NULL. +#ifndef NULL +#define NULL 0 +#endif + +/* A NumberlikeArray object holds a heap-allocated array of Blk with a + * length and a capacity and provides basic memory management features. + * BigUnsigned and BigUnsignedInABase both subclass it. + * + * NumberlikeArray provides no information hiding. Subclasses should use + * nonpublic inheritance and manually expose members as desired using + * declarations like this: + * + * public: + * NumberlikeArray< the-type-argument >::getLength; + */ +template +class NumberlikeArray { +public: + + // Type for the index of a block in the array + typedef unsigned int Index; + // The number of bits in a block, defined below. + static const unsigned int N; + + // The current allocated capacity of this NumberlikeArray (in blocks) + Index cap; + // The actual length of the value stored in this NumberlikeArray (in blocks) + Index len; + // Heap-allocated array of the blocks (can be NULL if len == 0) + Blk *blk; + + // Constructs a ``zero'' NumberlikeArray with the given capacity. + NumberlikeArray(Index c) : cap(c), len(0) { + blk = (cap > 0) ? (new Blk[cap]) : NULL; + } + + /* Constructs a zero NumberlikeArray without allocating a backing array. + * A subclass that doesn't know the needed capacity at initialization + * time can use this constructor and then overwrite blk without first + * deleting it. */ + NumberlikeArray() : cap(0), len(0) { + blk = NULL; + } + + // Destructor. Note that `delete NULL' is a no-op. + ~NumberlikeArray() { + delete [] blk; + } + + /* Ensures that the array has at least the requested capacity; may + * destroy the contents. */ + void allocate(Index c); + + /* Ensures that the array has at least the requested capacity; does not + * destroy the contents. */ + void allocateAndCopy(Index c); + + // Copy constructor + NumberlikeArray(const NumberlikeArray &x); + + // Assignment operator + void operator=(const NumberlikeArray &x); + + // Constructor that copies from a given array of blocks + NumberlikeArray(const Blk *b, Index blen); + + // ACCESSORS + Index getCapacity() const { return cap; } + Index getLength() const { return len; } + Blk getBlock(Index i) const { return blk[i]; } + bool isEmpty() const { return len == 0; } + + /* Equality comparison: checks if both objects have the same length and + * equal (==) array elements to that length. Subclasses may wish to + * override. */ + bool operator ==(const NumberlikeArray &x) const; + + bool operator !=(const NumberlikeArray &x) const { + return !operator ==(x); + } +}; + +/* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that + * include this header file can generate the necessary real definitions. */ + +template +const unsigned int NumberlikeArray::N = 8 * sizeof(Blk); + +template +void NumberlikeArray::allocate(Index c) { + // If the requested capacity is more than the current capacity... + if (c > cap) { + // Delete the old number array + delete [] blk; + // Allocate the new array + cap = c; + blk = new Blk[cap]; + } +} + +template +void NumberlikeArray::allocateAndCopy(Index c) { + // If the requested capacity is more than the current capacity... + if (c > cap) { + Blk *oldBlk = blk; + // Allocate the new number array + cap = c; + blk = new Blk[cap]; + // Copy number blocks + Index i; + for (i = 0; i < len; i++) + blk[i] = oldBlk[i]; + // Delete the old array + delete [] oldBlk; + } +} + +template +NumberlikeArray::NumberlikeArray(const NumberlikeArray &x) + : len(x.len) { + // Create array + cap = len; + blk = new Blk[cap]; + // Copy blocks + Index i; + for (i = 0; i < len; i++) + blk[i] = x.blk[i]; +} + +template +void NumberlikeArray::operator=(const NumberlikeArray &x) { + /* Calls like a = a have no effect; catch them before the aliasing + * causes a problem */ + if (this == &x) + return; + // Copy length + len = x.len; + // Expand array if necessary + allocate(len); + // Copy number blocks + Index i; + for (i = 0; i < len; i++) + blk[i] = x.blk[i]; +} + +template +NumberlikeArray::NumberlikeArray(const Blk *b, Index blen) + : cap(blen), len(blen) { + // Create array + blk = new Blk[cap]; + // Copy blocks + Index i; + for (i = 0; i < len; i++) + blk[i] = b[i]; +} + +template +bool NumberlikeArray::operator ==(const NumberlikeArray &x) const { + if (len != x.len) + // Definitely unequal. + return false; + else { + // Compare corresponding blocks one by one. + Index i; + for (i = 0; i < len; i++) + if (blk[i] != x.blk[i]) + return false; + // No blocks differed, so the objects are equal. + return true; + } +} + +#endif diff --git a/ImageProcess/include/win32/zxing/iconv.h b/ImageProcess/include/win32/zxing/iconv.h new file mode 100644 index 0000000..d354f53 --- /dev/null +++ b/ImageProcess/include/win32/zxing/iconv.h @@ -0,0 +1,14 @@ +#ifndef _LIBICONV_H +#define _LIBICONV_H +#include +#ifdef __cplusplus +extern "C" { +#endif +typedef void* iconv_t; +iconv_t iconv_open(const char *tocode, const char *fromcode); +int iconv_close(iconv_t cd); +size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); +#ifdef __cplusplus +} +#endif +#endif//_LIBICONV_H \ No newline at end of file diff --git a/ImageProcess/include/win32/zxing/stdint.h b/ImageProcess/include/win32/zxing/stdint.h new file mode 100644 index 0000000..d02608a --- /dev/null +++ b/ImageProcess/include/win32/zxing/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/ImageProcess/include/win32/zxing/win_iconv.c b/ImageProcess/include/win32/zxing/win_iconv.c new file mode 100644 index 0000000..17f6773 --- /dev/null +++ b/ImageProcess/include/win32/zxing/win_iconv.c @@ -0,0 +1,2035 @@ +/* + * iconv implementation using Win32 API to convert. + * + * This file is placed in the public domain. + */ + +/* for WC_NO_BEST_FIT_CHARS */ +#ifndef WINVER +# define WINVER 0x0500 +#endif + +#define STRICT +#include +#include +#include +#include + +/* WORKAROUND: */ +#ifndef UNDER_CE +#define GetProcAddressA GetProcAddress +#endif + +#if 0 +# define MAKE_EXE +# define MAKE_DLL +# define USE_LIBICONV_DLL +#endif + +#if !defined(DEFAULT_LIBICONV_DLL) +# define DEFAULT_LIBICONV_DLL "" +#endif + +#define MB_CHAR_MAX 16 + +#define UNICODE_MODE_BOM_DONE 1 +#define UNICODE_MODE_SWAPPED 2 + +#define FLAG_USE_BOM 1 +#define FLAG_TRANSLIT 2 /* //TRANSLIT */ +#define FLAG_IGNORE 4 /* //IGNORE */ + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; + +typedef void* iconv_t; + +iconv_t iconv_open(const char *tocode, const char *fromcode); +int iconv_close(iconv_t cd); +size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); + +/* libiconv interface for vim */ +#if defined(MAKE_DLL) +int +iconvctl (iconv_t cd, int request, void* argument) +{ + /* not supported */ + return 0; +} +#endif + +typedef struct compat_t compat_t; +typedef struct csconv_t csconv_t; +typedef struct rec_iconv_t rec_iconv_t; + +typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode); +typedef int (*f_iconv_close)(iconv_t cd); +typedef size_t (*f_iconv)(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); +typedef int* (*f_errno)(void); +typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize); +typedef int (*f_flush)(csconv_t *cv, uchar *buf, int bufsize); + +#define COMPAT_IN 1 +#define COMPAT_OUT 2 + +/* unicode mapping for compatibility with other conversion table. */ +struct compat_t { + uint in; + uint out; + uint flag; +}; + +struct csconv_t { + int codepage; + int flags; + f_mbtowc mbtowc; + f_wctomb wctomb; + f_mblen mblen; + f_flush flush; + DWORD mode; + compat_t *compat; +}; + +struct rec_iconv_t { + iconv_t cd; + f_iconv_close iconv_close; + f_iconv iconv; + f_errno _errno; + csconv_t from; + csconv_t to; +#if defined(USE_LIBICONV_DLL) + HMODULE hlibiconv; +#endif +}; + +static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode); +static int win_iconv_close(iconv_t cd); +static size_t win_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); + +static int load_mlang(); +static int make_csconv(const char *name, csconv_t *cv); +static int name_to_codepage(const char *name); +static uint utf16_to_ucs4(const ushort *wbuf); +static void ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize); +static int mbtowc_flags(int codepage); +static int must_use_null_useddefaultchar(int codepage); +static char *strrstr(const char *str, const char *token); +static char *xstrndup(const char *s, size_t n); +static int seterror(int err); + +#if defined(USE_LIBICONV_DLL) +static int libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode); +static PVOID MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size); +static HMODULE find_imported_module_by_funcname(HMODULE hModule, const char *funcname); + +static HMODULE hwiniconv; +#endif + +static int sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize); + +static int kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize); + +static struct { + int codepage; + const char *name; +} codepage_alias[] = { + {65001, "CP65001"}, + {65001, "UTF8"}, + {65001, "UTF-8"}, + + {1200, "CP1200"}, + {1200, "UTF16LE"}, + {1200, "UTF-16LE"}, + {1200, "UCS2LE"}, + {1200, "UCS-2LE"}, + + {1201, "CP1201"}, + {1201, "UTF16BE"}, + {1201, "UTF-16BE"}, + {1201, "UCS2BE"}, + {1201, "UCS-2BE"}, + {1201, "unicodeFFFE"}, + + {12000, "CP12000"}, + {12000, "UTF32LE"}, + {12000, "UTF-32LE"}, + {12000, "UCS4LE"}, + {12000, "UCS-4LE"}, + + {12001, "CP12001"}, + {12001, "UTF32BE"}, + {12001, "UTF-32BE"}, + {12001, "UCS4BE"}, + {12001, "UCS-4BE"}, + +#ifndef GLIB_COMPILATION + /* + * Default is big endian. + * See rfc2781 4.3 Interpreting text labelled as UTF-16. + */ + {1201, "UTF16"}, + {1201, "UTF-16"}, + {1201, "UCS2"}, + {1201, "UCS-2"}, + {12001, "UTF32"}, + {12001, "UTF-32"}, + {12001, "UCS-4"}, + {12001, "UCS4"}, +#else + /* Default is little endian, because the platform is */ + {1200, "UTF16"}, + {1200, "UTF-16"}, + {1200, "UCS2"}, + {1200, "UCS-2"}, + {12000, "UTF32"}, + {12000, "UTF-32"}, + {12000, "UCS4"}, + {12000, "UCS-4"}, +#endif + + /* copy from libiconv `iconv -l` */ + /* !IsValidCodePage(367) */ + {20127, "ANSI_X3.4-1968"}, + {20127, "ANSI_X3.4-1986"}, + {20127, "ASCII"}, + {20127, "CP367"}, + {20127, "IBM367"}, + {20127, "ISO-IR-6"}, + {20127, "ISO646-US"}, + {20127, "ISO_646.IRV:1991"}, + {20127, "US"}, + {20127, "US-ASCII"}, + {20127, "CSASCII"}, + + /* !IsValidCodePage(819) */ + {1252, "CP819"}, + {1252, "IBM819"}, + {28591, "ISO-8859-1"}, + {28591, "ISO-IR-100"}, + {28591, "ISO8859-1"}, + {28591, "ISO_8859-1"}, + {28591, "ISO_8859-1:1987"}, + {28591, "L1"}, + {28591, "LATIN1"}, + {28591, "CSISOLATIN1"}, + + {1250, "CP1250"}, + {1250, "MS-EE"}, + {1250, "WINDOWS-1250"}, + + {1251, "CP1251"}, + {1251, "MS-CYRL"}, + {1251, "WINDOWS-1251"}, + + {1252, "CP1252"}, + {1252, "MS-ANSI"}, + {1252, "WINDOWS-1252"}, + + {1253, "CP1253"}, + {1253, "MS-GREEK"}, + {1253, "WINDOWS-1253"}, + + {1254, "CP1254"}, + {1254, "MS-TURK"}, + {1254, "WINDOWS-1254"}, + + {1255, "CP1255"}, + {1255, "MS-HEBR"}, + {1255, "WINDOWS-1255"}, + + {1256, "CP1256"}, + {1256, "MS-ARAB"}, + {1256, "WINDOWS-1256"}, + + {1257, "CP1257"}, + {1257, "WINBALTRIM"}, + {1257, "WINDOWS-1257"}, + + {1258, "CP1258"}, + {1258, "WINDOWS-1258"}, + + {850, "850"}, + {850, "CP850"}, + {850, "IBM850"}, + {850, "CSPC850MULTILINGUAL"}, + + /* !IsValidCodePage(862) */ + {862, "862"}, + {862, "CP862"}, + {862, "IBM862"}, + {862, "CSPC862LATINHEBREW"}, + + {866, "866"}, + {866, "CP866"}, + {866, "IBM866"}, + {866, "CSIBM866"}, + + /* !IsValidCodePage(154) */ + {154, "CP154"}, + {154, "CYRILLIC-ASIAN"}, + {154, "PT154"}, + {154, "PTCP154"}, + {154, "CSPTCP154"}, + + /* !IsValidCodePage(1133) */ + {1133, "CP1133"}, + {1133, "IBM-CP1133"}, + + {874, "CP874"}, + {874, "WINDOWS-874"}, + + /* !IsValidCodePage(51932) */ + {51932, "CP51932"}, + {51932, "MS51932"}, + {51932, "WINDOWS-51932"}, + {51932, "EUC-JP"}, + + {932, "CP932"}, + {932, "MS932"}, + {932, "SHIFFT_JIS"}, + {932, "SHIFFT_JIS-MS"}, + {932, "SJIS"}, + {932, "SJIS-MS"}, + {932, "SJIS-OPEN"}, + {932, "SJIS-WIN"}, + {932, "WINDOWS-31J"}, + {932, "WINDOWS-932"}, + {932, "CSWINDOWS31J"}, + + {50221, "CP50221"}, + {50221, "ISO-2022-JP"}, + {50221, "ISO-2022-JP-MS"}, + {50221, "ISO2022-JP"}, + {50221, "ISO2022-JP-MS"}, + {50221, "MS50221"}, + {50221, "WINDOWS-50221"}, + + {936, "CP936"}, + {936, "GBK"}, + {936, "MS936"}, + {936, "WINDOWS-936"}, + + {950, "CP950"}, + {950, "BIG5"}, + {950, "BIG5HKSCS"}, + {950, "BIG5-HKSCS"}, + + {949, "CP949"}, + {949, "UHC"}, + {949, "EUC-KR"}, + + {1361, "CP1361"}, + {1361, "JOHAB"}, + + {437, "437"}, + {437, "CP437"}, + {437, "IBM437"}, + {437, "CSPC8CODEPAGE437"}, + + {737, "CP737"}, + + {775, "CP775"}, + {775, "IBM775"}, + {775, "CSPC775BALTIC"}, + + {852, "852"}, + {852, "CP852"}, + {852, "IBM852"}, + {852, "CSPCP852"}, + + /* !IsValidCodePage(853) */ + {853, "CP853"}, + + {855, "855"}, + {855, "CP855"}, + {855, "IBM855"}, + {855, "CSIBM855"}, + + {857, "857"}, + {857, "CP857"}, + {857, "IBM857"}, + {857, "CSIBM857"}, + + /* !IsValidCodePage(858) */ + {858, "CP858"}, + + {860, "860"}, + {860, "CP860"}, + {860, "IBM860"}, + {860, "CSIBM860"}, + + {861, "861"}, + {861, "CP-IS"}, + {861, "CP861"}, + {861, "IBM861"}, + {861, "CSIBM861"}, + + {863, "863"}, + {863, "CP863"}, + {863, "IBM863"}, + {863, "CSIBM863"}, + + {864, "CP864"}, + {864, "IBM864"}, + {864, "CSIBM864"}, + + {865, "865"}, + {865, "CP865"}, + {865, "IBM865"}, + {865, "CSIBM865"}, + + {869, "869"}, + {869, "CP-GR"}, + {869, "CP869"}, + {869, "IBM869"}, + {869, "CSIBM869"}, + + /* !IsValidCodePage(1152) */ + {1125, "CP1125"}, + + /* + * Code Page Identifiers + * http://msdn2.microsoft.com/en-us/library/ms776446.aspx + */ + {37, "IBM037"}, /* IBM EBCDIC US-Canada */ + {437, "IBM437"}, /* OEM United States */ + {500, "IBM500"}, /* IBM EBCDIC International */ + {708, "ASMO-708"}, /* Arabic (ASMO 708) */ + /* 709 Arabic (ASMO-449+, BCON V4) */ + /* 710 Arabic - Transparent Arabic */ + {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */ + {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */ + {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */ + {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */ + {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */ + {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */ + {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */ + {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */ + {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */ + {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */ + {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */ + {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */ + {864, "IBM864"}, /* OEM Arabic; Arabic (864) */ + {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */ + {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */ + {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */ + {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */ + {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */ + {875, "cp875"}, /* IBM EBCDIC Greek Modern */ + {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */ + {932, "shift-jis"}, /* alternative name for it */ + {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */ + {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */ + {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */ + {950, "big5hkscs"}, /* ANSI/OEM Traditional Chinese (Hong Kong SAR); Chinese Traditional (Big5-HKSCS) */ + {950, "big5-hkscs"}, /* alternative name for it */ + {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */ + {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */ + {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */ + {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */ + {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */ + {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */ + {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */ + {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */ + {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */ + {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */ + {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */ + {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */ + {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */ + {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */ + {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */ + {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */ + {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */ + {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */ + {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */ + {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */ + {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */ + {1361, "Johab"}, /* Korean (Johab) */ + {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */ + {10001, "x-mac-japanese"}, /* Japanese (Mac) */ + {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */ + {10003, "x-mac-korean"}, /* Korean (Mac) */ + {10004, "x-mac-arabic"}, /* Arabic (Mac) */ + {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */ + {10006, "x-mac-greek"}, /* Greek (Mac) */ + {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */ + {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */ + {10010, "x-mac-romanian"}, /* Romanian (Mac) */ + {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */ + {10021, "x-mac-thai"}, /* Thai (Mac) */ + {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */ + {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */ + {10081, "x-mac-turkish"}, /* Turkish (Mac) */ + {10082, "x-mac-croatian"}, /* Croatian (Mac) */ + {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */ + {20001, "x-cp20001"}, /* TCA Taiwan */ + {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */ + {20003, "x-cp20003"}, /* IBM5550 Taiwan */ + {20004, "x-cp20004"}, /* TeleText Taiwan */ + {20005, "x-cp20005"}, /* Wang Taiwan */ + {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */ + {20106, "x-IA5-German"}, /* IA5 German (7-bit) */ + {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */ + {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */ + {20127, "us-ascii"}, /* US-ASCII (7-bit) */ + {20261, "x-cp20261"}, /* T.61 */ + {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */ + {20273, "IBM273"}, /* IBM EBCDIC Germany */ + {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */ + {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */ + {20280, "IBM280"}, /* IBM EBCDIC Italy */ + {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */ + {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */ + {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */ + {20297, "IBM297"}, /* IBM EBCDIC France */ + {20420, "IBM420"}, /* IBM EBCDIC Arabic */ + {20423, "IBM423"}, /* IBM EBCDIC Greek */ + {20424, "IBM424"}, /* IBM EBCDIC Hebrew */ + {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */ + {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */ + {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */ + {20871, "IBM871"}, /* IBM EBCDIC Icelandic */ + {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */ + {20905, "IBM905"}, /* IBM EBCDIC Turkish */ + {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */ + {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */ + {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */ + {20949, "x-cp20949"}, /* Korean Wansung */ + {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */ + /* 21027 (deprecated) */ + {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */ + {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */ + {28591, "iso8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */ + {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */ + {28592, "iso8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */ + {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */ + {28593, "iso8859-3"}, /* ISO 8859-3 Latin 3 */ + {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */ + {28594, "iso8859-4"}, /* ISO 8859-4 Baltic */ + {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */ + {28595, "iso8859-5"}, /* ISO 8859-5 Cyrillic */ + {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */ + {28596, "iso8859-6"}, /* ISO 8859-6 Arabic */ + {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */ + {28597, "iso8859-7"}, /* ISO 8859-7 Greek */ + {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */ + {28598, "iso8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */ + {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */ + {28599, "iso8859-9"}, /* ISO 8859-9 Turkish */ + {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */ + {28603, "iso8859-13"}, /* ISO 8859-13 Estonian */ + {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */ + {28605, "iso8859-15"}, /* ISO 8859-15 Latin 9 */ + {29001, "x-Europa"}, /* Europa 3 */ + {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */ + {38598, "iso8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */ + {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */ + {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */ + {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */ + {50225, "iso-2022-kr"}, /* ISO 2022 Korean */ + {50225, "iso2022-kr"}, /* ISO 2022 Korean */ + {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */ + /* 50229 ISO 2022 Traditional Chinese */ + /* 50930 EBCDIC Japanese (Katakana) Extended */ + /* 50931 EBCDIC US-Canada and Japanese */ + /* 50933 EBCDIC Korean Extended and Korean */ + /* 50935 EBCDIC Simplified Chinese Extended and Simplified Chinese */ + /* 50936 EBCDIC Simplified Chinese */ + /* 50937 EBCDIC US-Canada and Traditional Chinese */ + /* 50939 EBCDIC Japanese (Latin) Extended and Japanese */ + {51932, "euc-jp"}, /* EUC Japanese */ + {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */ + {51949, "euc-kr"}, /* EUC Korean */ + /* 51950 EUC Traditional Chinese */ + {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */ + {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */ + {57002, "x-iscii-de"}, /* ISCII Devanagari */ + {57003, "x-iscii-be"}, /* ISCII Bengali */ + {57004, "x-iscii-ta"}, /* ISCII Tamil */ + {57005, "x-iscii-te"}, /* ISCII Telugu */ + {57006, "x-iscii-as"}, /* ISCII Assamese */ + {57007, "x-iscii-or"}, /* ISCII Oriya */ + {57008, "x-iscii-ka"}, /* ISCII Kannada */ + {57009, "x-iscii-ma"}, /* ISCII Malayalam */ + {57010, "x-iscii-gu"}, /* ISCII Gujarati */ + {57011, "x-iscii-pa"}, /* ISCII Punjabi */ + + {0, NULL} +}; + +/* + * SJIS SHIFTJIS table CP932 table + * ---- --------------------------- -------------------------------- + * 5C U+00A5 YEN SIGN U+005C REVERSE SOLIDUS + * 7E U+203E OVERLINE U+007E TILDE + * 815C U+2014 EM DASH U+2015 HORIZONTAL BAR + * 815F U+005C REVERSE SOLIDUS U+FF3C FULLWIDTH REVERSE SOLIDUS + * 8160 U+301C WAVE DASH U+FF5E FULLWIDTH TILDE + * 8161 U+2016 DOUBLE VERTICAL LINE U+2225 PARALLEL TO + * 817C U+2212 MINUS SIGN U+FF0D FULLWIDTH HYPHEN-MINUS + * 8191 U+00A2 CENT SIGN U+FFE0 FULLWIDTH CENT SIGN + * 8192 U+00A3 POUND SIGN U+FFE1 FULLWIDTH POUND SIGN + * 81CA U+00AC NOT SIGN U+FFE2 FULLWIDTH NOT SIGN + * + * EUC-JP and ISO-2022-JP should be compatible with CP932. + * + * Kernel and MLang have different Unicode mapping table. Make sure + * which API is used. + */ +static compat_t cp932_compat[] = { + {0x00A5, 0x005C, COMPAT_OUT}, + {0x203E, 0x007E, COMPAT_OUT}, + {0x2014, 0x2015, COMPAT_OUT}, + {0x301C, 0xFF5E, COMPAT_OUT}, + {0x2016, 0x2225, COMPAT_OUT}, + {0x2212, 0xFF0D, COMPAT_OUT}, + {0x00A2, 0xFFE0, COMPAT_OUT}, + {0x00A3, 0xFFE1, COMPAT_OUT}, + {0x00AC, 0xFFE2, COMPAT_OUT}, + {0, 0, 0} +}; + +static compat_t cp20932_compat[] = { + {0x00A5, 0x005C, COMPAT_OUT}, + {0x203E, 0x007E, COMPAT_OUT}, + {0x2014, 0x2015, COMPAT_OUT}, + {0xFF5E, 0x301C, COMPAT_OUT|COMPAT_IN}, + {0x2225, 0x2016, COMPAT_OUT|COMPAT_IN}, + {0xFF0D, 0x2212, COMPAT_OUT|COMPAT_IN}, + {0xFFE0, 0x00A2, COMPAT_OUT|COMPAT_IN}, + {0xFFE1, 0x00A3, COMPAT_OUT|COMPAT_IN}, + {0xFFE2, 0x00AC, COMPAT_OUT|COMPAT_IN}, + {0, 0, 0} +}; + +static compat_t *cp51932_compat = cp932_compat; + +/* cp20932_compat for kernel. cp932_compat for mlang. */ +static compat_t *cp5022x_compat = cp932_compat; + +typedef HRESULT (WINAPI *CONVERTINETSTRING)( + LPDWORD lpdwMode, + DWORD dwSrcEncoding, + DWORD dwDstEncoding, + LPCSTR lpSrcStr, + LPINT lpnSrcSize, + LPBYTE lpDstStr, + LPINT lpnDstSize +); +typedef HRESULT (WINAPI *CONVERTINETMULTIBYTETOUNICODE)( + LPDWORD lpdwMode, + DWORD dwSrcEncoding, + LPCSTR lpSrcStr, + LPINT lpnMultiCharCount, + LPWSTR lpDstStr, + LPINT lpnWideCharCount +); +typedef HRESULT (WINAPI *CONVERTINETUNICODETOMULTIBYTE)( + LPDWORD lpdwMode, + DWORD dwEncoding, + LPCWSTR lpSrcStr, + LPINT lpnWideCharCount, + LPSTR lpDstStr, + LPINT lpnMultiCharCount +); +typedef HRESULT (WINAPI *ISCONVERTINETSTRINGAVAILABLE)( + DWORD dwSrcEncoding, + DWORD dwDstEncoding +); +typedef HRESULT (WINAPI *LCIDTORFC1766A)( + LCID Locale, + LPSTR pszRfc1766, + int nChar +); +typedef HRESULT (WINAPI *LCIDTORFC1766W)( + LCID Locale, + LPWSTR pszRfc1766, + int nChar +); +typedef HRESULT (WINAPI *RFC1766TOLCIDA)( + LCID *pLocale, + LPSTR pszRfc1766 +); +typedef HRESULT (WINAPI *RFC1766TOLCIDW)( + LCID *pLocale, + LPWSTR pszRfc1766 +); +static CONVERTINETSTRING ConvertINetString; +static CONVERTINETMULTIBYTETOUNICODE ConvertINetMultiByteToUnicode; +static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte; +static ISCONVERTINETSTRINGAVAILABLE IsConvertINetStringAvailable; +static LCIDTORFC1766A LcidToRfc1766A; +static RFC1766TOLCIDA Rfc1766ToLcidA; + +static int +load_mlang() +{ + HMODULE h; + if (ConvertINetString != NULL) + return TRUE; + h = LoadLibrary(TEXT("mlang.dll")); + if (!h) + return FALSE; + ConvertINetString = (CONVERTINETSTRING)GetProcAddressA(h, "ConvertINetString"); + ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddressA(h, "ConvertINetMultiByteToUnicode"); + ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddressA(h, "ConvertINetUnicodeToMultiByte"); + IsConvertINetStringAvailable = (ISCONVERTINETSTRINGAVAILABLE)GetProcAddressA(h, "IsConvertINetStringAvailable"); + LcidToRfc1766A = (LCIDTORFC1766A)GetProcAddressA(h, "LcidToRfc1766A"); + Rfc1766ToLcidA = (RFC1766TOLCIDA)GetProcAddressA(h, "Rfc1766ToLcidA"); + return TRUE; +} + +iconv_t +iconv_open(const char *tocode, const char *fromcode) +{ + rec_iconv_t *cd; + + cd = (rec_iconv_t *)calloc(1, sizeof(rec_iconv_t)); + if (cd == NULL) + return (iconv_t)(-1); + +#if defined(USE_LIBICONV_DLL) + errno = 0; + if (libiconv_iconv_open(cd, tocode, fromcode)) + return (iconv_t)cd; +#endif + + /* reset the errno to prevent reporting wrong error code. + * 0 for unsorted error. */ + errno = 0; + if (win_iconv_open(cd, tocode, fromcode)) + return (iconv_t)cd; + + free(cd); + + return (iconv_t)(-1); +} + +int +iconv_close(iconv_t _cd) +{ + rec_iconv_t *cd = (rec_iconv_t *)_cd; + int r = cd->iconv_close(cd->cd); + int e = *(cd->_errno()); +#if defined(USE_LIBICONV_DLL) + if (cd->hlibiconv != NULL) + FreeLibrary(cd->hlibiconv); +#endif + free(cd); + errno = e; + return r; +} + +size_t +iconv(iconv_t _cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) +{ + rec_iconv_t *cd = (rec_iconv_t *)_cd; + size_t r = cd->iconv(cd->cd, inbuf, inbytesleft, outbuf, outbytesleft); + errno = *(cd->_errno()); + return r; +} + +static int +win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode) +{ + if (!make_csconv(fromcode, &cd->from) || !make_csconv(tocode, &cd->to)) + return FALSE; + cd->iconv_close = win_iconv_close; + cd->iconv = win_iconv; + cd->_errno = _errno; + cd->cd = (iconv_t)cd; + return TRUE; +} + +static int +win_iconv_close(iconv_t cd) +{ + return 0; +} + +static size_t +win_iconv(iconv_t _cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) +{ + rec_iconv_t *cd = (rec_iconv_t *)_cd; + ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */ + int insize; + int outsize; + int wsize; + DWORD frommode; + DWORD tomode; + uint wc; + compat_t *cp; + int i; + + if (inbuf == NULL || *inbuf == NULL) + { + if (outbuf != NULL && *outbuf != NULL && cd->to.flush != NULL) + { + tomode = cd->to.mode; + outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, *outbytesleft); + if (outsize == -1) + { + if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) + { + outsize = 0; + } + else + { + cd->to.mode = tomode; + return (size_t)(-1); + } + } + *outbuf += outsize; + *outbytesleft -= outsize; + } + cd->from.mode = 0; + cd->to.mode = 0; + return 0; + } + + while (*inbytesleft != 0) + { + frommode = cd->from.mode; + tomode = cd->to.mode; + wsize = MB_CHAR_MAX; + + insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, *inbytesleft, wbuf, &wsize); + if (insize == -1) + { + if (cd->to.flags & FLAG_IGNORE) + { + cd->from.mode = frommode; + insize = 1; + wsize = 0; + } + else + { + cd->from.mode = frommode; + return (size_t)(-1); + } + } + + if (wsize == 0) + { + *inbuf += insize; + *inbytesleft -= insize; + continue; + } + + if (cd->from.compat != NULL) + { + wc = utf16_to_ucs4(wbuf); + cp = cd->from.compat; + for (i = 0; cp[i].in != 0; ++i) + { + if ((cp[i].flag & COMPAT_IN) && cp[i].out == wc) + { + ucs4_to_utf16(cp[i].in, wbuf, &wsize); + break; + } + } + } + + if (cd->to.compat != NULL) + { + wc = utf16_to_ucs4(wbuf); + cp = cd->to.compat; + for (i = 0; cp[i].in != 0; ++i) + { + if ((cp[i].flag & COMPAT_OUT) && cp[i].in == wc) + { + ucs4_to_utf16(cp[i].out, wbuf, &wsize); + break; + } + } + } + + outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, *outbytesleft); + if (outsize == -1) + { + if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) + { + cd->to.mode = tomode; + outsize = 0; + } + else + { + cd->from.mode = frommode; + cd->to.mode = tomode; + return (size_t)(-1); + } + } + + *inbuf += insize; + *outbuf += outsize; + *inbytesleft -= insize; + *outbytesleft -= outsize; + } + + return 0; +} + +static int +make_csconv(const char *_name, csconv_t *cv) +{ + CPINFO cpinfo; + int use_compat = TRUE; + int flag = 0; + char *name; + char *p; + + name = xstrndup(_name, strlen(_name)); + if (name == NULL) + return FALSE; + + /* check for option "enc_name//opt1//opt2" */ + while ((p = strrstr(name, "//")) != NULL) + { + if (_stricmp(p + 2, "nocompat") == 0) + use_compat = FALSE; + else if (_stricmp(p + 2, "translit") == 0) + flag |= FLAG_TRANSLIT; + else if (_stricmp(p + 2, "ignore") == 0) + flag |= FLAG_IGNORE; + *p = 0; + } + + cv->mode = 0; + cv->flags = flag; + cv->mblen = NULL; + cv->flush = NULL; + cv->compat = NULL; + cv->codepage = name_to_codepage(name); + if (cv->codepage == 1200 || cv->codepage == 1201) + { + cv->mbtowc = utf16_mbtowc; + cv->wctomb = utf16_wctomb; + if (_stricmp(name, "UTF-16") == 0 || _stricmp(name, "UTF16") == 0 || + _stricmp(name, "UCS-2") == 0 || _stricmp(name, "UCS2") == 0) + cv->flags |= FLAG_USE_BOM; + } + else if (cv->codepage == 12000 || cv->codepage == 12001) + { + cv->mbtowc = utf32_mbtowc; + cv->wctomb = utf32_wctomb; + if (_stricmp(name, "UTF-32") == 0 || _stricmp(name, "UTF32") == 0 || + _stricmp(name, "UCS-4") == 0 || _stricmp(name, "UCS4") == 0) + cv->flags |= FLAG_USE_BOM; + } + else if (cv->codepage == 65001) + { + cv->mbtowc = kernel_mbtowc; + cv->wctomb = kernel_wctomb; + cv->mblen = utf8_mblen; + } + else if ((cv->codepage == 50220 || cv->codepage == 50221 || cv->codepage == 50222) && load_mlang()) + { + cv->mbtowc = iso2022jp_mbtowc; + cv->wctomb = iso2022jp_wctomb; + cv->flush = iso2022jp_flush; + } + else if (cv->codepage == 51932 && load_mlang()) + { + cv->mbtowc = mlang_mbtowc; + cv->wctomb = mlang_wctomb; + cv->mblen = eucjp_mblen; + } + else if (IsValidCodePage(cv->codepage) + && GetCPInfo(cv->codepage, &cpinfo) != 0) + { + cv->mbtowc = kernel_mbtowc; + cv->wctomb = kernel_wctomb; + if (cpinfo.MaxCharSize == 1) + cv->mblen = sbcs_mblen; + else if (cpinfo.MaxCharSize == 2) + cv->mblen = dbcs_mblen; + else + cv->mblen = mbcs_mblen; + } + else + { + /* not supported */ + free(name); + errno = EINVAL; + return FALSE; + } + + if (use_compat) + { + switch (cv->codepage) + { + case 932: cv->compat = cp932_compat; break; + case 20932: cv->compat = cp20932_compat; break; + case 51932: cv->compat = cp51932_compat; break; + case 50220: case 50221: case 50222: cv->compat = cp5022x_compat; break; + } + } + + free(name); + + return TRUE; +} + +static int +name_to_codepage(const char *name) +{ + int i; + + if (*name == '\0' || + strcmp(name, "char") == 0) + return GetACP(); + else if (strcmp(name, "wchar_t") == 0) + return 1200; + else if (_strnicmp(name, "cp", 2) == 0) + return atoi(name + 2); /* CP123 */ + else if ('0' <= name[0] && name[0] <= '9') + return atoi(name); /* 123 */ + else if (_strnicmp(name, "xx", 2) == 0) + return atoi(name + 2); /* XX123 for debug */ + + for (i = 0; codepage_alias[i].name != NULL; ++i) + if (_stricmp(name, codepage_alias[i].name) == 0) + return codepage_alias[i].codepage; + return -1; +} + +/* + * http://www.faqs.org/rfcs/rfc2781.html + */ +static uint +utf16_to_ucs4(const ushort *wbuf) +{ + uint wc = wbuf[0]; + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + wc = ((wbuf[0] & 0x3FF) << 10) + (wbuf[1] & 0x3FF) + 0x10000; + return wc; +} + +static void +ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize) +{ + if (wc < 0x10000) + { + wbuf[0] = wc; + *wbufsize = 1; + } + else + { + wc -= 0x10000; + wbuf[0] = 0xD800 | ((wc >> 10) & 0x3FF); + wbuf[1] = 0xDC00 | (wc & 0x3FF); + *wbufsize = 2; + } +} + +/* + * Check if codepage is one of those for which the dwFlags parameter + * to MultiByteToWideChar() must be zero. Return zero or + * MB_ERR_INVALID_CHARS. The docs in Platform SDK for for Windows + * Server 2003 R2 claims that also codepage 65001 is one of these, but + * that doesn't seem to be the case. The MSDN docs for MSVS2008 leave + * out 65001 (UTF-8), and that indeed seems to be the case on XP, it + * works fine to pass MB_ERR_INVALID_CHARS in dwFlags when converting + * from UTF-8. + */ +static int +mbtowc_flags(int codepage) +{ + return (codepage == 50220 || codepage == 50221 || + codepage == 50222 || codepage == 50225 || + codepage == 50227 || codepage == 50229 || + codepage == 52936 || codepage == 54936 || + (codepage >= 57002 && codepage <= 57011) || + codepage == 65000 || codepage == 42) ? 0 : MB_ERR_INVALID_CHARS; +} + +/* + * Check if codepage is one those for which the lpUsedDefaultChar + * parameter to WideCharToMultiByte() must be NULL. The docs in + * Platform SDK for for Windows Server 2003 R2 claims that this is the + * list below, while the MSDN docs for MSVS2008 claim that it is only + * for 65000 (UTF-7) and 65001 (UTF-8). This time the earlier Platform + * SDK seems to be correct, at least for XP. + */ +static int +must_use_null_useddefaultchar(int codepage) +{ + return (codepage == 65000 || codepage == 65001 || + codepage == 50220 || codepage == 50221 || + codepage == 50222 || codepage == 50225 || + codepage == 50227 || codepage == 50229 || + codepage == 52936 || codepage == 54936 || + (codepage >= 57002 && codepage <= 57011) || + codepage == 42); +} + +static char * +strrstr(const char *str, const char *token) +{ + int len = strlen(token); + const char *p = str + strlen(str); + + while (str <= --p) + if (p[0] == token[0] && strncmp(p, token, len) == 0) + return (char *)p; + return NULL; +} + +static char * +xstrndup(const char *s, size_t n) +{ + char *p; + + p = (char *)malloc(n + 1); + if (p == NULL) + return NULL; + memcpy(p, s, n); + p[n] = '\0'; + return p; +} + +static int +seterror(int err) +{ + errno = err; + return -1; +} + +#if defined(USE_LIBICONV_DLL) +static int +libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode) +{ + HMODULE hlibiconv = NULL; + HMODULE hmsvcrt = NULL; + char *dllname; + const char *p; + const char *e; + f_iconv_open _iconv_open; + + /* + * always try to load dll, so that we can switch dll in runtime. + */ + + /* XXX: getenv() can't get variable set by SetEnvironmentVariable() */ + p = getenv("WINICONV_LIBICONV_DLL"); + if (p == NULL) + p = DEFAULT_LIBICONV_DLL; + /* parse comma separated value */ + for ( ; *p != 0; p = (*e == ',') ? e + 1 : e) + { + e = strchr(p, ','); + if (p == e) + continue; + else if (e == NULL) + e = p + strlen(p); + dllname = xstrndup(p, e - p); + if (dllname == NULL) + return FALSE; + hlibiconv = LoadLibraryA(dllname); + free(dllname); + if (hlibiconv != NULL) + { + if (hlibiconv == hwiniconv) + { + FreeLibrary(hlibiconv); + hlibiconv = NULL; + continue; + } + break; + } + } + + if (hlibiconv == NULL) + goto failed; + + hmsvcrt = find_imported_module_by_funcname(hlibiconv, "_errno"); + if (hmsvcrt == NULL) + goto failed; + + _iconv_open = (f_iconv_open)GetProcAddressA(hlibiconv, "libiconv_open"); + if (_iconv_open == NULL) + _iconv_open = (f_iconv_open)GetProcAddressA(hlibiconv, "iconv_open"); + cd->iconv_close = (f_iconv_close)GetProcAddressA(hlibiconv, "libiconv_close"); + if (cd->iconv_close == NULL) + cd->iconv_close = (f_iconv_close)GetProcAddressA(hlibiconv, "iconv_close"); + cd->iconv = (f_iconv)GetProcAddressA(hlibiconv, "libiconv"); + if (cd->iconv == NULL) + cd->iconv = (f_iconv)GetProcAddressA(hlibiconv, "iconv"); + cd->_errno = (f_errno)GetProcAddressA(hmsvcrt, "_errno"); + if (_iconv_open == NULL || cd->iconv_close == NULL + || cd->iconv == NULL || cd->_errno == NULL) + goto failed; + + cd->cd = _iconv_open(tocode, fromcode); + if (cd->cd == (iconv_t)(-1)) + goto failed; + + cd->hlibiconv = hlibiconv; + return TRUE; + +failed: + if (hlibiconv != NULL) + FreeLibrary(hlibiconv); + /* do not free hmsvcrt which is obtained by GetModuleHandle() */ + return FALSE; +} + +/* + * Reference: + * http://forums.belution.com/ja/vc/000/234/78s.shtml + * http://nienie.com/~masapico/api_ImageDirectoryEntryToData.html + * + * The formal way is + * imagehlp.h or dbghelp.h + * imagehlp.lib or dbghelp.lib + * ImageDirectoryEntryToData() + */ +#define TO_DOS_HEADER(base) ((PIMAGE_DOS_HEADER)(base)) +#define TO_NT_HEADERS(base) ((PIMAGE_NT_HEADERS)((LPBYTE)(base) + TO_DOS_HEADER(base)->e_lfanew)) +static PVOID +MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size) +{ + /* TODO: MappedAsImage? */ + PIMAGE_DATA_DIRECTORY p; + p = TO_NT_HEADERS(Base)->OptionalHeader.DataDirectory + DirectoryEntry; + if (p->VirtualAddress == 0) { + *Size = 0; + return NULL; + } + *Size = p->Size; + return (PVOID)((LPBYTE)Base + p->VirtualAddress); +} + +static HMODULE +find_imported_module_by_funcname(HMODULE hModule, const char *funcname) +{ + DWORD_PTR Base; + ULONG Size; + PIMAGE_IMPORT_DESCRIPTOR Imp; + PIMAGE_THUNK_DATA Name; /* Import Name Table */ + PIMAGE_IMPORT_BY_NAME ImpName; + + Base = (DWORD_PTR)hModule; + Imp = (PIMAGE_IMPORT_DESCRIPTOR)MyImageDirectoryEntryToData( + (LPVOID)Base, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &Size); + if (Imp == NULL) + return NULL; + for ( ; Imp->OriginalFirstThunk != 0; ++Imp) + { + Name = (PIMAGE_THUNK_DATA)(Base + Imp->OriginalFirstThunk); + for ( ; Name->u1.Ordinal != 0; ++Name) + { + if (!IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal)) + { + ImpName = (PIMAGE_IMPORT_BY_NAME) + (Base + (DWORD_PTR)Name->u1.AddressOfData); + if (strcmp((char *)ImpName->Name, funcname) == 0) + return GetModuleHandleA((char *)(Base + Imp->Name)); + } + } + } + return NULL; +} +#endif + +static int +sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + return 1; +} + +static int +dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = IsDBCSLeadByteEx(cv->codepage, buf[0]) ? 2 : 1; + if (bufsize < len) + return seterror(EINVAL); + return len; +} + +static int +mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = 0; + + if (cv->codepage == 54936) { + if (buf[0] <= 0x7F) len = 1; + else if (buf[0] >= 0x81 && buf[0] <= 0xFE && + bufsize >= 2 && + ((buf[1] >= 0x40 && buf[1] <= 0x7E) || + (buf[1] >= 0x80 && buf[1] <= 0xFE))) len = 2; + else if (buf[0] >= 0x81 && buf[0] <= 0xFE && + bufsize >= 4 && + buf[1] >= 0x30 && buf[1] <= 0x39) len = 4; + else + return seterror(EINVAL); + return len; + } + else + return seterror(EINVAL); +} + +static int +utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = 0; + + if (buf[0] < 0x80) len = 1; + else if ((buf[0] & 0xE0) == 0xC0) len = 2; + else if ((buf[0] & 0xF0) == 0xE0) len = 3; + else if ((buf[0] & 0xF8) == 0xF0) len = 4; + else if ((buf[0] & 0xFC) == 0xF8) len = 5; + else if ((buf[0] & 0xFE) == 0xFC) len = 6; + + if (len == 0) + return seterror(EILSEQ); + else if (bufsize < len) + return seterror(EINVAL); + return len; +} + +static int +eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + if (buf[0] < 0x80) /* ASCII */ + return 1; + else if (buf[0] == 0x8E) /* JIS X 0201 */ + { + if (bufsize < 2) + return seterror(EINVAL); + else if (!(0xA1 <= buf[1] && buf[1] <= 0xDF)) + return seterror(EILSEQ); + return 2; + } + else if (buf[0] == 0x8F) /* JIS X 0212 */ + { + if (bufsize < 3) + return seterror(EINVAL); + else if (!(0xA1 <= buf[1] && buf[1] <= 0xFE) + || !(0xA1 <= buf[2] && buf[2] <= 0xFE)) + return seterror(EILSEQ); + return 3; + } + else /* JIS X 0208 */ + { + if (bufsize < 2) + return seterror(EINVAL); + else if (!(0xA1 <= buf[0] && buf[0] <= 0xFE) + || !(0xA1 <= buf[1] && buf[1] <= 0xFE)) + return seterror(EILSEQ); + return 2; + } +} + +static int +kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int len; + + len = cv->mblen(cv, buf, bufsize); + if (len == -1) + return -1; + *wbufsize = MultiByteToWideChar(cv->codepage, mbtowc_flags (cv->codepage), + (const char *)buf, len, (wchar_t *)wbuf, *wbufsize); + if (*wbufsize == 0) + return seterror(EILSEQ); + return len; +} + +static int +kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + BOOL usedDefaultChar = 0; + BOOL *p = NULL; + int flags = 0; + int len; + + if (bufsize == 0) + return seterror(E2BIG); + if (!must_use_null_useddefaultchar(cv->codepage)) + { + p = &usedDefaultChar; +#ifdef WC_NO_BEST_FIT_CHARS + if (!(cv->flags & FLAG_TRANSLIT)) + flags |= WC_NO_BEST_FIT_CHARS; +#endif + } + len = WideCharToMultiByte(cv->codepage, flags, + (const wchar_t *)wbuf, wbufsize, (char *)buf, bufsize, NULL, p); + if (len == 0) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + return seterror(E2BIG); + return seterror(EILSEQ); + } + else if (usedDefaultChar && !(cv->flags & FLAG_TRANSLIT)) + return seterror(EILSEQ); + else if (cv->mblen(cv, buf, len) != len) /* validate result */ + return seterror(EILSEQ); + return len; +} + +/* + * It seems that the mode (cv->mode) is fixnum. + * For example, when converting iso-2022-jp(cp50221) to unicode: + * in ascii sequence: mode=0xC42C0000 + * in jisx0208 sequence: mode=0xC42C0001 + * "C42C" is same for each convert session. + * It should be: ((codepage-1)<<16)|state + */ +static int +mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int len; + int insize; + HRESULT hr; + + len = cv->mblen(cv, buf, bufsize); + if (len == -1) + return -1; + insize = len; + hr = ConvertINetMultiByteToUnicode(&cv->mode, cv->codepage, + (const char *)buf, &insize, (wchar_t *)wbuf, wbufsize); + if (hr != S_OK || insize != len) + return seterror(EILSEQ); + return len; +} + +static int +mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + char tmpbuf[MB_CHAR_MAX]; /* enough room for one character */ + int tmpsize = MB_CHAR_MAX; + int insize = wbufsize; + HRESULT hr; + + hr = ConvertINetUnicodeToMultiByte(&cv->mode, cv->codepage, + (const wchar_t *)wbuf, &wbufsize, tmpbuf, &tmpsize); + if (hr != S_OK || insize != wbufsize) + return seterror(EILSEQ); + else if (bufsize < tmpsize) + return seterror(E2BIG); + else if (cv->mblen(cv, (uchar *)tmpbuf, tmpsize) != tmpsize) + return seterror(EILSEQ); + memcpy(buf, tmpbuf, tmpsize); + return tmpsize; +} + +static int +utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int codepage = cv->codepage; + + /* swap endian: 1200 <-> 1201 */ + if (cv->mode & UNICODE_MODE_SWAPPED) + codepage ^= 1; + + if (bufsize < 2) + return seterror(EINVAL); + if (codepage == 1200) /* little endian */ + wbuf[0] = (buf[1] << 8) | buf[0]; + else if (codepage == 1201) /* big endian */ + wbuf[0] = (buf[0] << 8) | buf[1]; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + cv->mode |= UNICODE_MODE_BOM_DONE; + if (wbuf[0] == 0xFFFE) + { + cv->mode |= UNICODE_MODE_SWAPPED; + *wbufsize = 0; + return 2; + } + else if (wbuf[0] == 0xFEFF) + { + *wbufsize = 0; + return 2; + } + } + + if (0xDC00 <= wbuf[0] && wbuf[0] <= 0xDFFF) + return seterror(EILSEQ); + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + { + if (bufsize < 4) + return seterror(EINVAL); + if (codepage == 1200) /* little endian */ + wbuf[1] = (buf[3] << 8) | buf[2]; + else if (codepage == 1201) /* big endian */ + wbuf[1] = (buf[2] << 8) | buf[3]; + if (!(0xDC00 <= wbuf[1] && wbuf[1] <= 0xDFFF)) + return seterror(EILSEQ); + *wbufsize = 2; + return 4; + } + *wbufsize = 1; + return 2; +} + +static int +utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + int r; + + cv->mode |= UNICODE_MODE_BOM_DONE; + if (bufsize < 2) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + memcpy(buf, "\xFF\xFE", 2); + else if (cv->codepage == 1201) /* big endian */ + memcpy(buf, "\xFE\xFF", 2); + + r = utf16_wctomb(cv, wbuf, wbufsize, buf + 2, bufsize - 2); + if (r == -1) + return -1; + return r + 2; + } + + if (bufsize < 2) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + { + buf[0] = (wbuf[0] & 0x00FF); + buf[1] = (wbuf[0] & 0xFF00) >> 8; + } + else if (cv->codepage == 1201) /* big endian */ + { + buf[0] = (wbuf[0] & 0xFF00) >> 8; + buf[1] = (wbuf[0] & 0x00FF); + } + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + { + if (bufsize < 4) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + { + buf[2] = (wbuf[1] & 0x00FF); + buf[3] = (wbuf[1] & 0xFF00) >> 8; + } + else if (cv->codepage == 1201) /* big endian */ + { + buf[2] = (wbuf[1] & 0xFF00) >> 8; + buf[3] = (wbuf[1] & 0x00FF); + } + return 4; + } + return 2; +} + +static int +utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int codepage = cv->codepage; + uint wc; + + /* swap endian: 12000 <-> 12001 */ + if (cv->mode & UNICODE_MODE_SWAPPED) + codepage ^= 1; + + if (bufsize < 4) + return seterror(EINVAL); + if (codepage == 12000) /* little endian */ + wc = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + else if (codepage == 12001) /* big endian */ + wc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + cv->mode |= UNICODE_MODE_BOM_DONE; + if (wc == 0xFFFE0000) + { + cv->mode |= UNICODE_MODE_SWAPPED; + *wbufsize = 0; + return 4; + } + else if (wc == 0x0000FEFF) + { + *wbufsize = 0; + return 4; + } + } + + if ((0xD800 <= wc && wc <= 0xDFFF) || 0x10FFFF < wc) + return seterror(EILSEQ); + ucs4_to_utf16(wc, wbuf, wbufsize); + return 4; +} + +static int +utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + uint wc; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + int r; + + cv->mode |= UNICODE_MODE_BOM_DONE; + if (bufsize < 4) + return seterror(E2BIG); + if (cv->codepage == 12000) /* little endian */ + memcpy(buf, "\xFF\xFE\x00\x00", 4); + else if (cv->codepage == 12001) /* big endian */ + memcpy(buf, "\x00\x00\xFE\xFF", 4); + + r = utf32_wctomb(cv, wbuf, wbufsize, buf + 4, bufsize - 4); + if (r == -1) + return -1; + return r + 4; + } + + if (bufsize < 4) + return seterror(E2BIG); + wc = utf16_to_ucs4(wbuf); + if (cv->codepage == 12000) /* little endian */ + { + buf[0] = wc & 0x000000FF; + buf[1] = (wc & 0x0000FF00) >> 8; + buf[2] = (wc & 0x00FF0000) >> 16; + buf[3] = (wc & 0xFF000000) >> 24; + } + else if (cv->codepage == 12001) /* big endian */ + { + buf[0] = (wc & 0xFF000000) >> 24; + buf[1] = (wc & 0x00FF0000) >> 16; + buf[2] = (wc & 0x0000FF00) >> 8; + buf[3] = wc & 0x000000FF; + } + return 4; +} + +/* + * 50220: ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) + * 50221: ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow + * 1 byte Kana) + * 50222: ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte + * Kana - SO/SI) + * + * MultiByteToWideChar() and WideCharToMultiByte() behave differently + * depending on Windows version. On XP, WideCharToMultiByte() doesn't + * terminate result sequence with ascii escape. But Vista does. + * Use MLang instead. + */ + +#define ISO2022_MODE(cs, shift) (((cs) << 8) | (shift)) +#define ISO2022_MODE_CS(mode) (((mode) >> 8) & 0xFF) +#define ISO2022_MODE_SHIFT(mode) ((mode) & 0xFF) + +#define ISO2022_SI 0 +#define ISO2022_SO 1 + +/* shift in */ +static const char iso2022_SI_seq[] = "\x0F"; +/* shift out */ +static const char iso2022_SO_seq[] = "\x0E"; + +typedef struct iso2022_esc_t iso2022_esc_t; +struct iso2022_esc_t { + const char *esc; + int esc_len; + int len; + int cs; +}; + +#define ISO2022JP_CS_ASCII 0 +#define ISO2022JP_CS_JISX0201_ROMAN 1 +#define ISO2022JP_CS_JISX0201_KANA 2 +#define ISO2022JP_CS_JISX0208_1978 3 +#define ISO2022JP_CS_JISX0208_1983 4 +#define ISO2022JP_CS_JISX0212 5 + +static iso2022_esc_t iso2022jp_esc[] = { + {"\x1B\x28\x42", 3, 1, ISO2022JP_CS_ASCII}, + {"\x1B\x28\x4A", 3, 1, ISO2022JP_CS_JISX0201_ROMAN}, + {"\x1B\x28\x49", 3, 1, ISO2022JP_CS_JISX0201_KANA}, + {"\x1B\x24\x40", 3, 2, ISO2022JP_CS_JISX0208_1983}, /* unify 1978 with 1983 */ + {"\x1B\x24\x42", 3, 2, ISO2022JP_CS_JISX0208_1983}, + {"\x1B\x24\x28\x44", 4, 2, ISO2022JP_CS_JISX0212}, + {NULL, 0, 0, 0} +}; + +static int +iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + char tmp[MB_CHAR_MAX]; + int insize; + HRESULT hr; + DWORD dummy = 0; + int len; + int esc_len; + int cs; + int shift; + int i; + + if (buf[0] == 0x1B) + { + for (i = 0; iesc[i].esc != NULL; ++i) + { + esc_len = iesc[i].esc_len; + if (bufsize < esc_len) + { + if (strncmp((char *)buf, iesc[i].esc, bufsize) == 0) + return seterror(EINVAL); + } + else + { + if (strncmp((char *)buf, iesc[i].esc, esc_len) == 0) + { + cv->mode = ISO2022_MODE(iesc[i].cs, ISO2022_SI); + *wbufsize = 0; + return esc_len; + } + } + } + /* not supported escape sequence */ + return seterror(EILSEQ); + } + else if (buf[0] == iso2022_SO_seq[0]) + { + cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SO); + *wbufsize = 0; + return 1; + } + else if (buf[0] == iso2022_SI_seq[0]) + { + cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SI); + *wbufsize = 0; + return 1; + } + + cs = ISO2022_MODE_CS(cv->mode); + shift = ISO2022_MODE_SHIFT(cv->mode); + + /* reset the mode for informal sequence */ + if (buf[0] < 0x20) + { + cs = ISO2022JP_CS_ASCII; + shift = ISO2022_SI; + } + + len = iesc[cs].len; + if (bufsize < len) + return seterror(EINVAL); + for (i = 0; i < len; ++i) + if (!(buf[i] < 0x80)) + return seterror(EILSEQ); + esc_len = iesc[cs].esc_len; + memcpy(tmp, iesc[cs].esc, esc_len); + if (shift == ISO2022_SO) + { + memcpy(tmp + esc_len, iso2022_SO_seq, 1); + esc_len += 1; + } + memcpy(tmp + esc_len, buf, len); + + if ((cv->codepage == 50220 || cv->codepage == 50221 + || cv->codepage == 50222) && shift == ISO2022_SO) + { + /* XXX: shift-out cannot be used for mbtowc (both kernel and + * mlang) */ + esc_len = iesc[ISO2022JP_CS_JISX0201_KANA].esc_len; + memcpy(tmp, iesc[ISO2022JP_CS_JISX0201_KANA].esc, esc_len); + memcpy(tmp + esc_len, buf, len); + } + + insize = len + esc_len; + hr = ConvertINetMultiByteToUnicode(&dummy, cv->codepage, + (const char *)tmp, &insize, (wchar_t *)wbuf, wbufsize); + if (hr != S_OK || insize != len + esc_len) + return seterror(EILSEQ); + + /* Check for conversion error. Assuming defaultChar is 0x3F. */ + /* ascii should be converted from ascii */ + if (wbuf[0] == buf[0] + && cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI)) + return seterror(EILSEQ); + + /* reset the mode for informal sequence */ + if (cv->mode != ISO2022_MODE(cs, shift)) + cv->mode = ISO2022_MODE(cs, shift); + + return len; +} + +static int +iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + char tmp[MB_CHAR_MAX]; + int tmpsize = MB_CHAR_MAX; + int insize = wbufsize; + HRESULT hr; + DWORD dummy = 0; + int len; + int esc_len; + int cs; + int shift; + int i; + + /* + * MultiByte = [escape sequence] + character + [escape sequence] + * + * Whether trailing escape sequence is added depends on which API is + * used (kernel or MLang, and its version). + */ + hr = ConvertINetUnicodeToMultiByte(&dummy, cv->codepage, + (const wchar_t *)wbuf, &wbufsize, tmp, &tmpsize); + if (hr != S_OK || insize != wbufsize) + return seterror(EILSEQ); + else if (bufsize < tmpsize) + return seterror(E2BIG); + + if (tmpsize == 1) + { + cs = ISO2022JP_CS_ASCII; + esc_len = 0; + } + else + { + for (i = 1; iesc[i].esc != NULL; ++i) + { + esc_len = iesc[i].esc_len; + if (strncmp(tmp, iesc[i].esc, esc_len) == 0) + { + cs = iesc[i].cs; + break; + } + } + if (iesc[i].esc == NULL) + /* not supported escape sequence */ + return seterror(EILSEQ); + } + + shift = ISO2022_SI; + if (tmp[esc_len] == iso2022_SO_seq[0]) + { + shift = ISO2022_SO; + esc_len += 1; + } + + len = iesc[cs].len; + + /* Check for converting error. Assuming defaultChar is 0x3F. */ + /* ascii should be converted from ascii */ + if (cs == ISO2022JP_CS_ASCII && !(wbuf[0] < 0x80)) + return seterror(EILSEQ); + else if (tmpsize < esc_len + len) + return seterror(EILSEQ); + + if (cv->mode == ISO2022_MODE(cs, shift)) + { + /* remove escape sequence */ + if (esc_len != 0) + memmove(tmp, tmp + esc_len, len); + esc_len = 0; + } + else + { + if (cs == ISO2022JP_CS_ASCII) + { + esc_len = iesc[ISO2022JP_CS_ASCII].esc_len; + memmove(tmp + esc_len, tmp, len); + memcpy(tmp, iesc[ISO2022JP_CS_ASCII].esc, esc_len); + } + if (ISO2022_MODE_SHIFT(cv->mode) == ISO2022_SO) + { + /* shift-in before changing to other mode */ + memmove(tmp + 1, tmp, len + esc_len); + memcpy(tmp, iso2022_SI_seq, 1); + esc_len += 1; + } + } + + if (bufsize < len + esc_len) + return seterror(E2BIG); + memcpy(buf, tmp, len + esc_len); + cv->mode = ISO2022_MODE(cs, shift); + return len + esc_len; +} + +static int +iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + int esc_len; + + if (cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI)) + { + esc_len = 0; + if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI) + esc_len += 1; + if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII) + esc_len += iesc[ISO2022JP_CS_ASCII].esc_len; + if (bufsize < esc_len) + return seterror(E2BIG); + + esc_len = 0; + if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI) + { + memcpy(buf, iso2022_SI_seq, 1); + esc_len += 1; + } + if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII) + { + memcpy(buf + esc_len, iesc[ISO2022JP_CS_ASCII].esc, + iesc[ISO2022JP_CS_ASCII].esc_len); + esc_len += iesc[ISO2022JP_CS_ASCII].esc_len; + } + return esc_len; + } + return 0; +} + +#if defined(MAKE_DLL) && defined(USE_LIBICONV_DLL) +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +{ + switch( fdwReason ) + { + case DLL_PROCESS_ATTACH: + hwiniconv = (HMODULE)hinstDLL; + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#endif + +#if defined(MAKE_EXE) +#include +#include +#include +int +main(int argc, char **argv) +{ + char *fromcode = NULL; + char *tocode = NULL; + int i; + char inbuf[BUFSIZ]; + char outbuf[BUFSIZ]; + char *pin; + char *pout; + size_t inbytesleft; + size_t outbytesleft; + size_t rest = 0; + iconv_t cd; + size_t r; + FILE *in = stdin; + int ignore = 0; + char *p; + + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); + + for (i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "-l") == 0) + { + for (i = 0; codepage_alias[i].name != NULL; ++i) + printf("%s\n", codepage_alias[i].name); + return 0; + } + + if (strcmp(argv[i], "-f") == 0) + fromcode = argv[++i]; + else if (strcmp(argv[i], "-t") == 0) + tocode = argv[++i]; + else if (strcmp(argv[i], "-c") == 0) + ignore = 1; + else + { + in = fopen(argv[i], "rb"); + if (in == NULL) + { + fprintf(stderr, "cannot open %s\n", argv[i]); + return 1; + } + break; + } + } + + if (fromcode == NULL || tocode == NULL) + { + printf("usage: %s [-c] -f from-enc -t to-enc [file]\n", argv[0]); + return 0; + } + + if (ignore) + { + p = tocode; + tocode = (char *)malloc(strlen(p) + strlen("//IGNORE") + 1); + if (tocode == NULL) + { + perror("fatal error"); + return 1; + } + strcpy(tocode, p); + strcat(tocode, "//IGNORE"); + } + + cd = iconv_open(tocode, fromcode); + if (cd == (iconv_t)(-1)) + { + perror("iconv_open error"); + return 1; + } + + while ((inbytesleft = fread(inbuf + rest, 1, sizeof(inbuf) - rest, in)) != 0 + || rest != 0) + { + inbytesleft += rest; + pin = inbuf; + pout = outbuf; + outbytesleft = sizeof(outbuf); + r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft); + fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, stdout); + if (r == (size_t)(-1) && errno != E2BIG && (errno != EINVAL || feof(in))) + { + perror("conversion error"); + return 1; + } + memmove(inbuf, pin, inbytesleft); + rest = inbytesleft; + } + pout = outbuf; + outbytesleft = sizeof(outbuf); + r = iconv(cd, NULL, NULL, &pout, &outbytesleft); + fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, stdout); + if (r == (size_t)(-1)) + { + perror("conversion error"); + return 1; + } + + iconv_close(cd); + + return 0; +} +#endif + diff --git a/ImageProcess/include/zbar.h b/ImageProcess/include/zbar.h new file mode 100644 index 0000000..dfc0b03 --- /dev/null +++ b/ImageProcess/include/zbar.h @@ -0,0 +1,1498 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ +#ifndef _ZBAR_H_ +#define _ZBAR_H_ + + /** @file + * ZBar Barcode Reader C API definition + */ + + /** @mainpage + * + * interface to the barcode reader is available at several levels. + * most applications will want to use the high-level interfaces: + * + * @section high-level High-Level Interfaces + * + * these interfaces wrap all library functionality into an easy-to-use + * package for a specific toolkit: + * - the "GTK+ 2.x widget" may be used with GTK GUI applications. a + * Python wrapper is included for PyGtk + * - the @ref zbar::QZBar "Qt4 widget" may be used with Qt GUI + * applications + * - the Processor interface (in @ref c-processor "C" or @ref + * zbar::Processor "C++") adds a scanning window to an application + * with no GUI. + * + * @section mid-level Intermediate Interfaces + * + * building blocks used to construct high-level interfaces: + * - the ImageScanner (in @ref c-imagescanner "C" or @ref + * zbar::ImageScanner "C++") looks for barcodes in a library defined + * image object + * - the Window abstraction (in @ref c-window "C" or @ref + * zbar::Window "C++") sinks library images, displaying them on the + * platform display + * - the Video abstraction (in @ref c-video "C" or @ref zbar::Video + * "C++") sources library images from a video device + * + * @section low-level Low-Level Interfaces + * + * direct interaction with barcode scanning and decoding: + * - the Scanner (in @ref c-scanner "C" or @ref zbar::Scanner "C++") + * looks for barcodes in a linear intensity sample stream + * - the Decoder (in @ref c-decoder "C" or @ref zbar::Decoder "C++") + * extracts barcodes from a stream of bar and space widths + */ + +#ifdef __cplusplus + + /** C++ namespace for library interfaces */ +namespace zbar { + extern "C" { +#endif + + + /** @name Global library interfaces */ + /*@{*/ + + /** "color" of element: bar or space. */ + typedef enum zbar_color_e { + ZBAR_SPACE = 0, /**< light area or space between bars */ + ZBAR_BAR = 1, /**< dark area or colored bar segment */ + } zbar_color_t; + + /** decoded symbol type. */ + typedef enum zbar_symbol_type_e { + ZBAR_NONE = 0, /**< no symbol decoded */ + ZBAR_PARTIAL = 1, /**< intermediate status */ + ZBAR_EAN2 = 2, /**< GS1 2-digit add-on */ + ZBAR_EAN5 = 5, /**< GS1 5-digit add-on */ + ZBAR_EAN8 = 8, /**< EAN-8 */ + ZBAR_UPCE = 9, /**< UPC-E */ + ZBAR_ISBN10 = 10, /**< ISBN-10 (from EAN-13). @since 0.4 */ + ZBAR_UPCA = 12, /**< UPC-A */ + ZBAR_EAN13 = 13, /**< EAN-13 */ + ZBAR_ISBN13 = 14, /**< ISBN-13 (from EAN-13). @since 0.4 */ + ZBAR_COMPOSITE = 15, /**< EAN/UPC composite */ + ZBAR_I25 = 25, /**< Interleaved 2 of 5. @since 0.4 */ + ZBAR_DATABAR = 34, /**< GS1 DataBar (RSS). @since 0.11 */ + ZBAR_DATABAR_EXP = 35, /**< GS1 DataBar Expanded. @since 0.11 */ + ZBAR_CODABAR = 38, /**< Codabar. @since 0.11 */ + ZBAR_CODE39 = 39, /**< Code 39. @since 0.4 */ + ZBAR_PDF417 = 57, /**< PDF417. @since 0.6 */ + ZBAR_QRCODE = 64, /**< QR Code. @since 0.10 */ + ZBAR_CODE93 = 93, /**< Code 93. @since 0.11 */ + ZBAR_CODE128 = 128, /**< Code 128 */ + + /** mask for base symbol type. + * @deprecated in 0.11, remove this from existing code + */ + ZBAR_SYMBOL = 0x00ff, + /** 2-digit add-on flag. + * @deprecated in 0.11, a ::ZBAR_EAN2 component is used for + * 2-digit GS1 add-ons + */ + ZBAR_ADDON2 = 0x0200, + /** 5-digit add-on flag. + * @deprecated in 0.11, a ::ZBAR_EAN5 component is used for + * 5-digit GS1 add-ons + */ + ZBAR_ADDON5 = 0x0500, + /** add-on flag mask. + * @deprecated in 0.11, GS1 add-ons are represented using composite + * symbols of type ::ZBAR_COMPOSITE; add-on components use ::ZBAR_EAN2 + * or ::ZBAR_EAN5 + */ + ZBAR_ADDON = 0x0700, + } zbar_symbol_type_t; + + /** decoded symbol coarse orientation. + * @since 0.11 + */ + typedef enum zbar_orientation_e { + ZBAR_ORIENT_UNKNOWN = -1, /**< unable to determine orientation */ + ZBAR_ORIENT_UP, /**< upright, read left to right */ + ZBAR_ORIENT_RIGHT, /**< sideways, read top to bottom */ + ZBAR_ORIENT_DOWN, /**< upside-down, read right to left */ + ZBAR_ORIENT_LEFT, /**< sideways, read bottom to top */ + } zbar_orientation_t; + + /** error codes. */ + typedef enum zbar_error_e { + ZBAR_OK = 0, /**< no error */ + ZBAR_ERR_NOMEM, /**< out of memory */ + ZBAR_ERR_INTERNAL, /**< internal library error */ + ZBAR_ERR_UNSUPPORTED, /**< unsupported request */ + ZBAR_ERR_INVALID, /**< invalid request */ + ZBAR_ERR_SYSTEM, /**< system error */ + ZBAR_ERR_LOCKING, /**< locking error */ + ZBAR_ERR_BUSY, /**< all resources busy */ + ZBAR_ERR_XDISPLAY, /**< X11 display error */ + ZBAR_ERR_XPROTO, /**< X11 protocol error */ + ZBAR_ERR_CLOSED, /**< output window is closed */ + ZBAR_ERR_WINAPI, /**< windows system error */ + ZBAR_ERR_NUM /**< number of error codes */ + } zbar_error_t; + + /** decoder configuration options. + * @since 0.4 + */ + typedef enum zbar_config_e { + ZBAR_CFG_ENABLE = 0, /**< enable symbology/feature */ + ZBAR_CFG_ADD_CHECK, /**< enable check digit when optional */ + ZBAR_CFG_EMIT_CHECK, /**< return check digit when present */ + ZBAR_CFG_ASCII, /**< enable full ASCII character set */ + ZBAR_CFG_NUM, /**< number of boolean decoder configs */ + + ZBAR_CFG_MIN_LEN = 0x20, /**< minimum data length for valid decode */ + ZBAR_CFG_MAX_LEN, /**< maximum data length for valid decode */ + + ZBAR_CFG_UNCERTAINTY = 0x40,/**< required video consistency frames */ + + ZBAR_CFG_POSITION = 0x80, /**< enable scanner to collect position data */ + + ZBAR_CFG_X_DENSITY = 0x100, /**< image scanner vertical scan density */ + ZBAR_CFG_Y_DENSITY, /**< image scanner horizontal scan density */ + } zbar_config_t; + + /** decoder symbology modifier flags. + * @since 0.11 + */ + typedef enum zbar_modifier_e { + /** barcode tagged as GS1 (EAN.UCC) reserved + * (eg, FNC1 before first data character). + * data may be parsed as a sequence of GS1 AIs + */ + ZBAR_MOD_GS1 = 0, + + /** barcode tagged as AIM reserved + * (eg, FNC1 after first character or digit pair) + */ + ZBAR_MOD_AIM, + + /** number of modifiers */ + ZBAR_MOD_NUM, + } zbar_modifier_t; + + /** retrieve runtime library version information. + * @param major set to the running major version (unless NULL) + * @param minor set to the running minor version (unless NULL) + * @returns 0 + */ + extern int zbar_version(unsigned* major, + unsigned* minor); + + /** set global library debug level. + * @param verbosity desired debug level. higher values create more spew + */ + extern void zbar_set_verbosity(int verbosity); + + /** increase global library debug level. + * eg, for -vvvv + */ + extern void zbar_increase_verbosity(void); + + /** retrieve string name for symbol encoding. + * @param sym symbol type encoding + * @returns the static string name for the specified symbol type, + * or "UNKNOWN" if the encoding is not recognized + */ + extern const char* zbar_get_symbol_name(zbar_symbol_type_t sym); + + /** retrieve string name for addon encoding. + * @param sym symbol type encoding + * @returns static string name for any addon, or the empty string + * if no addons were decoded + * @deprecated in 0.11 + */ + extern const char* zbar_get_addon_name(zbar_symbol_type_t sym); + + /** retrieve string name for configuration setting. + * @param config setting to name + * @returns static string name for config, + * or the empty string if value is not a known config + */ + extern const char* zbar_get_config_name(zbar_config_t config); + + /** retrieve string name for modifier. + * @param modifier flag to name + * @returns static string name for modifier, + * or the empty string if the value is not a known flag + */ + extern const char* zbar_get_modifier_name(zbar_modifier_t modifier); + + /** retrieve string name for orientation. + * @param orientation orientation encoding + * @returns the static string name for the specified orientation, + * or "UNKNOWN" if the orientation is not recognized + * @since 0.11 + */ + extern const char* zbar_get_orientation_name(zbar_orientation_t orientation); + + /** parse a configuration string of the form "[symbology.]config[=value]". + * the config must match one of the recognized names. + * the symbology, if present, must match one of the recognized names. + * if symbology is unspecified, it will be set to 0. + * if value is unspecified it will be set to 1. + * @returns 0 if the config is parsed successfully, 1 otherwise + * @since 0.4 + */ + extern int zbar_parse_config(const char* config_string, + zbar_symbol_type_t* symbology, + zbar_config_t* config, + int* value); + + /** consistently compute fourcc values across architectures + * (adapted from v4l2 specification) + * @since 0.11 + */ +#define zbar_fourcc(a, b, c, d) \ + ((unsigned long)(a) | \ + ((unsigned long)(b) << 8) | \ + ((unsigned long)(c) << 16) | \ + ((unsigned long)(d) << 24)) + + /** parse a fourcc string into its encoded integer value. + * @since 0.11 + */ + static __inline unsigned long zbar_fourcc_parse(const char* format) + { + unsigned long fourcc = 0; + if (format) { + int i; + for (i = 0; i < 4 && format[i]; i++) + fourcc |= ((unsigned long)format[i]) << (i * 8); + } + return(fourcc); + } + + /** @internal type unsafe error API (don't use) */ + extern int _zbar_error_spew(const void* object, + int verbosity); + extern const char* _zbar_error_string(const void* object, + int verbosity); + extern zbar_error_t _zbar_get_error_code(const void* object); + + /*@}*/ + + struct zbar_symbol_s; + typedef struct zbar_symbol_s zbar_symbol_t; + + struct zbar_symbol_set_s; + typedef struct zbar_symbol_set_s zbar_symbol_set_t; + + + /*------------------------------------------------------------*/ + /** @name Symbol interface + * decoded barcode symbol result object. stores type, data, and image + * location of decoded symbol. all memory is owned by the library + */ + /*@{*/ + + /** @typedef zbar_symbol_t + * opaque decoded symbol object. + */ + + /** symbol reference count manipulation. + * increment the reference count when you store a new reference to the + * symbol. decrement when the reference is no longer used. do not + * refer to the symbol once the count is decremented and the + * containing image has been recycled or destroyed. + * @note the containing image holds a reference to the symbol, so you + * only need to use this if you keep a symbol after the image has been + * destroyed or reused. + * @since 0.9 + */ + extern void zbar_symbol_ref(const zbar_symbol_t* symbol, + int refs); + + /** retrieve type of decoded symbol. + * @returns the symbol type + */ + extern zbar_symbol_type_t zbar_symbol_get_type(const zbar_symbol_t* symbol); + + /** retrieve symbology boolean config settings. + * @returns a bitmask indicating which configs were set for the detected + * symbology during decoding. + * @since 0.11 + */ + extern unsigned int zbar_symbol_get_configs(const zbar_symbol_t* symbol); + + /** retrieve symbology modifier flag settings. + * @returns a bitmask indicating which characteristics were detected + * during decoding. + * @since 0.11 + */ + extern unsigned int zbar_symbol_get_modifiers(const zbar_symbol_t* symbol); + + /** retrieve data decoded from symbol. + * @returns the data string + */ + extern const char* zbar_symbol_get_data(const zbar_symbol_t* symbol); + + /** retrieve length of binary data. + * @returns the length of the decoded data + */ + extern unsigned int zbar_symbol_get_data_length(const zbar_symbol_t* symbol); + + /** retrieve a symbol confidence metric. + * @returns an unscaled, relative quantity: larger values are better + * than smaller values, where "large" and "small" are application + * dependent. + * @note expect the exact definition of this quantity to change as the + * metric is refined. currently, only the ordered relationship + * between two values is defined and will remain stable in the future + * @since 0.9 + */ + extern int zbar_symbol_get_quality(const zbar_symbol_t* symbol); + + /** 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 + */ + extern int zbar_symbol_get_count(const zbar_symbol_t* symbol); + + /** retrieve the number of points in the location polygon. the + * location polygon defines the image area that the symbol was + * extracted from. + * @returns the number of points in the location polygon + * @note this is currently not a polygon, but the scan locations + * where the symbol was decoded + */ + extern unsigned zbar_symbol_get_loc_size(const zbar_symbol_t* symbol); + + /** retrieve location polygon x-coordinates. + * points are specified by 0-based index. + * @returns the x-coordinate for a point in the location polygon. + * @returns -1 if index is out of range + */ + extern int zbar_symbol_get_loc_x(const zbar_symbol_t* symbol, + unsigned index); + + /** retrieve location polygon y-coordinates. + * points are specified by 0-based index. + * @returns the y-coordinate for a point in the location polygon. + * @returns -1 if index is out of range + */ + extern int zbar_symbol_get_loc_y(const zbar_symbol_t* symbol, + unsigned index); + + /** retrieve general orientation of decoded symbol. + * @returns a coarse, axis-aligned indication of symbol orientation or + * ::ZBAR_ORIENT_UNKNOWN if unknown + * @since 0.11 + */ + extern zbar_orientation_t + zbar_symbol_get_orientation(const zbar_symbol_t* symbol); + + /** iterate the set to which this symbol belongs (there can be only one). + * @returns the next symbol in the set, or + * @returns NULL when no more results are available + */ + extern const zbar_symbol_t* zbar_symbol_next(const zbar_symbol_t* symbol); + + /** retrieve components of a composite result. + * @returns the symbol set containing the components + * @returns NULL if the symbol is already a physical symbol + * @since 0.10 + */ + extern const zbar_symbol_set_t* + zbar_symbol_get_components(const zbar_symbol_t* symbol); + + /** iterate components of a composite result. + * @returns the first physical component symbol of a composite result + * @returns NULL if the symbol is already a physical symbol + * @since 0.10 + */ + extern const zbar_symbol_t* + zbar_symbol_first_component(const zbar_symbol_t* symbol); + + /** print XML symbol element representation to user result buffer. + * @see http://zbar.sourceforge.net/2008/barcode.xsd for the schema. + * @param symbol is the symbol to print + * @param buffer is the inout result pointer, it will be reallocated + * with a larger size if necessary. + * @param buflen is inout length of the result buffer. + * @returns the buffer pointer + * @since 0.6 + */ + extern char* zbar_symbol_xml(const zbar_symbol_t* symbol, + char** buffer, + unsigned* buflen); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Symbol Set interface + * container for decoded result symbols associated with an image + * or a composite symbol. + * @since 0.10 + */ + /*@{*/ + + /** @typedef zbar_symbol_set_t + * opaque symbol iterator object. + * @since 0.10 + */ + + /** reference count manipulation. + * increment the reference count when you store a new reference. + * decrement when the reference is no longer used. do not refer to + * the object any longer once references have been released. + * @since 0.10 + */ + extern void zbar_symbol_set_ref(const zbar_symbol_set_t* symbols, + int refs); + + /** retrieve set size. + * @returns the number of symbols in the set. + * @since 0.10 + */ + extern int zbar_symbol_set_get_size(const zbar_symbol_set_t* symbols); + + /** set iterator. + * @returns the first decoded symbol result in a set + * @returns NULL if the set is empty + * @since 0.10 + */ + extern const zbar_symbol_t* + zbar_symbol_set_first_symbol(const zbar_symbol_set_t* symbols); + + /** raw result iterator. + * @returns the first decoded symbol result in a set, *before* filtering + * @returns NULL if the set is empty + * @since 0.11 + */ + extern const zbar_symbol_t* + zbar_symbol_set_first_unfiltered(const zbar_symbol_set_t* symbols); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Image interface + * stores image data samples along with associated format and size + * metadata + */ + /*@{*/ + + struct zbar_image_s; + /** opaque image object. */ + typedef struct zbar_image_s zbar_image_t; + + /** cleanup handler callback function. + * called to free sample data when an image is destroyed. + */ + typedef void (zbar_image_cleanup_handler_t)(zbar_image_t* image); + + /** data handler callback function. + * called when decoded symbol results are available for an image + */ + typedef void (zbar_image_data_handler_t)(zbar_image_t* image, + const void* userdata); + + /** new image constructor. + * @returns a new image object with uninitialized data and format. + * this image should be destroyed (using zbar_image_destroy()) as + * soon as the application is finished with it + */ + extern zbar_image_t* zbar_image_create(void); + + /** image destructor. all images created by or returned to the + * application should be destroyed using this function. when an image + * is destroyed, the associated data cleanup handler will be invoked + * if available + * @note make no assumptions about the image or the data buffer. + * they may not be destroyed/cleaned immediately if the library + * is still using them. if necessary, use the cleanup handler hook + * to keep track of image data buffers + */ + extern void zbar_image_destroy(zbar_image_t* image); + + /** image reference count manipulation. + * increment the reference count when you store a new reference to the + * image. decrement when the reference is no longer used. do not + * refer to the image any longer once the count is decremented. + * zbar_image_ref(image, -1) is the same as zbar_image_destroy(image) + * @since 0.5 + */ + extern void zbar_image_ref(zbar_image_t* image, + int refs); + + /** image format conversion. refer to the documentation for supported + * image formats + * @returns a @em new image with the sample data from the original image + * converted to the requested format. the original image is + * unaffected. + * @note the converted image size may be rounded (up) due to format + * constraints + */ + extern zbar_image_t* zbar_image_convert(const zbar_image_t* image, + unsigned long format); + + /** image format conversion with crop/pad. + * if the requested size is larger than the image, the last row/column + * are duplicated to cover the difference. if the requested size is + * smaller than the image, the extra rows/columns are dropped from the + * right/bottom. + * @returns a @em new image with the sample data from the original + * image converted to the requested format and size. + * @note the image is @em not scaled + * @see zbar_image_convert() + * @since 0.4 + */ + extern zbar_image_t* zbar_image_convert_resize(const zbar_image_t* image, + unsigned long format, + unsigned width, + unsigned height); + + /** retrieve the image format. + * @returns the fourcc describing the format of the image sample data + */ + extern unsigned long zbar_image_get_format(const zbar_image_t* image); + + /** retrieve a "sequence" (page/frame) number associated with this image. + * @since 0.6 + */ + extern unsigned zbar_image_get_sequence(const zbar_image_t* image); + + /** retrieve the width of the image. + * @returns the width in sample columns + */ + extern unsigned zbar_image_get_width(const zbar_image_t* image); + + /** retrieve the height of the image. + * @returns the height in sample rows + */ + extern unsigned zbar_image_get_height(const zbar_image_t* image); + + /** retrieve both dimensions of the image. + * fills in the width and height in samples + */ + extern void zbar_image_get_size(const zbar_image_t* image, + unsigned* width, + unsigned* height); + + /** retrieve the crop rectangle. + * fills in the image coordinates of the upper left corner and size + * of an axis-aligned rectangular area of the image that will be scanned. + * defaults to the full image + * @since 0.11 + */ + extern void zbar_image_get_crop(const zbar_image_t* image, + unsigned* x, + unsigned* y, + unsigned* width, + unsigned* height); + + /** return the image sample data. the returned data buffer is only + * valid until zbar_image_destroy() is called + */ + extern const void* zbar_image_get_data(const zbar_image_t* image); + + /** return the size of image data. + * @since 0.6 + */ + extern unsigned long zbar_image_get_data_length(const zbar_image_t* img); + + /** retrieve the decoded results. + * @returns the (possibly empty) set of decoded symbols + * @returns NULL if the image has not been scanned + * @since 0.10 + */ + extern const zbar_symbol_set_t* + zbar_image_get_symbols(const zbar_image_t* image); + + /** associate the specified symbol set with the image, replacing any + * existing results. use NULL to release the current results from the + * image. + * @see zbar_image_scanner_recycle_image() + * @since 0.10 + */ + extern void zbar_image_set_symbols(zbar_image_t* image, + const zbar_symbol_set_t* symbols); + + /** image_scanner decode result iterator. + * @returns the first decoded symbol result for an image + * or NULL if no results are available + */ + extern const zbar_symbol_t* + zbar_image_first_symbol(const zbar_image_t* image); + + /** specify the fourcc image format code for image sample data. + * refer to the documentation for supported formats. + * @note this does not convert the data! + * (see zbar_image_convert() for that) + */ + extern void zbar_image_set_format(zbar_image_t* image, + unsigned long format); + + /** associate a "sequence" (page/frame) number with this image. + * @since 0.6 + */ + extern void zbar_image_set_sequence(zbar_image_t* image, + unsigned sequence_num); + + /** specify the pixel size of the image. + * @note this also resets the crop rectangle to the full image + * (0, 0, width, height) + * @note this does not affect the data! + */ + extern void zbar_image_set_size(zbar_image_t* image, + unsigned width, + unsigned height); + + /** specify a rectangular region of the image to scan. + * the rectangle will be clipped to the image boundaries. + * defaults to the full image specified by zbar_image_set_size() + */ + extern void zbar_image_set_crop(zbar_image_t* image, + unsigned x, + unsigned y, + unsigned width, + unsigned height); + + /** specify image sample data. when image data is no longer needed by + * the library the specific data cleanup handler will be called + * (unless NULL) + * @note application image data will not be modified by the library + */ + extern void zbar_image_set_data(zbar_image_t* image, + const void* data, + unsigned long data_byte_length, + zbar_image_cleanup_handler_t* cleanup_hndlr); + + /** built-in cleanup handler. + * passes the image data buffer to free() + */ + extern void zbar_image_free_data(zbar_image_t* image); + + /** associate user specified data value with an image. + * @since 0.5 + */ + extern void zbar_image_set_userdata(zbar_image_t* image, + void* userdata); + + /** return user specified data value associated with the image. + * @since 0.5 + */ + extern void* zbar_image_get_userdata(const zbar_image_t* image); + + /** dump raw image data to a file for debug. + * the data will be prefixed with a 16 byte header consisting of: + * - 4 bytes uint = 0x676d697a ("zimg") + * - 4 bytes format fourcc + * - 2 bytes width + * - 2 bytes height + * - 4 bytes size of following image data in bytes + * this header can be dumped w/eg: + * @verbatim + od -Ax -tx1z -N16 -w4 [file] + @endverbatim + * for some formats the image can be displayed/converted using + * ImageMagick, eg: + * @verbatim + display -size 640x480+16 [-depth ?] [-sampling-factor ?x?] \ + {GRAY,RGB,UYVY,YUV}:[file] + @endverbatim + * + * @param image the image object to dump + * @param filebase base filename, appended with ".XXXX.zimg" where + * XXXX is the format fourcc + * @returns 0 on success or a system error code on failure + */ + extern int zbar_image_write(const zbar_image_t* image, + const char* filebase); + + /** read back an image in the format written by zbar_image_write() + * @note TBD + */ + extern zbar_image_t* zbar_image_read(char* filename); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Processor interface + * @anchor c-processor + * high-level self-contained image processor. + * processes video and images for barcodes, optionally displaying + * images to a library owned output window + */ + /*@{*/ + + struct zbar_processor_s; + /** opaque standalone processor object. */ + typedef struct zbar_processor_s zbar_processor_t; + + /** constructor. + * if threaded is set and threading is available the processor + * will spawn threads where appropriate to avoid blocking and + * improve responsiveness + */ + extern zbar_processor_t* zbar_processor_create(int threaded); + + /** destructor. cleans up all resources associated with the processor + */ + extern void zbar_processor_destroy(zbar_processor_t* processor); + + /** (re)initialization. + * opens a video input device and/or prepares to display output + */ + extern int zbar_processor_init(zbar_processor_t* processor, + const char* video_device, + int enable_display); + + /** request a preferred size for the video image from the device. + * the request may be adjusted or completely ignored by the driver. + * @note must be called before zbar_processor_init() + * @since 0.6 + */ + extern int zbar_processor_request_size(zbar_processor_t* processor, + unsigned width, + unsigned height); + + /** request a preferred video driver interface version for + * debug/testing. + * @note must be called before zbar_processor_init() + * @since 0.6 + */ + extern int zbar_processor_request_interface(zbar_processor_t* processor, + int version); + + /** request a preferred video I/O mode for debug/testing. You will + * get errors if the driver does not support the specified mode. + * @verbatim + 0 = auto-detect + 1 = force I/O using read() + 2 = force memory mapped I/O using mmap() + 3 = force USERPTR I/O (v4l2 only) + @endverbatim + * @note must be called before zbar_processor_init() + * @since 0.7 + */ + extern int zbar_processor_request_iomode(zbar_processor_t* video, + int iomode); + + /** force specific input and output formats for debug/testing. + * @note must be called before zbar_processor_init() + */ + extern int zbar_processor_force_format(zbar_processor_t* processor, + unsigned long input_format, + unsigned long output_format); + + /** setup result handler callback. + * the specified function will be called by the processor whenever + * new results are available from the video stream or a static image. + * pass a NULL value to disable callbacks. + * @param processor the object on which to set the handler. + * @param handler the function to call when new results are available. + * @param userdata is set as with zbar_processor_set_userdata(). + * @returns the previously registered handler + */ + extern zbar_image_data_handler_t* + zbar_processor_set_data_handler(zbar_processor_t* processor, + zbar_image_data_handler_t* handler, + const void* userdata); + + /** associate user specified data value with the processor. + * @since 0.6 + */ + extern void zbar_processor_set_userdata(zbar_processor_t* processor, + void* userdata); + + /** return user specified data value associated with the processor. + * @since 0.6 + */ + extern void* zbar_processor_get_userdata(const zbar_processor_t* processor); + + /** set config for indicated symbology (0 for all) to specified value. + * @returns 0 for success, non-0 for failure (config does not apply to + * specified symbology, or value out of range) + * @see zbar_decoder_set_config() + * @since 0.4 + */ + extern int zbar_processor_set_config(zbar_processor_t* processor, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); + + /** parse configuration string using zbar_parse_config() + * and apply to processor using zbar_processor_set_config(). + * @returns 0 for success, non-0 for failure + * @see zbar_parse_config() + * @see zbar_processor_set_config() + * @since 0.4 + */ + static __inline int zbar_processor_parse_config(zbar_processor_t* processor, + const char* config_string) + { + zbar_symbol_type_t sym; + zbar_config_t cfg; + int val; + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_processor_set_config(processor, sym, cfg, val)); + } + + /** retrieve the current state of the ouput window. + * @returns 1 if the output window is currently displayed, 0 if not. + * @returns -1 if an error occurs + */ + extern int zbar_processor_is_visible(zbar_processor_t* processor); + + /** show or hide the display window owned by the library. + * the size will be adjusted to the input size + */ + extern int zbar_processor_set_visible(zbar_processor_t* processor, + int visible); + + /** control the processor in free running video mode. + * only works if video input is initialized. if threading is in use, + * scanning will occur in the background, otherwise this is only + * useful wrapping calls to zbar_processor_user_wait(). if the + * library output window is visible, video display will be enabled. + */ + extern int zbar_processor_set_active(zbar_processor_t* processor, + int active); + + /** retrieve decode results for last scanned image/frame. + * @returns the symbol set result container or NULL if no results are + * available + * @note the returned symbol set has its reference count incremented; + * ensure that the count is decremented after use + * @since 0.10 + */ + extern const zbar_symbol_set_t* + zbar_processor_get_results(const zbar_processor_t* processor); + + /** wait for input to the display window from the user + * (via mouse or keyboard). + * @returns >0 when input is received, 0 if timeout ms expired + * with no input or -1 in case of an error + */ + extern int zbar_processor_user_wait(zbar_processor_t* processor, + int timeout); + + /** process from the video stream until a result is available, + * or the timeout (in milliseconds) expires. + * specify a timeout of -1 to scan indefinitely + * (zbar_processor_set_active() may still be used to abort the scan + * from another thread). + * if the library window is visible, video display will be enabled. + * @note that multiple results may still be returned (despite the + * name). + * @returns >0 if symbols were successfully decoded, + * 0 if no symbols were found (ie, the timeout expired) + * or -1 if an error occurs + */ + extern int zbar_process_one(zbar_processor_t* processor, + int timeout); + + /** process the provided image for barcodes. + * if the library window is visible, the image will be displayed. + * @returns >0 if symbols were successfully decoded, + * 0 if no symbols were found or -1 if an error occurs + */ + extern int zbar_process_image(zbar_processor_t* processor, + zbar_image_t* image); + + /** display detail for last processor error to stderr. + * @returns a non-zero value suitable for passing to exit() + */ + static __inline int + zbar_processor_error_spew(const zbar_processor_t* processor, + int verbosity) + { + return(_zbar_error_spew(processor, verbosity)); + } + + /** retrieve the detail string for the last processor error. */ + static __inline const char* + zbar_processor_error_string(const zbar_processor_t* processor, + int verbosity) + { + return(_zbar_error_string(processor, verbosity)); + } + + /** retrieve the type code for the last processor error. */ + static __inline zbar_error_t + zbar_processor_get_error_code(const zbar_processor_t* processor) + { + return(_zbar_get_error_code(processor)); + } + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Video interface + * @anchor c-video + * mid-level video source abstraction. + * captures images from a video device + */ + /*@{*/ + + struct zbar_video_s; + /** opaque video object. */ + typedef struct zbar_video_s zbar_video_t; + + /** constructor. */ + extern zbar_video_t* zbar_video_create(void); + + /** destructor. */ + extern void zbar_video_destroy(zbar_video_t* video); + + /** open and probe a video device. + * the device specified by platform specific unique name + * (v4l device node path in *nix eg "/dev/video", + * DirectShow DevicePath property in windows). + * @returns 0 if successful or -1 if an error occurs + */ + extern int zbar_video_open(zbar_video_t* video, + const char* device); + + /** retrieve file descriptor associated with open *nix video device + * useful for using select()/poll() to tell when new images are + * available (NB v4l2 only!!). + * @returns the file descriptor or -1 if the video device is not open + * or the driver only supports v4l1 + */ + extern int zbar_video_get_fd(const zbar_video_t* video); + + /** request a preferred size for the video image from the device. + * the request may be adjusted or completely ignored by the driver. + * @returns 0 if successful or -1 if the video device is already + * initialized + * @since 0.6 + */ + extern int zbar_video_request_size(zbar_video_t* video, + unsigned width, + unsigned height); + + /** request a preferred driver interface version for debug/testing. + * @note must be called before zbar_video_open() + * @since 0.6 + */ + extern int zbar_video_request_interface(zbar_video_t* video, + int version); + + /** request a preferred I/O mode for debug/testing. You will get + * errors if the driver does not support the specified mode. + * @verbatim + 0 = auto-detect + 1 = force I/O using read() + 2 = force memory mapped I/O using mmap() + 3 = force USERPTR I/O (v4l2 only) + @endverbatim + * @note must be called before zbar_video_open() + * @since 0.7 + */ + extern int zbar_video_request_iomode(zbar_video_t* video, + int iomode); + + /** retrieve current output image width. + * @returns the width or 0 if the video device is not open + */ + extern int zbar_video_get_width(const zbar_video_t* video); + + /** retrieve current output image height. + * @returns the height or 0 if the video device is not open + */ + extern int zbar_video_get_height(const zbar_video_t* video); + + /** initialize video using a specific format for debug. + * use zbar_negotiate_format() to automatically select and initialize + * the best available format + */ + extern int zbar_video_init(zbar_video_t* video, + unsigned long format); + + /** start/stop video capture. + * all buffered images are retired when capture is disabled. + * @returns 0 if successful or -1 if an error occurs + */ + extern int zbar_video_enable(zbar_video_t* video, + int enable); + + /** retrieve next captured image. blocks until an image is available. + * @returns NULL if video is not enabled or an error occurs + */ + extern zbar_image_t* zbar_video_next_image(zbar_video_t* video); + + /** display detail for last video error to stderr. + * @returns a non-zero value suitable for passing to exit() + */ + static __inline int zbar_video_error_spew(const zbar_video_t* video, + int verbosity) + { + return(_zbar_error_spew(video, verbosity)); + } + + /** retrieve the detail string for the last video error. */ + static __inline const char* zbar_video_error_string(const zbar_video_t* video, + int verbosity) + { + return(_zbar_error_string(video, verbosity)); + } + + /** retrieve the type code for the last video error. */ + static __inline zbar_error_t + zbar_video_get_error_code(const zbar_video_t* video) + { + return(_zbar_get_error_code(video)); + } + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Window interface + * @anchor c-window + * mid-level output window abstraction. + * displays images to user-specified platform specific output window + */ + /*@{*/ + + struct zbar_window_s; + /** opaque window object. */ + typedef struct zbar_window_s zbar_window_t; + + /** constructor. */ + extern zbar_window_t* zbar_window_create(void); + + /** destructor. */ + extern void zbar_window_destroy(zbar_window_t* window); + + /** associate reader with an existing platform window. + * This can be any "Drawable" for X Windows or a "HWND" for windows. + * input images will be scaled into the output window. + * pass NULL to detach from the resource, further input will be + * ignored + */ + extern int zbar_window_attach(zbar_window_t* window, + void* x11_display_w32_hwnd, + unsigned long x11_drawable); + + /** control content level of the reader overlay. + * the overlay displays graphical data for informational or debug + * purposes. higher values increase the level of annotation (possibly + * decreasing performance). @verbatim + 0 = disable overlay + 1 = outline decoded symbols (default) + 2 = also track and display input frame rate + @endverbatim + */ + extern void zbar_window_set_overlay(zbar_window_t* window, + int level); + + /** retrieve current content level of reader overlay. + * @see zbar_window_set_overlay() + * @since 0.10 + */ + extern int zbar_window_get_overlay(const zbar_window_t* window); + + /** draw a new image into the output window. */ + extern int zbar_window_draw(zbar_window_t* window, + zbar_image_t* image); + + /** redraw the last image (exposure handler). */ + extern int zbar_window_redraw(zbar_window_t* window); + + /** resize the image window (reconfigure handler). + * this does @em not update the contents of the window + * @since 0.3, changed in 0.4 to not redraw window + */ + extern int zbar_window_resize(zbar_window_t* window, + unsigned width, + unsigned height); + + /** display detail for last window error to stderr. + * @returns a non-zero value suitable for passing to exit() + */ + static __inline int zbar_window_error_spew(const zbar_window_t* window, + int verbosity) + { + return(_zbar_error_spew(window, verbosity)); + } + + /** retrieve the detail string for the last window error. */ + static __inline const char* + zbar_window_error_string(const zbar_window_t* window, + int verbosity) + { + return(_zbar_error_string(window, verbosity)); + } + + /** retrieve the type code for the last window error. */ + static __inline zbar_error_t + zbar_window_get_error_code(const zbar_window_t* window) + { + return(_zbar_get_error_code(window)); + } + + + /** select a compatible format between video input and output window. + * the selection algorithm attempts to use a format shared by + * video input and window output which is also most useful for + * barcode scanning. if a format conversion is necessary, it will + * heuristically attempt to minimize the cost of the conversion + */ + extern int zbar_negotiate_format(zbar_video_t* video, + zbar_window_t* window); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Image Scanner interface + * @anchor c-imagescanner + * mid-level image scanner interface. + * reads barcodes from 2-D images + */ + /*@{*/ + + struct zbar_image_scanner_s; + /** opaque image scanner object. */ + typedef struct zbar_image_scanner_s zbar_image_scanner_t; + + /** constructor. */ + extern zbar_image_scanner_t* zbar_image_scanner_create(void); + + /** destructor. */ + extern void zbar_image_scanner_destroy(zbar_image_scanner_t* scanner); + + /** setup result handler callback. + * the specified function will be called by the scanner whenever + * new results are available from a decoded image. + * pass a NULL value to disable callbacks. + * @returns the previously registered handler + */ + extern zbar_image_data_handler_t* + zbar_image_scanner_set_data_handler(zbar_image_scanner_t* scanner, + zbar_image_data_handler_t* handler, + const void* userdata); + + + /** set config for indicated symbology (0 for all) to specified value. + * @returns 0 for success, non-0 for failure (config does not apply to + * specified symbology, or value out of range) + * @see zbar_decoder_set_config() + * @since 0.4 + */ + extern int zbar_image_scanner_set_config(zbar_image_scanner_t* scanner, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); + + /** parse configuration string using zbar_parse_config() + * and apply to image scanner using zbar_image_scanner_set_config(). + * @returns 0 for success, non-0 for failure + * @see zbar_parse_config() + * @see zbar_image_scanner_set_config() + * @since 0.4 + */ + static __inline int + zbar_image_scanner_parse_config(zbar_image_scanner_t* scanner, + const char* config_string) + { + zbar_symbol_type_t sym; + zbar_config_t cfg; + int val; + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_image_scanner_set_config(scanner, sym, cfg, val)); + } + + /** 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. + * this interface also clears the cache + */ + extern void zbar_image_scanner_enable_cache(zbar_image_scanner_t* scanner, + int enable); + + /** remove any previously decoded results from the image scanner and the + * specified image. somewhat more efficient version of + * zbar_image_set_symbols(image, NULL) which may retain memory for + * subsequent decodes + * @since 0.10 + */ + extern void zbar_image_scanner_recycle_image(zbar_image_scanner_t* scanner, + zbar_image_t* image); + + /** retrieve decode results for last scanned image. + * @returns the symbol set result container or NULL if no results are + * available + * @note the symbol set does not have its reference count adjusted; + * ensure that the count is incremented if the results may be kept + * after the next image is scanned + * @since 0.10 + */ + extern const zbar_symbol_set_t* + zbar_image_scanner_get_results(const zbar_image_scanner_t* scanner); + + /** scan for symbols in provided image. The image format must be + * "Y800" or "GRAY". + * @returns >0 if symbols were successfully decoded from the image, + * 0 if no symbols were found or -1 if an error occurs + * @see zbar_image_convert() + * @since 0.9 - changed to only accept grayscale images + */ + extern int zbar_scan_image(zbar_image_scanner_t* scanner, + zbar_image_t* image); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Decoder interface + * @anchor c-decoder + * low-level bar width stream decoder interface. + * identifies symbols and extracts encoded data + */ + /*@{*/ + + struct zbar_decoder_s; + /** opaque decoder object. */ + typedef struct zbar_decoder_s zbar_decoder_t; + + /** decoder data handler callback function. + * called by decoder when new data has just been decoded + */ + typedef void (zbar_decoder_handler_t)(zbar_decoder_t* decoder); + + /** constructor. */ + extern zbar_decoder_t* zbar_decoder_create(void); + + /** destructor. */ + extern void zbar_decoder_destroy(zbar_decoder_t* decoder); + + /** set config for indicated symbology (0 for all) to specified value. + * @returns 0 for success, non-0 for failure (config does not apply to + * specified symbology, or value out of range) + * @since 0.4 + */ + extern int zbar_decoder_set_config(zbar_decoder_t* decoder, + zbar_symbol_type_t symbology, + zbar_config_t config, + int value); + + /** parse configuration string using zbar_parse_config() + * and apply to decoder using zbar_decoder_set_config(). + * @returns 0 for success, non-0 for failure + * @see zbar_parse_config() + * @see zbar_decoder_set_config() + * @since 0.4 + */ + static __inline int zbar_decoder_parse_config(zbar_decoder_t* decoder, + const char* config_string) + { + zbar_symbol_type_t sym; + zbar_config_t cfg; + int val; + return(zbar_parse_config(config_string, &sym, &cfg, &val) || + zbar_decoder_set_config(decoder, sym, cfg, val)); + } + + /** retrieve symbology boolean config settings. + * @returns a bitmask indicating which configs are currently set for the + * specified symbology. + * @since 0.11 + */ + extern unsigned int zbar_decoder_get_configs(const zbar_decoder_t* decoder, + zbar_symbol_type_t symbology); + + /** clear all decoder state. + * any partial symbols are flushed + */ + extern void zbar_decoder_reset(zbar_decoder_t* decoder); + + /** mark start of a new scan pass. + * clears any intra-symbol state and resets color to ::ZBAR_SPACE. + * any partially decoded symbol state is retained + */ + extern void zbar_decoder_new_scan(zbar_decoder_t* decoder); + + /** process next bar/space width from input stream. + * the width is in arbitrary relative units. first value of a scan + * is ::ZBAR_SPACE width, alternating from there. + * @returns appropriate symbol type if width completes + * decode of a symbol (data is available for retrieval) + * @returns ::ZBAR_PARTIAL as a hint if part of a symbol was decoded + * @returns ::ZBAR_NONE (0) if no new symbol data is available + */ + extern zbar_symbol_type_t zbar_decode_width(zbar_decoder_t* decoder, + unsigned width); + + /** retrieve color of @em next element passed to + * zbar_decode_width(). */ + extern zbar_color_t zbar_decoder_get_color(const zbar_decoder_t* decoder); + + /** retrieve last decoded data. + * @returns the data string or NULL if no new data available. + * the returned data buffer is owned by library, contents are only + * valid between non-0 return from zbar_decode_width and next library + * call + */ + extern const char* zbar_decoder_get_data(const zbar_decoder_t* decoder); + + /** retrieve length of binary data. + * @returns the length of the decoded data or 0 if no new data + * available. + */ + extern unsigned int + zbar_decoder_get_data_length(const zbar_decoder_t* decoder); + + /** retrieve last decoded symbol type. + * @returns the type or ::ZBAR_NONE if no new data available + */ + extern zbar_symbol_type_t + zbar_decoder_get_type(const zbar_decoder_t* decoder); + + /** retrieve modifier flags for the last decoded symbol. + * @returns a bitmask indicating which characteristics were detected + * during decoding. + * @since 0.11 + */ + extern unsigned int zbar_decoder_get_modifiers(const zbar_decoder_t* decoder); + + /** retrieve last decode direction. + * @returns 1 for forward and -1 for reverse + * @returns 0 if the decode direction is unknown or does not apply + * @since 0.11 + */ + extern int zbar_decoder_get_direction(const zbar_decoder_t* decoder); + + /** setup data handler callback. + * the registered function will be called by the decoder + * just before zbar_decode_width() returns a non-zero value. + * pass a NULL value to disable callbacks. + * @returns the previously registered handler + */ + extern zbar_decoder_handler_t* + zbar_decoder_set_handler(zbar_decoder_t* decoder, + zbar_decoder_handler_t* handler); + + /** associate user specified data value with the decoder. */ + extern void zbar_decoder_set_userdata(zbar_decoder_t* decoder, + void* userdata); + + /** return user specified data value associated with the decoder. */ + extern void* zbar_decoder_get_userdata(const zbar_decoder_t* decoder); + + /*@}*/ + + /*------------------------------------------------------------*/ + /** @name Scanner interface + * @anchor c-scanner + * low-level linear intensity sample stream scanner interface. + * identifies "bar" edges and measures width between them. + * optionally passes to bar width decoder + */ + /*@{*/ + + struct zbar_scanner_s; + /** opaque scanner object. */ + typedef struct zbar_scanner_s zbar_scanner_t; + + /** constructor. + * if decoder is non-NULL it will be attached to scanner + * and called automatically at each new edge + * current color is initialized to ::ZBAR_SPACE + * (so an initial BAR->SPACE transition may be discarded) + */ + extern zbar_scanner_t* zbar_scanner_create(zbar_decoder_t* decoder); + + /** destructor. */ + extern void zbar_scanner_destroy(zbar_scanner_t* scanner); + + /** clear all scanner state. + * also resets an associated decoder + */ + extern zbar_symbol_type_t zbar_scanner_reset(zbar_scanner_t* scanner); + + /** mark start of a new scan pass. resets color to ::ZBAR_SPACE. + * also updates an associated decoder. + * @returns any decode results flushed from the pipeline + * @note when not using callback handlers, the return value should + * be checked the same as zbar_scan_y() + * @note call zbar_scanner_flush() at least twice before calling this + * method to ensure no decode results are lost + */ + extern zbar_symbol_type_t zbar_scanner_new_scan(zbar_scanner_t* scanner); + + /** flush scanner processing pipeline. + * forces current scanner position to be a scan boundary. + * call multiple times (max 3) to completely flush decoder. + * @returns any decode/scan results flushed from the pipeline + * @note when not using callback handlers, the return value should + * be checked the same as zbar_scan_y() + * @since 0.9 + */ + extern zbar_symbol_type_t zbar_scanner_flush(zbar_scanner_t* scanner); + + /** process next sample intensity value. + * intensity (y) is in arbitrary relative units. + * @returns result of zbar_decode_width() if a decoder is attached, + * otherwise @returns (::ZBAR_PARTIAL) when new edge is detected + * or 0 (::ZBAR_NONE) if no new edge is detected + */ + extern zbar_symbol_type_t zbar_scan_y(zbar_scanner_t* scanner, + int y); + + /** process next sample from RGB (or BGR) triple. */ + static __inline zbar_symbol_type_t zbar_scan_rgb24(zbar_scanner_t* scanner, + unsigned char* rgb) + { + return(zbar_scan_y(scanner, rgb[0] + rgb[1] + rgb[2])); + } + + /** retrieve last scanned width. */ + extern unsigned zbar_scanner_get_width(const zbar_scanner_t* scanner); + + /** retrieve sample position of last edge. + * @since 0.10 + */ + extern unsigned zbar_scanner_get_edge(const zbar_scanner_t* scn, + unsigned offset, + int prec); + + /** retrieve last scanned color. */ + extern zbar_color_t zbar_scanner_get_color(const zbar_scanner_t* scanner); + + /*@}*/ + +#ifdef __cplusplus + } +} + +# include "zbar/Exception.h" +# include "zbar/Decoder.h" +# include "zbar/Scanner.h" +# include "zbar/Symbol.h" +# include "zbar/Image.h" +# include "zbar/ImageScanner.h" +# include "zbar/Video.h" +# include "zbar/Window.h" +# include "zbar/Processor.h" +#endif + +#endif diff --git a/ImageProcess/include/zbar/Decoder.h b/ImageProcess/include/zbar/Decoder.h new file mode 100644 index 0000000..27e78d8 --- /dev/null +++ b/ImageProcess/include/zbar/Decoder.h @@ -0,0 +1,202 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_DECODER_H_ +#define _ZBAR_DECODER_H_ + +/// @file +/// Decoder C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Decoder.h" +#endif + +#include + +namespace zbar { + +/// low-level bar width stream decoder interface. +/// identifies symbols and extracts encoded data + +class Decoder { + public: + + /// Decoder result handler. + /// applications should subtype this and pass an instance to + /// set_handler() to implement result processing + class Handler { + public: + virtual ~Handler() { } + + /// invoked by the Decoder as decode results become available. + virtual void decode_callback(Decoder &decoder) = 0; + }; + + /// constructor. + Decoder () + : _handler(NULL) + { + _decoder = zbar_decoder_create(); + } + + ~Decoder () + { + zbar_decoder_destroy(_decoder); + } + + /// clear all decoder state. + /// see zbar_decoder_reset() + void reset () + { + zbar_decoder_reset(_decoder); + } + + /// mark start of a new scan pass. + /// see zbar_decoder_new_scan() + void new_scan () + { + zbar_decoder_new_scan(_decoder); + } + + /// process next bar/space width from input stream. + /// see zbar_decode_width() + zbar_symbol_type_t decode_width (unsigned width) + { + return(zbar_decode_width(_decoder, width)); + } + + /// process next bar/space width from input stream. + /// see zbar_decode_width() + Decoder& operator<< (unsigned width) + { + zbar_decode_width(_decoder, width); + return(*this); + } + + /// retrieve color of @em next element passed to Decoder. + /// see zbar_decoder_get_color() + zbar_color_t get_color () const + { + return(zbar_decoder_get_color(_decoder)); + } + + /// retrieve last decoded symbol type. + /// see zbar_decoder_get_type() + zbar_symbol_type_t get_type () const + { + return(zbar_decoder_get_type(_decoder)); + } + + /// retrieve string name of last decoded symbol type. + /// see zbar_get_symbol_name() + const char *get_symbol_name () const + { + return(zbar_get_symbol_name(zbar_decoder_get_type(_decoder))); + } + + /// retrieve string name for last decode addon. + /// see zbar_get_addon_name() + /// @deprecated in 0.11 + const char *get_addon_name () const + { + return(zbar_get_addon_name(zbar_decoder_get_type(_decoder))); + } + + /// retrieve last decoded data in ASCII format as a char array. + /// see zbar_decoder_get_data() + const char *get_data_chars() const + { + return(zbar_decoder_get_data(_decoder)); + } + + /// retrieve last decoded data as a std::string. + /// see zbar_decoder_get_data() + const std::string get_data_string() const + { + return(std::string(zbar_decoder_get_data(_decoder), + zbar_decoder_get_data_length(_decoder))); + } + + /// retrieve last decoded data as a std::string. + /// see zbar_decoder_get_data() + const std::string get_data() const + { + return(get_data_string()); + } + + /// retrieve length of decoded binary data. + /// see zbar_decoder_get_data_length() + int get_data_length() const + { + return(zbar_decoder_get_data_length(_decoder)); + } + + /// retrieve last decode direction. + /// see zbar_decoder_get_direction() + /// @since 0.11 + int get_direction() const + { + return(zbar_decoder_get_direction(_decoder)); + } + + /// setup callback to handle result data. + void set_handler (Handler &handler) + { + _handler = &handler; + zbar_decoder_set_handler(_decoder, _cb); + zbar_decoder_set_userdata(_decoder, this); + } + + /// set config for indicated symbology (0 for all) to specified value. + /// @see zbar_decoder_set_config() + /// @since 0.4 + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, + int value) + { + return(zbar_decoder_set_config(_decoder, symbology, config, value)); + } + + /// set config parsed from configuration string. + /// @see zbar_decoder_parse_config() + /// @since 0.4 + int set_config (std::string cfgstr) + { + return(zbar_decoder_parse_config(_decoder, cfgstr.c_str())); + } + + private: + friend class Scanner; + zbar_decoder_t *_decoder; + Handler *_handler; + + static void _cb (zbar_decoder_t *cdcode) + { + Decoder *dcode = (Decoder*)zbar_decoder_get_userdata(cdcode); + if(dcode && dcode->_handler) + dcode->_handler->decode_callback(*dcode); + } +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/Exception.h b/ImageProcess/include/zbar/Exception.h new file mode 100644 index 0000000..a57222e --- /dev/null +++ b/ImageProcess/include/zbar/Exception.h @@ -0,0 +1,187 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2009 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_EXCEPTION_H_ +#define _ZBAR_EXCEPTION_H_ + +/// @file +/// C++ Exception definitions + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Exception.h" +#endif + +#include +#include + +namespace zbar { + +/// base class for exceptions defined by this API. +class Exception : public std::exception { + +public: + /// create exception from C library error + Exception (const void *obj = NULL) + : std::exception(), + _obj(obj) + { } + + ~Exception () throw() { } + + /// retrieve error message + virtual const char* what () const throw() + { + if(!_obj) + return("zbar library unspecified generic error"); + return(_zbar_error_string(_obj, 0)); + } + +private: + const void *_obj; +}; + +/// internal library error. +class InternalError : public Exception { +public: + /// create exception from C library error + InternalError (const void *obj) + : Exception(obj) + { } +}; + +/// unsupported request. +class UnsupportedError : public Exception { +public: + /// create exception from C library error + UnsupportedError (const void *obj) + : Exception(obj) + { } +}; + +/// invalid request. +class InvalidError : public Exception { +public: + /// create exception from C library error + InvalidError (const void *obj) + : Exception(obj) + { } +}; + +/// failed system call. +class SystemError : public Exception { +public: + /// create exception from C library error + SystemError (const void *obj) + : Exception(obj) + { } +}; + +/// locking error. +class LockingError : public Exception { +public: + /// create exception from C library error + LockingError (const void *obj) + : Exception(obj) + { } +}; + +/// all resources busy. +class BusyError : public Exception { +public: + /// create exception from C library error + BusyError (const void *obj) + : Exception(obj) + { } +}; + +/// X11 display error. +class XDisplayError : public Exception { +public: + /// create exception from C library error + XDisplayError (const void *obj) + : Exception(obj) + { } +}; + +/// X11 protocol error. +class XProtoError : public Exception { +public: + /// create exception from C library error + XProtoError (const void *obj) + : Exception(obj) + { } +}; + +/// output window is closed. +class ClosedError : public Exception { +public: + /// create exception from C library error + ClosedError (const void *obj) + : Exception(obj) + { } +}; + +/// image format error +class FormatError : public Exception { + // FIXME needs c equivalent + + virtual const char* what () const throw() + { + // FIXME what format? + return("unsupported format"); + } +}; + +/// @internal + +/// extract error information and create exception. +static __inline std::exception throw_exception (const void *obj) +{ + switch(_zbar_get_error_code(obj)) { + case ZBAR_ERR_NOMEM: + throw std::bad_alloc(); + case ZBAR_ERR_INTERNAL: + throw InternalError(obj); + case ZBAR_ERR_UNSUPPORTED: + throw UnsupportedError(obj); + case ZBAR_ERR_INVALID: + throw InvalidError(obj); + case ZBAR_ERR_SYSTEM: + throw SystemError(obj); + case ZBAR_ERR_LOCKING: + throw LockingError(obj); + case ZBAR_ERR_BUSY: + throw BusyError(obj); + case ZBAR_ERR_XDISPLAY: + throw XDisplayError(obj); + case ZBAR_ERR_XPROTO: + throw XProtoError(obj); + case ZBAR_ERR_CLOSED: + throw ClosedError(obj); + default: + throw Exception(obj); + } +} + +} + +#endif diff --git a/ImageProcess/include/zbar/Image.h b/ImageProcess/include/zbar/Image.h new file mode 100644 index 0000000..713b1f9 --- /dev/null +++ b/ImageProcess/include/zbar/Image.h @@ -0,0 +1,329 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_IMAGE_H_ +#define _ZBAR_IMAGE_H_ + +/// @file +/// Image C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Image.h" +#endif + +#include +#include +#include "Symbol.h" +#include "Exception.h" + +namespace zbar { + +class Video; + +/// stores image data samples along with associated format and size +/// metadata + +class Image { +public: + + /// general Image result handler. + /// applications should subtype this and pass an instance to + /// eg. ImageScanner::set_handler() to implement result processing + class Handler { + public: + virtual ~Handler() { } + + /// invoked by library when Image should be processed + virtual void image_callback(Image &image) = 0; + + /// cast this handler to the C handler + operator zbar_image_data_handler_t* () const + { + return(_cb); + } + + private: + static void _cb (zbar_image_t *zimg, + const void *userdata) + { + if(userdata) { + Image *image = (Image*)zbar_image_get_userdata(zimg); + if(image) + ((Handler*)userdata)->image_callback(*image); + else { + Image tmp(zimg, 1); + ((Handler*)userdata)->image_callback(tmp); + } + } + } + }; + + class SymbolIterator : public zbar::SymbolIterator { + public: + /// default constructor. + SymbolIterator () + : zbar::SymbolIterator() + { } + + /// constructor. + SymbolIterator (const SymbolSet &syms) + : zbar::SymbolIterator(syms) + { } + + /// copy constructor. + SymbolIterator (const SymbolIterator& iter) + : zbar::SymbolIterator(iter) + { } + }; + + /// constructor. + /// create a new Image with the specified parameters + Image (unsigned width = 0, + unsigned height = 0, + const std::string& format = "", + const void *data = NULL, + unsigned long length = 0) + : _img(zbar_image_create()) + { + zbar_image_set_userdata(_img, this); + if(width && height) + set_size(width, height); + if(format.length()) + set_format(format); + if(data && length) + set_data(data, length); + } + + ~Image () + { + if(zbar_image_get_userdata(_img) == this) + zbar_image_set_userdata(_img, NULL); + zbar_image_ref(_img, -1); + } + + /// cast to C image object + operator const zbar_image_t* () const + { + return(_img); + } + + /// cast to C image object + operator zbar_image_t* () + { + return(_img); + } + + /// retrieve the image format. + /// see zbar_image_get_format() + unsigned long get_format () const + { + return(zbar_image_get_format(_img)); + } + + /// specify the fourcc image format code for image sample data. + /// see zbar_image_set_format() + void set_format (unsigned long format) + { + zbar_image_set_format(_img, format); + } + + /// specify the fourcc image format code for image sample data. + /// see zbar_image_set_format() + void set_format (const std::string& format) + { + unsigned long fourcc = zbar_fourcc_parse(format.c_str()); + zbar_image_set_format(_img, fourcc); + } + + /// retrieve a "sequence" (page/frame) number associated with this + /// image. + /// see zbar_image_get_sequence() + /// @since 0.6 + unsigned get_sequence () const + { + return(zbar_image_get_sequence(_img)); + } + + /// associate a "sequence" (page/frame) number with this image. + /// see zbar_image_set_sequence() + /// @since 0.6 + void set_sequence (unsigned sequence_num) + { + zbar_image_set_sequence(_img, sequence_num); + } + + /// retrieve the width of the image. + /// see zbar_image_get_width() + unsigned get_width () const + { + return(zbar_image_get_width(_img)); + } + + /// retrieve the height of the image. + /// see zbar_image_get_height() + unsigned get_height () const + { + return(zbar_image_get_height(_img)); + } + + /// retrieve both dimensions of the image. + /// see zbar_image_get_size() + /// @since 0.11 + void get_size (unsigned &width, + unsigned &height) const + { + zbar_image_get_size(_img, &width, &height); + } + + /// specify the pixel size of the image. + /// see zbar_image_set_size() + void set_size (unsigned width, + unsigned height) + { + zbar_image_set_size(_img, width, height); + } + + /// retrieve the scan crop rectangle. + /// see zbar_image_get_crop() + void get_crop (unsigned &x, + unsigned &y, + unsigned &width, + unsigned &height) const + { + zbar_image_get_crop(_img, &x, &y, &width, &height); + } + + /// set the scan crop rectangle. + /// see zbar_image_set_crop() + void set_crop (unsigned x, + unsigned y, + unsigned width, + unsigned height) + { + zbar_image_set_crop(_img, x, y, width, height); + } + + /// return the image sample data. + /// see zbar_image_get_data() + const void *get_data () const + { + return(zbar_image_get_data(_img)); + } + + /// return the size of the image sample data. + /// see zbar_image_get_data_length() + /// @since 0.6 + unsigned long get_data_length () const + { + return(zbar_image_get_data_length(_img)); + } + + /// specify image sample data. + /// see zbar_image_set_data() + void set_data (const void *data, + unsigned long length) + { + zbar_image_set_data(_img, data, length, _cleanup); + } + + /// image format conversion. + /// see zbar_image_convert() + Image convert (unsigned long format) const + { + zbar_image_t *img = zbar_image_convert(_img, format); + if(img) + return(Image(img)); + throw FormatError(); + } + + /// image format conversion. + /// see zbar_image_convert() + /// @since 0.11 + Image convert (std::string format) const + { + unsigned long fourcc = zbar_fourcc_parse(format.c_str()); + return(convert(fourcc)); + } + + /// image format conversion with crop/pad. + /// see zbar_image_convert_resize() + /// @since 0.4 + Image convert (unsigned long format, + unsigned width, + unsigned height) const + { + zbar_image_t *img = + zbar_image_convert_resize(_img, format, width, height); + if(img) + return(Image(img)); + throw FormatError(); + } + + const SymbolSet get_symbols () const { + return(SymbolSet(zbar_image_get_symbols(_img))); + } + + void set_symbols (const SymbolSet &syms) { + zbar_image_set_symbols(_img, syms); + } + + /// create a new SymbolIterator over decoded results. + SymbolIterator symbol_begin () const { + return(SymbolIterator(get_symbols())); + } + + /// return a SymbolIterator suitable for ending iteration. + SymbolIterator symbol_end () const { + return(SymbolIterator()); + } + +protected: + + friend class Video; + + /// constructor. + /// @internal + /// create a new Image from a zbar_image_t C object + Image (zbar_image_t *src, + int refs = 0) + : _img(src) + { + if(refs) + zbar_image_ref(_img, refs); + zbar_image_set_userdata(_img, this); + } + + /// default data cleanup (noop) + /// @internal + static void _cleanup (zbar_image_t *img) + { + // by default nothing is cleaned + assert(img); + } + +private: + zbar_image_t *_img; +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/ImageScanner.h b/ImageProcess/include/zbar/ImageScanner.h new file mode 100644 index 0000000..bda8433 --- /dev/null +++ b/ImageProcess/include/zbar/ImageScanner.h @@ -0,0 +1,130 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2009 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_IMAGE_SCANNER_H_ +#define _ZBAR_IMAGE_SCANNER_H_ + +/// @file +/// Image Scanner C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/ImageScanner.h" +#endif + +#include "Image.h" + +namespace zbar { + +/// mid-level image scanner interface. +/// reads barcodes from a 2-D Image + +class ImageScanner { +public: + /// constructor. + ImageScanner (zbar_image_scanner_t *scanner = NULL) + { + if(scanner) + _scanner = scanner; + else + _scanner = zbar_image_scanner_create(); + } + + ~ImageScanner () + { + zbar_image_scanner_destroy(_scanner); + } + + /// cast to C image_scanner object + operator zbar_image_scanner_t* () const + { + return(_scanner); + } + + /// setup result handler callback. + void set_handler (Image::Handler &handler) + { + zbar_image_scanner_set_data_handler(_scanner, handler, &handler); + } + + /// set config for indicated symbology (0 for all) to specified value. + /// @see zbar_image_scanner_set_config() + /// @since 0.4 + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, + int value) + { + return(zbar_image_scanner_set_config(_scanner, symbology, + config, value)); + } + + /// set config parsed from configuration string. + /// @see zbar_image_scanner_parse_config() + /// @since 0.4 + int set_config (std::string cfgstr) + { + return(zbar_image_scanner_parse_config(_scanner, cfgstr.c_str())); + } + + /// enable or disable the inter-image result cache. + /// see zbar_image_scanner_enable_cache() + void enable_cache (bool enable = true) + { + zbar_image_scanner_enable_cache(_scanner, enable); + } + + /// remove previous results from scanner and image. + /// @see zbar_image_scanner_recycle_image() + /// @since 0.10 + void recycle_image (Image &image) + { + zbar_image_scanner_recycle_image(_scanner, image); + } + + /// retrieve decode results for last scanned image. + /// @see zbar_image_scanner_get_results() + /// @since 0.10 + const SymbolSet get_results () const { + return(SymbolSet(zbar_image_scanner_get_results(_scanner))); + } + + /// scan for symbols in provided image. + /// see zbar_scan_image() + int scan (Image& image) + { + return(zbar_scan_image(_scanner, image)); + } + + /// scan for symbols in provided image. + /// see zbar_scan_image() + ImageScanner& operator<< (Image& image) + { + scan(image); + return(*this); + } + +private: + zbar_image_scanner_t *_scanner; +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/Processor.h b/ImageProcess/include/zbar/Processor.h new file mode 100644 index 0000000..2622ee8 --- /dev/null +++ b/ImageProcess/include/zbar/Processor.h @@ -0,0 +1,223 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_PROCESSOR_H_ +#define _ZBAR_PROCESSOR_H_ + +/// @file +/// Processor C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Processor.h" +#endif + +#include "Exception.h" +#include "Image.h" + +namespace zbar { + +/// high-level self-contained image processor. +/// processes video and images for barcodes, optionally displaying +/// images to a library owned output window + +class Processor { + public: + /// value to pass for no timeout. + static const int FOREVER = -1; + + /// constructor. + Processor (bool threaded = true, + const char *video_device = "", + bool enable_display = true) + { + _processor = zbar_processor_create(threaded); + if(!_processor) + throw std::bad_alloc(); + init(video_device, enable_display); + } + + ~Processor () + { + zbar_processor_destroy(_processor); + } + + /// cast to C processor object. + operator zbar_processor_t* () + { + return(_processor); + } + + /// opens a video input device and/or prepares to display output. + /// see zbar_processor_init() + void init (const char *video_device = "", + bool enable_display = true) + { + if(zbar_processor_init(_processor, video_device, enable_display)) + throw_exception(_processor); + } + + /// setup result handler callback. + /// see zbar_processor_set_data_handler() + void set_handler (Image::Handler& handler) + { + zbar_processor_set_data_handler(_processor, handler, &handler); + } + + /// set config for indicated symbology (0 for all) to specified value. + /// @see zbar_processor_set_config() + /// @since 0.4 + int set_config (zbar_symbol_type_t symbology, + zbar_config_t config, + int value) + { + return(zbar_processor_set_config(_processor, symbology, + config, value)); + } + + /// set config parsed from configuration string. + /// @see zbar_processor_parse_config() + /// @since 0.4 + int set_config (std::string cfgstr) + { + return(zbar_processor_parse_config(_processor, cfgstr.c_str())); + } + + /// retrieve the current state of the ouput window. + /// see zbar_processor_is_visible() + bool is_visible () + { + int rc = zbar_processor_is_visible(_processor); + if(rc < 0) + throw_exception(_processor); + return(rc != 0); + } + + /// show or hide the display window owned by the library. + /// see zbar_processor_set_visible() + void set_visible (bool visible = true) + { + if(zbar_processor_set_visible(_processor, visible) < 0) + throw_exception(_processor); + } + + /// control the processor in free running video mode. + /// see zbar_processor_set_active() + void set_active (bool active = true) + { + if(zbar_processor_set_active(_processor, active) < 0) + throw_exception(_processor); + } + + /// retrieve decode results for last scanned image. + /// @see zbar_processor_get_results() + /// @since 0.10 + const SymbolSet get_results () const { + return(SymbolSet(zbar_processor_get_results(_processor))); + } + + /// wait for input to the display window from the user. + /// see zbar_processor_user_wait() + int user_wait (int timeout = FOREVER) + { + int rc = zbar_processor_user_wait(_processor, timeout); + if(rc < 0) + throw_exception(_processor); + return(rc); + } + + /// process from the video stream until a result is available. + /// see zbar_process_one() + void process_one (int timeout = FOREVER) + { + if(zbar_process_one(_processor, timeout) < 0) + throw_exception(_processor); + } + + /// process the provided image for barcodes. + /// see zbar_process_image() + void process_image (Image& image) + { + if(zbar_process_image(_processor, image) < 0) + throw_exception(_processor); + } + + /// process the provided image for barcodes. + /// see zbar_process_image() + Processor& operator<< (Image& image) + { + process_image(image); + return(*this); + } + + /// force specific input and output formats for debug/testing. + /// see zbar_processor_force_format() + void force_format (unsigned long input_format, + unsigned long output_format) + { + if(zbar_processor_force_format(_processor, input_format, + output_format)) + throw_exception(_processor); + } + + /// force specific input and output formats for debug/testing. + /// see zbar_processor_force_format() + void force_format (std::string& input_format, + std::string& output_format) + { + unsigned long ifourcc = zbar_fourcc_parse(input_format.c_str()); + unsigned long ofourcc = zbar_fourcc_parse(output_format.c_str()); + if(zbar_processor_force_format(_processor, ifourcc, ofourcc)) + throw_exception(_processor); + } + + /// request a preferred size for the video image from the device. + /// see zbar_processor_request_size() + /// @since 0.6 + void request_size (int width, int height) + { + zbar_processor_request_size(_processor, width, height); + } + + /// request a preferred driver interface version for debug/testing. + /// see zbar_processor_request_interface() + /// @since 0.6 + void request_interface (int version) + { + zbar_processor_request_interface(_processor, version); + } + + /// request a preferred I/O mode for debug/testing. + /// see zbar_processor_request_iomode() + /// @since 0.7 + void request_iomode (int iomode) + { + if(zbar_processor_request_iomode(_processor, iomode)) + throw_exception(_processor); + } + + private: + zbar_processor_t *_processor; +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/QZBar.h b/ImageProcess/include/zbar/QZBar.h new file mode 100644 index 0000000..1044499 --- /dev/null +++ b/ImageProcess/include/zbar/QZBar.h @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------ +// Copyright 2008-2009 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _QZBAR_H_ +#define _QZBAR_H_ + +/// @file +/// Barcode Reader Qt4 Widget + +#include + +namespace zbar { + +class QZBarThread; + +/// barcode reader Qt4 widget. +/// embeds a barcode reader directly into a Qt4 based GUI. the widget +/// can process barcodes from a video source (using the QZBar::videoDevice +/// and QZBar::videoEnabled properties) or from individual QImages +/// supplied to the QZBar::scanImage() slot +/// @since 1.5 + +class QZBar : public QWidget +{ + Q_OBJECT + + /// the currently opened video device. + /// + /// setting a new device opens it and automatically sets + /// QZBar::videoEnabled + /// + /// @see videoDevice(), setVideoDevice() + Q_PROPERTY(QString videoDevice + READ videoDevice + WRITE setVideoDevice + DESIGNABLE false) + + /// video device streaming state. + /// + /// use to pause/resume video scanning. + /// + /// @see isVideoEnabled(), setVideoEnabled() + Q_PROPERTY(bool videoEnabled + READ isVideoEnabled + WRITE setVideoEnabled + DESIGNABLE false) + + /// video device opened state. + /// + /// (re)setting QZBar::videoDevice should eventually cause it + /// to be opened or closed. any errors while streaming/scanning + /// will also cause the device to be closed + /// + /// @see isVideoOpened() + Q_PROPERTY(bool videoOpened + READ isVideoOpened + DESIGNABLE false) + +public: + + /// constructs a barcode reader widget with the given @a parent + QZBar(QWidget *parent = NULL); + + ~QZBar(); + + /// retrieve the currently opened video device. + /// @returns the current video device or the empty string if no + /// device is opened + QString videoDevice() const; + + /// retrieve the current video enabled state. + /// @returns true if video scanning is currently enabled, false + /// otherwise + bool isVideoEnabled() const; + + /// retrieve the current video opened state. + /// @returns true if video device is currently opened, false otherwise + bool isVideoOpened() const; + + /// @{ + /// @internal + + QSize sizeHint() const; + int heightForWidth(int) const; + QPaintEngine *paintEngine() const; + + /// @} + +public Q_SLOTS: + + /// open a new video device. + /// + /// use an empty string to close a currently opened device. + /// + /// @note since opening a device may take some time, this call will + /// return immediately and the device will be opened asynchronously + void setVideoDevice(const QString &videoDevice); + + /// enable/disable video scanning. + /// has no effect unless a video device is opened + void setVideoEnabled(bool videoEnabled = true); + + /// scan for barcodes in a QImage. + void scanImage(const QImage &image); + +Q_SIGNALS: + /// emitted when when a video device is opened or closed. + /// + /// (re)setting QZBar::videoDevice should eventually cause it + /// to be opened or closed. any errors while streaming/scanning + /// will also cause the device to be closed + void videoOpened(bool videoOpened); + + /// emitted when a barcode is decoded from an image. + /// the symbol type and contained data are provided as separate + /// parameters. + void decoded(int type, const QString &data); + + /// emitted when a barcode is decoded from an image. + /// the symbol type name is prefixed to the data, separated by a + /// colon + void decodedText(const QString &text); + + /// @{ + /// @internal + +protected: + void attach(); + void showEvent(QShowEvent*); + void paintEvent(QPaintEvent*); + void resizeEvent(QResizeEvent*); + void changeEvent(QEvent*); + void dragEnterEvent(QDragEnterEvent*); + void dropEvent(QDropEvent*); + +protected Q_SLOTS: + void sizeChange(); + + /// @} + +private: + QZBarThread *thread; + QString _videoDevice; + bool _videoEnabled; + bool _attached; +}; + +}; + +#endif diff --git a/ImageProcess/include/zbar/QZBarImage.h b/ImageProcess/include/zbar/QZBarImage.h new file mode 100644 index 0000000..1505177 --- /dev/null +++ b/ImageProcess/include/zbar/QZBarImage.h @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------ +// Copyright 2008-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _QZBARIMAGE_H_ +#define _QZBARIMAGE_H_ + +/// @file +/// QImage to Image type conversion wrapper + +#include +#include + +namespace zbar { + +/// wrap a QImage and convert into a format suitable for scanning. + +class QZBarImage + : public Image +{ +public: + + /// construct a zbar library image based on an existing QImage. + + QZBarImage (const QImage &qimg) + : qimg(qimg) + { + QImage::Format fmt = qimg.format(); + if(fmt != QImage::Format_RGB32 && + fmt != QImage::Format_ARGB32 && + fmt != QImage::Format_ARGB32_Premultiplied) + throw FormatError(); + + unsigned bpl = qimg.bytesPerLine(); + unsigned width = bpl / 4; + unsigned height = qimg.height(); + set_size(width, height); + set_format(zbar_fourcc('B','G','R','4')); + unsigned long datalen = qimg.numBytes(); + set_data(qimg.bits(), datalen); + + if((width * 4 != bpl) || + (width * height * 4 > datalen)) + throw FormatError(); + } + +private: + QImage qimg; +}; + +}; + + +#endif diff --git a/ImageProcess/include/zbar/Scanner.h b/ImageProcess/include/zbar/Scanner.h new file mode 100644 index 0000000..8c9a756 --- /dev/null +++ b/ImageProcess/include/zbar/Scanner.h @@ -0,0 +1,162 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2009 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_SCANNER_H_ +#define _ZBAR_SCANNER_H_ + +/// @file +/// Scanner C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Scanner.h" +#endif + +#include + +namespace zbar { + +/// low-level linear intensity sample stream scanner interface. +/// identifies "bar" edges and measures width between them. +/// optionally passes to bar width Decoder + +class Scanner { + public: + + /// constructor. + /// @param decoder reference to a Decoder instance which will + /// be passed scan results automatically + Scanner (Decoder& decoder) + { + _scanner = zbar_scanner_create(decoder._decoder); + } + + /// constructor. + /// @param decoder pointer to a Decoder instance which will + /// be passed scan results automatically + Scanner (Decoder* decoder = NULL) + { + zbar_decoder_t *zdcode = NULL; + if(decoder) + zdcode = decoder->_decoder; + _scanner = zbar_scanner_create(zdcode); + } + + ~Scanner () + { + zbar_scanner_destroy(_scanner); + } + + /// clear all scanner state. + /// see zbar_scanner_reset() + void reset () + { + zbar_scanner_reset(_scanner); + } + + /// mark start of a new scan pass. + /// see zbar_scanner_new_scan() + zbar_symbol_type_t new_scan () + { + _type = zbar_scanner_new_scan(_scanner); + return(_type); + } + + /// flush scanner pipeline. + /// see zbar_scanner_flush() + zbar_symbol_type_t flush () + { + _type = zbar_scanner_flush(_scanner); + return(_type); + } + + /// process next sample intensity value. + /// see zbar_scan_y() + zbar_symbol_type_t scan_y (int y) + { + _type = zbar_scan_y(_scanner, y); + return(_type); + } + + /// process next sample intensity value. + /// see zbar_scan_y() + Scanner& operator<< (int y) + { + _type = zbar_scan_y(_scanner, y); + return(*this); + } + + /// process next sample from RGB (or BGR) triple. + /// see zbar_scan_rgb24() + zbar_symbol_type_t scan_rgb24 (unsigned char *rgb) + { + _type = zbar_scan_rgb24(_scanner, rgb); + return(_type); + } + + /// process next sample from RGB (or BGR) triple. + /// see zbar_scan_rgb24() + Scanner& operator<< (unsigned char *rgb) + { + _type = zbar_scan_rgb24(_scanner, rgb); + return(*this); + } + + /// retrieve last scanned width. + /// see zbar_scanner_get_width() + unsigned get_width () const + { + return(zbar_scanner_get_width(_scanner)); + } + + /// retrieve last scanned color. + /// see zbar_scanner_get_color() + zbar_color_t get_color () const + { + return(zbar_scanner_get_color(_scanner)); + } + + /// retrieve last scan result. + zbar_symbol_type_t get_type () const + { + return(_type); + } + + /// cast to C scanner + operator zbar_scanner_t* () const + { + return(_scanner); + } + + /// retrieve C scanner + const zbar_scanner_t *get_c_scanner () const + { + return(_scanner); + } + + private: + zbar_scanner_t *_scanner; + zbar_symbol_type_t _type; +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/Symbol.h b/ImageProcess/include/zbar/Symbol.h new file mode 100644 index 0000000..f601e36 --- /dev/null +++ b/ImageProcess/include/zbar/Symbol.h @@ -0,0 +1,541 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_SYMBOL_H_ +#define _ZBAR_SYMBOL_H_ + +/// @file +/// Symbol C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Symbol.h" +#endif + +#include +#include +#include +#include + +namespace zbar { + +class SymbolIterator; + +/// container for decoded result symbols associated with an image +/// or a composite symbol. + +class SymbolSet { +public: + /// constructor. + SymbolSet (const zbar_symbol_set_t *syms = NULL) + : _syms(syms) + { + ref(); + } + + /// copy constructor. + SymbolSet (const SymbolSet& syms) + : _syms(syms._syms) + { + ref(); + } + + /// destructor. + ~SymbolSet () + { + ref(-1); + } + + /// assignment. + SymbolSet& operator= (const SymbolSet& syms) + { + syms.ref(); + ref(-1); + _syms = syms._syms; + return(*this); + } + + /// truth testing. + bool operator! () const + { + return(!_syms || !get_size()); + } + + /// manipulate reference count. + void ref (int delta = 1) const + { + if(_syms) + zbar_symbol_set_ref((zbar_symbol_set_t*)_syms, delta); + } + + /// cast to C symbol set. + operator const zbar_symbol_set_t* () const + { + return(_syms); + } + + int get_size () const + { + return((_syms) ? zbar_symbol_set_get_size(_syms) : 0); + } + + /// create a new SymbolIterator over decoded results. + SymbolIterator symbol_begin() const; + + /// return a SymbolIterator suitable for ending iteration. + const SymbolIterator symbol_end() const; + +private: + const zbar_symbol_set_t *_syms; +}; + +/// decoded barcode symbol result object. stores type, data, and +/// image location of decoded symbol + +class Symbol { +public: + + /// image pixel location (x, y) coordinate tuple. + class Point { + public: + int x; ///< x-coordinate. + int y; ///< y-coordinate. + + Point () { } + + Point(int x, int y) + : x(x), y(y) + { } + + /// copy constructor. + Point (const Point& pt) + : x(pt.x), + y(pt.y) + { } + + /// assignment. + Point& operator= (const Point& pt) + { + x = pt.x; + y = pt.y; + return(*this); + } + }; + + /// iteration over Point objects in a symbol location polygon. + class PointIterator + : public std::iterator { + + public: + /// constructor. + PointIterator (const Symbol *sym = NULL, + int index = 0) + : _sym(sym), + _index(index) + { + if(sym) + sym->ref(1); + if(!sym || + (unsigned)_index >= zbar_symbol_get_loc_size(*_sym)) + _index = -1; + } + + /// copy constructor. + PointIterator (const PointIterator& iter) + : _sym(iter._sym), + _index(iter._index) + { + if(_sym) + _sym->ref(); + } + + /// destructor. + ~PointIterator () + { + if(_sym) + _sym->ref(-1); + } + + /// assignment. + PointIterator& operator= (const PointIterator& iter) + { + if(iter._sym) + iter._sym->ref(); + if(_sym) + _sym->ref(-1); + _sym = iter._sym; + _index = iter._index; + return(*this); + } + + /// truth testing. + bool operator! () const + { + return(!_sym || _index < 0); + } + + /// advance iterator to next Point. + PointIterator& operator++ () + { + unsigned int i = ++_index; + if(!_sym || i >= zbar_symbol_get_loc_size(*_sym)) + _index = -1; + return(*this); + } + + /// retrieve currently referenced Point. + const Point operator* () const + { + assert(!!*this); + if(!*this) + return(Point()); + return(Point(zbar_symbol_get_loc_x(*_sym, _index), + zbar_symbol_get_loc_y(*_sym, _index))); + } + + /// test if two iterators refer to the same Point in the same + /// Symbol. + bool operator== (const PointIterator& iter) const + { + return(_index == iter._index && + ((_index < 0) || _sym == iter._sym)); + } + + /// test if two iterators refer to the same Point in the same + /// Symbol. + bool operator!= (const PointIterator& iter) const + { + return(!(*this == iter)); + } + + private: + const Symbol *_sym; + int _index; + }; + + /// constructor. + Symbol (const zbar_symbol_t *sym = NULL) + : _xmlbuf(NULL), + _xmllen(0) + { + init(sym); + ref(); + } + + /// copy constructor. + Symbol (const Symbol& sym) + : _sym(sym._sym), + _type(sym._type), + _data(sym._data), + _xmlbuf(NULL), + _xmllen(0) + { + ref(); + } + + /// destructor. + ~Symbol () { + if(_xmlbuf) + free(_xmlbuf); + ref(-1); + } + + /// assignment. + Symbol& operator= (const Symbol& sym) + { + sym.ref(1); + ref(-1); + _sym = sym._sym; + _type = sym._type; + _data = sym._data; + return(*this); + } + + Symbol& operator= (const zbar_symbol_t *sym) + { + if(sym) + zbar_symbol_ref(sym, 1); + ref(-1); + init(sym); + return(*this); + } + + /// truth testing. + bool operator! () const + { + return(!_sym); + } + + void ref (int delta = 1) const + { + if(_sym) + zbar_symbol_ref((zbar_symbol_t*)_sym, delta); + } + + /// cast to C symbol. + operator const zbar_symbol_t* () const + { + return(_sym); + } + + /// test if two Symbol objects refer to the same C symbol. + bool operator== (const Symbol& sym) const + { + return(_sym == sym._sym); + } + + /// test if two Symbol objects refer to the same C symbol. + bool operator!= (const Symbol& sym) const + { + return(!(*this == sym)); + } + + /// retrieve type of decoded symbol. + zbar_symbol_type_t get_type () const + { + return(_type); + } + + /// retrieve the string name of the symbol type. + const std::string get_type_name () const + { + return(zbar_get_symbol_name(_type)); + } + + /// retrieve the string name for any addon. + /// @deprecated in 0.11 + const std::string get_addon_name () const + { + return(zbar_get_addon_name(_type)); + } + + /// retrieve data decoded from symbol. + const std::string get_data () const + { + return(_data); + } + + /// retrieve length of binary data + unsigned get_data_length () const + { + return((_sym) ? zbar_symbol_get_data_length(_sym) : 0); + } + + /// retrieve inter-frame coherency count. + /// see zbar_symbol_get_count() + /// @since 0.5 + int get_count () const + { + return((_sym) ? zbar_symbol_get_count(_sym) : -1); + } + + /// retrieve loosely defined relative quality metric. + /// see zbar_symbol_get_quality() + /// @since 0.11 + int get_quality () const + { + return((_sym) ? zbar_symbol_get_quality(_sym) : 0); + } + + SymbolSet get_components () const + { + return(SymbolSet((_sym) ? zbar_symbol_get_components(_sym) : NULL)); + } + + /// create a new PointIterator at the start of the location + /// polygon. + PointIterator point_begin() const + { + return(PointIterator(this)); + } + + /// return a PointIterator suitable for ending iteration. + const PointIterator point_end() const + { + return(PointIterator()); + } + + /// see zbar_symbol_get_loc_size(). + int get_location_size () const + { + return((_sym) ? zbar_symbol_get_loc_size(_sym) : 0); + } + + /// see zbar_symbol_get_loc_x(). + int get_location_x (unsigned index) const + { + return((_sym) ? zbar_symbol_get_loc_x(_sym, index) : -1); + } + + /// see zbar_symbol_get_loc_y(). + int get_location_y (unsigned index) const + { + return((_sym) ? zbar_symbol_get_loc_y(_sym, index) : -1); + } + + /// see zbar_symbol_get_orientation(). + /// @since 0.11 + int get_orientation () const + { + return(zbar_symbol_get_orientation(_sym)); + } + + /// see zbar_symbol_xml(). + const std::string xml () const + { + if(!_sym) + return(""); + return(zbar_symbol_xml(_sym, (char**)&_xmlbuf, (unsigned*)&_xmllen)); + } + +protected: + /// (re)initialize Symbol from C symbol object. + void init (const zbar_symbol_t *sym = NULL) + { + _sym = sym; + if(sym) { + _type = zbar_symbol_get_type(sym); + _data = std::string(zbar_symbol_get_data(sym), + zbar_symbol_get_data_length(sym)); + } + else { + _type = ZBAR_NONE; + _data = ""; + } + } + +private: + const zbar_symbol_t *_sym; + zbar_symbol_type_t _type; + std::string _data; + char *_xmlbuf; + unsigned _xmllen; +}; + +/// iteration over Symbol result objects in a scanned Image or SymbolSet. +class SymbolIterator + : public std::iterator { + +public: + /// default constructor. + SymbolIterator () + { } + + /// constructor. + SymbolIterator (const SymbolSet &syms) + : _syms(syms) + { + const zbar_symbol_set_t *zsyms = _syms; + if(zsyms) + _sym = zbar_symbol_set_first_symbol(zsyms); + } + + /// copy constructor. + SymbolIterator (const SymbolIterator& iter) + : _syms(iter._syms) + { + const zbar_symbol_set_t *zsyms = _syms; + if(zsyms) + _sym = zbar_symbol_set_first_symbol(zsyms); + } + + ~SymbolIterator () + { + } + + /// assignment. + SymbolIterator& operator= (const SymbolIterator& iter) + { + _syms = iter._syms; + _sym = iter._sym; + return(*this); + } + + bool operator! () const + { + return(!_syms || !_sym); + } + + /// advance iterator to next Symbol. + SymbolIterator& operator++ () + { + if(!!_sym) + _sym = zbar_symbol_next(_sym); + else if(!!_syms) + _sym = zbar_symbol_set_first_symbol(_syms); + return(*this); + } + + /// retrieve currently referenced Symbol. + const Symbol operator* () const + { + return(_sym); + } + + /// access currently referenced Symbol. + const Symbol* operator-> () const + { + return(&_sym); + } + + /// test if two iterators refer to the same Symbol + bool operator== (const SymbolIterator& iter) const + { + // it is enough to test the symbols, as they belong + // to only one set (also simplifies invalid case) + return(_sym == iter._sym); + } + + /// test if two iterators refer to the same Symbol + bool operator!= (const SymbolIterator& iter) const + { + return(!(*this == iter)); + } + + const SymbolIterator end () const { + return(SymbolIterator()); + } + +private: + SymbolSet _syms; + Symbol _sym; +}; + +__inline SymbolIterator SymbolSet::symbol_begin () const { + return(SymbolIterator(*this)); +} + +__inline const SymbolIterator SymbolSet::symbol_end () const { + return(SymbolIterator()); +} + +/// @relates Symbol +/// stream the string representation of a Symbol. +static __inline std::ostream& operator<< (std::ostream& out, + const Symbol& sym) +{ + out << sym.get_type_name() << ":" << sym.get_data(); + return(out); +} + +} + +#endif diff --git a/ImageProcess/include/zbar/Video.h b/ImageProcess/include/zbar/Video.h new file mode 100644 index 0000000..61a49f1 --- /dev/null +++ b/ImageProcess/include/zbar/Video.h @@ -0,0 +1,170 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2010 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_VIDEO_H_ +#define _ZBAR_VIDEO_H_ + +/// @file +/// Video Input C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Video.h" +#endif + +#include "Image.h" + +namespace zbar { + +/// mid-level video source abstraction. +/// captures images from a video device + +class Video { +public: + /// constructor. + Video (zbar_video_t *video = NULL) + { + if(video) + _video = video; + else + _video = zbar_video_create(); + } + + /// constructor. + Video (std::string& device) + { + _video = zbar_video_create(); + open(device); + } + + ~Video () + { + zbar_video_destroy(_video); + } + + /// cast to C video object. + operator zbar_video_t* () const + { + return(_video); + } + + /// open and probe a video device. + void open (std::string& device) + { + if(zbar_video_open(_video, device.c_str())) + throw_exception(_video); + } + + /// close video device if open. + void close () + { + if(zbar_video_open(_video, NULL)) + throw_exception(_video); + } + + /// initialize video using a specific format for debug. + /// see zbar_video_init() + void init (unsigned long fourcc) + { + if(zbar_video_init(_video, fourcc)) + throw_exception(_video); + } + + /// initialize video using a specific format for debug. + /// see zbar_video_init() + void init (std::string& format) + { + unsigned int fourcc = zbar_fourcc_parse(format.c_str()); + if(zbar_video_init(_video, fourcc)) + throw_exception(_video); + } + + /// retrieve file descriptor associated with open *nix video device. + /// see zbar_video_get_fd() + int get_fd () + { + return(zbar_video_get_fd(_video)); + } + + /// retrieve current output image width. + /// see zbar_video_get_width() + int get_width () + { + return(zbar_video_get_width(_video)); + } + + /// retrieve current output image height. + /// see zbar_video_get_height() + int get_height () + { + return(zbar_video_get_height(_video)); + } + + /// start/stop video capture. + /// see zbar_video_enable() + void enable (bool enable = true) + { + if(zbar_video_enable(_video, enable)) + throw_exception(_video); + } + + /// retrieve next captured image. + /// see zbar_video_next_image() + Image next_image () + { + zbar_image_t *img = zbar_video_next_image(_video); + if(!img) + throw_exception(_video); + return(Image(img)); + } + + /// request a preferred size for the video image from the device. + /// see zbar_video_request_size() + /// @since 0.6 + void request_size (int width, int height) + { + zbar_video_request_size(_video, width, height); + } + + /// request a preferred driver interface version for debug/testing. + /// see zbar_video_request_interface() + /// @since 0.6 + void request_interface (int version) + { + zbar_video_request_interface(_video, version); + } + + /// request a preferred I/O mode for debug/testing. + /// see zbar_video_request_iomode() + /// @since 0.7 + void request_iomode (int iomode) + { + if(zbar_video_request_iomode(_video, iomode)) + throw_exception(_video); + } + +private: + zbar_video_t *_video; +}; + +} + +#endif diff --git a/ImageProcess/include/zbar/Window.h b/ImageProcess/include/zbar/Window.h new file mode 100644 index 0000000..c91a405 --- /dev/null +++ b/ImageProcess/include/zbar/Window.h @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------ +// Copyright 2007-2009 (c) Jeff Brown +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ +#ifndef _ZBAR_WINDOW_H_ +#define _ZBAR_WINDOW_H_ + +/// @file +/// Output Window C++ wrapper + +#ifndef _ZBAR_H_ +# error "include zbar.h in your application, **not** zbar/Window.h" +#endif + +#include "Image.h" + +namespace zbar { + +/// mid-level output window abstraction. +/// displays images to user-specified platform specific output window + +class Window { +public: + /// constructor. + Window (zbar_window_t *window = NULL) + { + if(window) + _window = window; + else + _window = zbar_window_create(); + } + + /// constructor. + Window (void *x11_display_w32_hwnd, + unsigned long x11_drawable) + { + _window = zbar_window_create(); + attach(x11_display_w32_hwnd, x11_drawable); + } + + ~Window () + { + zbar_window_destroy(_window); + } + + /// cast to C window object. + operator zbar_window_t* () const + { + return(_window); + } + + /// associate reader with an existing platform window. + /// see zbar_window_attach() + void attach (void *x11_display_w32_hwnd, + unsigned long x11_drawable = 0) + { + if(zbar_window_attach(_window, + x11_display_w32_hwnd, x11_drawable) < 0) + throw_exception(_window); + } + + /// control content level of the reader overlay. + /// see zbar_window_set_overlay() + void set_overlay (int level) + { + zbar_window_set_overlay(_window, level); + } + + /// retrieve current content level of reader overlay. + /// see zbar_window_get_overlay() + + /// draw a new image into the output window. + /// see zbar_window_draw() + void draw (Image& image) + { + if(zbar_window_draw(_window, image) < 0) + throw_exception(_window); + } + + /// clear the image from the output window. + /// see zbar_window_draw() + void clear () + { + if(zbar_window_draw(_window, NULL) < 0) + throw_exception(_window); + } + + /// redraw the last image. + /// zbar_window_redraw() + void redraw () + { + if(zbar_window_redraw(_window) < 0) + throw_exception(_window); + } + + /// resize the image window. + /// zbar_window_resize() + void resize (unsigned width, unsigned height) + { + if(zbar_window_resize(_window, width, height) < 0) + throw_exception(_window); + } + +private: + zbar_window_t *_window; +}; + +/// select a compatible format between video input and output window. +/// see zbar_negotiate_format() +static inline void negotiate_format (Video& video, Window& window) +{ + if(zbar_negotiate_format(video, window) < 0) + throw_exception(video); +} + +} + +#endif diff --git a/ImageProcess/include/zbar/zbargtk.h b/ImageProcess/include/zbar/zbargtk.h new file mode 100644 index 0000000..ce068f2 --- /dev/null +++ b/ImageProcess/include/zbar/zbargtk.h @@ -0,0 +1,215 @@ +/*------------------------------------------------------------------------ + * Copyright 2008-2009 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ +#ifndef __ZBAR_GTK_H__ +#define __ZBAR_GTK_H__ + +/** SECTION:ZBarGtk + * @short_description: barcode reader GTK+ 2.x widget + * @include: zbar/zbargtk.h + * + * embeds a barcode reader directly into a GTK+ based GUI. the widget + * can process barcodes from a video source (using the + * #ZBarGtk:video-device and #ZBarGtk:video-enabled properties) or + * from individual GdkPixbufs supplied to zbar_gtk_scan_image() + * + * Since: 1.5 + */ + +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define ZBAR_TYPE_GTK (zbar_gtk_get_type()) +#define ZBAR_GTK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), ZBAR_TYPE_GTK, ZBarGtk)) +#define ZBAR_GTK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), ZBAR_TYPE_GTK, ZBarGtkClass)) +#define ZBAR_IS_GTK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), ZBAR_TYPE_GTK)) +#define ZBAR_IS_GTK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), ZBAR_TYPE_GTK)) +#define ZBAR_GTK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), ZBAR_TYPE_GTK, ZBarGtkClass)) + +typedef struct _ZBarGtk ZBarGtk; +typedef struct _ZBarGtkClass ZBarGtkClass; + +struct _ZBarGtk { + GtkWidget widget; + gpointer *_private; + + /* properties */ + + /** + * ZBarGtk:video-device: + * + * the currently set video device. + * + * setting a new device opens it and automatically sets + * #ZBarGtk:video-enabled. set the empty string ("") or NULL to + * close. + */ + + /** + * ZBarGtk:video-enabled: + * + * video device streaming state. + * + * use to pause/resume video scanning. + */ + + /** + * ZBarGtk:video-opened: + * + * video device opened state. + * + * (re)setting #ZBarGtk:video-device should eventually cause it + * to be opened or closed. any errors while streaming/scanning + * will also cause the device to be closed + */ +}; + +struct _ZBarGtkClass { + GtkWidgetClass parent_class; + + /* signals */ + + /** + * ZBarGtk::decoded: + * @widget: the object that received the signal + * @symbol_type: the type of symbol decoded (a zbar_symbol_type_t) + * @data: the data decoded from the symbol + * + * emitted when a barcode is decoded from an image. + * the symbol type and contained data are provided as separate + * parameters + */ + void (*decoded) (ZBarGtk *zbar, + zbar_symbol_type_t symbol_type, + const char *data); + + /** + * ZBarGtk::decoded-text: + * @widget: the object that received the signal + * @text: the decoded data prefixed by the string name of the + * symbol type (separated by a colon) + * + * emitted when a barcode is decoded from an image. + * the symbol type name is prefixed to the data, separated by a + * colon + */ + void (*decoded_text) (ZBarGtk *zbar, + const char *text); + + /** + * ZBarGtk::scan-image: + * @widget: the object that received the signal + * @image: the image to scan for barcodes + */ + void (*scan_image) (ZBarGtk *zbar, + GdkPixbuf *image); +}; + +GType zbar_gtk_get_type(void) G_GNUC_CONST; + +/** + * zbar_gtk_new: + * create a new barcode reader widget instance. + * initially has no associated video device or image. + * + * Returns: a new #ZBarGtk widget instance + */ +GtkWidget *zbar_gtk_new(void); + +/** + * zbar_gtk_scan_image: + * + */ +void zbar_gtk_scan_image(ZBarGtk *zbar, + GdkPixbuf *image); + +/** retrieve the currently opened video device. + * + * Returns: the current video device or NULL if no device is opened + */ +const char *zbar_gtk_get_video_device(ZBarGtk *zbar); + +/** open a new video device. + * + * @video_device: the platform specific name of the device to open. + * use NULL to close a currently opened device. + * + * @note since opening a device may take some time, this call will + * return immediately and the device will be opened asynchronously + */ +void zbar_gtk_set_video_device(ZBarGtk *zbar, + const char *video_device); + +/** retrieve the current video enabled state. + * + * Returns: true if video scanning is currently enabled, false otherwise + */ +gboolean zbar_gtk_get_video_enabled(ZBarGtk *zbar); + +/** enable/disable video scanning. + * @video_enabled: true to enable video scanning, false to disable + * + * has no effect unless a video device is opened + */ +void zbar_gtk_set_video_enabled(ZBarGtk *zbar, + gboolean video_enabled); + +/** retrieve the current video opened state. + * + * Returns: true if video device is currently opened, false otherwise + */ +gboolean zbar_gtk_get_video_opened(ZBarGtk *zbar); + +/** set video camera resolution. + * @width: width in pixels + * @height: height in pixels + * + * @note this call must be made before video is initialized + */ +void zbar_gtk_request_video_size(ZBarGtk *zbar, + int width, + int height); + +/** + * utility function to populate a zbar_image_t from a GdkPixbuf. + * @image: the zbar library image destination to populate + * @pixbuf: the GdkPixbuf source + * + * Returns: TRUE if successful or FALSE if the conversion could not be + * performed for some reason + */ +gboolean zbar_gtk_image_from_pixbuf(zbar_image_t *image, + GdkPixbuf *pixbuf); + +G_END_DECLS + +#endif diff --git a/ImageProcess/include/zxing/BarcodeFormat.h b/ImageProcess/include/zxing/BarcodeFormat.h new file mode 100644 index 0000000..487d501 --- /dev/null +++ b/ImageProcess/include/zxing/BarcodeFormat.h @@ -0,0 +1,58 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __BARCODE_FORMAT_H__ +#define __BARCODE_FORMAT_H__ + +/* + * BarcodeFormat.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +namespace zxing { + class BarcodeFormat { + public: + // if you update the enum, update BarcodeFormat.cpp + + enum Value { + NONE, + AZTEC, + CODABAR, + CODE_39, + CODE_93, + CODE_128, + DATA_MATRIX, + EAN_8, + EAN_13, + ITF, + MAXICODE, + PDF_417, + QR_CODE, + RSS_14, + RSS_EXPANDED, + UPC_A, + UPC_E, + UPC_EAN_EXTENSION + }; + + BarcodeFormat(Value v) : value(v) {} + const Value value; + operator Value () const { return value; } + + static char const* barcodeFormatNames[]; + }; +} + +#endif // __BARCODE_FORMAT_H__ diff --git a/ImageProcess/include/zxing/Binarizer.h b/ImageProcess/include/zxing/Binarizer.h new file mode 100644 index 0000000..c9d3a32 --- /dev/null +++ b/ImageProcess/include/zxing/Binarizer.h @@ -0,0 +1,49 @@ +#ifndef BINARIZER_H_ +#define BINARIZER_H_ + +/* + * Binarizer.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class Binarizer : public Counted { + private: + Ref source_; + + public: + Binarizer(Ref source); + virtual ~Binarizer(); + + virtual Ref getBlackRow(int y, Ref row) = 0; + virtual Ref getBlackMatrix() = 0; + + Ref getLuminanceSource() const; + virtual Ref createBinarizer(Ref source) = 0; + + int getWidth() const; + int getHeight() const; + }; + +} +#endif /* BINARIZER_H_ */ diff --git a/ImageProcess/include/zxing/BinaryBitmap.h b/ImageProcess/include/zxing/BinaryBitmap.h new file mode 100644 index 0000000..8e44589 --- /dev/null +++ b/ImageProcess/include/zxing/BinaryBitmap.h @@ -0,0 +1,55 @@ +#ifndef __BINARYBITMAP_H__ +#define __BINARYBITMAP_H__ + +/* + * BinaryBitmap.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class BinaryBitmap : public Counted { + private: + Ref binarizer_; + + public: + BinaryBitmap(Ref binarizer); + virtual ~BinaryBitmap(); + + Ref getBlackRow(int y, Ref row); + Ref getBlackMatrix(); + + Ref getLuminanceSource() const; + + int getWidth() const; + int getHeight() const; + + bool isRotateSupported() const; + Ref rotateCounterClockwise(); + + bool isCropSupported() const; + Ref crop(int left, int top, int width, int height); + }; + +} + +#endif /* BINARYBITMAP_H_ */ diff --git a/ImageProcess/include/zxing/ChecksumException.h b/ImageProcess/include/zxing/ChecksumException.h new file mode 100644 index 0000000..7d23a33 --- /dev/null +++ b/ImageProcess/include/zxing/ChecksumException.h @@ -0,0 +1,34 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __CHECKSUM_EXCEPTION_H__ +#define __NOT_FOUND_EXCEPTION_H__ + +/* + * Copyright 20011 ZXing authors + * + * 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. + */ + +#include + +namespace zxing { + class ChecksumException : public ReaderException { + typedef ReaderException Base; + public: + ChecksumException() throw(); + ChecksumException(const char* msg) throw(); + ~ChecksumException() throw(); + }; +} + +#endif // __CHECKSUM_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/DecodeHints.h b/ImageProcess/include/zxing/DecodeHints.h new file mode 100644 index 0000000..63ca748 --- /dev/null +++ b/ImageProcess/include/zxing/DecodeHints.h @@ -0,0 +1,85 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __DECODEHINTS_H_ +#define __DECODEHINTS_H_ +/* + * DecodeHintType.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + + typedef unsigned int DecodeHintType; + class DecodeHints; + DecodeHints operator | (DecodeHints const&, DecodeHints const&); + + class DecodeHints { + private: + DecodeHintType hints; + Ref callback; + + public: + static const DecodeHintType AZTEC_HINT = 1 << BarcodeFormat::AZTEC; + static const DecodeHintType CODABAR_HINT = 1 << BarcodeFormat::CODABAR; + static const DecodeHintType CODE_39_HINT = 1 << BarcodeFormat::CODE_39; + static const DecodeHintType CODE_93_HINT = 1 << BarcodeFormat::CODE_93; + static const DecodeHintType CODE_128_HINT = 1 << BarcodeFormat::CODE_128; + static const DecodeHintType DATA_MATRIX_HINT = 1 << BarcodeFormat::DATA_MATRIX; + static const DecodeHintType EAN_8_HINT = 1 << BarcodeFormat::EAN_8; + static const DecodeHintType EAN_13_HINT = 1 << BarcodeFormat::EAN_13; + static const DecodeHintType ITF_HINT = 1 << BarcodeFormat::ITF; + static const DecodeHintType MAXICODE_HINT = 1 << BarcodeFormat::MAXICODE; + static const DecodeHintType PDF_417_HINT = 1 << BarcodeFormat::PDF_417; + static const DecodeHintType QR_CODE_HINT = 1 << BarcodeFormat::QR_CODE; + static const DecodeHintType RSS_14_HINT = 1 << BarcodeFormat::RSS_14; + static const DecodeHintType RSS_EXPANDED_HINT = 1 << BarcodeFormat::RSS_EXPANDED; + static const DecodeHintType UPC_A_HINT = 1 << BarcodeFormat::UPC_A; + static const DecodeHintType UPC_E_HINT = 1 << BarcodeFormat::UPC_E; + static const DecodeHintType UPC_EAN_EXTENSION_HINT = 1 << BarcodeFormat::UPC_EAN_EXTENSION; + + static const DecodeHintType TRYHARDER_HINT = 1 << 31; + static const DecodeHintType CHARACTER_SET = 1 << 30; + // static const DecodeHintType ALLOWED_LENGTHS = 1 << 29; + // static const DecodeHintType ASSUME_CODE_39_CHECK_DIGIT = 1 << 28; + static const DecodeHintType ASSUME_GS1 = 1 << 27; + // static const DecodeHintType NEED_RESULT_POINT_CALLBACK = 1 << 26; + + static const DecodeHints PRODUCT_HINT; + static const DecodeHints ONED_HINT; + static const DecodeHints DEFAULT_HINT; + + DecodeHints(); + DecodeHints(DecodeHintType init); + + void addFormat(BarcodeFormat toadd); + bool containsFormat(BarcodeFormat tocheck) const; + bool isEmpty() const { return (hints == 0); } + void clear() { hints = 0; } + void setTryHarder(bool toset); + bool getTryHarder() const; + + void setResultPointCallback(Ref const&); + Ref getResultPointCallback() const; + + friend DecodeHints operator | (DecodeHints const&, DecodeHints const&); + }; + +} + +#endif diff --git a/ImageProcess/include/zxing/Exception.h b/ImageProcess/include/zxing/Exception.h new file mode 100644 index 0000000..7a1b7cf --- /dev/null +++ b/ImageProcess/include/zxing/Exception.h @@ -0,0 +1,51 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +/* + * Exception.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + + class Exception : public std::exception { + private: + char const* const message; + + public: + Exception() throw() : message(0) {} + Exception(const char* msg) throw() : message(copy(msg)) {} + Exception(Exception const& that) throw() : std::exception(that), message(copy(that.message)) {} + ~Exception() throw() { + if (message) { + deleteMessage(); + } + } + char const* what() const throw() { return message ? message : ""; } + + private: + static char const* copy(char const*); + void deleteMessage(); + }; + +} + +#endif // __EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/FormatException.h b/ImageProcess/include/zxing/FormatException.h new file mode 100644 index 0000000..a09ad36 --- /dev/null +++ b/ImageProcess/include/zxing/FormatException.h @@ -0,0 +1,37 @@ +#ifndef __FORMAT_EXCEPTION_H__ +#define __FORMAT_EXCEPTION_H__ + +/* + * FormatException.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + class FormatException : public ReaderException { + public: + FormatException(); + FormatException(const char* msg); + ~FormatException() throw(); + + static FormatException const& getFormatInstance(); + }; + +} +#endif // __FORMAT_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/IllegalStateException.h b/ImageProcess/include/zxing/IllegalStateException.h new file mode 100644 index 0000000..594eded --- /dev/null +++ b/ImageProcess/include/zxing/IllegalStateException.h @@ -0,0 +1,35 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __ILLEGAL_STATE_EXCEPTION_H__ +#define __ILLEGAL_STATE_EXCEPTION_H__ + +/* + * Copyright 20011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may illegal 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. + */ + +#include + +namespace zxing { + + class IllegalStateException : public ReaderException { + public: + IllegalStateException() throw() {} + IllegalStateException(const char* msg) throw() : ReaderException(msg) {} + ~IllegalStateException() throw() {} + }; + +} + +#endif // __ILLEGAL_STATE_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/InvertedLuminanceSource.h b/ImageProcess/include/zxing/InvertedLuminanceSource.h new file mode 100644 index 0000000..7d20a22 --- /dev/null +++ b/ImageProcess/include/zxing/InvertedLuminanceSource.h @@ -0,0 +1,48 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __INVERTEDLUMINANCESOURCE_H__ +#define __INVERTEDLUMINANCESOURCE_H__ +/* + * Copyright 2013 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + + class InvertedLuminanceSource : public LuminanceSource { + private: + typedef LuminanceSource Super; + const Ref delegate; + + public: + InvertedLuminanceSource(Ref const&); + + ArrayRef getRow(int y, ArrayRef row) const; + ArrayRef getMatrix() const; + + boolean isCropSupported() const; + Ref crop(int left, int top, int width, int height) const; + + boolean isRotateSupported() const; + + virtual Ref invert() const; + + Ref rotateCounterClockwise() const; + }; + +} + +#endif /* INVERTEDLUMINANCESOURCE_H_ */ diff --git a/ImageProcess/include/zxing/LuminanceSource.h b/ImageProcess/include/zxing/LuminanceSource.h new file mode 100644 index 0000000..33d86c8 --- /dev/null +++ b/ImageProcess/include/zxing/LuminanceSource.h @@ -0,0 +1,59 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __LUMINANCESOURCE_H__ +#define __LUMINANCESOURCE_H__ +/* + * LuminanceSource.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + + class LuminanceSource : public Counted { + private: + const int width; + const int height; + + public: + LuminanceSource(int width, int height); + virtual ~LuminanceSource(); + + int getWidth() const { return width; } + int getHeight() const { return height; } + + // Callers take ownership of the returned memory and must call delete [] on it themselves. + virtual ArrayRef getRow(int y, ArrayRef row) const = 0; + virtual ArrayRef getMatrix() const = 0; + + virtual bool isCropSupported() const; + virtual Ref crop(int left, int top, int width, int height) const; + + virtual bool isRotateSupported() const; + + virtual Ref invert() const; + + virtual Ref rotateCounterClockwise() const; + + operator std::string() const; + }; + +} + +#endif /* LUMINANCESOURCE_H_ */ diff --git a/ImageProcess/include/zxing/MultiFormatReader.h b/ImageProcess/include/zxing/MultiFormatReader.h new file mode 100644 index 0000000..edfaf05 --- /dev/null +++ b/ImageProcess/include/zxing/MultiFormatReader.h @@ -0,0 +1,48 @@ +#ifndef __MULTI_FORMAT_READER_H__ +#define __MULTI_FORMAT_READER_H__ + +/* + * MultiFormatBarcodeReader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + + +#include +#include +#include +#include + +namespace zxing { + class MultiFormatReader : public Reader { + private: + Ref decodeInternal(Ref image); + + std::vector > readers_; + DecodeHints hints_; + + public: + MultiFormatReader(); + + Ref decode(Ref image); + Ref decode(Ref image, DecodeHints hints); + Ref decodeWithState(Ref image); + void setHints(DecodeHints hints); + ~MultiFormatReader(); + }; +} + +#endif diff --git a/ImageProcess/include/zxing/NotFoundException.h b/ImageProcess/include/zxing/NotFoundException.h new file mode 100644 index 0000000..6c977aa --- /dev/null +++ b/ImageProcess/include/zxing/NotFoundException.h @@ -0,0 +1,35 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __NOT_FOUND_EXCEPTION_H__ +#define __NOT_FOUND_EXCEPTION_H__ + +/* + * Copyright 20011 ZXing authors + * + * 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. + */ + +#include + +namespace zxing { + + class NotFoundException : public ReaderException { + public: + NotFoundException() throw() {} + NotFoundException(const char* msg) throw() : ReaderException(msg) {} + ~NotFoundException() throw() {} + }; + +} + +#endif // __NOT_FOUND_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/Reader.h b/ImageProcess/include/zxing/Reader.h new file mode 100644 index 0000000..7ee7e53 --- /dev/null +++ b/ImageProcess/include/zxing/Reader.h @@ -0,0 +1,40 @@ +#ifndef __READER_H__ +#define __READER_H__ + +/* + * Reader.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + + class Reader : public Counted { + protected: + Reader() {} + public: + virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints) = 0; + virtual ~Reader(); + }; + +} + +#endif // __READER_H__ diff --git a/ImageProcess/include/zxing/ReaderException.h b/ImageProcess/include/zxing/ReaderException.h new file mode 100644 index 0000000..9de61e7 --- /dev/null +++ b/ImageProcess/include/zxing/ReaderException.h @@ -0,0 +1,37 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __READER_EXCEPTION_H__ +#define __READER_EXCEPTION_H__ + +/* + * ReaderException.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + class ReaderException : public Exception { + public: + ReaderException() throw() {} + ReaderException(char const* msg) throw() : Exception(msg) {} + ~ReaderException() throw() {} + }; + +} + +#endif // __READER_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/Result.h b/ImageProcess/include/zxing/Result.h new file mode 100644 index 0000000..c913c5a --- /dev/null +++ b/ImageProcess/include/zxing/Result.h @@ -0,0 +1,55 @@ +#ifndef __RESULT_H__ +#define __RESULT_H__ + +/* + * Result.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + + class Result : public Counted { + private: + Ref text_; + ArrayRef rawBytes_; + ArrayRef< Ref > resultPoints_; + BarcodeFormat format_; + + public: + Result(Ref text, + ArrayRef rawBytes, + ArrayRef< Ref > resultPoints, + BarcodeFormat format); + ~Result(); + Ref getText(); + ArrayRef getRawBytes(); + ArrayRef< Ref > const& getResultPoints() const; + ArrayRef< Ref >& getResultPoints(); + BarcodeFormat getBarcodeFormat() const; + + friend std::ostream& operator<<(std::ostream& out, Result& result); + }; + +} +#endif // __RESULT_H__ diff --git a/ImageProcess/include/zxing/ResultPoint.h b/ImageProcess/include/zxing/ResultPoint.h new file mode 100644 index 0000000..7b01649 --- /dev/null +++ b/ImageProcess/include/zxing/ResultPoint.h @@ -0,0 +1,55 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __RESULT_POINT_H__ +#define __RESULT_POINT_H__ + +/* + * ResultPoint.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + + class ResultPoint : public Counted { + protected: + const float posX_; + const float posY_; + + public: + ResultPoint(); + ResultPoint(float x, float y); + ResultPoint(int x, int y); + virtual ~ResultPoint(); + + virtual float getX() const; + virtual float getY() const; + + bool equals(Ref other); + + static void orderBestPatterns(std::vector >& patterns); + static float distance(Ref point1, Ref point2); + static float distance(float x1, float x2, float y1, float y2); + + private: + static float crossProductZ(Ref pointA, Ref pointB, Ref pointC); + }; + +} + +#endif // __RESULT_POINT_H__ diff --git a/ImageProcess/include/zxing/ResultPointCallback.h b/ImageProcess/include/zxing/ResultPointCallback.h new file mode 100644 index 0000000..259c549 --- /dev/null +++ b/ImageProcess/include/zxing/ResultPointCallback.h @@ -0,0 +1,39 @@ +#ifndef __RESULT_POINT_CALLBACK_H__ +#define __RESULT_POINT_CALLBACK_H__ + +/* + * ResultPointCallback.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + class ResultPoint; + + class ResultPointCallback : public Counted { + protected: + ResultPointCallback() {} + public: + virtual void foundPossibleResultPoint(ResultPoint const& point) = 0; + virtual ~ResultPointCallback(); + }; + +} + +#endif // __RESULT_POINT_CALLBACK_H__ diff --git a/ImageProcess/include/zxing/ZXing.h b/ImageProcess/include/zxing/ZXing.h new file mode 100644 index 0000000..0c109d5 --- /dev/null +++ b/ImageProcess/include/zxing/ZXing.h @@ -0,0 +1,134 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * Copyright 2013 ZXing authors All rights reserved. + * + * 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. + */ +#ifndef __ZXING_H_ +#define __ZXING_H_ + +#define ZXING_ARRAY_LEN(v) ((int)(sizeof(v)/sizeof(v[0]))) +#define ZX_LOG_DIGITS(digits) \ + ((digits == 8) ? 3 : \ + ((digits == 16) ? 4 : \ + ((digits == 32) ? 5 : \ + ((digits == 64) ? 6 : \ + ((digits == 128) ? 7 : \ + (-1)))))) + +#ifndef ZXING_DEBUG +#define ZXING_DEBUG 0 +#endif + +namespace zxing { + typedef char byte; + typedef bool boolean; +} + +#include + +#if defined(_WIN32) || defined(_WIN64) + +#include + +namespace zxing { + inline bool isnan(float v) { return _isnan(v) != 0; } + inline bool isnan(double v) { return _isnan(v) != 0; } + inline float nan() { return std::numeric_limits::quiet_NaN(); } +} + +#else + +#include + +namespace zxing { + inline bool isnan(float v) { return std::isnan(v); } + inline bool isnan(double v) { return std::isnan(v); } + inline float nan() { return std::numeric_limits::quiet_NaN(); } +} + +#endif + +#if ZXING_DEBUG + +#include +#include + +using std::cout; +using std::cerr; +using std::endl; +using std::flush; +using std::string; +using std::ostream; + +#if ZXING_DEBUG_TIMER + +#include + +namespace zxing { + + class DebugTimer { + public: + DebugTimer(char const* string_) : chars(string_) { + gettimeofday(&start, 0); + } + + DebugTimer(std::string const& string_) : chars(0), string(string_) { + gettimeofday(&start, 0); + } + + void mark(char const* string) { + struct timeval end; + gettimeofday(&end, 0); + int diff = + (end.tv_sec - start.tv_sec) * 1000 * 1000 + (end.tv_usec - start.tv_usec); + + cerr << diff << " " << string << '\n'; + } + + void mark(std::string string) { + mark(string.c_str()); + } + + ~DebugTimer() { + if (chars) { + mark(chars); + } + else { + mark(string.c_str()); + } + } + + private: + char const* const chars; + std::string string; + struct timeval start; + }; + +} + +#define ZXING_TIME(string) DebugTimer __timer__ (string) +#define ZXING_TIME_MARK(string) __timer__.mark(string) + +#endif + +#endif // ZXING_DEBUG + +#ifndef ZXING_TIME +#define ZXING_TIME(string) (void)0 +#endif +#ifndef ZXING_TIME_MARK +#define ZXING_TIME_MARK(string) (void)0 +#endif + +#endif diff --git a/ImageProcess/include/zxing/aztec/AztecDetectorResult.h b/ImageProcess/include/zxing/aztec/AztecDetectorResult.h new file mode 100644 index 0000000..5f2bafb --- /dev/null +++ b/ImageProcess/include/zxing/aztec/AztecDetectorResult.h @@ -0,0 +1,47 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * AtztecDetecorResult.h + * zxing + * + * Created by Lukas Stabe on 08/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +#ifndef ZXingWidget_AtztecDetecorResult_h +#define ZXingWidget_AtztecDetecorResult_h + +namespace zxing { + namespace aztec { + class AztecDetectorResult : public DetectorResult { + private: + bool compact_; + int nbDatablocks_, nbLayers_; + public: + AztecDetectorResult(Ref bits, + ArrayRef< Ref > points, + bool compact, + int nbDatablocks, + int nbLayers); + bool isCompact(); + int getNBDatablocks(); + int getNBLayers(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/aztec/AztecReader.h b/ImageProcess/include/zxing/aztec/AztecReader.h new file mode 100644 index 0000000..3842b3e --- /dev/null +++ b/ImageProcess/include/zxing/aztec/AztecReader.h @@ -0,0 +1,49 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * AztecReader.h + * zxing + * + * Created by Lukas Stabe on 08/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +#ifndef ZXingWidget_AztecReader_h +#define ZXingWidget_AztecReader_h + +namespace zxing { + namespace aztec { + + class AztecReader : public Reader { + private: + Decoder decoder_; + + protected: + Decoder& getDecoder(); + + public: + AztecReader(); + virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints); + virtual ~AztecReader(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/aztec/decoder/Decoder.h b/ImageProcess/include/zxing/aztec/decoder/Decoder.h new file mode 100644 index 0000000..a4f8865 --- /dev/null +++ b/ImageProcess/include/zxing/aztec/decoder/Decoder.h @@ -0,0 +1,69 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * Decoder.h + * zxing + * + * Created by Lukas Stabe on 08/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#ifndef __ZXING_AZTEC_DECODER_DECODER_H__ +#define __ZXING_AZTEC_DECODER_DECODER_H__ + +#include +#include +#include + +namespace zxing { + + class DecoderResult; + + namespace aztec { + + class Decoder : public Counted { + private: + enum Table { + UPPER, + LOWER, + MIXED, + DIGIT, + PUNCT, + BINARY + }; + + static Table getTable(char t); + static const char* getCharacter(Table table, int code); + + int numCodewords_; + int codewordSize_; + Ref ddata_; + int invertedBitCount_; + + Ref getEncodedData(Ref correctedBits); + Ref correctBits(Ref rawbits); + Ref extractBits(Ref matrix); + static Ref removeDashedLines(Ref matrix); + static int readCode(Ref rawbits, int startIndex, int length); + + + public: + Decoder(); + Ref decode(Ref detectorResult); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/aztec/detector/Detector.h b/ImageProcess/include/zxing/aztec/detector/Detector.h new file mode 100644 index 0000000..38c690b --- /dev/null +++ b/ImageProcess/include/zxing/aztec/detector/Detector.h @@ -0,0 +1,92 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * Detector.h + * zxing + * + * Created by Lukas Stabe on 08/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#ifndef __ZXING_AZTEC_DETECTOR_DETECTOR_H__ +#define __ZXING_AZTEC_DETECTOR_DETECTOR_H__ + +#include + +#include +#include +#include +#include +#include + +namespace zxing { + namespace aztec { + + class Point : public Counted { + private: + const int x; + const int y; + + public: + Ref toResultPoint() { + return Ref(new ResultPoint(float(x), float(y))); + } + + Point(int ax, int ay) : x(ax), y(ay) {} + + int getX() const { return x; } + int getY() const { return y; } + }; + + class Detector : public Counted { + + private: + Ref image_; + + bool compact_; + int nbLayers_; + int nbDataBlocks_; + int nbCenterLayers_; + int shift_; + + void extractParameters(std::vector > bullEyeCornerPoints); + ArrayRef< Ref > getMatrixCornerPoints(std::vector > bullEyeCornerPoints); + static void correctParameterData(Ref parameterData, bool compact); + std::vector > getBullEyeCornerPoints(Ref pCenter); + Ref getMatrixCenter(); + Ref sampleGrid(Ref image, + Ref topLeft, + Ref bottomLeft, + Ref bottomRight, + Ref topRight); + void getParameters(Ref parameterData); + Ref sampleLine(Ref p1, Ref p2, int size); + bool isWhiteOrBlackRectangle(Ref p1, + Ref p2, + Ref p3, + Ref p4); + int getColor(Ref p1, Ref p2); + Ref getFirstDifferent(Ref init, bool color, int dx, int dy); + bool isValid(int x, int y); + static float distance(Ref a, Ref b); + + public: + Detector(Ref image); + Ref detect(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/common/Array.h b/ImageProcess/include/zxing/common/Array.h new file mode 100644 index 0000000..19fdb82 --- /dev/null +++ b/ImageProcess/include/zxing/common/Array.h @@ -0,0 +1,170 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __ARRAY_H__ +#define __ARRAY_H__ + +/* + * Array.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +#include + +namespace zxing { + + template class Array : public Counted { + protected: + public: + std::vector values_; + Array() {} + Array(int n) : + Counted(), values_(n, T()) { + } + Array(T const* ts, int n) : + Counted(), values_(ts, ts + n) { + } + Array(T const* ts, T const* te) : + Counted(), values_(ts, te) { + } + Array(T v, int n) : + Counted(), values_(n, v) { + } + Array(std::vector& v) : + Counted(), values_(v) { + } + Array(Array& other) : + Counted(), values_(other.values_) { + } + Array(Array* other) : + Counted(), values_(other->values_) { + } + virtual ~Array() { + } + Array& operator=(const Array& other) { + values_ = other.values_; + return *this; + } + Array& operator=(const std::vector& array) { + values_ = array; + return *this; + } + T const& operator[](int i) const { + return values_[i]; + } + T& operator[](int i) { + return values_[i]; + } + int size() const { + return values_.size(); + } + bool empty() const { + return values_.size() == 0; + } + std::vector const& values() const { + return values_; + } + std::vector& values() { + return values_; + } + }; + + template class ArrayRef : public Counted { + private: + public: + Array* array_; + ArrayRef() : + array_(0) { + } + explicit ArrayRef(int n) : + array_(0) { + reset(new Array(n)); + } + ArrayRef(T* ts, int n) : + array_(0) { + reset(new Array(ts, n)); + } + ArrayRef(Array* a) : + array_(0) { + reset(a); + } + ArrayRef(const ArrayRef& other) : + Counted(), array_(0) { + reset(other.array_); + } + + template + ArrayRef(const ArrayRef& other) : + array_(0) { + reset(static_cast*>(other.array_)); + } + + ~ArrayRef() { + if (array_) { + array_->release(); + } + array_ = 0; + } + + T const& operator[](int i) const { + return (*array_)[i]; + } + + T& operator[](int i) { + return (*array_)[i]; + } + + void reset(Array* a) { + if (a) { + a->retain(); + } + if (array_) { + array_->release(); + } + array_ = a; + } + void reset(const ArrayRef& other) { + reset(other.array_); + } + ArrayRef& operator=(const ArrayRef& other) { + reset(other); + return *this; + } + ArrayRef& operator=(Array* a) { + reset(a); + return *this; + } + + Array& operator*() const { + return *array_; + } + + Array* operator->() const { + return array_; + } + + operator bool() const { + return array_ != 0; + } + bool operator ! () const { + return array_ == 0; + } + }; + +} // namespace zxing + +#endif // __ARRAY_H__ diff --git a/ImageProcess/include/zxing/common/BitArray.h b/ImageProcess/include/zxing/common/BitArray.h new file mode 100644 index 0000000..a2a852c --- /dev/null +++ b/ImageProcess/include/zxing/common/BitArray.h @@ -0,0 +1,81 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __BIT_ARRAY_H__ +#define __BIT_ARRAY_H__ + +/* + * Copyright 2010 ZXing authors. All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + + class BitArray : public Counted { + public: + static const int bitsPerWord = std::numeric_limits::digits; + + private: + int size; + ArrayRef bits; + static const int logBits = ZX_LOG_DIGITS(bitsPerWord); + static const int bitsMask = (1 << logBits) - 1; + + public: + BitArray(int size); + ~BitArray(); + int getSize() const; + + bool get(int i) const { + return (bits[i >> logBits] & (1 << (i & bitsMask))) != 0; + } + + void set(int i) { + bits[i >> logBits] |= 1 << (i & bitsMask); + } + + int getNextSet(int from); + int getNextUnset(int from); + + void setBulk(int i, int newBits); + void setRange(int start, int end); + void clear(); + bool isRange(int start, int end, bool value); + std::vector& getBitArray(); + + void reverse(); + + class Reverse { + private: + Ref array; + public: + Reverse(Ref array); + ~Reverse(); + }; + + private: + static int makeArraySize(int size); + }; + + std::ostream& operator << (std::ostream&, BitArray const&); + +} + +#endif // __BIT_ARRAY_H__ diff --git a/ImageProcess/include/zxing/common/BitMatrix.h b/ImageProcess/include/zxing/common/BitMatrix.h new file mode 100644 index 0000000..4672e3b --- /dev/null +++ b/ImageProcess/include/zxing/common/BitMatrix.h @@ -0,0 +1,91 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __BIT_MATRIX_H__ +#define __BIT_MATRIX_H__ + +/* + * BitMatrix.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class BitMatrix : public Counted { + public: + static const int bitsPerWord = std::numeric_limits::digits; + + private: + int width; + int height; + int rowSize; + ArrayRef bits; + +#define ZX_LOG_DIGITS(digits) \ + ((digits == 8) ? 3 : \ + ((digits == 16) ? 4 : \ + ((digits == 32) ? 5 : \ + ((digits == 64) ? 6 : \ + ((digits == 128) ? 7 : \ + (-1)))))) + + static const int logBits = ZX_LOG_DIGITS(bitsPerWord); + static const int bitsMask = (1 << logBits) - 1; + + public: + BitMatrix(int dimension); + BitMatrix(int width, int height); + + ~BitMatrix(); + + bool get(int x, int y) const { + int offset = y * rowSize + (x >> logBits); + return ((((unsigned)bits[offset]) >> (x & bitsMask)) & 1) != 0; + } + + void set(int x, int y) { + int offset = y * rowSize + (x >> logBits); + bits[offset] |= 1 << (x & bitsMask); + } + + void flip(int x, int y); + void clear(); + void setRegion(int left, int top, int width, int height); + Ref getRow(int y, Ref row); + + int getWidth() const; + int getHeight() const; + + ArrayRef getTopLeftOnBit() const; + ArrayRef getBottomRightOnBit() const; + + friend std::ostream& operator<<(std::ostream& out, const BitMatrix& bm); + const char* description(); + + private: + inline void init(int, int); + + BitMatrix(const BitMatrix&); + BitMatrix& operator =(const BitMatrix&); + }; + +} + +#endif // __BIT_MATRIX_H__ diff --git a/ImageProcess/include/zxing/common/BitSource.h b/ImageProcess/include/zxing/common/BitSource.h new file mode 100644 index 0000000..41732c4 --- /dev/null +++ b/ImageProcess/include/zxing/common/BitSource.h @@ -0,0 +1,74 @@ +#ifndef __BIT_SOURCE_H__ +#define __BIT_SOURCE_H__ + +/* + * BitSource.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + /** + *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the + * number of bits read is not often a multiple of 8.

+ * + *

This class is not thread-safe.

+ * + * @author srowen@google.com (Sean Owen) + * @author christian.brunschen@gmail.com (Christian Brunschen) + */ + class BitSource : public Counted { + typedef char byte; + private: + ArrayRef bytes_; + int byteOffset_; + int bitOffset_; + public: + /** + * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. + * Bits are read within a byte from most-significant to least-significant bit. + */ + BitSource(ArrayRef& bytes) : + bytes_(bytes), byteOffset_(0), bitOffset_(0) { + } + + int getBitOffset() { + return bitOffset_; + } + + int getByteOffset() { + return byteOffset_; + } + + /** + * @param numBits number of bits to read + * @return int representing the bits read. The bits will appear as the least-significant + * bits of the int + * @throws IllegalArgumentException if numBits isn't in [1,32] + */ + int readBits(int numBits); + + /** + * @return number of bits that can be read successfully + */ + int available(); + }; + +} + +#endif // __BIT_SOURCE_H__ diff --git a/ImageProcess/include/zxing/common/CharacterSetECI.h b/ImageProcess/include/zxing/common/CharacterSetECI.h new file mode 100644 index 0000000..f8a5f38 --- /dev/null +++ b/ImageProcess/include/zxing/common/CharacterSetECI.h @@ -0,0 +1,53 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __CHARACTERSET_ECI__ +#define __CHARACTERSET_ECI__ + +/* + * Copyright 2008-2011 ZXing authors + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace common { + + class CharacterSetECI { + private: + static std::map VALUE_TO_ECI; + static std::map NAME_TO_ECI; + static const bool inited; + static bool init_tables(); + + int const* const values_; + char const* const* const names_; + + CharacterSetECI(int const* values, char const* const* names); + + static void addCharacterSet(int const* value, char const* const* encodingNames); + + public: + char const* name() const; + int getValue() const; + + static CharacterSetECI* getCharacterSetECIByValue(int value); + static CharacterSetECI* getCharacterSetECIByName(std::string const& name); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/common/Counted.h b/ImageProcess/include/zxing/common/Counted.h new file mode 100644 index 0000000..fc1e8d5 --- /dev/null +++ b/ImageProcess/include/zxing/common/Counted.h @@ -0,0 +1,140 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __COUNTED_H__ +#define __COUNTED_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + /* base class for reference-counted objects */ + class Counted { + private: + unsigned int count_; + public: + Counted() : + count_(0) { + } + virtual ~Counted() { + } + Counted* retain() { + count_++; + return this; + } + void release() { + count_--; + if (count_ == 0) { + count_ = 0xDEADF001; + delete this; + } + } + + + /* return the current count for denugging purposes or similar */ + int count() const { + return count_; + } + }; + + /* counting reference to reference-counted objects */ + template class Ref { + private: + public: + T* object_; + explicit Ref(T* o = 0) : + object_(0) { + reset(o); + } + Ref(const Ref& other) : + object_(0) { + reset(other.object_); + } + + template + Ref(const Ref& other) : + object_(0) { + reset(other.object_); + } + + ~Ref() { + if (object_) { + object_->release(); + } + } + + void reset(T* o) { + if (o) { + o->retain(); + } + if (object_ != 0) { + object_->release(); + } + object_ = o; + } + Ref& operator=(const Ref& other) { + reset(other.object_); + return *this; + } + template + Ref& operator=(const Ref& other) { + reset(other.object_); + return *this; + } + Ref& operator=(T* o) { + reset(o); + return *this; + } + template + Ref& operator=(Y* o) { + reset(o); + return *this; + } + + T& operator*() { + return *object_; + } + T* operator->() const { + return object_; + } + operator T* () const { + return object_; + } + + bool operator==(const T* that) { + return object_ == that; + } + bool operator==(const Ref& other) const { + return object_ == other.object_ || *object_ == *(other.object_); + } + template + bool operator==(const Ref& other) const { + return object_ == other.object_ || *object_ == *(other.object_); + } + + bool operator!=(const T* that) { + return !(*this == that); + } + + bool empty() const { + return object_ == 0; + } + }; + +} + +#endif // __COUNTED_H__ diff --git a/ImageProcess/include/zxing/common/DecoderResult.h b/ImageProcess/include/zxing/common/DecoderResult.h new file mode 100644 index 0000000..65e8b0b --- /dev/null +++ b/ImageProcess/include/zxing/common/DecoderResult.h @@ -0,0 +1,51 @@ +#ifndef __DECODER_RESULT_H__ +#define __DECODER_RESULT_H__ + +/* + * DecoderResult.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class DecoderResult : public Counted { + private: + ArrayRef rawBytes_; + Ref text_; + ArrayRef< ArrayRef > byteSegments_; + std::string ecLevel_; + + public: + DecoderResult(ArrayRef rawBytes, + Ref text, + ArrayRef< ArrayRef >& byteSegments, + std::string const& ecLevel); + + DecoderResult(ArrayRef rawBytes, Ref text); + + ArrayRef getRawBytes(); + Ref getText(); + }; + +} + +#endif // __DECODER_RESULT_H__ diff --git a/ImageProcess/include/zxing/common/DetectorResult.h b/ImageProcess/include/zxing/common/DetectorResult.h new file mode 100644 index 0000000..d947ffa --- /dev/null +++ b/ImageProcess/include/zxing/common/DetectorResult.h @@ -0,0 +1,43 @@ +#ifndef __DETECTOR_RESULT_H__ +#define __DETECTOR_RESULT_H__ + +/* + * DetectorResult.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class DetectorResult : public Counted { + private: + Ref bits_; + ArrayRef< Ref > points_; + + public: + DetectorResult(Ref bits, ArrayRef< Ref > points); + Ref getBits(); + ArrayRef< Ref > getPoints(); + }; + +} + +#endif // __DETECTOR_RESULT_H__ diff --git a/ImageProcess/include/zxing/common/GlobalHistogramBinarizer.h b/ImageProcess/include/zxing/common/GlobalHistogramBinarizer.h new file mode 100644 index 0000000..c221be1 --- /dev/null +++ b/ImageProcess/include/zxing/common/GlobalHistogramBinarizer.h @@ -0,0 +1,48 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __GLOBALHISTOGRAMBINARIZER_H__ +#define __GLOBALHISTOGRAMBINARIZER_H__ +/* + * GlobalHistogramBinarizer.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + + class GlobalHistogramBinarizer : public Binarizer { + private: + ArrayRef luminances; + ArrayRef buckets; + public: + GlobalHistogramBinarizer(Ref source); + virtual ~GlobalHistogramBinarizer(); + + virtual Ref getBlackRow(int y, Ref row); + virtual Ref getBlackMatrix(); + static int estimateBlackPoint(ArrayRef const& buckets); + Ref createBinarizer(Ref source); + private: + void initArrays(int luminanceSize); + }; + +} + +#endif /* GLOBALHISTOGRAMBINARIZER_H_ */ diff --git a/ImageProcess/include/zxing/common/GreyscaleLuminanceSource.h b/ImageProcess/include/zxing/common/GreyscaleLuminanceSource.h new file mode 100644 index 0000000..a96ecb3 --- /dev/null +++ b/ImageProcess/include/zxing/common/GreyscaleLuminanceSource.h @@ -0,0 +1,53 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __GREYSCALE_LUMINANCE_SOURCE__ +#define __GREYSCALE_LUMINANCE_SOURCE__ +/* + * GreyscaleLuminanceSource.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + class GreyscaleLuminanceSource : public LuminanceSource { + + private: + typedef LuminanceSource Super; + ArrayRef greyData_; + const int dataWidth_; + const int dataHeight_; + const int left_; + const int top_; + + public: + GreyscaleLuminanceSource(ArrayRef greyData, int dataWidth, int dataHeight, int left, + int top, int width, int height); + + ArrayRef getRow(int y, ArrayRef row) const; + ArrayRef getMatrix() const; + + bool isRotateSupported() const { + return true; + } + + Ref rotateCounterClockwise() const; + }; + +} + +#endif diff --git a/ImageProcess/include/zxing/common/GreyscaleRotatedLuminanceSource.h b/ImageProcess/include/zxing/common/GreyscaleRotatedLuminanceSource.h new file mode 100644 index 0000000..b10cd9b --- /dev/null +++ b/ImageProcess/include/zxing/common/GreyscaleRotatedLuminanceSource.h @@ -0,0 +1,46 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __GREYSCALE_ROTATED_LUMINANCE_SOURCE__ +#define __GREYSCALE_ROTATED_LUMINANCE_SOURCE__ +/* + * GreyscaleRotatedLuminanceSource.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + + +#include + +namespace zxing { + + class GreyscaleRotatedLuminanceSource : public LuminanceSource { + private: + typedef LuminanceSource Super; + ArrayRef greyData_; + const int dataWidth_; + const int left_; + const int top_; + + public: + GreyscaleRotatedLuminanceSource(ArrayRef greyData, int dataWidth, int dataHeight, + int left, int top, int width, int height); + + ArrayRef getRow(int y, ArrayRef row) const; + ArrayRef getMatrix() const; + }; + +} + +#endif diff --git a/ImageProcess/include/zxing/common/GridSampler.h b/ImageProcess/include/zxing/common/GridSampler.h new file mode 100644 index 0000000..4dd90cf --- /dev/null +++ b/ImageProcess/include/zxing/common/GridSampler.h @@ -0,0 +1,45 @@ +#ifndef __GRID_SAMPLER_H__ +#define __GRID_SAMPLER_H__ + +/* + * GridSampler.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + class GridSampler { + private: + static GridSampler gridSampler; + GridSampler(); + + public: + Ref sampleGrid(Ref image, int dimension, Ref transform); + Ref sampleGrid(Ref image, int dimensionX, int dimensionY, Ref transform); + + Ref sampleGrid(Ref image, int dimension, float p1ToX, float p1ToY, float p2ToX, float p2ToY, + float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, + float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY); + static void checkAndNudgePoints(Ref image, std::vector& points); + static GridSampler& getInstance(); + }; +} + +#endif // __GRID_SAMPLER_H__ diff --git a/ImageProcess/include/zxing/common/HybridBinarizer.h b/ImageProcess/include/zxing/common/HybridBinarizer.h new file mode 100644 index 0000000..63561bc --- /dev/null +++ b/ImageProcess/include/zxing/common/HybridBinarizer.h @@ -0,0 +1,67 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __HYBRIDBINARIZER_H__ +#define __HYBRIDBINARIZER_H__ +/* + * HybridBinarizer.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + + class HybridBinarizer : public GlobalHistogramBinarizer { + private: + Ref matrix_; + Ref cached_row_; + + public: + HybridBinarizer(Ref source); + virtual ~HybridBinarizer(); + + virtual Ref getBlackMatrix(); + Ref createBinarizer(Ref source); + private: + // We'll be using one-D arrays because C++ can't dynamically allocate 2D + // arrays + ArrayRef calculateBlackPoints(ArrayRef luminances, + int subWidth, + int subHeight, + int width, + int height); + void calculateThresholdForBlock(ArrayRef luminances, + int subWidth, + int subHeight, + int width, + int height, + ArrayRef blackPoints, + Ref const& matrix); + void thresholdBlock(ArrayRefluminances, + int xoffset, + int yoffset, + int threshold, + int stride, + Ref const& matrix); + }; + +} + +#endif diff --git a/ImageProcess/include/zxing/common/IllegalArgumentException.h b/ImageProcess/include/zxing/common/IllegalArgumentException.h new file mode 100644 index 0000000..17711d9 --- /dev/null +++ b/ImageProcess/include/zxing/common/IllegalArgumentException.h @@ -0,0 +1,36 @@ +#ifndef __ILLEGAL_ARGUMENT_EXCEPTION_H__ +#define __ILLEGAL_ARGUMENT_EXCEPTION_H__ + +/* + * IllegalArgumentException.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + + class IllegalArgumentException : public Exception { + public: + IllegalArgumentException(); + IllegalArgumentException(const char* msg); + ~IllegalArgumentException() throw(); + }; + +} + +#endif // __ILLEGAL_ARGUMENT_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/common/PerspectiveTransform.h b/ImageProcess/include/zxing/common/PerspectiveTransform.h new file mode 100644 index 0000000..0002d91 --- /dev/null +++ b/ImageProcess/include/zxing/common/PerspectiveTransform.h @@ -0,0 +1,49 @@ +#ifndef __PERSPECTIVE_TANSFORM_H__ +#define __PERSPECTIVE_TANSFORM_H__ + +/* + * PerspectiveTransform.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + class PerspectiveTransform : public Counted { + private: + float a11, a12, a13, a21, a22, a23, a31, a32, a33; + PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, float a23, + float a33); + + public: + static Ref + quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, + float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p); + static Ref squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, + float x3, float y3); + static Ref quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, float y2, + float x3, float y3); + Ref buildAdjoint(); + Ref times(Ref other); + void transformPoints(std::vector& points); + + friend std::ostream& operator<<(std::ostream& out, const PerspectiveTransform& pt); + }; +} + +#endif // __PERSPECTIVE_TANSFORM_H__ diff --git a/ImageProcess/include/zxing/common/Point.h b/ImageProcess/include/zxing/common/Point.h new file mode 100644 index 0000000..2284ad2 --- /dev/null +++ b/ImageProcess/include/zxing/common/Point.h @@ -0,0 +1,47 @@ +#ifndef __POINT_H__ +#define __POINT_H__ + +/* + * Point.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +namespace zxing { + class PointI { + public: + int x; + int y; + }; + + class Point { + public: + Point() : x(0.0f), y(0.0f) {}; + Point(float x_, float y_) : x(x_), y(y_) {}; + + float x; + float y; + }; + + class Line { + public: + Line(Point start_, Point end_) : start(start_), end(end_) {}; + + Point start; + Point end; + }; +} +#endif // POINT_H_ diff --git a/ImageProcess/include/zxing/common/Str.h b/ImageProcess/include/zxing/common/Str.h new file mode 100644 index 0000000..5fdaeaa --- /dev/null +++ b/ImageProcess/include/zxing/common/Str.h @@ -0,0 +1,51 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __STR_H__ +#define __STR_H__ + +/* + * Str.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + + class String; + std::ostream& operator << (std::ostream& out, String const& s); + + class String : public Counted { + private: + std::string text_; + public: + explicit String(const std::string& text); + explicit String(int); + char charAt(int) const; + Ref substring(int) const; + const std::string& getText() const; + int size() const; + void append(std::string const& tail); + void append(char c); + int length() const; + friend std::ostream& zxing::operator << (std::ostream& out, String const& s); + }; + +} + +#endif // __COMMON__STRING_H__ diff --git a/ImageProcess/include/zxing/common/StringUtils.h b/ImageProcess/include/zxing/common/StringUtils.h new file mode 100644 index 0000000..367a789 --- /dev/null +++ b/ImageProcess/include/zxing/common/StringUtils.h @@ -0,0 +1,52 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __STRING_UTILS__ +#define __STRING_UTILS__ + +/* + * Copyright (C) 2010-2011 ZXing authors + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace common { + + class StringUtils { + private: + static char const* const PLATFORM_DEFAULT_ENCODING; + + StringUtils() {} + + public: + static char const* const ASCII; + static char const* const SHIFT_JIS; + static char const* const GB2312; + static char const* const EUC_JP; + static char const* const UTF8; + static char const* const ISO88591; + static const bool ASSUME_SHIFT_JIS; + + typedef std::map Hashtable; + + static std::string guessEncoding(char* bytes, int length, Hashtable const& hints); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/common/detector/JavaMath.h b/ImageProcess/include/zxing/common/detector/JavaMath.h new file mode 100644 index 0000000..406ba2a --- /dev/null +++ b/ImageProcess/include/zxing/common/detector/JavaMath.h @@ -0,0 +1,43 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __ZXING_COMMON_DETECTOR_MATH_H__ +#define __ZXING_COMMON_DETECTOR_MATH_H__ +/* + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace common { + namespace detector { + + class Math { + private: + Math(); + ~Math(); + public: + + // Java standard Math.round + static inline int round(float a) { + return (int)std::floor(a + 0.5f); + } + + }; + + } + } +} + +#endif diff --git a/ImageProcess/include/zxing/common/detector/MathUtils.h b/ImageProcess/include/zxing/common/detector/MathUtils.h new file mode 100644 index 0000000..71c7f0c --- /dev/null +++ b/ImageProcess/include/zxing/common/detector/MathUtils.h @@ -0,0 +1,57 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __ZXING_COMMON_DETECTOR_MATHUTILS_H__ +#define __ZXING_COMMON_DETECTOR_MATHUTILS_H__ +/* + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace common { + namespace detector { + + class MathUtils { + private: + MathUtils(); + ~MathUtils(); + public: + + /** + * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its + * argument to the nearest int, where x.5 rounds up to x+1. + */ + static inline int round(float d) { + return (int)(d + 0.5f); + } + + static inline float distance(float aX, float aY, float bX, float bY) { + float xDiff = aX - bX; + float yDiff = aY - bY; + return sqrt(xDiff * xDiff + yDiff * yDiff); + } + + static inline float distance(int aX, int aY, int bX, int bY) { + int xDiff = aX - bX; + int yDiff = aY - bY; + return sqrt(float(xDiff * xDiff + yDiff * yDiff)); + } + }; + + } + } +} + +#endif diff --git a/ImageProcess/include/zxing/common/detector/MonochromeRectangleDetector.h b/ImageProcess/include/zxing/common/detector/MonochromeRectangleDetector.h new file mode 100644 index 0000000..83c2682 --- /dev/null +++ b/ImageProcess/include/zxing/common/detector/MonochromeRectangleDetector.h @@ -0,0 +1,62 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __MONOCHROMERECTANGLEDETECTOR_H__ +#define __MONOCHROMERECTANGLEDETECTOR_H__ + +/* + * MonochromeRectangleDetector.h + * y_wmk + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 y_wmk authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + + struct TwoInts : public Counted { + int start; + int end; + }; + + class MonochromeRectangleDetector : public Counted { + private: + static const int MAX_MODULES = 32; + Ref image_; + + public: + MonochromeRectangleDetector(Ref image) : image_(image) { }; + + std::vector > detect(); + + private: + Ref findCornerFromCenter(int centerX, int deltaX, int left, int right, + int centerY, int deltaY, int top, int bottom, int maxWhiteRun); + + Ref blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, + bool horizontal); + + int max(int a, float b) { return (float)a > b ? a : (int)b; }; + }; + +} + +#endif // __MONOCHROMERECTANGLEDETECTOR_H__ diff --git a/ImageProcess/include/zxing/common/detector/WhiteRectangleDetector.h b/ImageProcess/include/zxing/common/detector/WhiteRectangleDetector.h new file mode 100644 index 0000000..ea27ec0 --- /dev/null +++ b/ImageProcess/include/zxing/common/detector/WhiteRectangleDetector.h @@ -0,0 +1,59 @@ +#ifndef __WHITERECTANGLEDETECTOR_H__ +#define __WHITERECTANGLEDETECTOR_H__ + +/* + * WhiteRectangleDetector.h + * + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + + +namespace zxing { + + class WhiteRectangleDetector : public Counted { + private: + static int INIT_SIZE; + static int CORR; + Ref image_; + int width_; + int height_; + int leftInit_; + int rightInit_; + int downInit_; + int upInit_; + + public: + WhiteRectangleDetector(Ref image); + WhiteRectangleDetector(Ref image, int initSize, int x, int y); + std::vector > detect(); + + private: + Ref getBlackPointOnSegment(int aX, int aY, int bX, int bY); + std::vector > centerEdges(Ref y, Ref z, + Ref x, Ref t); + bool containsBlackPoint(int a, int b, int fixed, bool horizontal); + }; +} + +#endif diff --git a/ImageProcess/include/zxing/common/reedsolomon/GenericGF.h b/ImageProcess/include/zxing/common/reedsolomon/GenericGF.h new file mode 100644 index 0000000..6b3a488 --- /dev/null +++ b/ImageProcess/include/zxing/common/reedsolomon/GenericGF.h @@ -0,0 +1,73 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * GenericGF.h + * zxing + * + * Created by Lukas Stabe on 13/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#ifndef GENERICGF_H +#define GENERICGF_H + +#include +#include + +namespace zxing { + class GenericGFPoly; + + class GenericGF : public Counted { + + private: + std::vector expTable; + std::vector logTable; + Ref zero; + Ref one; + int size; + int primitive; + int generatorBase; + bool initialized; + + void initialize(); + void checkInit(); + + public: + static Ref AZTEC_DATA_12; + static Ref AZTEC_DATA_10; + static Ref AZTEC_DATA_8; + static Ref AZTEC_DATA_6; + static Ref AZTEC_PARAM; + static Ref QR_CODE_FIELD_256; + static Ref DATA_MATRIX_FIELD_256; + static Ref MAXICODE_FIELD_64; + + GenericGF(int primitive, int size, int b); + + Ref getZero(); + Ref getOne(); + int getSize(); + int getGeneratorBase(); + Ref buildMonomial(int degree, int coefficient); + + static int addOrSubtract(int a, int b); + int exp(int a); + int log(int a); + int inverse(int a); + int multiply(int a, int b); + }; +} + +#endif //GENERICGF_H + diff --git a/ImageProcess/include/zxing/common/reedsolomon/GenericGFPoly.h b/ImageProcess/include/zxing/common/reedsolomon/GenericGFPoly.h new file mode 100644 index 0000000..1aa4321 --- /dev/null +++ b/ImageProcess/include/zxing/common/reedsolomon/GenericGFPoly.h @@ -0,0 +1,56 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * GenericGFPoly.h + * zxing + * + * Created by Lukas Stabe on 13/02/2012. + * Copyright 2012 ZXing authors All rights reserved. + * + * 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. + */ + +#ifndef GENERICGFPOLY_H +#define GENERICGFPOLY_H + +#include +#include +#include + +namespace zxing { + + class GenericGF; + + class GenericGFPoly : public Counted { + private: + Ref field_; + ArrayRef coefficients_; + + public: + GenericGFPoly(Ref field, ArrayRef coefficients); + ArrayRef getCoefficients(); + int getDegree(); + bool isZero(); + int getCoefficient(int degree); + int evaluateAt(int a); + Ref addOrSubtract(Ref other); + Ref multiply(Ref other); + Ref multiply(int scalar); + Ref multiplyByMonomial(int degree, int coefficient); + std::vector > divide(Ref other); + + + }; + +} + +#endif //GENERICGFPOLY_H diff --git a/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonDecoder.h b/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonDecoder.h new file mode 100644 index 0000000..0549eab --- /dev/null +++ b/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonDecoder.h @@ -0,0 +1,49 @@ +#ifndef __REED_SOLOMON_DECODER_H__ +#define __REED_SOLOMON_DECODER_H__ + +/* + * ReedSolomonDecoder.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + class GenericGFPoly; + class GenericGF; + + class ReedSolomonDecoder { + private: + Ref field; + public: + ReedSolomonDecoder(Ref fld); + ~ReedSolomonDecoder(); + void decode(ArrayRef received, int twoS); + std::vector > runEuclideanAlgorithm(Ref a, Ref b, int R); + + private: + ArrayRef findErrorLocations(Ref errorLocator); + ArrayRef findErrorMagnitudes(Ref errorEvaluator, ArrayRef errorLocations); + }; +} + +#endif // __REED_SOLOMON_DECODER_H__ diff --git a/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonException.h b/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonException.h new file mode 100644 index 0000000..1521c07 --- /dev/null +++ b/ImageProcess/include/zxing/common/reedsolomon/ReedSolomonException.h @@ -0,0 +1,33 @@ +#ifndef __REED_SOLOMON_EXCEPTION_H__ +#define __REED_SOLOMON_EXCEPTION_H__ + +/* + * ReedSolomonException.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + class ReedSolomonException : public Exception { + public: + ReedSolomonException(const char* msg) throw(); + ~ReedSolomonException() throw(); + }; +} + +#endif // __REED_SOLOMON_EXCEPTION_H__ diff --git a/ImageProcess/include/zxing/datamatrix/DataMatrixReader.h b/ImageProcess/include/zxing/datamatrix/DataMatrixReader.h new file mode 100644 index 0000000..cf5d4c8 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/DataMatrixReader.h @@ -0,0 +1,45 @@ +#ifndef __DATA_MATRIX_READER_H__ +#define __DATA_MATRIX_READER_H__ + +/* + * DataMatrixReader.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace datamatrix { + + class DataMatrixReader : public Reader { + private: + Decoder decoder_; + + public: + DataMatrixReader(); + virtual Ref decode(Ref image, DecodeHints hints); + virtual ~DataMatrixReader(); + + }; + + } +} + +#endif // __DATA_MATRIX_READER_H__ diff --git a/ImageProcess/include/zxing/datamatrix/Version.h b/ImageProcess/include/zxing/datamatrix/Version.h new file mode 100644 index 0000000..29174c1 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/Version.h @@ -0,0 +1,87 @@ +#ifndef __VERSION_H__ +#define __VERSION_H__ + +/* + * Version.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace datamatrix { + + class ECB { + private: + int count_; + int dataCodewords_; + public: + ECB(int count, int dataCodewords); + int getCount(); + int getDataCodewords(); + }; + + class ECBlocks { + private: + int ecCodewords_; + std::vector ecBlocks_; + public: + ECBlocks(int ecCodewords, ECB* ecBlocks); + ECBlocks(int ecCodewords, ECB* ecBlocks1, ECB* ecBlocks2); + int getECCodewords(); + std::vector& getECBlocks(); + ~ECBlocks(); + }; + + class Version : public Counted { + private: + int versionNumber_; + int symbolSizeRows_; + int symbolSizeColumns_; + int dataRegionSizeRows_; + int dataRegionSizeColumns_; + ECBlocks* ecBlocks_; + int totalCodewords_; + Version(int versionNumber, int symbolSizeRows, int symbolSizeColumns, int dataRegionSizeRows, + int dataRegionSizeColumns, ECBlocks* ecBlocks); + + public: + static std::vector > VERSIONS; + + ~Version(); + int getVersionNumber(); + int getSymbolSizeRows(); + int getSymbolSizeColumns(); + int getDataRegionSizeRows(); + int getDataRegionSizeColumns(); + int getTotalCodewords(); + ECBlocks* getECBlocks(); + static int buildVersions(); + Ref getVersionForDimensions(int numRows, int numColumns); + + private: + Version(const Version&); + Version& operator=(const Version&); + }; + } +} + +#endif // __VERSION_H__ diff --git a/ImageProcess/include/zxing/datamatrix/decoder/BitMatrixParser.h b/ImageProcess/include/zxing/datamatrix/decoder/BitMatrixParser.h new file mode 100644 index 0000000..a83dc98 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/decoder/BitMatrixParser.h @@ -0,0 +1,59 @@ +#ifndef __BIT_MATRIX_PARSER_DM_H__ +#define __BIT_MATRIX_PARSER_DM_H__ + +/* + * BitMatrixParser.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace datamatrix { + + class BitMatrixParser : public Counted { + private: + Ref bitMatrix_; + Ref parsedVersion_; + Ref readBitMatrix_; + + int copyBit(size_t x, size_t y, int versionBits); + + public: + BitMatrixParser(Ref bitMatrix); + Ref readVersion(Ref bitMatrix); + ArrayRef readCodewords(); + bool readModule(int row, int column, int numRows, int numColumns); + + private: + int readUtah(int row, int column, int numRows, int numColumns); + int readCorner1(int numRows, int numColumns); + int readCorner2(int numRows, int numColumns); + int readCorner3(int numRows, int numColumns); + int readCorner4(int numRows, int numColumns); + Ref extractDataRegion(Ref bitMatrix); + }; + + } +} + +#endif // __BIT_MATRIX_PARSER_DM_H__ diff --git a/ImageProcess/include/zxing/datamatrix/decoder/DataBlock.h b/ImageProcess/include/zxing/datamatrix/decoder/DataBlock.h new file mode 100644 index 0000000..619fc26 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/decoder/DataBlock.h @@ -0,0 +1,49 @@ +#ifndef __DATA_BLOCK_DM_H__ +#define __DATA_BLOCK_DM_H__ + +/* + * DataBlock.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace datamatrix { + + class DataBlock : public Counted { + private: + int numDataCodewords_; + ArrayRef codewords_; + + DataBlock(int numDataCodewords, ArrayRef codewords); + + public: + static std::vector > getDataBlocks(ArrayRef rawCodewords, Version* version); + + int getNumDataCodewords(); + ArrayRef getCodewords(); + }; + + } +} + +#endif // __DATA_BLOCK_DM_H__ diff --git a/ImageProcess/include/zxing/datamatrix/decoder/DecodedBitStreamParser.h b/ImageProcess/include/zxing/datamatrix/decoder/DecodedBitStreamParser.h new file mode 100644 index 0000000..6b0e96d --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/decoder/DecodedBitStreamParser.h @@ -0,0 +1,104 @@ +#ifndef __DECODED_BIT_STREAM_PARSER_DM_H__ +#define __DECODED_BIT_STREAM_PARSER_DM_H__ + +/* + * DecodedBitStreamParser.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + + +namespace zxing { + namespace datamatrix { + + class DecodedBitStreamParser { + private: + static const int PAD_ENCODE = 0; // Not really an encoding + static const int ASCII_ENCODE = 1; + static const int C40_ENCODE = 2; + static const int TEXT_ENCODE = 3; + static const int ANSIX12_ENCODE = 4; + static const int EDIFACT_ENCODE = 5; + static const int BASE256_ENCODE = 6; + + /** + * See ISO 16022:2006, Annex C Table C.1 + * The C40 Basic Character Set (*'s used for placeholders for the shift values) + */ + static const char C40_BASIC_SET_CHARS[]; + + static const char C40_SHIFT2_SET_CHARS[]; + /** + * See ISO 16022:2006, Annex C Table C.2 + * The Text Basic Character Set (*'s used for placeholders for the shift values) + */ + static const char TEXT_BASIC_SET_CHARS[]; + + static const char TEXT_SHIFT3_SET_CHARS[]; + /** + * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2 + */ + int decodeAsciiSegment(Ref bits, std::ostringstream& result, std::ostringstream& resultTrailer); + /** + * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1 + */ + void decodeC40Segment(Ref bits, std::ostringstream& result); + /** + * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2 + */ + void decodeTextSegment(Ref bits, std::ostringstream& result); + /** + * See ISO 16022:2006, 5.2.7 + */ + void decodeAnsiX12Segment(Ref bits, std::ostringstream& result); + /** + * See ISO 16022:2006, 5.2.8 and Annex C Table C.3 + */ + void decodeEdifactSegment(Ref bits, std::ostringstream& result); + /** + * See ISO 16022:2006, 5.2.9 and Annex B, B.2 + */ + void decodeBase256Segment(Ref bits, std::ostringstream& result, std::vector byteSegments); + + void parseTwoBytes(int firstByte, int secondByte, int* result); + /** + * See ISO 16022:2006, Annex B, B.2 + */ + char unrandomize255State(int randomizedBase256Codeword, + int base256CodewordPosition) { + int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1; + int tempVariable = randomizedBase256Codeword - pseudoRandomNumber; + return (char)(tempVariable >= 0 ? tempVariable : (tempVariable + 256)); + }; + void append(std::ostream& ost, const char* bufIn, size_t nIn, const char* src); + + public: + DecodedBitStreamParser() { }; + Ref decode(ArrayRef bytes); + }; + + } +} + +#endif // __DECODED_BIT_STREAM_PARSER_DM_H__ diff --git a/ImageProcess/include/zxing/datamatrix/decoder/Decoder.h b/ImageProcess/include/zxing/datamatrix/decoder/Decoder.h new file mode 100644 index 0000000..d9d4f18 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/decoder/Decoder.h @@ -0,0 +1,49 @@ +#ifndef __DECODER_DM_H__ +#define __DECODER_DM_H__ + +/* + * Decoder.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + + +namespace zxing { + namespace datamatrix { + + class Decoder { + private: + ReedSolomonDecoder rsDecoder_; + + void correctErrors(ArrayRef bytes, int numDataCodewords); + + public: + Decoder(); + + Ref decode(Ref bits); + }; + + } +} + +#endif // __DECODER_DM_H__ diff --git a/ImageProcess/include/zxing/datamatrix/detector/CornerPoint.h b/ImageProcess/include/zxing/datamatrix/detector/CornerPoint.h new file mode 100644 index 0000000..cbf2a7e --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/detector/CornerPoint.h @@ -0,0 +1,43 @@ +#ifndef __CORNER_FINDER_H__ +#define __CORNER_FINDER_H__ + +/* + * CornerPoint.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace datamatrix { + + class CornerPoint : public ResultPoint { + private: + int counter_; + + public: + CornerPoint(float posX, float posY); + int getCount() const; + void incrementCount(); + bool equals(Ref other) const; + }; + } +} + +#endif // __CORNER_FINDER_H__ diff --git a/ImageProcess/include/zxing/datamatrix/detector/Detector.h b/ImageProcess/include/zxing/datamatrix/detector/Detector.h new file mode 100644 index 0000000..ddba406 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/detector/Detector.h @@ -0,0 +1,94 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __DETECTOR_H__ +#define __DETECTOR_H__ + +/* + * Detector.h + * zxing + * + * Created by Luiz Silva on 09/02/2010. + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace datamatrix { + + class ResultPointsAndTransitions : public Counted { + private: + Ref to_; + Ref from_; + int transitions_; + + public: + ResultPointsAndTransitions(); + ResultPointsAndTransitions(Ref from, Ref to, int transitions); + Ref getFrom(); + Ref getTo(); + int getTransitions(); + }; + + class Detector : public Counted { + private: + Ref image_; + + protected: + Ref sampleGrid(Ref image, int dimensionX, int dimensionY, + Ref transform); + + void insertionSort(std::vector >& vector); + + Ref correctTopRightRectangular(Ref bottomLeft, + Ref bottomRight, Ref topLeft, Ref topRight, + int dimensionTop, int dimensionRight); + Ref correctTopRight(Ref bottomLeft, Ref bottomRight, + Ref topLeft, Ref topRight, int dimension); + bool isValid(Ref p); + int distance(Ref a, Ref b); + Ref transitionsBetween(Ref from, Ref to); + int min(int a, int b) { + return a > b ? b : a; + } + /** + * Ends up being a bit faster than round(). This merely rounds its + * argument to the nearest int, where x.5 rounds up. + */ + int round(float d) { + return (int)(d + 0.5f); + } + + public: + Ref getImage(); + Detector(Ref image); + + virtual Ref createTransform(Ref topLeft, + Ref topRight, Ref bottomLeft, Ref bottomRight, + int dimensionX, int dimensionY); + + Ref detect(); + + private: + int compare(Ref a, Ref b); + }; + + } +} + +#endif // __DETECTOR_H__ diff --git a/ImageProcess/include/zxing/datamatrix/detector/DetectorException.h b/ImageProcess/include/zxing/datamatrix/detector/DetectorException.h new file mode 100644 index 0000000..7f41e80 --- /dev/null +++ b/ImageProcess/include/zxing/datamatrix/detector/DetectorException.h @@ -0,0 +1,23 @@ +/* + * DetectorException.h + * + * Created on: Aug 26, 2011 + * Author: luiz + */ + +#ifndef DETECTOREXCEPTION_H_ +#define DETECTOREXCEPTION_H_ + +#include + +namespace zxing { + namespace datamatrix { + + class DetectorException : public Exception { + public: + DetectorException(const char* msg); + virtual ~DetectorException() throw(); + }; + } /* namespace nexxera */ +} /* namespace zxing */ +#endif /* DETECTOREXCEPTION_H_ */ diff --git a/ImageProcess/include/zxing/multi/ByQuadrantReader.h b/ImageProcess/include/zxing/multi/ByQuadrantReader.h new file mode 100644 index 0000000..7935d76 --- /dev/null +++ b/ImageProcess/include/zxing/multi/ByQuadrantReader.h @@ -0,0 +1,42 @@ +#ifndef __BY_QUADRANT_READER_H__ +#define __BY_QUADRANT_READER_H__ + +/* + * Copyright 2011 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace multi { + + class ByQuadrantReader : public Reader { + private: + Reader& delegate_; + + public: + ByQuadrantReader(Reader& delegate); + virtual ~ByQuadrantReader(); + virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints); + }; + + } +} + +#endif // __BY_QUADRANT_READER_H__ diff --git a/ImageProcess/include/zxing/multi/GenericMultipleBarcodeReader.h b/ImageProcess/include/zxing/multi/GenericMultipleBarcodeReader.h new file mode 100644 index 0000000..a01f568 --- /dev/null +++ b/ImageProcess/include/zxing/multi/GenericMultipleBarcodeReader.h @@ -0,0 +1,51 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __GENERIC_MULTIPLE_BARCODE_READER_H__ +#define __GENERIC_MULTIPLE_BARCODE_READER_H__ + +/* + * Copyright 2011 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace multi { + + class GenericMultipleBarcodeReader : public MultipleBarcodeReader { + private: + static Ref translateResultPoints(Ref result, + int xOffset, + int yOffset); + void doDecodeMultiple(Ref image, + DecodeHints hints, + std::vector >& results, + int xOffset, + int yOffset, + int currentDepth); + Reader& delegate_; + static const int MIN_DIMENSION_TO_RECUR = 100; + static const int MAX_DEPTH = 4; + + public: + GenericMultipleBarcodeReader(Reader& delegate); + virtual ~GenericMultipleBarcodeReader(); + virtual std::vector > decodeMultiple(Ref image, DecodeHints hints); + }; + + } +} + +#endif // __GENERIC_MULTIPLE_BARCODE_READER_H__ diff --git a/ImageProcess/include/zxing/multi/MultipleBarcodeReader.h b/ImageProcess/include/zxing/multi/MultipleBarcodeReader.h new file mode 100644 index 0000000..9b307a7 --- /dev/null +++ b/ImageProcess/include/zxing/multi/MultipleBarcodeReader.h @@ -0,0 +1,41 @@ +#ifndef __MULTIPLE_BARCODE_READER_H__ +#define __MULTIPLE_BARCODE_READER_H__ + +/* + * Copyright 2011 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace multi { + + class MultipleBarcodeReader : public Counted { + protected: + MultipleBarcodeReader() {} + public: + virtual std::vector > decodeMultiple(Ref image); + virtual std::vector > decodeMultiple(Ref image, DecodeHints hints) = 0; + virtual ~MultipleBarcodeReader(); + }; + + } +} + +#endif // __MULTIPLE_BARCODE_READER_H__ diff --git a/ImageProcess/include/zxing/multi/qrcode/QRCodeMultiReader.h b/ImageProcess/include/zxing/multi/qrcode/QRCodeMultiReader.h new file mode 100644 index 0000000..32dca26 --- /dev/null +++ b/ImageProcess/include/zxing/multi/qrcode/QRCodeMultiReader.h @@ -0,0 +1,36 @@ +#ifndef __QRCODE_MULTI_READER_H__ +#define __QRCODE_MULTI_READER_H__ + +/* + * Copyright 2011 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace multi { + + class QRCodeMultiReader : public zxing::qrcode::QRCodeReader, public MultipleBarcodeReader { + public: + QRCodeMultiReader(); + virtual ~QRCodeMultiReader(); + virtual std::vector > decodeMultiple(Ref image, DecodeHints hints); + }; + + } +} + +#endif // __QRCODE_MULTI_READER_H__ diff --git a/ImageProcess/include/zxing/multi/qrcode/detector/MultiDetector.h b/ImageProcess/include/zxing/multi/qrcode/detector/MultiDetector.h new file mode 100644 index 0000000..7c9a189 --- /dev/null +++ b/ImageProcess/include/zxing/multi/qrcode/detector/MultiDetector.h @@ -0,0 +1,37 @@ +#ifndef __MULTI_DETECTOR_H__ +#define __MULTI_DETECTOR_H__ + +/* + * Copyright 2011 ZXing authors + * + * 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. + */ + +#include +#include +#include + +namespace zxing { +namespace multi { + +class MultiDetector : public zxing::qrcode::Detector { + public: + MultiDetector(Ref image); + virtual ~MultiDetector(); + virtual std::vector > detectMulti(DecodeHints hints); +}; + +} +} + +#endif // __MULTI_DETECTOR_H__ diff --git a/ImageProcess/include/zxing/multi/qrcode/detector/MultiFinderPatternFinder.h b/ImageProcess/include/zxing/multi/qrcode/detector/MultiFinderPatternFinder.h new file mode 100644 index 0000000..37eed62 --- /dev/null +++ b/ImageProcess/include/zxing/multi/qrcode/detector/MultiFinderPatternFinder.h @@ -0,0 +1,47 @@ +#ifndef __MULTI_FINDER_PATTERN_FINDER_H__ +#define __MULTI_FINDER_PATTERN_FINDER_H__ + +/* + * Copyright 2011 ZXing authors + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace multi { + + class MultiFinderPatternFinder : zxing::qrcode::FinderPatternFinder { + private: + std::vector > > selectBestPatterns(); + + static const float MAX_MODULE_COUNT_PER_EDGE; + static const float MIN_MODULE_COUNT_PER_EDGE; + static const float DIFF_MODSIZE_CUTOFF_PERCENT; + static const float DIFF_MODSIZE_CUTOFF; + + public: + MultiFinderPatternFinder(Ref image, Ref resultPointCallback); + virtual ~MultiFinderPatternFinder(); + virtual std::vector > findMulti(DecodeHints const& hints); + + + }; + + } +} + +#endif // __MULTI_FINDER_PATTERN_FINDER_H__ diff --git a/ImageProcess/include/zxing/oned/CodaBarReader.h b/ImageProcess/include/zxing/oned/CodaBarReader.h new file mode 100644 index 0000000..0df03a4 --- /dev/null +++ b/ImageProcess/include/zxing/oned/CodaBarReader.h @@ -0,0 +1,57 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __CODA_BAR_READER_H__ +#define __CODA_BAR_READER_H__ +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + class CodaBarReader : public OneDReader { + private: + static const int MAX_ACCEPTABLE; + static const int PADDING; + + // Keep some instance variables to avoid reallocations + std::string decodeRowResult; + std::vector counters; + int counterLength; + + public: + CodaBarReader(); + + Ref decodeRow(int rowNumber, Ref row); + + void validatePattern(int start); + + private: + void setCounters(Ref row); + void counterAppend(int e); + int findStartPattern(); + + static bool arrayContains(char const array[], char key); + + int toNarrowWidePattern(int position); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/Code128Reader.h b/ImageProcess/include/zxing/oned/Code128Reader.h new file mode 100644 index 0000000..2af31c8 --- /dev/null +++ b/ImageProcess/include/zxing/oned/Code128Reader.h @@ -0,0 +1,48 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __CODE_128_READER_H__ +#define __CODE_128_READER_H__ +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + class Code128Reader : public OneDReader { + private: + static const int MAX_AVG_VARIANCE; + static const int MAX_INDIVIDUAL_VARIANCE; + + static std::vector findStartPattern(Ref row); + static int decodeCode(Ref row, + std::vector& counters, + int rowOffset); + + public: + Ref decodeRow(int rowNumber, Ref row); + Code128Reader(); + ~Code128Reader(); + + BarcodeFormat getBarcodeFormat(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/Code39Reader.h b/ImageProcess/include/zxing/oned/Code39Reader.h new file mode 100644 index 0000000..ed5a60e --- /dev/null +++ b/ImageProcess/include/zxing/oned/Code39Reader.h @@ -0,0 +1,63 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __CODE_39_READER_H__ +#define __CODE_39_READER_H__ +/* + * Code39Reader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + /** + *

Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.

+ * Ported form Java (author Sean Owen) + * @author Lukasz Warchol + */ + class Code39Reader : public OneDReader { + private: + bool usingCheckDigit; + bool extendedMode; + std::string decodeRowResult; + std::vector counters; + + void init(bool usingCheckDigit = false, bool extendedMode = false); + + static std::vector findAsteriskPattern(Ref row, + std::vector& counters); + static int toNarrowWidePattern(std::vector& counters); + static char patternToChar(int pattern); + static Ref decodeExtended(std::string encoded); + + void append(char* s, char c); + + public: + Code39Reader(); + Code39Reader(bool usingCheckDigit_); + Code39Reader(bool usingCheckDigit_, bool extendedMode_); + + Ref decodeRow(int rowNumber, Ref row); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/Code93Reader.h b/ImageProcess/include/zxing/oned/Code93Reader.h new file mode 100644 index 0000000..f1875f6 --- /dev/null +++ b/ImageProcess/include/zxing/oned/Code93Reader.h @@ -0,0 +1,58 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __CODE_93_READER_H__ +#define __CODE_93_READER_H__ +/* + * Code93Reader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + /** + *

Decodes Code 93 barcodes. This does not support "Full ASCII Code 93" yet.

+ * Ported form Java (author Sean Owen) + * @author Lukasz Warchol + */ + class Code93Reader : public OneDReader { + public: + Code93Reader(); + Ref decodeRow(int rowNumber, Ref row); + + private: + std::string decodeRowResult; + std::vector counters; + + Range findAsteriskPattern(Ref row); + + static int toPattern(std::vector& counters); + static char patternToChar(int pattern); + static Ref decodeExtended(std::string const& encoded); + static void checkChecksums(std::string const& result); + static void checkOneChecksum(std::string const& result, + int checkPosition, + int weightMax); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/EAN13Reader.h b/ImageProcess/include/zxing/oned/EAN13Reader.h new file mode 100644 index 0000000..9489cdf --- /dev/null +++ b/ImageProcess/include/zxing/oned/EAN13Reader.h @@ -0,0 +1,49 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __EAN_13_READER_H__ +#define __EAN_13_READER_H__ + +/* + * EAN13Reader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace oned { + + class EAN13Reader : public UPCEANReader { + private: + std::vector decodeMiddleCounters; + static void determineFirstDigit(std::string& resultString, + int lgPatternFound); + + public: + EAN13Reader(); + + int decodeMiddle(Ref row, + Range const& startRange, + std::string& resultString); + + BarcodeFormat getBarcodeFormat(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/EAN8Reader.h b/ImageProcess/include/zxing/oned/EAN8Reader.h new file mode 100644 index 0000000..f024d8f --- /dev/null +++ b/ImageProcess/include/zxing/oned/EAN8Reader.h @@ -0,0 +1,47 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __EAN_8_READER_H__ +#define __EAN_8_READER_H__ + +/* + * EAN8Reader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace oned { + + class EAN8Reader : public UPCEANReader { + private: + std::vector decodeMiddleCounters; + + public: + EAN8Reader(); + + int decodeMiddle(Ref row, + Range const& startRange, + std::string& resultString); + + BarcodeFormat getBarcodeFormat(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/ITFReader.h b/ImageProcess/include/zxing/oned/ITFReader.h new file mode 100644 index 0000000..2879c20 --- /dev/null +++ b/ImageProcess/include/zxing/oned/ITFReader.h @@ -0,0 +1,54 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __ITF_READER_H__ +#define __ITF_READER_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + class ITFReader : public OneDReader { + private: + enum { MAX_AVG_VARIANCE = (unsigned int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 420 / 1000) }; + enum { MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 780 / 1000) }; + // Stores the actual narrow line width of the image being decoded. + int narrowLineWidth; + + Range decodeStart(Ref row); + Range decodeEnd(Ref row); + static void decodeMiddle(Ref row, int payloadStart, int payloadEnd, std::string& resultString); + void validateQuietZone(Ref row, int startPattern); + static int skipWhiteSpace(Ref row); + + static Range findGuardPattern(Ref row, int rowOffset, std::vector const& pattern); + static int decodeDigit(std::vector& counters); + + void append(char* s, char c); + public: + Ref decodeRow(int rowNumber, Ref row); + ITFReader(); + ~ITFReader(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/MultiFormatOneDReader.h b/ImageProcess/include/zxing/oned/MultiFormatOneDReader.h new file mode 100644 index 0000000..67077db --- /dev/null +++ b/ImageProcess/include/zxing/oned/MultiFormatOneDReader.h @@ -0,0 +1,38 @@ +#ifndef __MULTI_FORMAT_ONED_READER_H__ +#define __MULTI_FORMAT_ONED_READER_H__ +/* + * MultiFormatOneDReader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace oned { + class MultiFormatOneDReader : public OneDReader { + + private: + std::vector > readers; + public: + MultiFormatOneDReader(DecodeHints hints); + + Ref decodeRow(int rowNumber, Ref row); + }; + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/MultiFormatUPCEANReader.h b/ImageProcess/include/zxing/oned/MultiFormatUPCEANReader.h new file mode 100644 index 0000000..689deb6 --- /dev/null +++ b/ImageProcess/include/zxing/oned/MultiFormatUPCEANReader.h @@ -0,0 +1,41 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __MULTI_FORMAT_UPC_EAN_READER_H__ +#define __MULTI_FORMAT_UPC_EAN_READER_H__ +/* + * MultiFormatUPCEANReader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace oned { + + class UPCEANReader; + + class MultiFormatUPCEANReader : public OneDReader { + private: + std::vector< Ref > readers; + public: + MultiFormatUPCEANReader(DecodeHints hints); + Ref decodeRow(int rowNumber, Ref row); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/OneDReader.h b/ImageProcess/include/zxing/oned/OneDReader.h new file mode 100644 index 0000000..dbe4218 --- /dev/null +++ b/ImageProcess/include/zxing/oned/OneDReader.h @@ -0,0 +1,81 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __ONED_READER_H__ +#define __ONED_READER_H__ + +/* + * OneDReader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace oned { + + class OneDReader : public Reader { + private: + Ref doDecode(Ref image, DecodeHints hints); + + protected: + static const int INTEGER_MATH_SHIFT = 8; + + struct Range { + private: + int data[2]; + public: + Range() {} + Range(int zero, int one) { + data[0] = zero; + data[1] = one; + } + int& operator [] (int index) { + return data[index]; + } + int const& operator [] (int index) const { + return data[index]; + } + }; + + static int patternMatchVariance(std::vector& counters, + std::vector const& pattern, + int maxIndividualVariance); + static int patternMatchVariance(std::vector& counters, + int const pattern[], + int maxIndividualVariance); + + protected: + static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; + + public: + + OneDReader(); + virtual Ref decode(Ref image, DecodeHints hints); + + // Implementations must not throw any exceptions. If a barcode is not found on this row, + // a empty ref should be returned e.g. return Ref(); + virtual Ref decodeRow(int rowNumber, Ref row) = 0; + + static void recordPattern(Ref row, + int start, + std::vector& counters); + virtual ~OneDReader(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/OneDResultPoint.h b/ImageProcess/include/zxing/oned/OneDResultPoint.h new file mode 100644 index 0000000..a0f3b62 --- /dev/null +++ b/ImageProcess/include/zxing/oned/OneDResultPoint.h @@ -0,0 +1,35 @@ +#ifndef __ONED_RESULT_POINT_H__ +#define __ONED_RESULT_POINT_H__ +/* + * OneDResultPoint.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ +#include +#include + +namespace zxing { + namespace oned { + + class OneDResultPoint : public ResultPoint { + + public: + OneDResultPoint(float posX, float posY); + }; + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/UPCAReader.h b/ImageProcess/include/zxing/oned/UPCAReader.h new file mode 100644 index 0000000..5d1e2fb --- /dev/null +++ b/ImageProcess/include/zxing/oned/UPCAReader.h @@ -0,0 +1,50 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __UPCA_READER_H__ +#define __UPCA_READER_H__ +/* + * UPCAReader.h + * ZXing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace oned { + + class UPCAReader : public UPCEANReader { + + private: + EAN13Reader ean13Reader; + static Ref maybeReturnResult(Ref result); + + public: + UPCAReader(); + + int decodeMiddle(Ref row, Range const& startRange, std::string& resultString); + + Ref decodeRow(int rowNumber, Ref row); + Ref decodeRow(int rowNumber, Ref row, Range const& startGuardRange); + Ref decode(Ref image, DecodeHints hints); + + BarcodeFormat getBarcodeFormat(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/UPCEANReader.h b/ImageProcess/include/zxing/oned/UPCEANReader.h new file mode 100644 index 0000000..f3b712d --- /dev/null +++ b/ImageProcess/include/zxing/oned/UPCEANReader.h @@ -0,0 +1,88 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __UPC_EAN_READER_H__ +#define __UPC_EAN_READER_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace oned { + + class UPCEANReader : public OneDReader { + private: + std::string decodeRowStringBuffer; + // UPCEANExtensionSupport extensionReader; + // EANManufacturerOrgSupport eanManSupport; + + static const int MAX_AVG_VARIANCE; + static const int MAX_INDIVIDUAL_VARIANCE; + + static Range findStartGuardPattern(Ref row); + + virtual Range decodeEnd(Ref row, int endStart); + + static bool checkStandardUPCEANChecksum(Ref const& s); + + static Range findGuardPattern(Ref row, + int rowOffset, + bool whiteFirst, + std::vector const& pattern, + std::vector& counters); + + + protected: + static const std::vector START_END_PATTERN; + static const std::vector MIDDLE_PATTERN; + + static const std::vector L_PATTERNS; + static const std::vector L_AND_G_PATTERNS; + + static Range findGuardPattern(Ref row, + int rowOffset, + bool whiteFirst, + std::vector const& pattern); + + public: + UPCEANReader(); + + virtual int decodeMiddle(Ref row, + Range const& startRange, + std::string& resultString) = 0; + + virtual Ref decodeRow(int rowNumber, Ref row); + virtual Ref decodeRow(int rowNumber, Ref row, Range const& range); + + static int decodeDigit(Ref row, + std::vector& counters, + int rowOffset, + std::vector const& patterns); + + virtual bool checkChecksum(Ref const& s); + + virtual BarcodeFormat getBarcodeFormat() = 0; + virtual ~UPCEANReader(); + + friend class MultiFormatUPCEANReader; + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/oned/UPCEReader.h b/ImageProcess/include/zxing/oned/UPCEReader.h new file mode 100644 index 0000000..370d175 --- /dev/null +++ b/ImageProcess/include/zxing/oned/UPCEReader.h @@ -0,0 +1,47 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __UPC_E_READER_H__ +#define __UPC_E_READER_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace oned { + + class UPCEReader : public UPCEANReader { + private: + std::vector decodeMiddleCounters; + static bool determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound); + + protected: + Range decodeEnd(Ref row, int endStart); + bool checkChecksum(Ref const& s); + public: + UPCEReader(); + + int decodeMiddle(Ref row, Range const& startRange, std::string& resultString); + static Ref convertUPCEtoUPCA(Ref const& upce); + + BarcodeFormat getBarcodeFormat(); + }; + + } +} + +#endif diff --git a/ImageProcess/include/zxing/pdf417/PDF417Reader.h b/ImageProcess/include/zxing/pdf417/PDF417Reader.h new file mode 100644 index 0000000..5277dcd --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/PDF417Reader.h @@ -0,0 +1,49 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __PDF417_READER_H__ +#define __PDF417_READER_H__ + +/* + * PDF417Reader.h + * zxing + * + * Copyright 2010,2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace pdf417 { + + + class PDF417Reader : public Reader { + private: + decoder::Decoder decoder; + + static Ref extractPureBits(Ref image); + static int moduleSize(ArrayRef leftTopBlack, Ref image); + static int findPatternStart(int x, int y, Ref image); + static int findPatternEnd(int x, int y, Ref image); + + public: + Ref decode(Ref image, DecodeHints hints); + void reset(); + }; + + } +} + +#endif // __PDF417_READER_H__ diff --git a/ImageProcess/include/zxing/pdf417/decoder/BitMatrixParser.h b/ImageProcess/include/zxing/pdf417/decoder/BitMatrixParser.h new file mode 100644 index 0000000..2fd7b60 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/BitMatrixParser.h @@ -0,0 +1,84 @@ +#ifndef __BIT_MATRIX_PARSER__PDF_H__ +#define __BIT_MATRIX_PARSER__PDF_H__ + +/* + * BitMatrixParser.h / PDF417 + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace decoder { + + class BitMatrixParser : public Counted { + private: + static const int MAX_ROWS; + // Maximum Codewords (Data + Error) + static const int MAX_CW_CAPACITY; + static const int MODULES_IN_SYMBOL; + + Ref bitMatrix_; + int rows_; /* = 0 */ + int leftColumnECData_; /* = 0 */ + int rightColumnECData_; /* = 0 */ + /* added 2012-06-22 HFN */ + int aLeftColumnTriple_[3]; + int aRightColumnTriple_[3]; + int eraseCount_; /* = 0 */ + ArrayRef erasures_; + int ecLevel_; /* = -1 */ + + public: + static const int SYMBOL_TABLE[]; + static const int SYMBOL_TABLE_LENGTH; + static const int CODEWORD_TABLE[]; + + public: + BitMatrixParser(Ref bitMatrix); + ArrayRef getErasures() const { return erasures_; } + int getECLevel() const { return ecLevel_; } + int getEraseCount() const { return eraseCount_; } + ArrayRef readCodewords(); /* throw(FormatException) */ + static int getCodeword(int64_t symbol, int* pi = NULL); + + private: + bool VerifyOuterColumns(int rownumber); + static ArrayRef trimArray(ArrayRef array, int size); + static int findCodewordIndex(int64_t symbol); + + + int processRow(int rowNumber, + ArrayRef codewords, int next); + + int processRow(ArrayRef rowCounters, int rowNumber, int rowHeight, + ArrayRef codewords, int next); /* throw(FormatException) */ + protected: + bool IsEqual(int& a, int& b, int rownumber); + }; + + } + } +} + +#endif // __BIT_MATRIX_PARSER__PDF_H__ diff --git a/ImageProcess/include/zxing/pdf417/decoder/DecodedBitStreamParser.h b/ImageProcess/include/zxing/pdf417/decoder/DecodedBitStreamParser.h new file mode 100644 index 0000000..22c3a74 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/DecodedBitStreamParser.h @@ -0,0 +1,84 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __DECODED_BIT_STREAM_PARSER_PD_H__ +#define __DECODED_BIT_STREAM_PARSER_PD_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + + class DecodedBitStreamParser { + protected: + enum Mode { + ALPHA, + LOWER, + MIXED, + PUNCT, + ALPHA_SHIFT, + PUNCT_SHIFT + }; + + private: + + static const int TEXT_COMPACTION_MODE_LATCH; + static const int BYTE_COMPACTION_MODE_LATCH; + static const int NUMERIC_COMPACTION_MODE_LATCH; + static const int BYTE_COMPACTION_MODE_LATCH_6; + static const int BEGIN_MACRO_PDF417_CONTROL_BLOCK; + static const int BEGIN_MACRO_PDF417_OPTIONAL_FIELD; + static const int MACRO_PDF417_TERMINATOR; + static const int MODE_SHIFT_TO_BYTE_COMPACTION_MODE; + static const int MAX_NUMERIC_CODEWORDS; + + static const int PL; + static const int LL; + static const int AS; + static const int ML; + static const int AL; + static const int PS; + static const int PAL; + static const int EXP900_SIZE; + + static const char PUNCT_CHARS[]; + static const char MIXED_CHARS[]; + + static ArrayRef EXP900; + static ArrayRef initEXP900(); + + static int textCompaction(ArrayRef codewords, int codeIndex, Ref result); + static void decodeTextCompaction(ArrayRef textCompactionData, + ArrayRef byteCompactionData, + int length, + Ref result); + static int byteCompaction(int mode, ArrayRef codewords, int codeIndex, Ref result); + static int numericCompaction(ArrayRef codewords, int codeIndex, Ref result); + static Ref decodeBase900toBase10(ArrayRef codewords, int count); + + public: + DecodedBitStreamParser(); + static Ref decode(ArrayRef codewords); + }; + + } /* namespace pdf417 */ +} /* namespace zxing */ + +#endif // __DECODED_BIT_STREAM_PARSER_PD_H__ diff --git a/ImageProcess/include/zxing/pdf417/decoder/Decoder.cpp b/ImageProcess/include/zxing/pdf417/decoder/Decoder.cpp new file mode 100644 index 0000000..7fb8cb0 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/Decoder.cpp @@ -0,0 +1,118 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +/* + * Copyright 2010, 2012 ZXing authors All rights reserved. + * + * 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. + * + * 2012-06-27 hfn: PDF417 Reed-Solomon error correction, using following Java + * source code: + * http://code.google.com/p/zxing/issues/attachmentText?id=817&aid=8170033000&name=pdf417-java-reed-solomon-error-correction-2.patch&token=0819f5d7446ae2814fd91385eeec6a11 + */ + +#include +#include +#include +#include +#include +#include + +using zxing::pdf417::decoder::Decoder; +using zxing::pdf417::decoder::ec::ErrorCorrection; +using zxing::Ref; +using zxing::DecoderResult; + +// VC++ + +using zxing::BitMatrix; +using zxing::DecodeHints; +using zxing::ArrayRef; + +const int Decoder::MAX_ERRORS = 3; +const int Decoder::MAX_EC_CODEWORDS = 512; + +Ref Decoder::decode(Ref bits, DecodeHints const& hints) { + (void)hints; + // Construct a parser to read the data codewords and error-correction level + BitMatrixParser parser(bits); + ArrayRef codewords(parser.readCodewords()); + if (codewords->size() == 0) { + throw FormatException("PDF:Decoder:decode: cannot read codewords"); + } + + int ecLevel = parser.getECLevel(); + int numECCodewords = 1 << (ecLevel + 1); + ArrayRef erasures = parser.getErasures(); + + correctErrors(codewords, erasures, numECCodewords); + verifyCodewordCount(codewords, numECCodewords); + + // Decode the codewords + return DecodedBitStreamParser::decode(codewords); +} + +/** + * Verify that all is OK with the codeword array. + * + * @param codewords + * @return an index to the first data codeword. + * @throws FormatException + */ +void Decoder::verifyCodewordCount(ArrayRef codewords, int numECCodewords) { + int cwsize = codewords->size(); + if (cwsize < 4) { + // Codeword array size should be at least 4 allowing for + // Count CW, At least one Data CW, Error Correction CW, Error Correction CW + throw FormatException("PDF:Decoder:verifyCodewordCount: codeword array too small!"); + } + // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data + // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad + // codewords, but excluding the number of error correction codewords. + int numberOfCodewords = codewords[0]; + if (numberOfCodewords > cwsize) { + throw FormatException("PDF:Decoder:verifyCodewordCount: bad codeword number descriptor!"); + } + if (numberOfCodewords == 0) { + // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords) + if (numECCodewords < cwsize) { + codewords[0] = cwsize - numECCodewords; + } else { + throw FormatException("PDF:Decoder:verifyCodewordCount: bad error correction cw number!"); + } + } +} + +/** + * Correct errors whenever it is possible using Reed-Solomom algorithm + * + * @param codewords, erasures, numECCodewords + * @return 0. + * @throws FormatException + */ +void Decoder::correctErrors(ArrayRef codewords, + ArrayRef erasures, int numECCodewords) { + if (erasures->size() > numECCodewords / 2 + MAX_ERRORS || + numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS) { + throw FormatException("PDF:Decoder:correctErrors: Too many errors or EC Codewords corrupted"); + } + + Ref errorCorrection(new ErrorCorrection); + errorCorrection->decode(codewords, numECCodewords, erasures); + + // 2012-06-27 HFN if, despite of error correction, there are still codewords with invalid + // value, throw an exception here: + for (int i = 0; i < codewords->size(); i++) { + if (codewords[i]<0) { + throw FormatException("PDF:Decoder:correctErrors: Error correction did not succeed!"); + } + } +} diff --git a/ImageProcess/include/zxing/pdf417/decoder/Decoder.h b/ImageProcess/include/zxing/pdf417/decoder/Decoder.h new file mode 100644 index 0000000..36b66ab --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/Decoder.h @@ -0,0 +1,62 @@ +#ifndef __DECOCER_PDF_H__ +#define __DECOCER_PDF_H__ + +/* + * Decoder.h + * zxing + * + * Created by Hartmut Neubauer, 2012-05-25 + * Copyright 2010,2012 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + + +namespace zxing { + namespace pdf417 { + namespace decoder { + + /** + *

The main class which implements PDF417 Code decoding -- as + * opposed to locating and extracting the PDF417 Code from an image.

+ * + *

2012-06-27 HFN Reed-Solomon error correction activated, see class PDF417RSDecoder.

+ *

2012-09-19 HFN Reed-Solomon error correction via ErrorCorrection/ModulusGF/ModulusPoly.

+ */ + + class Decoder { + private: + static const int MAX_ERRORS; + static const int MAX_EC_CODEWORDS; + + void correctErrors(ArrayRef codewords, + ArrayRef erasures, int numECCodewords); + static void verifyCodewordCount(ArrayRef codewords, int numECCodewords); + + public: + + Ref decode(Ref bits, DecodeHints const& hints); + }; + + } + } +} + +#endif // __DECOCER_PDF_H__ diff --git a/ImageProcess/include/zxing/pdf417/decoder/ec/ErrorCorrection.h b/ImageProcess/include/zxing/pdf417/decoder/ec/ErrorCorrection.h new file mode 100644 index 0000000..d37b708 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/ec/ErrorCorrection.h @@ -0,0 +1,71 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __ERROR_CORRECTION_PDF_H__ +#define __ERROR_CORRECTION_PDF_H__ +/* + * Copyright 2012 ZXing authors + * + * 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. + * + * 2012-09-17 HFN translation from Java into C++ + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace decoder { + namespace ec { + + + /** + *

PDF417 error correction implementation.

+ * + *

This example + * is quite useful in understanding the algorithm.

+ * + * @author Sean Owen + * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder + */ + class ErrorCorrection : public Counted { + + private: + ModulusGF& field_; + + public: + ErrorCorrection(); + void decode(ArrayRef received, + int numECCodewords, + ArrayRef erasures); + + private: + std::vector > runEuclideanAlgorithm(Ref a, Ref b, int R); + + ArrayRef findErrorLocations(Ref errorLocator); + ArrayRef findErrorMagnitudes(Ref errorEvaluator, + Ref errorLocator, + ArrayRef errorLocations); + }; + + } + } + } +} + +#endif /* __ERROR_CORRECTION_PDF_H__ */ diff --git a/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusGF.h b/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusGF.h new file mode 100644 index 0000000..86dac1c --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusGF.h @@ -0,0 +1,72 @@ +#ifndef __MODULUS_GF_PDF_H__ +#define __MODULUS_GF_PDF_H__ +/* + * Copyright 2012 ZXing authors + * + * 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. + * + * 2012-09-17 HFN translation from Java into C++ + */ + +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace decoder { + namespace ec { + + class ModulusPoly; + + /** + *

A field based on powers of a generator integer, modulo some modulus.

+ * + * @author Sean Owen + * @see com.google.zxing.common.reedsolomon.GenericGF + */ + class ModulusGF { + + public: + static ModulusGF PDF417_GF; + + private: + ArrayRef expTable_; + ArrayRef logTable_; + Ref zero_; + Ref one_; + int modulus_; + + public: + ModulusGF(int modulus, int generator); + Ref getZero(); + Ref getOne(); + Ref buildMonomial(int degree, int coefficient); + + int add(int a, int b); + int subtract(int a, int b); + int exp(int a); + int log(int a); + int inverse(int a); + int multiply(int a, int b); + int getSize(); + + }; + + } + } + } +} + +#endif /* __MODULUS_GF_PDF_H__ */ diff --git a/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusPoly.h b/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusPoly.h new file mode 100644 index 0000000..38eac16 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/decoder/ec/ModulusPoly.h @@ -0,0 +1,68 @@ +#ifndef __MODULUS_GFPOLY_PDF_H__ +#define __MODULUS_GFPOLY_PDF_H__ + +/* + * Copyright 2012 ZXing authors + * + * 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. + * + * 2012-09-17 HFN translation from Java into C++ + */ + +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace decoder { + namespace ec { + + class ModulusGF; + + /** + * @author Sean Owen + * @see com.google.zxing.common.reedsolomon.GenericGFPoly + */ + class ModulusPoly : public Counted { + + private: + ModulusGF& field_; + ArrayRef coefficients_; + public: + ModulusPoly(ModulusGF& field, ArrayRef coefficients); + ~ModulusPoly(); + ArrayRef getCoefficients(); + int getDegree(); + bool isZero(); + int getCoefficient(int degree); + int evaluateAt(int a); + Ref add(Ref other); + Ref subtract(Ref other); + Ref multiply(Ref other); + Ref negative(); + Ref multiply(int scalar); + Ref multiplyByMonomial(int degree, int coefficient); + std::vector > divide(Ref other); +#if 0 + public String toString(); +#endif + }; + + } + } + } +} + +#endif /* __MODULUS_GFPOLY_PDF_H__ */ diff --git a/ImageProcess/include/zxing/pdf417/detector/Detector.h b/ImageProcess/include/zxing/pdf417/detector/Detector.h new file mode 100644 index 0000000..bf00583 --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/detector/Detector.h @@ -0,0 +1,106 @@ +#ifndef __DETECTOR_H__ +#define __DETECTOR_H__ + +/* + * Detector.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace detector { + + class Detector { + private: + static const int INTEGER_MATH_SHIFT = 8; + static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; + static const int MAX_AVG_VARIANCE; + static const int MAX_INDIVIDUAL_VARIANCE; + + static const int START_PATTERN[]; + static const int START_PATTERN_LENGTH; + static const int START_PATTERN_REVERSE[]; + static const int START_PATTERN_REVERSE_LENGTH; + static const int STOP_PATTERN[]; + static const int STOP_PATTERN_LENGTH; + static const int STOP_PATTERN_REVERSE[]; + static const int STOP_PATTERN_REVERSE_LENGTH; + + Ref image_; + + static ArrayRef< Ref > findVertices(Ref matrix, int rowStep); + static ArrayRef< Ref > findVertices180(Ref matrix, int rowStep); + + static ArrayRef findGuardPattern(Ref matrix, + int column, + int row, + int width, + bool whiteFirst, + const int pattern[], + int patternSize, + ArrayRef& counters); + static int patternMatchVariance(ArrayRef& counters, const int pattern[], + int maxIndividualVariance); + + static void correctVertices(Ref matrix, + ArrayRef< Ref >& vertices, + bool upsideDown); + static void findWideBarTopBottom(Ref matrix, + ArrayRef< Ref >& vertices, + int offsetVertice, + int startWideBar, + int lenWideBar, + int lenPattern, + int nIncrement); + static void findCrossingPoint(ArrayRef< Ref >& vertices, + int idxResult, + int idxLineA1, int idxLineA2, + int idxLineB1, int idxLineB2, + Ref& matrix); + static Point intersection(Line a, Line b); + static float computeModuleWidth(ArrayRef< Ref >& vertices); + static int computeDimension(Ref const& topLeft, + Ref const& topRight, + Ref const& bottomLeft, + Ref const& bottomRight, + float moduleWidth); + int computeYDimension(Ref const& topLeft, + Ref const& topRight, + Ref const& bottomLeft, + Ref const& bottomRight, + float moduleWidth); + + Ref sampleLines(ArrayRef< Ref > const& vertices, int dimensionY, int dimension); + + public: + Detector(Ref image); + Ref getImage(); + Ref detect(); + Ref detect(DecodeHints const& hints); + }; + + } + } +} + +#endif // __DETECTOR_H__ diff --git a/ImageProcess/include/zxing/pdf417/detector/LinesSampler.h b/ImageProcess/include/zxing/pdf417/detector/LinesSampler.h new file mode 100644 index 0000000..64d7aca --- /dev/null +++ b/ImageProcess/include/zxing/pdf417/detector/LinesSampler.h @@ -0,0 +1,122 @@ +#ifndef __LINESSAMPLER_H__ +#define __LINESSAMPLER_H__ + +/* + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace pdf417 { + namespace detector { + + class LinesSampler { + private: + static const int MODULES_IN_SYMBOL = 17; + static const int BARS_IN_SYMBOL = 8; + static const int POSSIBLE_SYMBOLS = 2787; + static const std::vector RATIOS_TABLE; + static std::vector init_ratios_table(); + static const int BARCODE_START_OFFSET = 2; + + Ref linesMatrix_; + int symbolsPerLine_; + int dimension_; + + static std::vector > findVertices(Ref matrix, int rowStep); + static std::vector > findVertices180(Ref matrix, int rowStep); + + static ArrayRef findGuardPattern(Ref matrix, + int column, + int row, + int width, + bool whiteFirst, + const int pattern[], + int patternSize, + ArrayRef counters); + static int patternMatchVariance(ArrayRef counters, const int pattern[], + int maxIndividualVariance); + + static void correctVertices(Ref matrix, + std::vector >& vertices, + bool upsideDown); + static void findWideBarTopBottom(Ref matrix, + std::vector >& vertices, + int offsetVertice, + int startWideBar, + int lenWideBar, + int lenPattern, + int nIncrement); + static void findCrossingPoint(std::vector >& vertices, + int idxResult, + int idxLineA1, int idxLineA2, + int idxLineB1, int idxLineB2, + Ref matrix); + static float computeModuleWidth(std::vector >& vertices); + static int computeDimension(Ref topLeft, + Ref topRight, + Ref bottomLeft, + Ref bottomRight, + float moduleWidth); + int computeYDimension(Ref topLeft, + Ref topRight, + Ref bottomLeft, + Ref bottomRight, + float moduleWidth); + + Ref sampleLines(std::vector > const& vertices, + int dimensionY, + int dimension); + + static void codewordsToBitMatrix(std::vector >& codewords, + Ref& matrix); + static int calculateClusterNumber(int codeword); + static Ref sampleGrid(Ref image, + int dimension); + static void computeSymbolWidths(std::vector& symbolWidths, + const int symbolsPerLine, Ref linesMatrix); + static void linesMatrixToCodewords(std::vector >& clusterNumbers, + const int symbolsPerLine, + const std::vector& symbolWidths, + Ref linesMatrix, + std::vector >& codewords); + static std::vector > > + distributeVotes(const int symbolsPerLine, + const std::vector >& codewords, + const std::vector >& clusterNumbers); + static std::vector + findMissingLines(const int symbolsPerLine, + std::vector >& detectedCodeWords); + static int decodeRowCount(const int symbolsPerLine, + std::vector >& detectedCodeWords, + std::vector& insertLinesAt); + + static int round(float d); + static Point intersection(Line a, Line b); + + public: + LinesSampler(Ref linesMatrix, int dimension); + Ref sample(); + }; + + } + } +} + +#endif // __LINESSAMPLER_H__ diff --git a/ImageProcess/include/zxing/qrcode/ErrorCorrectionLevel.h b/ImageProcess/include/zxing/qrcode/ErrorCorrectionLevel.h new file mode 100644 index 0000000..087ae10 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/ErrorCorrectionLevel.h @@ -0,0 +1,52 @@ +#ifndef __ERROR_CORRECTION_LEVEL_H__ +#define __ERROR_CORRECTION_LEVEL_H__ + +/* + * ErrorCorrectionLevel.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include + +namespace zxing { + namespace qrcode { + + class ErrorCorrectionLevel { + private: + int ordinal_; + int bits_; + std::string name_; + ErrorCorrectionLevel(int inOrdinal, int bits, char const* name); + static ErrorCorrectionLevel* FOR_BITS[]; + static int N_LEVELS; + public: + static ErrorCorrectionLevel L; + static ErrorCorrectionLevel M; + static ErrorCorrectionLevel Q; + static ErrorCorrectionLevel H; + + int ordinal() const; + int bits() const; + std::string const& name() const; + operator std::string const& () const; + + static ErrorCorrectionLevel& forBits(int bits); + }; + } +} + +#endif // __ERROR_CORRECTION_LEVEL_H__ diff --git a/ImageProcess/include/zxing/qrcode/FormatInformation.h b/ImageProcess/include/zxing/qrcode/FormatInformation.h new file mode 100644 index 0000000..3a43a4a --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/FormatInformation.h @@ -0,0 +1,54 @@ +#ifndef __FORMAT_INFORMATION_H__ +#define __FORMAT_INFORMATION_H__ + +/* + * FormatInformation.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class FormatInformation : public Counted { + private: + static int FORMAT_INFO_MASK_QR; + static int FORMAT_INFO_DECODE_LOOKUP[][2]; + static int N_FORMAT_INFO_DECODE_LOOKUPS; + static int BITS_SET_IN_HALF_BYTE[]; + + ErrorCorrectionLevel& errorCorrectionLevel_; + char dataMask_; + + FormatInformation(int formatInfo); + + public: + static int numBitsDiffering(int a, int b); + static Ref decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); + static Ref doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); + ErrorCorrectionLevel& getErrorCorrectionLevel(); + char getDataMask(); + friend bool operator==(const FormatInformation& a, const FormatInformation& b); + friend std::ostream& operator<<(std::ostream& out, const FormatInformation& fi); + }; + } +} + +#endif // __FORMAT_INFORMATION_H__ diff --git a/ImageProcess/include/zxing/qrcode/QRCodeReader.h b/ImageProcess/include/zxing/qrcode/QRCodeReader.h new file mode 100644 index 0000000..9ff973a --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/QRCodeReader.h @@ -0,0 +1,48 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __QR_CODE_READER_H__ +#define __QR_CODE_READER_H__ + +/* + * QRCodeReader.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class QRCodeReader : public Reader { + private: + Decoder decoder_; + + protected: + Decoder& getDecoder(); + + public: + QRCodeReader(); + virtual ~QRCodeReader(); + + Ref decode(Ref image, DecodeHints hints); + }; + + } +} + +#endif // __QR_CODE_READER_H__ diff --git a/ImageProcess/include/zxing/qrcode/Version.h b/ImageProcess/include/zxing/qrcode/Version.h new file mode 100644 index 0000000..e0d0db8 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/Version.h @@ -0,0 +1,85 @@ +#ifndef __VERSION_H__ +#define __VERSION_H__ + +/* + * Version.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class ECB { + private: + int count_; + int dataCodewords_; + public: + ECB(int count, int dataCodewords); + int getCount(); + int getDataCodewords(); + }; + + class ECBlocks { + private: + int ecCodewords_; + std::vector ecBlocks_; + public: + ECBlocks(int ecCodewords, ECB* ecBlocks); + ECBlocks(int ecCodewords, ECB* ecBlocks1, ECB* ecBlocks2); + int getECCodewords(); + std::vector& getECBlocks(); + ~ECBlocks(); + }; + + class Version : public Counted { + + private: + int versionNumber_; + std::vector& alignmentPatternCenters_; + std::vector ecBlocks_; + int totalCodewords_; + Version(int versionNumber, std::vector* alignmentPatternCenters, ECBlocks* ecBlocks1, ECBlocks* ecBlocks2, + ECBlocks* ecBlocks3, ECBlocks* ecBlocks4); + + public: + static unsigned int VERSION_DECODE_INFO[]; + static int N_VERSION_DECODE_INFOS; + static std::vector > VERSIONS; + + ~Version(); + int getVersionNumber(); + std::vector& getAlignmentPatternCenters(); + int getTotalCodewords(); + int getDimensionForVersion(); + ECBlocks& getECBlocksForLevel(ErrorCorrectionLevel& ecLevel); + static Version* getProvisionalVersionForDimension(int dimension); + static Version* getVersionForNumber(int versionNumber); + static Version* decodeVersionInformation(unsigned int versionBits); + Ref buildFunctionPattern(); + static int buildVersions(); + }; + } +} + +#endif // __VERSION_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/BitMatrixParser.h b/ImageProcess/include/zxing/qrcode/decoder/BitMatrixParser.h new file mode 100644 index 0000000..5b27eb1 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/BitMatrixParser.h @@ -0,0 +1,56 @@ +#ifndef __BIT_MATRIX_PARSER_H__ +#define __BIT_MATRIX_PARSER_H__ + +/* + * BitMatrixParser.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class BitMatrixParser : public Counted { + private: + Ref bitMatrix_; + Version* parsedVersion_; + Ref parsedFormatInfo_; + + int copyBit(size_t x, size_t y, int versionBits); + + public: + BitMatrixParser(Ref bitMatrix); + Ref readFormatInformation(); + Version* readVersion(); + ArrayRef readCodewords(); + + private: + BitMatrixParser(const BitMatrixParser&); + BitMatrixParser& operator =(const BitMatrixParser&); + + }; + + } +} + +#endif // __BIT_MATRIX_PARSER_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/DataBlock.h b/ImageProcess/include/zxing/qrcode/decoder/DataBlock.h new file mode 100644 index 0000000..99dea4f --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/DataBlock.h @@ -0,0 +1,50 @@ +#ifndef __DATA_BLOCK_H__ +#define __DATA_BLOCK_H__ + +/* + * DataBlock.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class DataBlock : public Counted { + private: + int numDataCodewords_; + ArrayRef codewords_; + + DataBlock(int numDataCodewords, ArrayRef codewords); + + public: + static std::vector > + getDataBlocks(ArrayRef rawCodewords, Version* version, ErrorCorrectionLevel& ecLevel); + + int getNumDataCodewords(); + ArrayRef getCodewords(); + }; + + } +} + +#endif // __DATA_BLOCK_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/DataMask.h b/ImageProcess/include/zxing/qrcode/decoder/DataMask.h new file mode 100644 index 0000000..fd85d94 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/DataMask.h @@ -0,0 +1,50 @@ +#ifndef __DATA_MASK_H__ +#define __DATA_MASK_H__ + +/* + * DataMask.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include + +#include + +namespace zxing { + namespace qrcode { + + class DataMask : public Counted { + private: + static std::vector > DATA_MASKS; + + protected: + + public: + static int buildDataMasks(); + DataMask(); + virtual ~DataMask(); + void unmaskBitMatrix(BitMatrix& matrix, size_t dimension); + virtual bool isMasked(size_t x, size_t y) = 0; + static DataMask& forReference(int reference); + }; + + } +} + +#endif // __DATA_MASK_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/DecodedBitStreamParser.h b/ImageProcess/include/zxing/qrcode/decoder/DecodedBitStreamParser.h new file mode 100644 index 0000000..b8f0e38 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/DecodedBitStreamParser.h @@ -0,0 +1,72 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __DECODED_BIT_STREAM_PARSER_H__ +#define __DECODED_BIT_STREAM_PARSER_H__ + +/* + * DecodedBitStreamParser.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class DecodedBitStreamParser { + public: + typedef std::map Hashtable; + + private: + static char const ALPHANUMERIC_CHARS[]; + static char toAlphaNumericChar(size_t value); + + static void decodeHanziSegment(Ref bits, std::string& result, int count); + static void decodeKanjiSegment(Ref bits, std::string& result, int count); + static void decodeByteSegment(Ref bits, std::string& result, int count); + static void decodeByteSegment(Ref bits_, + std::string& result, + int count, + zxing::common::CharacterSetECI* currentCharacterSetECI, + ArrayRef< ArrayRef >& byteSegments, + Hashtable const& hints); + static void decodeAlphanumericSegment(Ref bits, std::string& result, int count, bool fc1InEffect); + static void decodeNumericSegment(Ref bits, std::string& result, int count); + + static void append(std::string& ost, const char* bufIn, size_t nIn, const char* src); + static void append(std::string& ost, std::string const& in, const char* src); + + public: + static Ref decode(ArrayRef bytes, + Version* version, + ErrorCorrectionLevel const& ecLevel, + Hashtable const& hints); + }; + + } +} + +#endif // __DECODED_BIT_STREAM_PARSER_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/Decoder.h b/ImageProcess/include/zxing/qrcode/decoder/Decoder.h new file mode 100644 index 0000000..6c53bfd --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/Decoder.h @@ -0,0 +1,46 @@ +#ifndef __DECODER_H__ +#define __DECODER_H__ + +/* + * Decoder.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class Decoder { + private: + ReedSolomonDecoder rsDecoder_; + + void correctErrors(ArrayRef bytes, int numDataCodewords); + + public: + Decoder(); + Ref decode(Ref bits); + }; + + } +} + +#endif // __DECODER_H__ diff --git a/ImageProcess/include/zxing/qrcode/decoder/Mode.h b/ImageProcess/include/zxing/qrcode/decoder/Mode.h new file mode 100644 index 0000000..8b3f37d --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/decoder/Mode.h @@ -0,0 +1,57 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __MODE_H__ +#define __MODE_H__ + +/* + * Mode.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class Mode { + private: + int characterCountBitsForVersions0To9_; + int characterCountBitsForVersions10To26_; + int characterCountBitsForVersions27AndHigher_; + std::string name_; + + Mode(int cbv0_9, int cbv10_26, int cbv27, int bits, char const* name); + + public: + static Mode TERMINATOR; + static Mode NUMERIC; + static Mode ALPHANUMERIC; + static Mode STRUCTURED_APPEND; + static Mode BYTE; + static Mode ECI; + static Mode KANJI; + static Mode FNC1_FIRST_POSITION; + static Mode FNC1_SECOND_POSITION; + static Mode HANZI; + + static Mode& forBits(int bits); + int getCharacterCountBits(Version* version); + }; + } +} + +#endif // __MODE_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/AlignmentPattern.h b/ImageProcess/include/zxing/qrcode/detector/AlignmentPattern.h new file mode 100644 index 0000000..e591cf9 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/AlignmentPattern.h @@ -0,0 +1,45 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __ALIGNMENT_PATTERN_H__ +#define __ALIGNMENT_PATTERN_H__ + +/* + * AlignmentPattern.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class AlignmentPattern : public ResultPoint { + private: + float estimatedModuleSize_; + + public: + AlignmentPattern(float posX, float posY, float estimatedModuleSize); + bool aboutEquals(float moduleSize, float i, float j) const; + Ref combineEstimate(float i, float j, + float newModuleSize) const; + }; + + } +} + +#endif // __ALIGNMENT_PATTERN_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/AlignmentPatternFinder.h b/ImageProcess/include/zxing/qrcode/detector/AlignmentPatternFinder.h new file mode 100644 index 0000000..c9d58cc --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/AlignmentPatternFinder.h @@ -0,0 +1,68 @@ +#ifndef __ALIGNMENT_PATTERN_FINDER_H__ +#define __ALIGNMENT_PATTERN_FINDER_H__ + +/* + * AlignmentPatternFinder.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include "AlignmentPattern.h" +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class AlignmentPatternFinder : public Counted { + private: + static int CENTER_QUORUM; + static int MIN_SKIP; + static int MAX_MODULES; + + Ref image_; + std::vector* possibleCenters_; + int startX_; + int startY_; + int width_; + int height_; + float moduleSize_; + + static float centerFromEnd(std::vector& stateCount, int end); + bool foundPatternCross(std::vector& stateCount); + + float crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal); + + Ref handlePossibleCenter(std::vector& stateCount, int i, int j); + + public: + AlignmentPatternFinder(Ref image, int startX, int startY, int width, int height, + float moduleSize, Refconst& callback); + ~AlignmentPatternFinder(); + Ref find(); + + private: + AlignmentPatternFinder(const AlignmentPatternFinder&); + AlignmentPatternFinder& operator =(const AlignmentPatternFinder&); + + Ref callback_; + }; + } +} + +#endif // __ALIGNMENT_PATTERN_FINDER_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/Detector.h b/ImageProcess/include/zxing/qrcode/detector/Detector.h new file mode 100644 index 0000000..ef67195 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/Detector.h @@ -0,0 +1,69 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __DETECTOR_H__ +#define __DETECTOR_H__ + +/* + * Detector.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { + + class DecodeHints; + + namespace qrcode { + + class Detector : public Counted { + private: + Ref image_; + Ref callback_; + + protected: + Ref getImage() const; + Ref getResultPointCallback() const; + + static Ref sampleGrid(Ref image, int dimension, Ref); + static int computeDimension(Ref topLeft, Ref topRight, Ref bottomLeft, + float moduleSize); + float calculateModuleSize(Ref topLeft, Ref topRight, Ref bottomLeft); + float calculateModuleSizeOneWay(Ref pattern, Ref otherPattern); + float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY); + float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY); + Ref findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, + float allowanceFactor); + Ref processFinderPatternInfo(Ref info); + public: + virtual Ref createTransform(Ref topLeft, Ref topRight, Ref < + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension); + + Detector(Ref image); + Ref detect(DecodeHints const& hints); + + + }; + } +} + +#endif // __DETECTOR_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/FinderPattern.h b/ImageProcess/include/zxing/qrcode/detector/FinderPattern.h new file mode 100644 index 0000000..2560b7f --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/FinderPattern.h @@ -0,0 +1,48 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __FINDER_PATTERN_H__ +#define __FINDER_PATTERN_H__ + +/* + * FinderPattern.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include + +namespace zxing { + namespace qrcode { + + class FinderPattern : public ResultPoint { + private: + float estimatedModuleSize_; + int count_; + + FinderPattern(float posX, float posY, float estimatedModuleSize, int count); + + public: + FinderPattern(float posX, float posY, float estimatedModuleSize); + int getCount() const; + float getEstimatedModuleSize() const; + void incrementCount(); + bool aboutEquals(float moduleSize, float i, float j) const; + Ref combineEstimate(float i, float j, float newModuleSize) const; + }; + } +} + +#endif // __FINDER_PATTERN_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/FinderPatternFinder.h b/ImageProcess/include/zxing/qrcode/detector/FinderPatternFinder.h new file mode 100644 index 0000000..c0b066c --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/FinderPatternFinder.h @@ -0,0 +1,76 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- +#ifndef __FINDER_PATTERN_FINDER_H__ +#define __FINDER_PATTERN_FINDER_H__ + +/* + * FinderPatternFinder.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +namespace zxing { + + class DecodeHints; + + namespace qrcode { + + class FinderPatternFinder { + private: + static int CENTER_QUORUM; + + protected: + static int MIN_SKIP; + static int MAX_MODULES; + + Ref image_; + std::vector > possibleCenters_; + bool hasSkipped_; + + Ref callback_; + + /** stateCount must be int[5] */ + static float centerFromEnd(int* stateCount, int end); + static bool foundPatternCross(int* stateCount); + + float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal); + float crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount, int originalStateCountTotal); + + /** stateCount must be int[5] */ + bool handlePossibleCenter(int* stateCount, size_t i, size_t j); + int findRowSkip(); + bool haveMultiplyConfirmedCenters(); + std::vector > selectBestPatterns(); + static std::vector > orderBestPatterns(std::vector > patterns); + + Ref getImage(); + std::vector >& getPossibleCenters(); + + public: + static float distance(Ref p1, Ref p2); + FinderPatternFinder(Ref image, Refconst&); + Ref find(DecodeHints const& hints); + }; + } +} + +#endif // __FINDER_PATTERN_FINDER_H__ diff --git a/ImageProcess/include/zxing/qrcode/detector/FinderPatternInfo.h b/ImageProcess/include/zxing/qrcode/detector/FinderPatternInfo.h new file mode 100644 index 0000000..daedda2 --- /dev/null +++ b/ImageProcess/include/zxing/qrcode/detector/FinderPatternInfo.h @@ -0,0 +1,47 @@ +#ifndef __FINDER_PATTERN_INFO_H__ +#define __FINDER_PATTERN_INFO_H__ + +/* + * FinderPatternInfo.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +namespace zxing { + namespace qrcode { + + class FinderPatternInfo : public Counted { + private: + Ref bottomLeft_; + Ref topLeft_; + Ref topRight_; + + public: + FinderPatternInfo(std::vector > patternCenters); + + Ref getBottomLeft(); + Ref getTopLeft(); + Ref getTopRight(); + }; + } +} + +#endif // __FINDER_PATTERN_INFO_H__ diff --git a/SaneUI/Global.h b/SaneUI/Global.h new file mode 100644 index 0000000..6de1b9a --- /dev/null +++ b/SaneUI/Global.h @@ -0,0 +1,143 @@ +#pragma once +#include "json.hpp" +#ifdef WIN32 +#include +#endif // WIN32 +#include +#include //std::cout + + +#define MACR2STR(R) #R +#define STR2MACRO(R) MACR2STR(R) + +using json = nlohmann::json; +using namespace std; +struct Func +{ + Func(std::function scan, std::function confirm, std::function canle, std::function stop, std::function getfw, std::function getser) : + IscanFunction(scan), IconfirmFunction(confirm), IcancelFunction(canle), IstopFunction(stop),Igetfw(getfw),Igetser(getser) {} + std::function IscanFunction; + std::function IconfirmFunction; + std::function IcancelFunction; + std::function IstopFunction; + std::function Igetfw; + std::function Igetser; +}; + + +namespace Global { + static inline std::string getSettingPath() + { +#ifdef WIN32 + TCHAR dir[MAX_PATH] = { 0 }; + SHGetSpecialFolderPath(NULL, dir, CSIDL_LOCAL_APPDATA, TRUE); + int iLen = WideCharToMultiByte(CP_ACP, 0, (LPCWCH)dir, -1, NULL, 0, NULL, NULL); + char* chRtn = new char[iLen * sizeof(char)]; + WideCharToMultiByte(CP_ACP, 0, (LPCWCH)dir, -1, chRtn, iLen, NULL, NULL); + std::string path(chRtn); + delete[] chRtn; + return path + "/huagoscan/"; +#else + std::cout< + + + + + + + + + + + + + + + + + diff --git a/SaneUI/JsonConfig.cpp b/SaneUI/JsonConfig.cpp new file mode 100644 index 0000000..5477cb1 --- /dev/null +++ b/SaneUI/JsonConfig.cpp @@ -0,0 +1,299 @@ +#include "JsonConfig.h" +#include +#include +#include +#include +#include +#include +//#include +//#include + +using namespace std; + +/************************************ +**091717171717171717json171704171717171717171717171717** +*************************************/ + +bool isFolderExist(const QString& folder) +{ + QDir dir(folder); + return dir.exists(); +} + +int createDirectory(const QString& folder) +{ + QDir dir; + return dir.mkdir(folder); +} + + +JsonConfig::JsonConfig(void) +{ +} + + +JsonConfig::~JsonConfig(void) +{ +} + +/************************************************************************/ +/* 17171717171717171717 */ +/************************************************************************/ + +void JsonConfig::WriteToJson(GScanCap* pConfigItem, const std::string fileName, bool isConfigItem) +{ + std::string header = "Config"; + GScanCap& pp = *pConfigItem; + json j; + auto& jobject = j[header]; + //jobject[PIXTYPE][0] = false; + jobject[PIXTYPE][0] = pConfigItem->pixelType; + jobject[PAPERSIZE][0] = pConfigItem->paperSize; + jobject[PAPERALIGN][0] = pConfigItem->paperAlign; + jobject[AUTOCROP][0] = pConfigItem->imageProcess.autoCrop; + jobject[RESOLUTION][0] = pConfigItem->resolution; + jobject[DUPLEX][0] = pConfigItem->scanSide.duplex; + jobject[DISCARBLANK][0] = pConfigItem->scanSide.discardBlank; + jobject[DISCARBLANKVINCE][0] = pConfigItem->scanSide.discardBlankVince; + jobject[FOLD][0] = pConfigItem->scanSide.fold; + jobject[EXCHANGEFB][0] = pConfigItem->scanSide.switchFrontBack; + + jobject[BRIGHTNESS][0] = pConfigItem->imageProcess.brightness; + jobject[CONTRAST][0] = pConfigItem->imageProcess.contrast; + jobject[GAMMA][0] = pConfigItem->imageProcess.gamma; + + jobject[AUTODESCREW][0] = pConfigItem->imageProcess.autoDescrew; + jobject[FILLBLACK][0] = pConfigItem->imageProcess.fillBlackRect; + jobject[OUTHOLE][0] = pConfigItem->imageProcess.fillHole.enable; + jobject[OUTHOLERATIO][0] = pConfigItem->imageProcess.fillHole.ratio; + jobject[FILTERTYPE][0] = pConfigItem->imageProcess.filter; + jobject[SHARPENTYPE][0] = pConfigItem->imageProcess.sharpenType; + jobject[MULTIOUTPUTR][0] = pConfigItem->imageProcess.multiOutFilterRed; + jobject[ANSWERSHEETR][0] = pConfigItem->imageProcess.answerSheetFilterRed; + + jobject[SCANCOUNT][0] = pConfigItem->scanCount; + jobject[DOCORIENTATION][0] = pConfigItem->imageProcess.orentation; + jobject[BACKROTATE180][0] = pConfigItem->imageProcess.backRotate180; + jobject[ULTRADETECT][0] = pConfigItem->hardwareParam.doubleFeedDetection; + jobject[BINDINGDETECT][0] = pConfigItem->hardwareParam.bindingDetection; + jobject[SKEWDENABLE][0] = pConfigItem->hardwareParam.skewDetection.enable; + jobject[SKEWLEVEL][0] = pConfigItem->hardwareParam.skewDetection.level; + if (isConfigItem) + { + jobject[ITEMCAPTION][0] = pConfigItem->Caption; + jobject[SAVEPATH][0] = pConfigItem->SavePath; + } + + std::ofstream o(fileName);//TODO:0117171717171717171717json170417Մ1717 + o << std::setw(4) << j << std::endl; +} + +void JsonConfig::WriteJsonData(const std::string fileName) +{ + +} + + +void JsonConfig::WriteJsonArrayToFile(std::vector cfgArray, const std::string filename) +{ + /*std::string header = "Config"; + json j; + auto& jobject = j[header]; + jobject[PIXTYPE] = nullptr; + jobject[PAPARSIZE] = nullptr; + jobject[AUTOCROP] = nullptr; + jobject[RESOLUTION] = nullptr; + jobject[DUPLEX] = nullptr; + jobject[DISCARBLANK] = nullptr; + jobject[DISCARBLANKVINCE] = nullptr; + jobject[DB_AREANUM] = nullptr; + jobject[DB_DEVNMAX] = nullptr; + jobject[FOLD] = nullptr; + jobject[EXCHANGEFB] = nullptr; + + jobject[BRIGHTNESS] = nullptr; + jobject[AUTOCONTRAST] = nullptr; + jobject[CONTRAST] = nullptr; + jobject[GAMMA_] = nullptr; + + jobject[FILTERTYPE] = nullptr; + jobject[SHARPENTYPE] = nullptr; + jobject[AUTODESCREW] = nullptr; + jobject[FILLBLACK] = nullptr; + jobject[MULTIOUTPUTR] = nullptr; + jobject[OUTHOLE] = nullptr; + jobject[OUTHOLERATIO] = nullptr; + jobject[ANSWERSHEETR] = nullptr; + + jobject[ULTRADETECT] = nullptr; + jobject[BINDINGDETECT] = nullptr; + jobject[SCANCOUNT] = nullptr; + jobject[DOCORIENTATION] = nullptr; + jobject[BACKROTATE180] = nullptr; + jobject[SCREWDETECT] = nullptr; + jobject[SCREWLEVEL] = nullptr; + + jobject[ITEMCAPTION] = nullptr; + jobject[SAVEPATH] = nullptr; + + for (int i = 0; i < cfgArray.size(); i++) + { + jobject[PIXTYPE][0] = cfgArray[i].Pixtype; + jobject[PAPARSIZE][0]= cfgArray[i].PaperSize; + jobject[AUTOCROP][i] = cfgArray[i].EnAutoCrop; + jobject[RESOLUTION][0]= cfgArray[i].Resolution; + jobject[DUPLEX][0] = cfgArray[i].EnDuplex; + jobject[DISCARBLANK][i] = cfgArray[i].EnDiscardBlank; + jobject[DISCARBLANKVINCE][i] = cfgArray[i].EnDiscardBlankVince; + jobject[DB_AREANUM][0] = cfgArray[i].DBlank_AreaNum; + jobject[DB_DEVNMAX][0] = cfgArray[i].DBlank_DevnMax; + jobject[FOLD][i] = cfgArray[i].EnFold; + jobject[EXCHANGEFB][i] = cfgArray[i].EnExchangeFrontBack; + + jobject[BRIGHTNESS][0] = cfgArray[i].Brightness; + jobject[AUTOCONTRAST][i]= cfgArray[i].EnAutoContrast; + jobject[CONTRAST][0] = cfgArray[i].Contrast; + jobject[GAMMA_][0] = cfgArray[i].Gamma; + + jobject[FILTERTYPE][0]=(cfgArray[i].Filter); + jobject[SHARPENTYPE][0]=(cfgArray[i].Sharpen); + jobject[AUTODESCREW][0]=(i,cfgArray[i].EnAutoDescrew); + jobject[FILLBLACK][0]=(i,cfgArray[i].EnFillBlack); + jobject[MULTIOUTPUTR][0]=(i,cfgArray[i].EnMultiOutPutR); + jobject[OUTHOLE][0]=(i,cfgArray[i].EnOutHole); + jobject[OUTHOLERATIO][0]=(cfgArray[i].OutHoleRatio); + jobject[ANSWERSHEETR][0] = (i, cfgArray[i].EnAnswerSheetR); + + jobject[ULTRADETECT][0]=(i,cfgArray[i].EnUltrasonicDetect); + jobject[BINDINGDETECT][0]=(i,cfgArray[i].EnBindingDetect); + jobject[SCANCOUNT][0]=(cfgArray[i].ScanCount); + jobject[DOCORIENTATION][0]=(cfgArray[i].Orentation); + jobject[BACKROTATE180][0]=(i,cfgArray[i].EnBackRotate180); + jobject[SCREWDETECT][0]=(i,cfgArray[i].EnScrewDetect); + jobject[SCREWLEVEL][0]=(cfgArray[i].ScrewDetectLevel); + + if (cfgArray[i].Caption.c_str()!=NULL) + jobject[ITEMCAPTION][0]=(cfgArray[i].Caption); + + if (cfgArray[i].SavePath.c_str()!=NULL) + jobject[SAVEPATH][0]=(cfgArray[i].SavePath); + } + std::ofstream o(filename); + o << std::setw(4) << j << std::endl;*/ +} + + +GScanCap JsonConfig::ReadDefaultConfig() +{ + return GetDefaultConfigParams(); +} + +bool JsonConfig::DeleteJsonFile(std::string path) +{ + return (remove(path.c_str())); +} + +GScanCap JsonConfig::ReadJsonFromFile(const std::string filename) +{ + GScanCap re; + FILE* file = fopen(filename.c_str(), "rb"); + if (!file) + { + return re; + } + fseek(file, 0, SEEK_END); + long size = ftell(file); + fseek(file, 0, SEEK_SET); + std::string text; + char* buffer = new char[size + 1]; + buffer[size] = 0; + if (!fread(buffer, 1, size, file) == (unsigned long)size) + { + return re; + } + text = buffer; + + fclose(file); + delete[]buffer; + re = parseJsonFromString(text); + return re; +} + +GScanCap JsonConfig::GetDefaultConfigParams() +{ + GScanCap params; + params.pixelType = ColorMode::RGB; + params.paperSize = TwSS::A3; + params.paperAlign = PaperAlign::Rot0; + params.imageProcess.autoCrop = 1; + params.resolution = 200; + params.scanSide.duplex = 1; + params.scanSide.discardBlank = 0; + params.scanSide.discardBlankVince = 0; + params.scanSide.fold = 0; + params.scanSide.switchFrontBack = 0; + + params.imageProcess.brightness = 128; + params.imageProcess.contrast = 4; + params.imageProcess.gamma = 1.0f; + + params.imageProcess.autoDescrew = 1; + params.imageProcess.fillBlackRect = 0; + params.imageProcess.fillHole.enable = 0; + params.imageProcess.fillHole.ratio = 10; + params.imageProcess.filter = ColorFilter::FILTER_NONE; + params.imageProcess.sharpenType = SharpenType::STNone; + params.imageProcess.multiOutFilterRed = 0; + params.imageProcess.answerSheetFilterRed = 0; + + params.scanCount = -1; + params.imageProcess.orentation = Orentation::ROTATE_NONE; + params.imageProcess.backRotate180 = 0; + params.hardwareParam.doubleFeedDetection = 1; + params.hardwareParam.bindingDetection = 0; + params.hardwareParam.skewDetection.enable = 1; + params.hardwareParam.skewDetection.level = 3; + return params; +} + +GScanCap JsonConfig::parseJsonFromString(const std::string str) +{ + std::string header = "Config"; + json j = json::parse(str); + auto& jobject = j[header]; + + GScanCap cfg; + cfg.pixelType = jobject[PIXTYPE][0]; + cfg.paperSize = jobject[PAPERSIZE][0]; + cfg.paperAlign = jobject[PAPERALIGN][0]; + cfg.imageProcess.autoCrop = jobject[AUTOCROP][0]; + cfg.resolution = jobject[RESOLUTION][0]; + cfg.scanSide.duplex = jobject[DUPLEX][0]; + cfg.scanSide.discardBlank = jobject[DISCARBLANK][0]; + cfg.scanSide.discardBlankVince = jobject[DISCARBLANKVINCE][0]; + cfg.scanSide.fold = jobject[FOLD][0]; + cfg.scanSide.switchFrontBack = jobject[EXCHANGEFB][0]; + + cfg.imageProcess.brightness = jobject[BRIGHTNESS][0]; + cfg.imageProcess.contrast = jobject[CONTRAST][0]; + cfg.imageProcess.gamma = jobject[GAMMA][0]; + + cfg.imageProcess.autoDescrew = jobject[AUTODESCREW][0]; + cfg.imageProcess.fillBlackRect = jobject[FILLBLACK][0]; + cfg.imageProcess.fillHole.enable = jobject[OUTHOLE][0]; + cfg.imageProcess.fillHole.ratio = jobject[OUTHOLERATIO][0]; + cfg.imageProcess.filter = jobject[FILTERTYPE][0]; + cfg.imageProcess.sharpenType = jobject[SHARPENTYPE][0]; + cfg.imageProcess.multiOutFilterRed = jobject[MULTIOUTPUTR][0]; + cfg.imageProcess.answerSheetFilterRed = jobject[ANSWERSHEETR][0]; + + cfg.scanCount = jobject[SCANCOUNT][0]; + cfg.imageProcess.orentation = jobject[DOCORIENTATION][0]; + cfg.imageProcess.backRotate180 = jobject[BACKROTATE180][0]; + cfg.hardwareParam.doubleFeedDetection = jobject[ULTRADETECT][0]; + cfg.hardwareParam.bindingDetection = jobject[BINDINGDETECT][0]; + cfg.hardwareParam.skewDetection.enable = jobject[SKEWDENABLE][0]; + cfg.hardwareParam.skewDetection.level = jobject[SKEWLEVEL][0]; + + return cfg; +} diff --git a/SaneUI/JsonConfig.h b/SaneUI/JsonConfig.h new file mode 100644 index 0000000..ec04956 --- /dev/null +++ b/SaneUI/JsonConfig.h @@ -0,0 +1,24 @@ +#pragma once +#include "common.h" +#include "Global.h" +#include + + + + +class JsonConfig +{ +public: + JsonConfig(void); + ~JsonConfig(void); +public: + void WriteToJson(GScanCap* pConfigItem, const std::string fileName, bool isConfigItem = true); + //PCONFIGPARAMS ReadJsonFromFile(const char* fileNames); + void WriteJsonData(const std::string fileName); + void WriteJsonArrayToFile(std::vector cfgArray, const std::string filename); + GScanCap ReadDefaultConfig(); + bool DeleteJsonFile(std::string path); + GScanCap ReadJsonFromFile(const std::string filename); + GScanCap GetDefaultConfigParams(); + GScanCap parseJsonFromString(const std::string str); +}; diff --git a/SaneUI/SaneUI.pro b/SaneUI/SaneUI.pro new file mode 100644 index 0000000..e33d197 --- /dev/null +++ b/SaneUI/SaneUI.pro @@ -0,0 +1,75 @@ +QT += gui core + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TEMPLATE = lib +#CONFIG += staticlib +#DEFINES += HGVERSION + +contains(DEFINES,HGVERSION){ + DEFINES +=USERJSONNAME=/opt/huagoscan/huago.json + DEFINES +=JSONPATH=/opt/huagoscan/ +} +else{ + DEFINES +=USERJSONNAME=/opt/lanxumscan/lanxum.json + DEFINES +=JSONPATH=/opt/lanxumscan/ +} + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +INCLUDEPATH += include +#LIBS += -lsane + + +CONFIG(debug, debug|release):DESTDIR += $$PWD/../bin/x86/debug +CONFIG(release, debug|release):DESTDIR += $$PWD/../bin/x86/release + +SOURCES += \ + JsonConfig.cpp \ + ScannerUI.cpp \ + cutdialog.cpp \ + cutpapertool.cpp \ + gaosixy.cpp \ + indicator.cpp \ + readwritejsonfile.cpp \ + scansettingdialog.cpp \ + setpicclrtool.cpp \ + widget.cpp + +HEADERS += \ + Global.h \ + JsonConfig.h \ + ScannerUI.h \ + common.h \ + cutdialog.h \ + cutpapertool.h \ + gaosixy.h \ + indicator.h \ + json.hpp \ + readwritejsonfile.h \ + scansettingdialog.h \ + setpicclrtool.h \ + widget.h \ + sane_wraper.h + +FORMS += \ + cutdialog.ui \ + cutpapertool.ui \ + indicator.ui \ + scansettingdialog.ui \ + setpicclrtool.ui \ + widget.ui + +RESOURCES += \ + images.qrc diff --git a/SaneUI/ScannerUI.cpp b/SaneUI/ScannerUI.cpp new file mode 100644 index 0000000..900b030 --- /dev/null +++ b/SaneUI/ScannerUI.cpp @@ -0,0 +1,147 @@ +#include "ScannerUI.h" +#include +#include "indicator.h" +#include "scansettingdialog.h" +#include +#ifdef WIN32 +#include +#endif + +int ScannerUI::argc = 0; +char** ScannerUI::argv = nullptr; +std::unique_ptr ScannerUI::application; +std::unique_ptr ScannerUI::scanDialog; +#ifdef WIN32 +std::unique_ptr ScannerUI::guiBridge; +#endif +std::unique_ptr ScannerUI::guiIndicator; +TwGlue ScannerUI::twglue = TwGlue(nullptr, nullptr); + + +ScannerUIPtr GUICreate::Instance() +{ + return ScannerUIPtr(new ScannerUI()); +} + +ScannerUI::ScannerUI() +{ + if (!qApp) + application = std::unique_ptr(new QApplication(argc, argv)); +} + +ScannerUI::~ScannerUI() +{ +#ifdef WIN32 + //if (modalfalg) + // ::EnableWindow(parent, true); +#endif // WIN32 + application.reset(); +} + +void ScannerUI::showTwainUI(void* handle, bool uiOnly, Func f,std::string model,bool modelui) +{ + QWidget* parent = nullptr; + // as a minimal source, we do not support GUI that just saves settings +#ifdef WIN32 +// we use Qt, some Windows-Qt glue is necessary to set the parent window of our dialog + if (handle) { + guiBridge = std::unique_ptr(new QWidget); + + HWND appWindow = static_cast(handle); + HWND bridgeWindow = reinterpret_cast(guiBridge->winId()); + long bridgeFlags = GetWindowLong(bridgeWindow, GWL_STYLE); + SetWindowLong(bridgeWindow, GWL_STYLE, bridgeFlags | WS_CHILD); + HWND ch= SetParent(bridgeWindow, appWindow); + //if (modelui) + //{ + // this->parent = appWindow; + // ::EnableWindow(appWindow, false); + //} + modalfalg = modelui; + if(f.IstopFunction) + guiIndicator.reset(new Indicator(f.IstopFunction)); + } + parent = guiBridge.get(); + +#endif + + + //TwGlue glue = {f.IscanFunction, f.IcancelFunction }; + //TwGlue glueUiOnly = { f.IconfirmFunction, f.IcancelFunction }; + func = f; + //twglue = uiOnly ? glueUiOnly: glue; + + scanDialog = std::unique_ptr(new ScanSettingDialog( + f, + uiOnly ? ScanSettingDialog::UIonly : ScanSettingDialog::showUI, + model, + parent)); + scanDialog->defaultjson = defaultjson; +#ifdef WIN32 + //if (modalfalg) + // scanDialog->enableparent = [=] { if (this->parent) ::EnableWindow(this->parent, true); }; +#endif // WIN32 + scanDialog->show(); + +} + +void ScannerUI::closeTwainUI() +{ + guiIndicator.reset(); + scanDialog.reset(); + //guiBridge.reset(); +} + +void ScannerUI::postMessage() +{ + if (static_cast(application)) { + // QApplication::processEvents(); - TODO: needs more investigation; results in freeze when attempting to scan using old DSM + QApplication::sendPostedEvents(); + } +} + +void ScannerUI::hideindicator() +{ + if (guiIndicator.get()) + guiIndicator->hide(); + if (scanDialog.get()) + scanDialog->EnableID_OKorID_Cancel(true); +} + +void ScannerUI::showindicator() +{ + if (guiIndicator.get()) + guiIndicator->show(); + if (scanDialog.get()) + scanDialog->EnableID_OKorID_Cancel(false); +} + +void ScannerUI::getjsonstring(std::string& str) +{ + defaultjson=json::parse(str); +} + +void ScannerUI::is_showindicator(bool enabel) +{ + if (enabel) + { + if (!guiIndicator.get()) + guiIndicator.reset(new Indicator(func.IstopFunction)); + } + else + { + if (guiIndicator.get()) + guiIndicator.reset(); + } + +} + +void ScannerUI::setHandle(TwGlue twglue) +{ + ScannerUI::twglue = twglue; +} + +void ScannerUI::Message(std::string title, std::string msg, int type) +{ + QMessageBox::warning(nullptr, title.c_str(), msg.c_str()); +} diff --git a/SaneUI/ScannerUI.h b/SaneUI/ScannerUI.h new file mode 100644 index 0000000..536fc14 --- /dev/null +++ b/SaneUI/ScannerUI.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include +#include "common.h" +#include "Global.h" +#include "twglue.hpp" + +class QApplication; +class QWidget; +class ScanSettingDialog; + + +class IScannerUI +{ +public: + virtual ~IScannerUI() {} + virtual void showTwainUI(void* handle, bool uiOnly,Func f,std::string model,bool modelui) = 0; + virtual void closeTwainUI() = 0; + virtual void postMessage() = 0; + virtual void setHandle(TwGlue twglue) = 0; + virtual void showindicator() = 0; + virtual void hideindicator() = 0; + virtual void getjsonstring(std::string& str) = 0; + virtual void is_showindicator(bool enabel)=0; + virtual void Message(std::string title, std::string msg, int type) = 0; +}; + + +typedef std::shared_ptr ScannerUIPtr; + +class GUICreate +{ +public: + static ScannerUIPtr Instance(); +}; + +class ScannerUI : public IScannerUI +{ +public: + ScannerUI(); + ~ScannerUI(); + virtual void showTwainUI(void* handle, bool uiOnly, Func f,std::string model,bool modelui); + virtual void closeTwainUI(); + virtual void postMessage(); + virtual void hideindicator(); + virtual void showindicator(); + virtual void getjsonstring(std::string& str); + virtual void is_showindicator(bool enabel); + virtual void setHandle(TwGlue twglue); + virtual void Message(std::string title, std::string msg, int type); + +private: + static int argc;// = 0; + static char** argv;// = nullptr; + static std::unique_ptr application; + static std::unique_ptr scanDialog; + json defaultjson; +#ifdef WIN32 + static std::unique_ptr guiBridge; + HWND parent; + bool modalfalg; +#endif + static std::unique_ptr guiIndicator; + static TwGlue twglue; + Func func{ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr }; +}; diff --git a/SaneUI/common.h b/SaneUI/common.h new file mode 100644 index 0000000..cd28f66 --- /dev/null +++ b/SaneUI/common.h @@ -0,0 +1,313 @@ +#ifndef COMMON_H +#define COMMON_H +#include + + + +#ifdef __cplusplus +extern "C"{ +#endif + + typedef struct Scan_Param +{ + int val; +} ScanParam; + +typedef struct tagImageInfo +{ + int Width; + int Height; + int bpp; +} ImageInfo; + +typedef struct Scan_Rect { + int width; + int height; + int x; + int y; +}ScanRect; + +/*********************************************************************************/ +//基础参数 +typedef enum tagColorMode { + BlackWhite, + Gray, + RGB +}ColorMode; + +typedef enum tagMulti_Output { + Unused = -1, + All, + ColorGray, + ColorBw, + GrayBw +}MultiOutput; + +typedef enum tagtwSS +{ + None = 0, + A4Letter = 1, + A4 = 1, + B5Letter = 2, + JISB5 = 2, + B5 = 2, + USLetter = 3, + USLegal = 4, + A5 = 5, + B4 = 6, + ISOB4 = 6, + B6 = 7, + ISOB6 = 7, + USLedger = 9, + USExecutive = 10, + A3 = 11, + B3 = 12, + ISOB3 = 12, + A6 = 13, + C4 = 14, + C5 = 15, + C6 = 16, + _4A0 = 17, + _2A0 = 18, + A0 = 19, + A1 = 20, + A2 = 21, + A7 = 22, + A8 = 23, + A9 = 24, + A10 = 25, + ISOB0 = 26, + ISOB1 = 27, + ISOB2 = 28, + ISOB5 = 29, + ISOB7 = 30, + ISOB8 = 31, + ISOB9 = 32, + ISOB10 = 33, + JISB0 = 34, + JISB1 = 35, + JISB2 = 36, + JISB3 = 37, + JISB4 = 38, + JISB6 = 39, + JISB7 = 40, + JISB8 = 41, + JISB9 = 42, + JISB10 = 43, + C0 = 44, + C1 = 45, + C2 = 46, + C3 = 47, + C7 = 48, + C8 = 49, + C9 = 50, + C10 = 51, + USStatement = 52, + BusinessCard = 53, + MaxSize = 54 +}TwSS; + +typedef enum tagPaper_Align { + Rot0 = 0, + Rot270 = 3 +}PaperAlign; + +typedef struct tagCrop_Rect +{ + int enable; + int x; /*****自定义裁切区域左上角x坐标*/ + int y; /*****自定义裁切区域左上角y坐标*/ + int width; /*****自定义裁切区域宽度*******/ + int height; /*****自定义裁切区域高度*******/ +}CropRect; + +typedef struct tagScan_Side { + int duplex; /*0: both ; 1: front*/ + int discardBlank; /*跳过空白页通用*/ + int discardBlankVince; /*跳过空白页(发票)*/ + int fold; /*对折*/ + int switchFrontBack; /*互换正反面*/ +}ScanSide; + +typedef struct tagSkew_Detection { + int enable; + int level; +}SkewDetection; + +typedef struct tagHhardware_Params +{ + int capturepixtype; + int doubleFeedDetection; + int bindingDetection; + int sizeDetection; + SkewDetection skewDetection; +}HardwareCaps; + +typedef struct tagCcustom_Gamma +{ + int enable; + unsigned char table[768]; + int tableLength; +}; + +typedef struct tagFill_Hole +{ + int enable; + int ratio;/*1~50;*/ +}FillHole; + +typedef enum tagColor_Filter +{ + FILTER_RED, + FILTER_GREEN, + FILTER_BLUE, + FILTER_NONE, + FILTER_ALL, + ENHANCE_RED, + ENHANCE_GREEN, + ENHANCE_BLUE +}ColorFilter; + +typedef enum tagSharpen_Type +{ + STNone, + Sharpen, + SharpenMore, + Blur, + BlurMore +}SharpenType; + +typedef enum tagOrentation +{ + ROTATE_NONE = 0, + ROTATE_90, + ROTATE_180, + ROTATE_270, + AUTOTEXT_DETECT = 4 +}Orentation; + +typedef struct tagjpegCompress { + int enable; + int ratio; +}JpegCompress; + +typedef struct tagImage_Process +{ + int autoCrop; /*自动裁剪尺寸*/ + //亮度对比度伽马值 + int brightness; /*1~255*/ + int contrast; /*1~7*/ + float gamma; /*0.1f~5.0f*/ + tagCcustom_Gamma customGamma; + //图像处理 + int fillBlackRect; + bool isfillcolor; + int autoDescrew; + int refuseInflow;/*防止渗透*/ + FillHole fillHole; + ColorFilter filter; + int colorCorrection;/*色彩校正*/ + int removeMorr; /*去除摩尔纹*/ + int errorExtention; /*错误扩散*/ + int nosieDetach;/*噪点优化*/ + int textureRemove;/*除网纹*/ + int indent;/*边缘缩进像素*/ + int noise;/*降噪像素点*/ + int AutoCrop_threshold;/*自动裁剪二值化阀值*/ + bool is_convex;/*填充黑框方式*/ + bool backgroundremoval; + bool automaticcolor; + int automaticcolortype; + SharpenType sharpenType; + int multiOutFilterRed;/*多流输出除红*/ + int answerSheetFilterRed;/*答题卡除红*/ + //送纸 + Orentation orentation; + int backRotate180; + //其他 + JpegCompress jpegCompress; + int splitImage; +}ImageProcess; + + + +#ifdef __cplusplus +} +#endif + +/*********************************************************************************/ +class GScanCap +{ +public: + ColorMode pixelType; + MultiOutput multiOutput; + TwSS paperSize; + PaperAlign paperAlign; + CropRect cropRect; + int resolution; + int resolution_native; + ScanSide scanSide; + ImageProcess imageProcess; + int scanCount; /* -1: 连续扫描 */ + HardwareCaps hardwareParam; + int previewScan; + int threshold; + /*保存信息*/ + std::string Caption; + std::string SavePath; +}; + +/****************** +**参数保存结构体** +*******************/ +typedef struct tagCONFIGPARAMS +{ + /*基本选项卡参数*/ + int Pixtype; + int PaperSize; + bool EnAutoCrop; + int Resolution; + bool EnDuplex; + bool EnDiscardBlank; + bool EnDiscardBlankVince; + int DBlank_AreaNum; + int DBlank_DevnMax; + bool EnFold; + bool EnExchangeFrontBack; + /*亮度对比度选项卡参数*/ + float Brightness; + bool EnAutoContrast; + float Contrast; + float Gamma; + + /*图像处理选项卡参数*/ + int Filter; + int Sharpen; + bool EnFillBlack; + bool EnAutoDescrew; + bool EnOutHole; + int OutHoleRatio; + bool EnMultiOutPutR; + bool EnAnswerSheetR; + + /*送纸部分选项卡参数*/ + bool EnUltrasonicDetect; + bool EnBindingDetect; + int ScanCount; + int Orentation; + bool EnBackRotate180; + bool EnScrewDetect; + int ScrewDetectLevel; + + /*保存信息*/ + std::string Caption; + std::string SavePath; +}CONFIGPARAMS, * PCONFIGPARAMS; + +typedef struct tagCONFIGINFO +{ + std::string Caption; + std::string SavePath; +}CONFIGINFO, * PCONFIGINFO; + +#endif diff --git a/SaneUI/cutdialog.cpp b/SaneUI/cutdialog.cpp new file mode 100644 index 0000000..6c0d8c0 --- /dev/null +++ b/SaneUI/cutdialog.cpp @@ -0,0 +1,447 @@ +#include "cutdialog.h" +#include "ui_cutdialog.h" +#include +#include +#include + +cutDialog::cutDialog(QWidget *parent) : + QWidget(parent), + ui(new Ui::cutDialog) +{ + ui->setupUi(this); + divisor = 8; + dpi = 1; + sizeType = 0; + paperWidth = 185; + h_w = 260.0/185.0; + sizeRate = 1; + paperHeight = paperWidth*h_w; + + this->setFixedSize(paperWidth,paperHeight); + setMouseTracking(true); + m_startPoint = QPoint(10,10); + m_endPoint = QPoint(50,50); + m_mouse_down = false; + + initAllCorner(); +} + +cutDialog::~cutDialog() +{ + delete ui; +} + +void cutDialog::setPaperSize(QString type, const int w) +{ + paperType = type; + + if(paperType == "A3") h_w = 420.0/297; + else if(paperType == "A4") h_w = 297.0/210; + else if(paperType == std::string("A4横向").c_str()) h_w = 210/297.0; + else if(paperType == "A5") h_w = 210.0/148; + else if(paperType == std::string("A5横向").c_str()) h_w = 148/210.0; + else if(paperType == "A6") h_w = 148.0/105; + else if(paperType == std::string("A6横向").c_str()) h_w = 105/148.0; + else if(paperType == "B4") h_w = 353.0/250; + else if(paperType == "B5") h_w = 250.0/176; + else if(paperType == std::string("B5横向").c_str()) h_w = 176/250.0; + else if(paperType == "B6") h_w = 176.0/125; + else if(paperType == std::string("B6横向").c_str()) h_w = 125/176.0; + else if(paperType == std::string("信封").c_str()) h_w = 279.0/210; + else if(paperType == std::string("信封横向").c_str()) h_w = 210.0/279; + else if(paperType == std::string("双倍信封").c_str()) h_w = 850.0/550; + else if(paperType == "Legal") h_w = 2800.0/1700; + else if(paperType == std::string("最大尺寸").c_str()) h_w = 3307.0*2/2338; + else if(paperType == std::string("匹配原始尺寸").c_str()) { + if(dpi == 100.0) h_w = 1795.0/1189; + if(dpi == 150.0) h_w = 1795.0/1784; + if(dpi == 200.0) h_w = 3307.0/2338; + if(dpi == 240.0) h_w = 4308.0/2854; + if(dpi == 200.0) h_w = 5385.0/3567; + }; + + + if(type.contains("3")) divisor = 2; + else if (type.contains("4")) divisor = 4; + else if (type.contains("5")) divisor = 6; + else if (type.contains("6")) divisor = 8; + else divisor = 4; + paperWidth = w; + if(type.contains(std::string("横向").c_str())) paperWidth = paperWidth*h_w*1.5; + double realW = paperWidth; + + if(paperType == "A3" || paperType == std::string("A4横向").c_str()) realRate = 297.0/realW; + else if(paperType == "A4" || paperType == std::string("A5横向").c_str()) realRate = 210.0/realW; + else if(paperType == "A5" || paperType == std::string("A6横向").c_str()) realRate = 148.0/realW; + else if(paperType == "A6") realRate = 105.0/realW; + else if(paperType == "B4" || paperType == std::string("B5横向").c_str()) realRate = 250.0/realW; + else if(paperType == "B5" || paperType == std::string("B6横向").c_str()) realRate = 176.0/realW; + else if(paperType == "B6") realRate = 125.0/realW; + else if(paperType == std::string("信封").c_str()) realRate = 216.0/realW; + else if(paperType == std::string("信封横向").c_str()) realRate = 279.0/realW; + else if(paperType == std::string("双倍信封").c_str()) realRate = 432.0/realW; + else if(paperType == "Legal") realRate = 297.0/realW; + else if(paperType == std::string("最大尺寸").c_str()) realRate = 297.0/realW; + else if(paperType == std::string("匹配原始尺寸").c_str()) { + if(dpi == 100.0) realRate = 1189.0*0.039377/dpi/realW; + if(dpi == 150.0) realRate = 1784*0.039377/dpi/realW; + if(dpi == 200.0) realRate = 2338*0.039377/dpi/realW; + if(dpi == 240.0) realRate = 2854*0.039377/dpi/realW; + if(dpi == 200.0) realRate = 3567*0.039377/dpi/realW; + }; + + paperHeight = paperWidth*h_w; + this->setFixedSize(paperWidth+4,paperHeight+4); + scaleRec = QRectF(0,0,paperWidth,paperHeight+0.5); + m_rect = QRectF(m_startPoint,m_endPoint); + update(); + refreshView(); +} + +void cutDialog::setDpiValue(const double d) +{ + dpi = d; + if(sizeType == PIXEL) sizeRate = 0.03937*dpi; + update(); +} + +void cutDialog::setSizeType(const SIZETYPE &t) +{ + sizeType = t; + switch (sizeType) { + case MILLIM: + sizeRate = 1; + break; + case INCH: + sizeRate = 0.03937; + break; + case PIXEL: + sizeRate = 0.03937*dpi; + break; + } + update(); +} + +void cutDialog::setCutRectWidth(double w) +{ + m_endPoint.setX(m_startPoint.x()+scaleRec.width()*w/getPaperSize().width()); + update(); +} + +void cutDialog::setCutRectHeight(double h) +{ + m_endPoint.setY(m_startPoint.y()+scaleRec.height()*h/getPaperSize().height()); + update(); +} + +void cutDialog::setCutRectStartX(double x) +{ + m_startPoint.setX(scaleRec.width()*x/getPaperSize().width()); + update(); +} + +void cutDialog::setCutRectStartY(double y) +{ + m_startPoint.setY(scaleRec.height()*y/getPaperSize().height()); + update(); +} + +QSizeF cutDialog::getPaperSize() const +{ + double realW = paperWidth*realRate*sizeRate; + double realH = paperHeight*realRate*sizeRate; + return QSizeF(realW,realH); +} + +QSizeF cutDialog::getCutRectSize() const +{ + double realCutW = getPaperSize().width()*m_rect.width()/scaleRec.width(); + double realCutH = getPaperSize().height()*m_rect.height()/scaleRec.height(); + return QSizeF(realCutW,realCutH); +} + +QPointF cutDialog::getCutRectStartPos() const +{ + double realCutX = getPaperSize().width()*m_startPoint.x()/scaleRec.width(); + double realCutY = getPaperSize().height()*m_startPoint.y()/scaleRec.height(); + return QPointF(realCutX,realCutY); +} + +QRectF cutDialog::getCutRectPixel() const +{ + double x = 0.03937*dpi*paperWidth*realRate*m_startPoint.x()/scaleRec.width(); + double y = 0.03937*dpi*paperHeight*realRate*m_startPoint.y()/scaleRec.height(); + double w = 0.03937*dpi*paperWidth*realRate*m_rect.width()/scaleRec.width(); + double h = 0.03937*dpi*paperHeight*realRate*m_rect.height()/scaleRec.height(); + return QRectF(x,y,w,h); +} + +void cutDialog::setCutRectPixel(QRectF &rect) +{ + m_startPoint.setX(scaleRec.width()*rect.x()/(paperWidth*realRate*0.03937*dpi)); + m_startPoint.setY(scaleRec.height()*rect.y()/(paperHeight*realRate*0.03937*dpi)); + m_endPoint.setX(m_startPoint.x()+scaleRec.width()*rect.width()/(paperWidth*realRate*0.03937*dpi)); + m_endPoint.setY(m_startPoint.y()+scaleRec.height()*rect.height()/(paperHeight*realRate*0.03937*dpi)); + update(); +} + +int cutDialog::getCutRectRight() const +{ + return getPaperSize().width()*m_rect.right()/scaleRec.right(); +} + +int cutDialog::getCutRectBottom() const +{ + return getPaperSize().height()*m_rect.bottom()/scaleRec.bottom(); +} + +void cutDialog::mousePressEvent(QMouseEvent *event) +{ + int x = event->x()/**paperWidth/width()*/; + int y = event->y()/**paperHeight/height()*/; + m_moveStart = QPoint(x,y); + m_mouse_down = event->button() == Qt::LeftButton; + update(); +} + +void cutDialog::mouseMoveEvent(QMouseEvent *event) +{ + int x = event->x()/**paperWidth/width()*/; + int y = event->y()/**paperHeight/height()*/; + if(m_mouse_down){ + int dx = m_moveStart.x() - x; + int dy = m_moveStart.y() - y; + m_moveStart = QPoint(x,y); + + if(m_leftCorn){ + m_startPoint.setX(x); + }else if(m_rightCorn){ + m_endPoint.setX(x); + }else if(m_topCorn){ + m_startPoint.setY(y); + }else if(m_bottomCorn){ + m_endPoint.setY(y); + }else if(m_leftTop){ + m_startPoint.setX(x); + m_startPoint.setY(y); + }else if(m_leftBottom){ + m_startPoint.setX(x); + m_endPoint.setY(y); + }else if(m_rightTop){ + m_startPoint.setY(y); + m_endPoint.setX(x); + }else if(m_rightBottom){ + m_endPoint.setX(x); + m_endPoint.setY(y); + } + else if(!m_out){ + if(m_startPoint.x() - dx < 0) dx = 0; + if(m_startPoint.y() - dy < 0) dy = 0; + if(m_endPoint.x() - dx > scaleRec.right()) dx = 0; + if(m_endPoint.y() - dy > scaleRec.bottom()) dy = 0; + m_startPoint.setX(m_rect.left()-dx); + m_startPoint.setY(m_rect.top()-dy); + m_endPoint.setX(m_rect.right()-dx); + m_endPoint.setY(m_rect.bottom()-dy); + } + if(m_startPoint.x()<=0) m_startPoint.setX(0); + if(m_startPoint.y()<=0) m_startPoint.setY(0); + if(m_endPoint.x()>=scaleRec.width()) m_endPoint.setX(scaleRec.right()); + if(m_endPoint.y()>=scaleRec.height()) m_endPoint.setY(scaleRec.bottom()); + + + if(qAbs(m_startPoint.x() - m_endPoint.x()) <= 10 || m_startPoint.x() > m_endPoint.x()){ + m_startPoint.setX(m_rect.left()); + m_endPoint.setX(m_rect.right()); + } + if(qAbs(m_startPoint.y() - m_endPoint.y()) <= 10 || m_startPoint.y() > m_endPoint.y()){ + m_startPoint.setY(m_rect.top()); + m_endPoint.setY(m_rect.bottom()); + } + + update(); + }else{ + mousePosition(QPoint(x,y)); + } +} + +void cutDialog::mouseReleaseEvent(QMouseEvent *) +{ + m_mouse_down = false; + update(); +} + +void cutDialog::enterEvent(QEvent *) +{ + emit lineEditEnable(false); +} + +void cutDialog::leaveEvent(QEvent *) +{ + emit lineEditEnable(true); +} + +void cutDialog::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.translate(0,0); + + drawScale(painter); + drawCutRect(painter); + drawTransparentColor(painter); + if(m_mouse_down){ + if(sizeType == INCH || sizeType == MILLIM){ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',2).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',2).toDouble()); + emit cutRectWidth(QString::number(getCutRectSize().width(),'f',2).toDouble()); + emit cutRectHeight(QString::number(getCutRectSize().height(),'f',2).toDouble()); + }else{ + emit cutRectX(double(int(getCutRectStartPos().x()))); + emit cutRectY(double(int(getCutRectStartPos().y()))); + emit cutRectWidth(double(int(getCutRectSize().width()))); + emit cutRectHeight(double(int(getCutRectSize().height()))); + } + } + + painter.end(); +} + +void cutDialog::drawScale(QPainter& painter) +{ + painter.setPen(QPen(Qt::black,1)); + scaleRec = QRectF(0,0,paperWidth,paperHeight+0.5); + painter.drawRect(scaleRec); + for(int i = 6 ; i <= paperWidth-6; i++){ + if(int(paperWidth/2) == i || int(paperWidth/4) == i || int(paperWidth*3/4) == i){ + painter.setPen(QPen(Qt::gray,1)); + painter.drawLine(i,0,i,paperHeight); + painter.setPen(QPen(Qt::black,1)); + } + if(i%divisor == 0){ + painter.drawLine(i,paperHeight-4,i,paperHeight); + painter.drawLine(i,0,i,4); + } + if(i%(divisor*5) == 0){ + painter.drawLine(i,paperHeight-8,i,paperHeight); + painter.drawLine(i,0,i,8); + } + } + for(int i = 6 ; i <= paperHeight-6; i++){ + if(int(paperHeight/2) == i || int(paperHeight/4) == i || int(paperHeight*3/4) == i){ + painter.setPen(QPen(Qt::gray,1)); + painter.drawLine(0,i,paperWidth,i); + painter.setPen(QPen(Qt::black,1)); + } + if(i%divisor == 0){ + painter.drawLine(0,i,4,i); + painter.drawLine(paperWidth,i,paperWidth-4,i); + } + if(i%(divisor*5) == 0){ + painter.drawLine(0,i,8,i); + painter.drawLine(paperWidth,i,paperWidth-8,i); + } + } +} + +void cutDialog::drawCutRect(QPainter &painter) +{ + painter.setPen(QPen(Qt::green,1)); + m_rect = QRectF(m_startPoint,m_endPoint); + painter.drawRect(m_rect); + painter.setPen(QPen(Qt::red,1)); + painter.setBrush(Qt::red); + painter.drawEllipse(m_rect.left()-2,(m_rect.bottom()-m_rect.top())/2+m_rect.top()-2,4,4); + painter.drawEllipse(m_rect.left()-2,m_rect.top()-2,4,4); + painter.drawEllipse(m_rect.left()-2,m_rect.bottom()-2,4,4); + painter.drawEllipse(m_rect.right()-2,m_rect.top()-2,4,4); + painter.drawEllipse(m_rect.right()-2,m_rect.bottom()-2,4,4); + painter.drawEllipse(m_rect.right()-2,(m_rect.bottom()-m_rect.top())/2+m_rect.top()-2,4,4); + painter.drawEllipse((m_rect.right()-m_rect.left())/2+m_rect.left()-2,m_rect.top()-2,4,4); + painter.drawEllipse((m_rect.right()-m_rect.left())/2+m_rect.left()-2,m_rect.bottom()-2,4,4); +} + +void cutDialog::drawTransparentColor(QPainter &painter) +{ + QPainterPath painterPath; + QPainterPath p; + p.addRect(scaleRec); + painterPath.addRect(m_rect); + QPainterPath drawPath =p.subtracted(painterPath); + painter.setOpacity(0.7); + painter.fillPath(drawPath,QBrush(Qt::gray)); +} + +void cutDialog::mousePosition(const QPoint& e) +{ + initAllCorner(); + QRectF r = QRectF(m_rect); + int x = e.x(); + int y = e.y(); + m_left = qAbs(x - r.left()) < 5; + m_right = qAbs(x - r.right()) < 5; + m_bottom = qAbs(y - r.bottom()) < 5; + m_top = qAbs(y - r.top()) < 5; + m_out = r.left()-x>=5 || x-r.right()>=5 || r.top()-y>=5 || y-r.bottom()>=5; + bool lorr = m_left | m_right; + bool torb = m_top | m_bottom; + if(lorr && torb) + { + if((m_left && m_top) || (m_right && m_bottom)) + setCursor(Qt::SizeFDiagCursor); + else + setCursor(Qt::SizeBDiagCursor); + } + else if(lorr) + setCursor(Qt::SizeHorCursor); + else if(torb) + setCursor(Qt::SizeVerCursor); + else if(!m_out) + { + setCursor(Qt::SizeAllCursor); + m_bottom = m_left = m_right = m_top = false; + }else if(m_out){ + setCursor(Qt::ArrowCursor); + m_bottom = m_left = m_right = m_top = false; + } + + if(m_left && m_top) m_leftTop = true; + else if(m_left && m_bottom) m_leftBottom = true; + else if(m_right && m_top) m_rightTop = true; + else if(m_right && m_bottom) m_rightBottom = true; + else if(m_left && !m_top && !m_bottom) m_leftCorn = true; + else if(m_right && !m_top && !m_bottom) m_rightCorn = true; + else if(m_top && !m_left && !m_right) m_topCorn = true; + else if(m_bottom && !m_left && !m_right) m_bottomCorn = true; + else initAllCorner(); +} + +void cutDialog::refreshView() +{ + if(sizeType == INCH){ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',2).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',2).toDouble()); + emit cutRectWidth(QString::number(getCutRectSize().width(),'f',2).toDouble()); + emit cutRectHeight(QString::number(getCutRectSize().height(),'f',2).toDouble()); + }else{ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',0).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',0).toDouble()); + emit cutRectWidth(double(int(getCutRectSize().width()))); + emit cutRectHeight(double(int(getCutRectSize().height()))); + } +} + +void cutDialog::initAllCorner() +{ + m_left = false; + m_right = false; + m_bottom = false; + m_top = false; + m_leftCorn = false; + m_rightCorn = false; + m_topCorn = false; + m_bottomCorn = false; + m_leftTop = false; + m_leftBottom = false; + m_rightTop = false; + m_rightBottom = false; +} diff --git a/SaneUI/cutdialog.h b/SaneUI/cutdialog.h new file mode 100644 index 0000000..2f77ef2 --- /dev/null +++ b/SaneUI/cutdialog.h @@ -0,0 +1,100 @@ +#ifndef CUTDIALOG_H +#define CUTDIALOG_H + +#include +#include +#include +#include + +namespace Ui { +class cutDialog; +} + +enum SIZETYPE{ + MILLIM , + INCH, + PIXEL +}; + +class cutDialog : public QWidget +{ + Q_OBJECT + +public: + explicit cutDialog(QWidget *parent = nullptr); + ~cutDialog(); + void setPaperSize(QString type = "A1", const int w = 200); + void setDpiValue(const double d); + void setSizeType(const SIZETYPE& t); + void setCutRectWidth(double w); + void setCutRectHeight(double h); + void setCutRectStartX(double x); + void setCutRectStartY(double y); + QSizeF getPaperSize()const; + QSizeF getCutRectSize()const; + QPointF getCutRectStartPos()const; + QRectF getCutRectPixel()const; + void setCutRectPixel(QRectF& rect); + int getCutRectRight()const; + int getCutRectBottom()const; + void refreshView(); + +signals: + void cutRectX(double x); + void cutRectY(double y); + void cutRectWidth(double w); + void cutRectHeight(double h); + void lineEditEnable(bool b); + +private: + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void enterEvent(QEvent*); + void leaveEvent(QEvent*); + //void resizeEvent(QResizeEvent*); + void paintEvent(QPaintEvent *); + void drawScale(QPainter &painter); + void drawCutRect(QPainter &painter); + void drawTransparentColor(QPainter &painter); + void drawPaperSize(); + void mousePosition(const QPoint &e); + void initAllCorner(); + //void mouseChangeRect(int dx,int dy); + +private: + Ui::cutDialog *ui; + QPointF m_startPoint; + QPointF m_endPoint; + QPointF m_moveStart; + + QRectF m_rect; + QRectF scaleRec; + + QString paperType; + double paperWidth; + double paperHeight; + int divisor; + int sizeType; + double dpi; + double h_w; + double realRate; + double sizeRate; + + bool m_mouse_down; + bool m_left; + bool m_right; + bool m_bottom; + bool m_top; + bool m_leftCorn; + bool m_rightCorn; + bool m_topCorn; + bool m_bottomCorn; + bool m_leftTop; + bool m_rightTop; + bool m_leftBottom; + bool m_rightBottom; + bool m_out; +}; + +#endif // CUTDIALOG_H diff --git a/SaneUI/cutdialog.ui b/SaneUI/cutdialog.ui new file mode 100644 index 0000000..de03c34 --- /dev/null +++ b/SaneUI/cutdialog.ui @@ -0,0 +1,44 @@ + + + cutDialog + + + true + + + + 0 + 0 + 321 + 342 + + + + + 0 + 0 + + + + + 2 + 0 + + + + + 2 + 0 + + + + true + + + cutDialog + + + + + + diff --git a/SaneUI/cutpapertool.cpp b/SaneUI/cutpapertool.cpp new file mode 100644 index 0000000..3893214 --- /dev/null +++ b/SaneUI/cutpapertool.cpp @@ -0,0 +1,210 @@ +#include "cutpapertool.h" +#include "ui_cutpapertool.h" +#include +#include + +CutPaperTool::CutPaperTool(QWidget *parent) : + QDialog(parent), + ui(new Ui::CutPaperTool) +{ + ui->setupUi(this); + connect(ui->widget,SIGNAL(cutRectX(double)),this,SLOT(cutRectXSlot(double))); + connect(ui->widget,SIGNAL(cutRectY(double)),this,SLOT(cutRectYSlot(double))); + connect(ui->widget,SIGNAL(cutRectWidth(double)),this,SLOT(cutRectWidthSlot(double))); + connect(ui->widget,SIGNAL(cutRectHeight(double)),this,SLOT(cutRectHeightSlot(double))); + connect(ui->widget,SIGNAL(lineEditEnable(bool)),this,SLOT(lineEditEnableSlot(bool))); + //setDpi(200); + //setPaperType(200,"A4",400); + ui->widget->setSizeType(MILLIM); + setSizeLabel(); + this->setFixedWidth(ui->widget->width()+20); +} + +CutPaperTool::~CutPaperTool() +{ + delete ui; +} + +void CutPaperTool::paintEvent(QPaintEvent *) +{ + +} + +void CutPaperTool::setPaperType(const int d, const QString &t, const int& w) +{ + dpi = d; + ui->dpiLab->setText(QString::number(dpi)); + ui->widget->setDpiValue(dpi); + paperType = t; + ui->paperLab->setText(paperType); + ui->widget->setPaperSize(paperType,w); + //ui->widget->refreshView(); + setSizeLabel(); + this->setFixedWidth(ui->widget->width()+20); + setSizeInit(); +} + +QRectF CutPaperTool::getCutRectPixel() +{ + return QRectF(ui->widget->getCutRectPixel()); +} + +void CutPaperTool::setCutRect(QRectF &rect) +{ + ui->widget->setCutRectPixel(rect); + ui->startXEdt->setText(QString::number(rect.x()/dpi/0.03937)); + ui->startYEdt->setText(QString::number(rect.y()/dpi/0.03937)); + ui->rectWidth->setText(QString::number(rect.width()/dpi/0.03937)); + ui->rectHeight->setText(QString::number(rect.height()/dpi/0.03937)); +} + +void CutPaperTool::setSizeLabel() +{ + QString wSize; + QString hSize; + if(ui->comboBox_2->currentIndex() == INCH){ + wSize = QString::number(ui->widget->getPaperSize().width(),'f',2); + hSize = QString::number(ui->widget->getPaperSize().height(),'f',2); + } + else { + wSize = QString::number(int(ui->widget->getPaperSize().width()+0.001)); + hSize = QString::number(int(ui->widget->getPaperSize().height()+0.001)); + } + ui->sizeLabel->setText("("+wSize + " * " +hSize+")"); +} + +void CutPaperTool::setSizeInit() +{ + ui->widget->setCutRectStartX(0); + ui->widget->setCutRectStartY(0); + ui->widget->setCutRectWidth(ui->widget->getPaperSize().width()); + ui->widget->setCutRectHeight(ui->widget->getPaperSize().height()); + ui->startXEdt->setText("0"); + ui->startYEdt->setText("0"); + ui->rectWidth->setText(QString::number(int(ui->widget->getPaperSize().width()))); + ui->rectHeight->setText(QString::number(int(ui->widget->getPaperSize().height()))); +} + +void CutPaperTool::setSizeInit(QRectF& rect){ + setSizeInit(); + if(rect != QRectF(0,0,0,0)) + setCutRect(rect); +} + +void CutPaperTool::cutRectXSlot(double x) +{ + ui->startXEdt->setText(QString::number(x)); +} + +void CutPaperTool::cutRectYSlot(double y) +{ + ui->startYEdt->setText(QString::number(y)); +} + +void CutPaperTool::cutRectWidthSlot(double w) +{ + ui->rectWidth->setText(QString::number(w)); +} + +void CutPaperTool::cutRectHeightSlot(double h) +{ + ui->rectHeight->setText(QString::number(h)); +} + +void CutPaperTool::lineEditEnableSlot(bool b) +{ + ui->startXEdt->setEnabled(b); + ui->startYEdt->setEnabled(b); + ui->rectWidth->setEnabled(b); + ui->rectHeight->setEnabled(b); +} + +void CutPaperTool::on_startXEdt_textEdited(QString arg1) +{ + double x = arg1.toDouble(); + if(x >ui->widget->getCutRectRight()) { + arg1.chop(1); + x = arg1.toDouble(); + } + if(type == PIXEL) x = arg1.toInt(); + ui->widget->setCutRectStartX(x); +} + +void CutPaperTool::on_startYEdt_textEdited(QString arg1) +{ + double y = arg1.toDouble(); + if(y >ui->widget->getCutRectBottom()) { + arg1.chop(1); + y = arg1.toDouble(); + } + if(type == PIXEL) y = arg1.toInt(); + ui->widget->setCutRectStartY(y); +} + +void CutPaperTool::on_rectWidth_textEdited(QString arg1) +{ + double v = arg1.toDouble(); + if(v > ui->widget->getPaperSize().width() - ui->widget->getCutRectStartPos().x()) { + arg1.chop(1); + v = arg1.toDouble(); + } + if(type == PIXEL) v = arg1.toInt(); + ui->widget->setCutRectWidth(v); +} + +void CutPaperTool::on_rectHeight_textEdited(QString arg1) +{ + double v = arg1.toDouble(); + if(v > ui->widget->getPaperSize().height() - ui->widget->getCutRectStartPos().y()) { + arg1.chop(1); + v = arg1.toDouble(); + } + if(type == PIXEL) v = arg1.toInt(); + ui->widget->setCutRectHeight(v); +} + +void CutPaperTool::on_comboBox_2_currentIndexChanged(int index) +{ + switch(index){ + case 0: + ui->xLabel->setText("mm"); + ui->yLabel->setText("mm"); + ui->wLabel->setText("mm"); + ui->hLabel->setText("mm"); + ui->widget->setSizeType(MILLIM); + break; + case 1: + ui->xLabel->setText("in"); + ui->yLabel->setText("in"); + ui->wLabel->setText("in"); + ui->hLabel->setText("in"); + ui->widget->setSizeType(INCH); + break; + case 2: + ui->xLabel->setText("px"); + ui->yLabel->setText("px"); + ui->wLabel->setText("px"); + ui->hLabel->setText("px"); + ui->widget->setSizeType(PIXEL); + break; + } + update(); + setSizeLabel(); + ui->widget->refreshView(); +} + + +void CutPaperTool::on_buttonBox_accepted() +{ + accept(); +} + +void CutPaperTool::on_buttonBox_rejected() +{ + reject(); +} + +void CutPaperTool::on_pbtn_init_clicked() +{ + setSizeInit(); +} diff --git a/SaneUI/cutpapertool.h b/SaneUI/cutpapertool.h new file mode 100644 index 0000000..cf6d40e --- /dev/null +++ b/SaneUI/cutpapertool.h @@ -0,0 +1,59 @@ +#ifndef CUTPAPERTOOL_H +#define CUTPAPERTOOL_H + +#include +#include "cutdialog.h" + +namespace Ui { +class CutPaperTool; +} + +class CutPaperTool : public QDialog +{ + Q_OBJECT + +public: + explicit CutPaperTool(QWidget *parent = nullptr); + ~CutPaperTool(); + void setPaperType(const int dpi, const QString& t,const int& w=200); + QRectF getCutRectPixel(); + void setCutRect(QRectF& rect); + void setSizeInit(); + void setSizeInit(QRectF& rect); + + +private: + void paintEvent(QPaintEvent *); + void setSizeLabel(); + +private slots: + void cutRectXSlot(double x); + void cutRectYSlot(double y); + void cutRectWidthSlot(double w); + void cutRectHeightSlot(double h); + void lineEditEnableSlot(bool b); + + void on_startXEdt_textEdited(QString arg1); + + void on_startYEdt_textEdited(QString arg1); + + void on_rectWidth_textEdited(QString arg1); + + void on_rectHeight_textEdited(QString arg1); + + void on_comboBox_2_currentIndexChanged(int index); + + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + + void on_pbtn_init_clicked(); + +private: + Ui::CutPaperTool *ui; + SIZETYPE type; + int dpi; + QString paperType; +}; + +#endif // CUTPAPERTOOL_H diff --git a/SaneUI/cutpapertool.ui b/SaneUI/cutpapertool.ui new file mode 100644 index 0000000..b1ff26f --- /dev/null +++ b/SaneUI/cutpapertool.ui @@ -0,0 +1,276 @@ + + + CutPaperTool + + + + 0 + 0 + 461 + 281 + + + + + 0 + 0 + + + + 自定义扫描区域 + + + + + + + + 纸张尺寸: + + + + + + + A4 + + + + + + + (210*297) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + DPI(像素/英寸): + + + Qt::AlignJustify|Qt::AlignVCenter + + + + + + + 200 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 单位: + + + + + + + + 毫米(mm) + + + + + 英寸(in) + + + + + 像素(px) + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 初始化选择区域 + + + + + + + + + + 0 + 0 + + + + + + + + + + x: + + + + + + + + + + mm + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + y: + + + + + + + + + + mm + + + + + + + + + + + w: + + + + + + + + + + mm + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + h: + + + + + + + + + + mm + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + cutDialog + QWidget +
cutdialog.h
+ 1 +
+
+ + +
diff --git a/SaneUI/gaosixy.cpp b/SaneUI/gaosixy.cpp new file mode 100644 index 0000000..15de754 --- /dev/null +++ b/SaneUI/gaosixy.cpp @@ -0,0 +1,54 @@ +#include "gaosixy.h" +#include +#include +#include + +GaoSiXY::GaoSiXY() +{ +} + +void GaoSiXY::solve(double**a,int n,double *recv) +{ + int m = 0; + int i,j; + + for(j = 0; j < n; j++){ + double max = 0; + double imax = 0; + for(i = j; i < n; i++){ + if(imax < fabs(a[i][j])){ + imax = fabs(a[i][j]); + max = a[i][j];//得到各行中所在列最大元素 + m = i; + } + } + if(fabs(a[j][j]) != max) { + double b = 0; + for(int k = j;k < n + 1; k++){ + b = a[j][k]; + a[j][k] = a[m][k]; + a[m][k] = b; } + } + for(int r = j;r < n + 1;r++){ + a[j][r] = a[j][r] / max;//让该行的所在列除以所在列的第一个元素,目的是让首元素为1 + } + for(i = j + 1;i < n; i++){ + double c = a[i][j]; + if(c == 0) continue; + for(int s = j;s < n + 1;s++){ + //double tempdata = a[i][s]; + a[i][s] = a[i][s] - a[j][s] * c;//前后行数相减,使下一行或者上一行的首元素为0 + } + } + } + for(i = n - 2; i >= 0; i--){ + for(j = i + 1;j < n; j++){ + a[i][n] = a[i][n] - a[j][n] * a[i][j]; + } + } + + for(int k = 0; k < n; k++){ + recv[k] = a[k][n]; + } + +} diff --git a/SaneUI/gaosixy.h b/SaneUI/gaosixy.h new file mode 100644 index 0000000..4b44675 --- /dev/null +++ b/SaneUI/gaosixy.h @@ -0,0 +1,17 @@ +#ifndef GAOSIXY_H +#define GAOSIXY_H + +#include +#include + +class GaoSiXY +{ +public: + GaoSiXY(); + void solve(double **a,int n,double *recv);//用于计算曲线方程 + +private: + +}; + +#endif // GAOSIXY_H diff --git a/SaneUI/huagao.json b/SaneUI/huagao.json new file mode 100644 index 0000000..8c69b4e --- /dev/null +++ b/SaneUI/huagao.json @@ -0,0 +1,608 @@ +{ + "G100": { + "default": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "bjpegcompress": false, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0, + "icroprect_w": 0, + "icroprect_x": 0, + "icroprect_y": 0, + "ijpegcompressratio": 80, + "ifillcolor": false, + "indent": 5, + "inoise": 40, + "refuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + }, + "system": { + "bMultiOutPutR": [ -1, 0, 1, 2, 3 ], + "dpi": [ 100, 150, 200, 240, 300, 600 ], + "iFilter": [ 0, 1, 2, 3, 4, 5, 6, 7 ], + "iOrientation": [ 0, 1, 2, 3, 5 ], + "iPaperAlign": [ 0, 3 ], + "iPaperSize": [ 11, 1, 5, 13, 6, 2, 7, 4, 3, 9, 52, 0 ], + "iPixType": [ 0, 1, 2 ], + "iSharpen": [ 0, 1, 2, 3, 4 ], + "imageRotateList": [ 0, 90, 180, 270 ], + "sPaperSize": { + "A3": 11, + "A4": 1, + "A4 Transverse": 1, + "A5": 5, + "A5 Transverse": 5, + "A6": 13, + "A6 Transverse": 13, + "B4": 6, + "B5": 2, + "B5 Transverse": 2, + "B6": 7, + "B6 Transverse": 7, + "Double Letter": 9, + "Legal": 4, + "Letter": 3, + "Letter Transverse": 3, + "Matches the original size": 0, + "Max Size": 54, + "Max Size Auto Crop": 52 + } + }, + "user": { + "Caption": "", + "SavePath": "", + "ScanCount": 1, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "bjpegcompress": false, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1.0, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0.0, + "icroprect_w": 0.0, + "icroprect_x": 0.0, + "icroprect_y": 0.0, + "ijpegcompressratio": 80, + "ifillcolor": false, + "igammatable": [ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, 188, 188, 188, 189, 189, 189, 190, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 ], + "igammatablelenght": 786, + "indent": 5, + "inoise": 40, + "refuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + } + }, + "G200": { + "default": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "bjpegcompress": false, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0, + "icroprect_w": 0, + "icroprect_x": 0, + "icroprect_y": 0, + "ijpegcompressratio": 80, + "ifillcolor": false, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + }, + "system": { + "bMultiOutPutR": [ -1, 0, 1, 2, 3 ], + "dpi": [ 100, 150, 200, 240, 300, 600 ], + "iFilter": [ 0, 1, 2, 3, 4, 5, 6, 7 ], + "iOrientation": [ 0, 1, 2, 3, 5 ], + "iPaperAlign": [ 0, 3 ], + "iPaperSize": [ 11, 1, 5, 13, 6, 2, 7, 4, 3, 9, 52, 0 ], + "iPixType": [ 0, 1, 2 ], + "iSharpen": [ 0, 1, 2, 3, 4 ], + "imageRotateList": [ 0, 90, 180, 270 ], + "sPaperSize": { + "A3": 11, + "A4": 1, + "A4 Transverse": 1, + "A5": 5, + "A5 Transverse": 5, + "A6": 13, + "A6 Transverse": 13, + "B4": 6, + "B5": 2, + "B5 Transverse": 2, + "B6": 7, + "B6 Transverse": 7, + "Double Letter": 9, + "Legal": 4, + "Letter": 3, + "Letter Transverse": 3, + "Matches the original size": 0, + "Max Size": 54, + "Max Size Auto Crop": 52 + } + }, + "user": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": false, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1.0, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0.0, + "icroprect_w": 0.0, + "icroprect_x": 0.0, + "icroprect_y": 0.0, + "ifillcolor": false, + "igammatable": [ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, 188, 188, 188, 189, 189, 189, 190, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 ], + "igammatablelenght": 786, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + } + }, + "G300": { + "default": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A4", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0, + "icroprect_w": 0, + "icroprect_x": 0, + "icroprect_y": 0, + "ifillcolor": false, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + }, + "system": { + "bMultiOutPutR": [ -1, 0, 1, 2, 3 ], + "dpi": [ 100, 150, 200, 240, 300, 600 ], + "iFilter": [ 0, 1, 2, 3, 4, 5, 6, 7 ], + "iOrientation": [ 0, 1, 2, 3, 5 ], + "iPaperAlign": [ 0, 3 ], + "iPaperSize": [ 1, 5, 13, 2, 7, 0, 52, 54 ], + "iPixType": [ 0, 1, 2 ], + "iSharpen": [ 0, 1, 2, 3, 4 ], + "imageRotateList": [ 0, 90, 180, 270 ], + "sPaperSize": { + "A4": 1, + "A5": 5, + "A6": 13, + "B5": 2, + "B6": 7, + "Matches the original size": 0, + "Max Size": 54, + "Max Size Auto Crop": 52 + } + }, + "user": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": false, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1.0, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 1, + "iPaperSizeName": "A4", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0.0, + "icroprect_w": 0.0, + "icroprect_x": 0.0, + "icroprect_y": 0.0, + "ifillcolor": false, + "igammatable": [ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, 188, 188, 188, 189, 189, 189, 190, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 ], + "igammatablelenght": 786, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + } + }, + "G400": { + "default": { + "Caption": "", + "SavePath": "", + "ScanCount": 65536, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0, + "icroprect_w": 0, + "icroprect_x": 0, + "icroprect_y": 0, + "ifillcolor": false, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": false, + "splitImage": false, + "textureRemove": false + }, + "system": { + "bMultiOutPutR": [ -1, 0, 1, 2, 3 ], + "dpi": [ 100, 150, 200, 240, 300, 600 ], + "iFilter": [ 0, 1, 2, 3, 4, 5, 6, 7 ], + "iOrientation": [ 0, 1, 2, 3, 5 ], + "iPaperAlign": [ 0, 3 ], + "iPaperSize": [ 11, 1, 5, 13, 6, 2, 7, 4, 3, 9, 0 ], + "iPixType": [ 0, 1, 2 ], + "iSharpen": [ 0, 1, 2, 3, 4 ], + "imageRotateList": [ 0, 90, 180, 270 ], + "sPaperSize": { + "A3": 11, + "A4": 1, + "A4 Transverse": 1, + "A5": 5, + "A5 Transverse": 5, + "A6": 13, + "A6 Transverse": 13, + "B4": 6, + "B5": 2, + "B5 Transverse": 2, + "B6": 7, + "B6 Transverse": 7, + "Double Letter": 9, + "Legal": 4, + "Letter": 3, + "Letter Transverse": 3, + "Matches the original size": 0 + } + }, + "user": { + "Caption": "", + "SavePath": "", + "ScanCount": 1, + "bAnswerSheetR": false, + "bAuotCrop": true, + "bAutoDescrew": true, + "bAutoMaticColorDetece": false, + "bBackRotate180": false, + "bBindingDetect": false, + "bDiscardBlank": false, + "bDiscardBlankVince": false, + "bDuplex": true, + "bExchangeFrontBack": false, + "bFillBlcak": true, + "bFold": false, + "bMultiOutPutR": false, + "bMultiOutput": -1, + "bOutHole": false, + "bUltrasonicDetect": true, + "bdoublefooddetection": true, + "capturepixtype": 1, + "customGamma": false, + "errorExtention": 0, + "fGamma": 1, + "iAutoCrop_threshold": 40, + "iAutoMaticColorDeteceType": 1, + "iBrightness": 128, + "iContrast": 4, + "iFilter": 3, + "iOrientation": 0, + "iOutHoleRatio": 10, + "iPaperAlign": 0, + "iPaperSize": 11, + "iPaperSizeName": "A3", + "iPixType": 2, + "iResolution": 200, + "iResolution_native": 200, + "iSharpen": 0, + "iSizeDetect": false, + "iSkewEnable": true, + "iSkewLevel": 3, + "ibackgroundremoval": false, + "icolorCorrection": false, + "iconvex": true, + "icroprect_enable": false, + "icroprect_h": 0, + "icroprect_w": 0, + "icroprect_x": 0, + "icroprect_y": 0, + "ifillcolor": false, + "indent": 5, + "inoise": 40, + "irefuseinflow": false, + "iremovemorr": false, + "nosieDetach": 6, + "splitImage": false, + "textureRemove": false + } + }} \ No newline at end of file diff --git a/SaneUI/images.qrc b/SaneUI/images.qrc new file mode 100644 index 0000000..320ec70 --- /dev/null +++ b/SaneUI/images.qrc @@ -0,0 +1,10 @@ + + + ImageResource/HUAGO-LOGO-for UI.bmp + ImageResource/hg.ico + ImageResource/huagoscan_LOGO_icon.png + huagao.json + ImageResource/Lanxum_logo.ico + ImageResource/RightWay_logo.ico + + diff --git a/SaneUI/include/twglue.hpp b/SaneUI/include/twglue.hpp new file mode 100644 index 0000000..7f05f75 --- /dev/null +++ b/SaneUI/include/twglue.hpp @@ -0,0 +1,16 @@ +#ifndef TWGLUE_HPP +#define TWGLUE_HPP + +#include + +struct TwGlue { + + TwGlue(const std::function& scan, const std::function& cancel) : + m_scan(scan), m_cancel(cancel){} + + std::function m_scan; + std::function m_cancel; + +}; + +#endif // TWGLUE_HPP diff --git a/SaneUI/indicator.cpp b/SaneUI/indicator.cpp new file mode 100644 index 0000000..6824b17 --- /dev/null +++ b/SaneUI/indicator.cpp @@ -0,0 +1,30 @@ +#include "indicator.h" +#include "ui_indicator.h" + +Indicator::Indicator(std::function canle, QWidget* parent) : + QDialog(parent), + btncanle(canle), + ui(new Ui::Indicator) +{ + ui->setupUi(this); + QObject::connect(ui->btncanle, &QPushButton::pressed, this, &Indicator::on_btncanle_click); + this->setWindowTitle("Indicator"); + //this->setWindowFlags(Qt::WindowCloseButtonHint); +} + +Indicator::~Indicator() +{ + delete ui; +} + +void Indicator::on_btncanle_click() +{ + if (btncanle) + btncanle(); +} + +void Indicator::closeEvent(QCloseEvent* event) +{ +// if (btncanle) +// btncanle(); +} diff --git a/SaneUI/indicator.h b/SaneUI/indicator.h new file mode 100644 index 0000000..8aa25e4 --- /dev/null +++ b/SaneUI/indicator.h @@ -0,0 +1,26 @@ +#ifndef INDICATOR_H +#define INDICATOR_H + +#include +#include +#include +namespace Ui { +class Indicator; +} + +class Indicator : public QDialog +{ + Q_OBJECT + +public: + explicit Indicator(std::function canle, QWidget *parent = nullptr); + ~Indicator(); + void on_btncanle_click(); + std::function btncanle; +private: + Ui::Indicator *ui; +protected: + virtual void closeEvent(QCloseEvent* event); +}; + +#endif // INDICATOR_H diff --git a/SaneUI/indicator.ui b/SaneUI/indicator.ui new file mode 100644 index 0000000..251d6ec --- /dev/null +++ b/SaneUI/indicator.ui @@ -0,0 +1,32 @@ + + + Indicator + + + + 0 + 0 + 225 + 115 + + + + Form + + + + + 70 + 40 + 75 + 23 + + + + 取消扫描 + + + + + + diff --git a/SaneUI/json.hpp b/SaneUI/json.hpp new file mode 100644 index 0000000..06da815 --- /dev/null +++ b/SaneUI/json.hpp @@ -0,0 +1,22875 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.7.3 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 7 +#define NLOHMANN_JSON_VERSION_PATCH 3 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include + +// #include + + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string + +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // pair +// #include +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 11 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(__COMPCERT__) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,3,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(__cplusplus) && (__cplusplus >= 201703L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_UNREACHABLE() __assume(0) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0) + #else + #define JSON_HEDLEY_UNREACHABLE() _nassert(0) + #endif + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#elif defined(EXIT_FAILURE) + #define JSON_HEDLEY_UNREACHABLE() abort() +#else + #define JSON_HEDLEY_UNREACHABLE() + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif + +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1))) +#else + #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr)) +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE) + #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5) +#endif +#elif \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else + #define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else + #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC __declspec(dllexport) + #define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else + #if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) + #define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) + #else + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC + #endif + #define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr))) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast(expr) +#else + #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + + +#include // random_access_iterator_tag + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include + +// #include + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template