2020-03-11 01:58:06 +00:00
|
|
|
#pragma once
|
|
|
|
#include <thread>
|
|
|
|
#include <mutex>
|
2021-07-02 03:29:24 +00:00
|
|
|
#include <atomic>
|
2021-08-24 10:17:32 +00:00
|
|
|
#include <opencv2/opencv.hpp>
|
2020-03-11 01:58:06 +00:00
|
|
|
#include "ImageProcess/ImageApplyHeaders.h"
|
|
|
|
#include "PublicFunc.h"
|
|
|
|
#include "BlockingQueue.h"
|
|
|
|
#include <memory>
|
2021-04-08 08:11:38 +00:00
|
|
|
//#include "threadpool.hpp"
|
2020-03-11 01:58:06 +00:00
|
|
|
#include "PaperSize.h"
|
2020-06-20 03:15:56 +00:00
|
|
|
#include "filetools.h"
|
2021-06-30 13:58:13 +00:00
|
|
|
//创建唯一 uuid
|
|
|
|
#include "snowflake.h"
|
|
|
|
|
2021-04-13 09:30:05 +00:00
|
|
|
using namespace std;
|
2020-03-11 01:58:06 +00:00
|
|
|
class IMat2Bmp {
|
|
|
|
public:
|
2021-08-09 10:42:20 +00:00
|
|
|
virtual ~IMat2Bmp() {
|
|
|
|
if (m_data.get())
|
|
|
|
m_data.reset();
|
|
|
|
}
|
2020-05-16 01:55:40 +00:00
|
|
|
virtual std::shared_ptr<std::vector<unsigned char>> getBmpDataBuffer() {
|
2020-03-11 01:58:06 +00:00
|
|
|
return m_data;
|
|
|
|
};
|
2020-05-16 01:55:40 +00:00
|
|
|
virtual void setBmpFileHeader(const cv::Mat& mat) {};
|
|
|
|
virtual void setBmpInfoHeader(const cv::Mat& mat, const long res) {};
|
2020-03-11 01:58:06 +00:00
|
|
|
protected:
|
2020-05-16 01:55:40 +00:00
|
|
|
std::shared_ptr<std::vector<unsigned char>> m_data;
|
2020-03-11 01:58:06 +00:00
|
|
|
};
|
|
|
|
|
2021-08-24 10:17:32 +00:00
|
|
|
class Mat2Bmp :public IMat2Bmp {
|
2020-03-11 01:58:06 +00:00
|
|
|
public:
|
2021-08-24 10:17:32 +00:00
|
|
|
Mat2Bmp(const cv::Mat& mat, float res) {
|
2021-08-09 10:42:20 +00:00
|
|
|
//m_data =std::shared_ptr<std::vector<unsigned char>>(new std::vector<unsigned char>());
|
2021-08-24 10:17:32 +00:00
|
|
|
//m_data.reset(new std::vector<unsigned char>());
|
2020-03-11 01:58:06 +00:00
|
|
|
int headersize = mat.channels() == 3 ? 54 : 1078;
|
2021-08-09 10:42:20 +00:00
|
|
|
int step = mat.step;
|
|
|
|
int bmpdatasize = (step + 3) / 4 * 4 * mat.rows;
|
|
|
|
int m_datalinesize = (step + 3) / 4 * 4;
|
|
|
|
int height = mat.rows;
|
|
|
|
//m_data->resize(headersize + bmpdatasize);
|
|
|
|
m_data.reset(new std::vector<unsigned char>(headersize + bmpdatasize));
|
|
|
|
if (mat.channels() == 1)
|
|
|
|
{
|
|
|
|
uchar colortable[256 * 4]{ 0 };
|
|
|
|
for (int i = 0; i < 256; i++) {
|
2021-08-24 10:17:32 +00:00
|
|
|
colortable[i * 4] = colortable[i * 4 + 1] = colortable[i * 4 + 2] = i;
|
2021-08-09 10:42:20 +00:00
|
|
|
}
|
|
|
|
memcpy(m_data->data() + 54, colortable, 256 * 4);
|
|
|
|
}
|
2021-11-20 03:09:04 +00:00
|
|
|
cv::imencode(".bmp", mat, *(m_data.get()));
|
2020-05-16 01:55:40 +00:00
|
|
|
setBmpFileHeader(mat);
|
|
|
|
setBmpInfoHeader(mat, res);
|
2021-09-23 01:19:47 +00:00
|
|
|
|
2021-11-20 03:09:04 +00:00
|
|
|
//uchar* data = m_data->data() + headersize + bmpdatasize;
|
|
|
|
//uchar* matdata = mat.data;
|
|
|
|
//for (int i = 0; i < mat.rows; i++) {
|
|
|
|
// data -= m_datalinesize;
|
|
|
|
// memcpy(data, matdata, step);
|
|
|
|
// matdata += step;
|
|
|
|
//}
|
2020-05-16 01:55:40 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
void setBmpFileHeader(const cv::Mat& mat)
|
|
|
|
{
|
|
|
|
BITMAPFILEHEADER* fileheader = (BITMAPFILEHEADER*)(m_data->data());
|
|
|
|
fileheader->bfType = ((unsigned short)('M' << 8) | 'B');
|
|
|
|
fileheader->bfSize = m_data.get()->size();
|
|
|
|
fileheader->bfReserved1 = 0;
|
|
|
|
fileheader->bfReserved2 = 0;
|
|
|
|
fileheader->bfOffBits = mat.channels() == 3 ? 54 : 1078;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setBmpInfoHeader(const cv::Mat& mat, const long res)
|
|
|
|
{
|
|
|
|
BITMAPINFOHEADER* infoheader = (BITMAPINFOHEADER*)(m_data->data() + sizeof(BITMAPFILEHEADER));
|
|
|
|
infoheader->biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
infoheader->biWidth = mat.cols;
|
|
|
|
infoheader->biHeight = mat.rows;
|
|
|
|
infoheader->biPlanes = 1;
|
|
|
|
infoheader->biBitCount = mat.channels() == 3 ? 24 : 8;
|
|
|
|
infoheader->biCompression = 0;
|
|
|
|
infoheader->biSizeImage = (int)((mat.cols * mat.channels() * 8 + 31) / 32) * 4 * mat.rows;
|
2020-04-18 03:18:06 +00:00
|
|
|
infoheader->biXPelsPerMeter = infoheader->biYPelsPerMeter = static_cast<LONG>(res * 39.37F + 0.5);
|
|
|
|
infoheader->biClrUsed = infoheader->biClrImportant = infoheader->biBitCount == 8 ? 256 : 0;
|
2020-03-11 01:58:06 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Mat2BmpBw :public IMat2Bmp {
|
|
|
|
public:
|
2021-08-24 10:17:32 +00:00
|
|
|
Mat2BmpBw(const cv::Mat& mat, float res) {
|
2020-05-16 01:55:40 +00:00
|
|
|
m_data = std::shared_ptr<std::vector<unsigned char>>(new std::vector<unsigned char >());
|
2020-03-11 01:58:06 +00:00
|
|
|
int headsize = 62;
|
|
|
|
int width = mat.cols;
|
|
|
|
int height = mat.rows;
|
2020-08-31 07:52:01 +00:00
|
|
|
int bmpdatasize = (width + 31) / 32 * 4 * height;
|
2020-05-16 01:55:40 +00:00
|
|
|
m_data->resize(headsize + bmpdatasize);
|
2020-08-31 07:52:01 +00:00
|
|
|
|
2021-08-24 10:17:32 +00:00
|
|
|
unsigned char* binary = m_data->data() + 62;//file header(14)+info header(40)+RGBQUAD(8)
|
|
|
|
setBmpFileHeader(mat, bmpdatasize);
|
2020-03-11 01:58:06 +00:00
|
|
|
setBmpInfoHeader(mat, bmpdatasize, res);
|
2020-05-16 01:55:40 +00:00
|
|
|
memcpy(m_data->data(), &m_fileHeader, sizeof(BITMAPFILEHEADER));
|
|
|
|
memcpy(m_data->data() + sizeof(BITMAPFILEHEADER), &m_infoHeader, sizeof(BITMAPINFOHEADER));
|
2021-08-24 10:17:32 +00:00
|
|
|
RGBQUAD* quad = (RGBQUAD*)(m_data->data() + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
|
2020-03-11 01:58:06 +00:00
|
|
|
quad->rgbBlue = quad->rgbGreen = quad->rgbRed = quad->rgbReserved = 0;
|
|
|
|
quad++;
|
|
|
|
quad->rgbBlue = quad->rgbGreen = quad->rgbRed = 255;
|
|
|
|
quad->rgbReserved = 0;
|
|
|
|
|
|
|
|
unsigned char* imageData = mat.data;
|
|
|
|
unsigned char temp;
|
|
|
|
int n_lineByte = (width + 7) >> 3;
|
|
|
|
int m_lineByte = ((n_lineByte * 8 + 31) >> 5) << 2;
|
|
|
|
for (int row = height - 1; row >= 0; row--)
|
|
|
|
{
|
|
|
|
for (int col = 0; col < width; col++)
|
|
|
|
{
|
|
|
|
int pos = col % 8;
|
|
|
|
int pix = *(imageData + row * mat.step1() + col);
|
|
|
|
temp = 1 << (7 - pos);
|
|
|
|
if (pix == 255)
|
|
|
|
{
|
2020-08-31 07:52:01 +00:00
|
|
|
*(binary + (height - row - 1) * m_lineByte + col / 8) |= temp;
|
2020-03-11 01:58:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(binary + (height - row - 1) * m_lineByte + col / 8) &= (~temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
2021-08-24 10:17:32 +00:00
|
|
|
void setBmpFileHeader(const cv::Mat& mat, const int bmpDataLen) {
|
2020-03-11 01:58:06 +00:00
|
|
|
memset(&m_fileHeader, 0, sizeof(BITMAPFILEHEADER));
|
|
|
|
m_fileHeader.bfType = ((unsigned short)('M' << 8) | 'B');
|
2020-08-31 07:52:01 +00:00
|
|
|
m_fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 2);
|
2020-03-11 01:58:06 +00:00
|
|
|
int nDIBSize = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 2) + bmpDataLen;
|
|
|
|
m_fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + nDIBSize;
|
2020-08-31 07:52:01 +00:00
|
|
|
m_fileHeader.bfReserved1 = m_fileHeader.bfReserved2 = 0;
|
2020-03-11 01:58:06 +00:00
|
|
|
}
|
|
|
|
|
2021-08-24 10:17:32 +00:00
|
|
|
void setBmpInfoHeader(const cv::Mat& mat, const int bmpDataLen, const long res) {
|
2020-03-11 01:58:06 +00:00
|
|
|
memset(&m_infoHeader, 0, sizeof(BITMAPINFOHEADER));
|
|
|
|
m_infoHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
m_infoHeader.biWidth = mat.cols;
|
|
|
|
m_infoHeader.biHeight = mat.rows;
|
|
|
|
m_infoHeader.biPlanes = 1;
|
|
|
|
m_infoHeader.biBitCount = 1;
|
|
|
|
m_infoHeader.biCompression = 0;
|
|
|
|
m_infoHeader.biSizeImage = bmpDataLen;
|
2020-04-18 03:18:06 +00:00
|
|
|
m_infoHeader.biXPelsPerMeter = m_infoHeader.biYPelsPerMeter = static_cast<LONG>(res * 39.37F + 0.5);
|
2020-05-16 01:55:40 +00:00
|
|
|
m_infoHeader.biClrUsed = m_infoHeader.biClrImportant = 2;
|
2020-03-11 01:58:06 +00:00
|
|
|
}
|
2021-08-24 10:17:32 +00:00
|
|
|
|
2020-03-11 01:58:06 +00:00
|
|
|
private:
|
|
|
|
BITMAPFILEHEADER m_fileHeader;
|
|
|
|
BITMAPINFOHEADER m_infoHeader;
|
|
|
|
};
|
|
|
|
|
|
|
|
class IDecode {
|
|
|
|
public:
|
|
|
|
virtual ~IDecode() {}
|
|
|
|
virtual std::vector<std::shared_ptr<std::vector<char>>> getImageBuffs() {
|
|
|
|
return m_buffs;
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
std::vector<std::shared_ptr<std::vector<char>>> m_buffs;
|
|
|
|
};
|
|
|
|
|
2021-08-24 10:17:32 +00:00
|
|
|
class G200Decode : public IDecode {
|
2020-03-11 01:58:06 +00:00
|
|
|
public:
|
|
|
|
G200Decode(std::shared_ptr<std::vector<char>> buff);
|
2021-06-30 13:58:13 +00:00
|
|
|
virtual ~G200Decode()
|
|
|
|
{
|
2021-08-24 10:17:32 +00:00
|
|
|
|
2021-06-30 13:58:13 +00:00
|
|
|
}
|
2020-03-11 01:58:06 +00:00
|
|
|
};
|
|
|
|
|
2021-01-22 07:18:41 +00:00
|
|
|
class G400Decode : public IDecode {
|
2020-03-11 01:58:06 +00:00
|
|
|
public:
|
2021-01-22 07:18:41 +00:00
|
|
|
G400Decode(std::shared_ptr<std::vector<char>> buff);
|
2021-06-30 13:58:13 +00:00
|
|
|
virtual ~G400Decode()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2020-03-11 01:58:06 +00:00
|
|
|
};
|
|
|
|
|
2021-06-30 13:58:13 +00:00
|
|
|
enum ScannerSerial
|
|
|
|
{
|
|
|
|
G200Serial,
|
|
|
|
G400Serial
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CacheInfo
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
ScannerSerial scannerType;
|
|
|
|
};
|
|
|
|
using snowflake_t = snowflake<1534832906275L, std::mutex>;
|
2020-03-11 01:58:06 +00:00
|
|
|
class ImageMatQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ImageMatQueue(void);
|
2021-06-30 13:58:13 +00:00
|
|
|
~ImageMatQueue(void);
|
2020-03-11 01:58:06 +00:00
|
|
|
|
|
|
|
void pushMat(std::shared_ptr<IDecode> buf);
|
2020-05-16 01:55:40 +00:00
|
|
|
std::shared_ptr<std::vector<unsigned char>> popBmpdata();
|
2020-03-11 01:58:06 +00:00
|
|
|
bool empty();
|
2020-06-20 03:15:56 +00:00
|
|
|
bool queuesempty();
|
2020-03-11 01:58:06 +00:00
|
|
|
bool valid();
|
2020-11-16 10:05:04 +00:00
|
|
|
bool get_isDogEar();
|
|
|
|
void reset_DogEar();
|
2020-03-11 01:58:06 +00:00
|
|
|
void clear();
|
2020-11-16 10:05:04 +00:00
|
|
|
void rawBuffsclear();
|
2020-03-11 01:58:06 +00:00
|
|
|
void setparam(const GScanCap& param);
|
|
|
|
void run();
|
|
|
|
int orginimgcount();
|
|
|
|
void setscanflags(const bool flags) { is_scanning = flags; }
|
2020-05-16 01:55:40 +00:00
|
|
|
void updatefixratio(float& hratio, float& vratio);
|
2021-08-24 10:17:32 +00:00
|
|
|
void SetGetimgnumcall(std::function<void(bool, int)> getimgnumcall);
|
2021-06-30 13:58:13 +00:00
|
|
|
void SetDogEarCallback(std::function<void(int)> dogearcall);
|
|
|
|
|
2020-03-11 01:58:06 +00:00
|
|
|
private:
|
|
|
|
void proc();
|
2020-05-16 01:55:40 +00:00
|
|
|
void EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>>);
|
2021-08-24 10:17:32 +00:00
|
|
|
void PaniusCount(int count = 1);
|
2021-06-30 13:58:13 +00:00
|
|
|
void init_cachethread();
|
2021-12-16 08:21:35 +00:00
|
|
|
void splitimg(std::vector<cv::Mat>& mats);
|
2022-06-29 12:24:24 +00:00
|
|
|
void duplex_process(CacheInfo info);
|
|
|
|
void single_process(cv::Mat& mat);
|
2021-06-30 13:58:13 +00:00
|
|
|
void cache_run();
|
2022-05-24 12:05:47 +00:00
|
|
|
void MultiOut(cv::Mat & pDid);
|
2021-06-30 13:58:13 +00:00
|
|
|
//清除缓存文件
|
|
|
|
void clear_cachefiles();
|
|
|
|
|
|
|
|
BlockingQueue<std::shared_ptr<std::vector<unsigned char>>> m_imagedata;//已处理图像队列
|
|
|
|
BlockingQueue<CacheInfo> m_imgCacheinfo;//缓存图像队列
|
|
|
|
BlockingQueue<std::shared_ptr<IDecode>> m_rawBuffs;//原图队列
|
|
|
|
std::unique_ptr<thread> m_threadProc;//图像处理线程
|
|
|
|
std::unique_ptr<thread> m_threadcache;//缓存线程
|
2020-11-16 10:05:04 +00:00
|
|
|
bool ischeck_dogear;
|
|
|
|
volatile int DogEar_index;
|
|
|
|
volatile bool is_DogEar;
|
2021-07-02 03:29:24 +00:00
|
|
|
atomic_bool bRun;
|
|
|
|
atomic_bool benablecache;
|
|
|
|
atomic_int atm_orgin_image_remains;
|
|
|
|
atomic_bool is_scanning;
|
2021-08-24 10:17:32 +00:00
|
|
|
GScanCap scanParam;
|
2020-03-11 01:58:06 +00:00
|
|
|
Device::PaperSize papersize;
|
2020-11-16 10:05:04 +00:00
|
|
|
std::shared_ptr<CImageApplyDogEarDetection> m_dogear;
|
2022-12-02 02:33:39 +00:00
|
|
|
std::shared_ptr<CImageApplyColorCastCorrect> m_colorcast;
|
2020-11-16 10:05:04 +00:00
|
|
|
std::vector<std::shared_ptr<CImageApply>> m_iaList; //ͼÏñ´¦Àíº¯Êý½Ó¿Ú
|
2020-05-16 01:55:40 +00:00
|
|
|
float fx, fy;
|
2021-06-30 13:58:13 +00:00
|
|
|
std::function<void(int)> m_DogEarDetection_callback;
|
2021-08-24 10:17:32 +00:00
|
|
|
std::function<void(bool, int)> m_Getimagenumber;
|
2021-06-30 13:58:13 +00:00
|
|
|
snowflake_t m_snowflake;
|
2020-03-17 13:04:43 +00:00
|
|
|
};
|