#pragma once #include #include #include #include #include "ImageProcess/ImageApplyHeaders.h" #include "PublicFunc.h" #include "BlockingQueue.h" #include //#include "threadpool.hpp" #include "PaperSize.h" #include "filetools.h" //创建唯一 uuid #include "snowflake.h" using namespace std; class IMat2Bmp { public: virtual ~IMat2Bmp() { if (m_data.get()) m_data.reset(); } virtual std::shared_ptr> getBmpDataBuffer() { return m_data; }; virtual void setBmpFileHeader(const cv::Mat& mat) {}; virtual void setBmpInfoHeader(const cv::Mat& mat, const long res) {}; protected: std::shared_ptr> m_data; }; class Mat2Bmp :public IMat2Bmp { public: Mat2Bmp(const cv::Mat& mat, float res) { //m_data =std::shared_ptr>(new std::vector()); //m_data.reset(new std::vector()); int headersize = mat.channels() == 3 ? 54 : 1078; 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(headersize + bmpdatasize)); if (mat.channels() == 1) { uchar colortable[256 * 4]{ 0 }; for (int i = 0; i < 256; i++) { colortable[i * 4] = colortable[i * 4 + 1] = colortable[i * 4 + 2] = i; } memcpy(m_data->data() + 54, colortable, 256 * 4); } cv::imencode(".bmp", mat, *(m_data.get())); setBmpFileHeader(mat); setBmpInfoHeader(mat, res); //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; //} } 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; infoheader->biXPelsPerMeter = infoheader->biYPelsPerMeter = static_cast(res * 39.37F + 0.5); infoheader->biClrUsed = infoheader->biClrImportant = infoheader->biBitCount == 8 ? 256 : 0; } }; class Mat2BmpBw :public IMat2Bmp { public: Mat2BmpBw(const cv::Mat& mat, float res) { m_data = std::shared_ptr>(new std::vector()); int headsize = 62; int width = mat.cols; int height = mat.rows; int bmpdatasize = (width + 31) / 32 * 4 * height; m_data->resize(headsize + bmpdatasize); unsigned char* binary = m_data->data() + 62;//file header(14)+info header(40)+RGBQUAD(8) setBmpFileHeader(mat, bmpdatasize); setBmpInfoHeader(mat, bmpdatasize, res); memcpy(m_data->data(), &m_fileHeader, sizeof(BITMAPFILEHEADER)); memcpy(m_data->data() + sizeof(BITMAPFILEHEADER), &m_infoHeader, sizeof(BITMAPINFOHEADER)); RGBQUAD* quad = (RGBQUAD*)(m_data->data() + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); 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) { *(binary + (height - row - 1) * m_lineByte + col / 8) |= temp; } else { *(binary + (height - row - 1) * m_lineByte + col / 8) &= (~temp); } } } } private: void setBmpFileHeader(const cv::Mat& mat, const int bmpDataLen) { memset(&m_fileHeader, 0, sizeof(BITMAPFILEHEADER)); m_fileHeader.bfType = ((unsigned short)('M' << 8) | 'B'); m_fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 2); int nDIBSize = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 2) + bmpDataLen; m_fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + nDIBSize; m_fileHeader.bfReserved1 = m_fileHeader.bfReserved2 = 0; } void setBmpInfoHeader(const cv::Mat& mat, const int bmpDataLen, const long res) { 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; m_infoHeader.biXPelsPerMeter = m_infoHeader.biYPelsPerMeter = static_cast(res * 39.37F + 0.5); m_infoHeader.biClrUsed = m_infoHeader.biClrImportant = 2; } private: BITMAPFILEHEADER m_fileHeader; BITMAPINFOHEADER m_infoHeader; }; class IDecode { public: virtual ~IDecode() {} virtual std::vector>> getImageBuffs() { return m_buffs; } protected: std::vector>> m_buffs; }; class G200Decode : public IDecode { public: G200Decode(std::shared_ptr> buff); virtual ~G200Decode() { } }; class G400Decode : public IDecode { public: G400Decode(std::shared_ptr> buff); virtual ~G400Decode() { } }; enum ScannerSerial { G200Serial, G400Serial }; struct CacheInfo { std::string path; ScannerSerial scannerType; }; using snowflake_t = snowflake<1534832906275L, std::mutex>; class ImageMatQueue { public: ImageMatQueue(void); ~ImageMatQueue(void); void pushMat(std::shared_ptr buf); std::shared_ptr> popBmpdata(); bool empty(); bool queuesempty(); bool valid(); bool get_isDogEar(); void reset_DogEar(); void clear(); void rawBuffsclear(); void setparam(const GScanCap& param); void run(); int orginimgcount(); void setscanflags(const bool flags) { is_scanning = flags; } void updatefixratio(float& hratio, float& vratio); void SetGetimgnumcall(std::function getimgnumcall); void SetDogEarCallback(std::function dogearcall); private: void proc(); void EnqueueBmpBuffer(std::shared_ptr>); void PaniusCount(int count = 1); void init_cachethread(); void splitimg(std::vector& mats); void duplex_process(CacheInfo info); void single_process(cv::Mat& mat); void cache_run(); void MultiOut(cv::Mat & pDid); //清除缓存文件 void clear_cachefiles(); BlockingQueue>> m_imagedata;//已处理图像队列 BlockingQueue m_imgCacheinfo;//缓存图像队列 BlockingQueue> m_rawBuffs;//原图队列 std::unique_ptr m_threadProc;//图像处理线程 std::unique_ptr m_threadcache;//缓存线程 bool ischeck_dogear; volatile int DogEar_index; volatile bool is_DogEar; atomic_bool bRun; atomic_bool benablecache; atomic_int atm_orgin_image_remains; atomic_bool is_scanning; GScanCap scanParam; Device::PaperSize papersize; std::shared_ptr m_dogear; std::shared_ptr m_colorcast; std::vector> m_iaList; //ͼÏñ´¦Àíº¯Êý½Ó¿Ú float fx, fy; std::function m_DogEarDetection_callback; std::function m_Getimagenumber; snowflake_t m_snowflake; };