1.二维码的生成
- 需要的库QR Code generator library
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include "qrcodegen.hpp"
using qrcodegen::QrCode;
using qrcodegen::QrSegment;
using std::uint8_t;
static void printQr(const QrCode &qr)
{
int border = 4;
for (int y = -border; y < qr.getSize() + border; y++)
{
for (int x = -border; x < qr.getSize() + border; x++)
{
std::cout << (qr.getModule(x, y) ? "##" : " ");
}
std::cout << std::endl;
}
std::cout << std::endl;
}
static std::string toSvgString(const QrCode &qr, int border)
{
if (border < 0)
throw std::domain_error("Border must be non-negative");
if (border > INT_MAX / 2 || border * 2 > INT_MAX - qr.getSize())
throw std::overflow_error("Border too large");
std::ostringstream sb;
sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
sb << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
sb << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ";
sb << (qr.getSize() + border * 2) << " " << (qr.getSize() + border * 2) << "\" stroke=\"none\">\n";
sb << "\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n";
sb << "\t<path d=\"";
for (int y = 0; y < qr.getSize(); y++)
{
for (int x = 0; x < qr.getSize(); x++)
{
if (qr.getModule(x, y))
{
if (x != 0 || y != 0)
sb << " ";
sb << "M" << (x + border) << "," << (y + border) << "h1v1h-1z";
}
}
}
sb << "\" fill=\"#000000\"/>\n";
sb << "</svg>\n";
return sb.str();
}
static void doBasicDemo()
{
const char *text = "http://httpbin.org/#/";
const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW;
const QrCode qr = QrCode::encodeText(text, errCorLvl);
std::fstream outfile("QRCode.svg", std::ios_base::out);
if (!outfile)
{
std::cout << "--------------------------------------" << std::endl;
exit(EXIT_FAILURE);
}
outfile << toSvgString(qr, 4);
}
2. svg 转 png
- 需要的库LunaSVG - SVG rendering library in C++
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <lunasvg.h>
#include "stb_image_write.h"
using namespace lunasvg;
bool svg2png(const std::string &filename, std::uint32_t width, std::uint32_t height, std::uint32_t backgroundColor)
{
auto document = Document::loadFromFile(filename);
if (!document)
{
std::cout << filename+"文件加载错误!请确认文件是否存在!" << std::endl;
exit(EXIT_FAILURE);
}
lunasvg::Bitmap bitmap = document->renderToBitmap(width, height, backgroundColor);
std::string basename = filename.substr(filename.find_last_of("/\\") + 1);
std::string::iterator ite = find(basename.begin(), basename.end(), '.');
std::string imgName(basename.begin(), ite);
imgName.append(".png");
stbi_write_png(imgName.c_str(), int(bitmap.width()), int(bitmap.height()), 4, bitmap.data(), 0);
std::cout << "svg to png finished" << std::endl;
}
3. 解码
- 需要的库ZXing C++
bool decode(cv::Mat &img)
{
try
{
cv::Mat grayColor;
if (img.type() != CV_8UC1)
{
cv::cvtColor(img, grayColor, COLOR_BGR2GRAY);
}
zxing::Ref<zxing::LuminanceSource> source = MatSource::create(grayColor);
zxing::Ref<zxing::Reader> reader;
reader.reset(new zxing::qrcode::QRCodeReader);
zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
zxing::Ref<zxing::Result> result(reader->decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::QR_CODE_HINT)));
url = result->getText()->getText();
std::cout << "二维码中包含的内容为:" + url << std::endl;
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
return false;
}
return true;
}
4. HTTP测试
- 需要的库libhv
bool GetHttps(std::string &url)
{
auto resp = requests::get(url.c_str());
if (resp == NULL)
{
std::cout << "requset failed!\n";
return false;
}
else
{
std::cout << resp->status_code << " " << resp->status_message() << std::endl;
std::cout << resp->body.c_str() << std::endl;
std::fstream urlhtml("urlhtml.html",std::ios_base::out);
if(!urlhtml)
{
std::cout << "urlhtml.html 文件加载错误!请确认文件是否存在!" << std::endl;
exit(EXIT_FAILURE);
}
else{
urlhtml<<resp->body.c_str()<<std::endl;
}
return true;
}
}
5. 总程序
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <lunasvg.h>
#include "stb_image_write.h"
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include "qrcodegen.hpp"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <zxing/LuminanceSource.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <MatSource.h>
#include <hv/hv.h>
#include <hv/requests.h>
using namespace hv;
using namespace zxing;
using namespace lunasvg;
using namespace cv;
using qrcodegen::QrCode;
using qrcodegen::QrSegment;
using std::uint8_t;
static std::string url = "";
static void printQr(const QrCode &qr)
{
int border = 4;
for (int y = -border; y < qr.getSize() + border; y++)
{
for (int x = -border; x < qr.getSize() + border; x++)
{
std::cout << (qr.getModule(x, y) ? "##" : " ");
}
std::cout << std::endl;
}
std::cout << std::endl;
}
static std::string toSvgString(const QrCode &qr, int border)
{
if (border < 0)
throw std::domain_error("Border must be non-negative");
if (border > INT_MAX / 2 || border * 2 > INT_MAX - qr.getSize())
throw std::overflow_error("Border too large");
std::ostringstream sb;
sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
sb << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
sb << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ";
sb << (qr.getSize() + border * 2) << " " << (qr.getSize() + border * 2) << "\" stroke=\"none\">\n";
sb << "\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n";
sb << "\t<path d=\"";
for (int y = 0; y < qr.getSize(); y++)
{
for (int x = 0; x < qr.getSize(); x++)
{
if (qr.getModule(x, y))
{
if (x != 0 || y != 0)
sb << " ";
sb << "M" << (x + border) << "," << (y + border) << "h1v1h-1z";
}
}
}
sb << "\" fill=\"#000000\"/>\n";
sb << "</svg>\n";
return sb.str();
}
static void doBasicDemo()
{
const char *text = "http://httpbin.org/#/";
const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW;
const QrCode qr = QrCode::encodeText(text, errCorLvl);
std::fstream outfile("QRCode.svg", std::ios_base::out);
if (!outfile)
{
std::cout << "--------------------------------------" << std::endl;
exit(EXIT_FAILURE);
}
outfile << toSvgString(qr, 4);
}
bool svg2png(const std::string &filename, std::uint32_t width, std::uint32_t height, std::uint32_t backgroundColor)
{
auto document = Document::loadFromFile(filename);
if (!document)
{
std::cout << filename+"文件加载错误!请确认文件是否存在!" << std::endl;
exit(EXIT_FAILURE);
}
lunasvg::Bitmap bitmap = document->renderToBitmap(width, height, backgroundColor);
std::string basename = filename.substr(filename.find_last_of("/\\") + 1);
std::string::iterator ite = find(basename.begin(), basename.end(), '.');
std::string imgName(basename.begin(), ite);
imgName.append(".png");
stbi_write_png(imgName.c_str(), int(bitmap.width()), int(bitmap.height()), 4, bitmap.data(), 0);
std::cout << "svg to png finished" << std::endl;
}
bool decode(cv::Mat &img)
{
try
{
cv::Mat grayColor;
if (img.type() != CV_8UC1)
{
cv::cvtColor(img, grayColor, COLOR_BGR2GRAY);
}
zxing::Ref<zxing::LuminanceSource> source = MatSource::create(grayColor);
zxing::Ref<zxing::Reader> reader;
reader.reset(new zxing::qrcode::QRCodeReader);
zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
zxing::Ref<zxing::Result> result(reader->decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::QR_CODE_HINT)));
url = result->getText()->getText();
std::cout << "二维码中包含的内容为:" + url << std::endl;
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
return false;
}
return true;
}
bool GetHttps(std::string &url)
{
auto resp = requests::get(url.c_str());
if (resp == NULL)
{
std::cout << "requset failed!\n";
return false;
}
else
{
std::cout << resp->status_code << " " << resp->status_message() << std::endl;
std::cout << resp->body.c_str() << std::endl;
std::fstream urlhtml("urlhtml.html",std::ios_base::out);
if(!urlhtml)
{
std::cout << "urlhtml.html 文件加载错误!请确认文件是否存在!" << std::endl;
exit(EXIT_FAILURE);
}
else{
urlhtml<<resp->body.c_str()<<std::endl;
}
return true;
}
}
int main()
{
try
{
doBasicDemo();
std::uint32_t width = 320, height = 320;
std::uint32_t bgColor = 0x00000000;
std::string filename = "QRCode.svg";
svg2png(filename, width, height, bgColor);
cv::Mat img = imread("QRCode.png");
assert(!img.empty());
imshow("", img);
waitKey(2000);
decode(img);
if(!url.empty())
GetHttps(url);
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
}
return 0;
}
cmake_minimum_required(VERSION 3.0)
project(QRTest)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native -pthread ")
# Check C++11 or C++0x support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-elide-constructors") -fno-elide-constructors
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
add_definitions(-DCOMPILEDWITHC11)
message(STATUS "Using flag -std=c++11.")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_definitions(-DCOMPILEDWITHC0X)
message(STATUS "Using flag -std=c++0x.")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/inlude)
find_package(OpenCV 3.0 QUIET)
if(NOT OpenCV_FOUND)
find_package(OpenCV 2.4.3 QUIET)
if(NOT OpenCV_FOUND)
message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
endif()
endif()
include_directories(${OpenCV_INCLUDE_DIRS})
# 生成 二维码
add_library(qrCode STATIC IMPORTED )
set_target_properties( qrCode PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/libqrcodegencpp.a )
# svg 转 png
add_library(lunaSvg STATIC IMPORTED )
set_target_properties( lunaSvg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/liblunasvg.a)
# 解码
add_library(zxing STATIC IMPORTED )
set_target_properties(zxing PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/libzxing.a)
# HTTP测试
add_library(hv STATIC IMPORTED )
set_target_properties(hv PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/libhv.a)
add_executable(${PROJECT_NAME} main.cpp MatSource.cpp MatSource.h stb_image_write.h)
target_link_libraries(${PROJECT_NAME} qrCode lunaSvg zxing hv ${OpenCV_LIBRARIES})
├── CMakeLists.txt
├── include
│ ├── hv
│ │ ├── axios.h
│ │ ├── base64.h
│ │ ├── Buffer.h
│ │ ├── Callback.h
│ │ ├── Channel.h
│ │ ├── Event.h
│ │ ├── EventLoop.h
│ │ ├── EventLoopThread.h
│ │ ├── EventLoopThreadPool.h
│ │ ├── grpcdef.h
│ │ ├── hatomic.h
│ │ ├── hbase.h
│ │ ├── hbuf.h
│ │ ├── hconfig.h
│ │ ├── hdef.h
│ │ ├── hdir.h
│ │ ├── hendian.h
│ │ ├── herr.h
│ │ ├── hexport.h
│ │ ├── hfile.h
│ │ ├── hlog.h
│ │ ├── hloop.h
│ │ ├── hmain.h
│ │ ├── hmap.h
│ │ ├── hmath.h
│ │ ├── hmutex.h
│ │ ├── hobjectpool.h
│ │ ├── hpath.h
│ │ ├── hplatform.h
│ │ ├── hproc.h
│ │ ├── hscope.h
│ │ ├── hsocket.h
│ │ ├── hssl.h
│ │ ├── hstring.h
│ │ ├── hsysinfo.h
│ │ ├── hthread.h
│ │ ├── hthreadpool.h
│ │ ├── htime.h
│ │ ├── http2def.h
│ │ ├── http_client.h
│ │ ├── http_content.h
│ │ ├── HttpContext.h
│ │ ├── httpdef.h
│ │ ├── HttpMessage.h
│ │ ├── HttpParser.h
│ │ ├── HttpResponseWriter.h
│ │ ├── HttpServer.h
│ │ ├── HttpService.h
│ │ ├── hurl.h
│ │ ├── hversion.h
│ │ ├── hv.h
│ │ ├── ifconfig.h
│ │ ├── iniparser.h
│ │ ├── json.hpp
│ │ ├── md5.h
│ │ ├── nlog.h
│ │ ├── requests.h
│ │ ├── sha1.h
│ │ ├── singleton.h
│ │ ├── Status.h
│ │ ├── TcpClient.h
│ │ ├── TcpServer.h
│ │ ├── ThreadLocalStorage.h
│ │ ├── UdpClient.h
│ │ ├── UdpServer.h
│ │ ├── WebSocketChannel.h
│ │ ├── WebSocketClient.h
│ │ ├── WebSocketParser.h
│ │ ├── WebSocketServer.h
│ │ └── wsdef.h
│ ├── lunasvg.h
│ └── zxing
│ ├── aztec
│ │ ├── AztecDetectorResult.h
│ │ ├── AztecReader.h
│ │ ├── decoder
│ │ │ └── Decoder.h
│ │ └── detector
│ │ └── Detector.h
│ ├── BarcodeFormat.h
│ ├── Binarizer.h
│ ├── BinaryBitmap.h
│ ├── ChecksumException.h
│ ├── common
│ │ ├── Array.h
│ │ ├── BitArray.h
│ │ ├── BitMatrix.h
│ │ ├── BitSource.h
│ │ ├── CharacterSetECI.h
│ │ ├── Counted.h
│ │ ├── DecoderResult.h
│ │ ├── detector
│ │ │ ├── JavaMath.h
│ │ │ ├── MathUtils.h
│ │ │ ├── MonochromeRectangleDetector.h
│ │ │ └── WhiteRectangleDetector.h
│ │ ├── DetectorResult.h
│ │ ├── GlobalHistogramBinarizer.h
│ │ ├── GreyscaleLuminanceSource.h
│ │ ├── GreyscaleRotatedLuminanceSource.h
│ │ ├── GridSampler.h
│ │ ├── HybridBinarizer.h
│ │ ├── IllegalArgumentException.h
│ │ ├── PerspectiveTransform.h
│ │ ├── Point.h
│ │ ├── reedsolomon
│ │ │ ├── GenericGF.h
│ │ │ ├── GenericGFPoly.h
│ │ │ ├── ReedSolomonDecoder.h
│ │ │ └── ReedSolomonException.h
│ │ ├── Str.h
│ │ └── StringUtils.h
│ ├── datamatrix
│ │ ├── DataMatrixReader.h
│ │ ├── decoder
│ │ │ ├── BitMatrixParser.h
│ │ │ ├── DataBlock.h
│ │ │ ├── DecodedBitStreamParser.h
│ │ │ └── Decoder.h
│ │ ├── detector
│ │ │ ├── CornerPoint.h
│ │ │ ├── DetectorException.h
│ │ │ └── Detector.h
│ │ └── Version.h
│ ├── DecodeHints.h
│ ├── Exception.h
│ ├── FormatException.h
│ ├── IllegalStateException.h
│ ├── InvertedLuminanceSource.h
│ ├── LuminanceSource.h
│ ├── multi
│ │ ├── ByQuadrantReader.h
│ │ ├── GenericMultipleBarcodeReader.h
│ │ ├── MultipleBarcodeReader.h
│ │ └── qrcode
│ │ ├── detector
│ │ │ ├── MultiDetector.h
│ │ │ └── MultiFinderPatternFinder.h
│ │ └── QRCodeMultiReader.h
│ ├── MultiFormatReader.h
│ ├── NotFoundException.h
│ ├── oned
│ │ ├── CodaBarReader.h
│ │ ├── Code128Reader.h
│ │ ├── Code39Reader.h
│ │ ├── Code93Reader.h
│ │ ├── EAN13Reader.h
│ │ ├── EAN8Reader.h
│ │ ├── ITFReader.h
│ │ ├── MultiFormatOneDReader.h
│ │ ├── MultiFormatUPCEANReader.h
│ │ ├── OneDReader.h
│ │ ├── OneDResultPoint.h
│ │ ├── UPCAReader.h
│ │ ├── UPCEANReader.h
│ │ └── UPCEReader.h
│ ├── pdf417
│ │ ├── decoder
│ │ │ ├── BitMatrixParser.h
│ │ │ ├── DecodedBitStreamParser.h
│ │ │ ├── Decoder.h
│ │ │ └── ec
│ │ │ ├── ErrorCorrection.h
│ │ │ ├── ModulusGF.h
│ │ │ └── ModulusPoly.h
│ │ ├── detector
│ │ │ ├── Detector.h
│ │ │ └── LinesSampler.h
│ │ └── PDF417Reader.h
│ ├── qrcode
│ │ ├── decoder
│ │ │ ├── BitMatrixParser.h
│ │ │ ├── DataBlock.h
│ │ │ ├── DataMask.h
│ │ │ ├── DecodedBitStreamParser.h
│ │ │ ├── Decoder.h
│ │ │ └── Mode.h
│ │ ├── detector
│ │ │ ├── AlignmentPatternFinder.h
│ │ │ ├── AlignmentPattern.h
│ │ │ ├── Detector.h
│ │ │ ├── FinderPatternFinder.h
│ │ │ ├── FinderPattern.h
│ │ │ └── FinderPatternInfo.h
│ │ ├── ErrorCorrectionLevel.h
│ │ ├── FormatInformation.h
│ │ ├── QRCodeReader.h
│ │ └── Version.h
│ ├── ReaderException.h
│ ├── Reader.h
│ ├── Result.h
│ ├── ResultPointCallback.h
│ ├── ResultPoint.h
│ └── ZXing.h
├── lib
│ ├── libhv.a
│ ├── liblunasvg.a
│ ├── libqrcodegencpp.a
│ └── libzxing.a
├── main.cpp
├── MatSource.cpp
├── MatSource.h
├── qrcodegen.cpp
├── qrcodegen.hpp
└── stb_image_write.h
完整工程文件
|