#include "image_process.h" #include "../wrapper/hg_log.h" #include #include #ifndef WIN32 #include #pragma pack(push) #pragma pack(1) typedef struct BITMAPFILEHEADER { u_int16_t bfType; u_int32_t bfSize; u_int16_t bfReserved1; u_int16_t bfReserved2; u_int32_t bfOffBits; }BITMAPFILEHEADER; typedef struct BITMAPINFOHEADER { u_int32_t biSize; u_int32_t biWidth; u_int32_t biHeight; u_int16_t biPlanes; u_int16_t biBitCount; u_int32_t biCompression; u_int32_t biSizeImage; u_int32_t biXPelsPerMeter; u_int32_t biYPelsPerMeter; u_int32_t biClrUsed; u_int32_t biClrImportant; }BITMAPINFODEADER; #pragma pack(pop) #define BI_RGB 0 #define MAKEWORD(a, b) (((a) & 0x0ff) | (((b) & 0x0ff) << 8)) #define MAKELONG(a, b) (((a) & 0x0ffff) | (((b) & 0x0ffff) << 16)) #define _countof(a) (sizeof(a) / sizeof((a)[0])) #else #include #include #pragma comment(lib, "Shell32.lib") #pragma comment(lib, "hanwangOCRdetect.lib") #endif #include #include "ImageMatQueue.h" #include "../ImageProcess/ImageApplyHeaders.h" #include "ImageMultiOutput.h" #include "PaperSize.h" #ifdef WIN32 #include "scanner_manager.h" #include "ocr/hanwangOCRdetect.h" #else #include extern "C" { #include "ocr/hanwangOCRdetect.h" } #endif #include "hg_ipc.h" #include "../ImageProcess/G4Tiff.h" using namespace std; #define GET_BYTE(a) ((a) & 0x0ff) #define MAKE_INT(a, b, c, d) (GET_BYTE(a) | (GET_BYTE(b) << 8) | (GET_BYTE(c) << 16) | (GET_BYTE(d) << 24)) #define IMAGE_DATA_BUF_CVMAT (void*)MAKE_INT('M', 'T', 'R', 'X') #define IMAGE_DATA_BUF_CHAR (void*)MAKE_INT('C', 'H', 'A', 'R') ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // functional ... //////////////////////////////////////////////////////////////////////////////// // NEW£¬flow ... static int num=0; namespace hg_imgproc { class imgproc { std::string my_path_; IMGPRCPARAM param_; SCANCONF img_conf_; std::shared_ptr raw_data_; std::shared_ptr> buffer_; std::vector mats_; int pid_; Device::PaperSize papersize_; void swap_rgb(cv::Mat& mat) { unsigned char* first = (unsigned char*)mat.data, * oper = first; int line_bytes = mat.rows ? mat.total() * mat.channels() / mat.rows : mat.cols * mat.channels(); for (int i = 0; i < mat.rows; ++i) { oper = first; for (int j = 0; j < mat.cols; ++j) { unsigned char ch = oper[0]; oper[0] = oper[2]; oper[2] = ch; oper += 3; } first += line_bytes; } } // construction public: imgproc(LPSCANCONF img_param,LPIMGPRCPARAM param,int pid) : img_conf_(*img_param),param_(*param),pid_(pid),papersize_(pid_) { my_path_ = hg_log::pe_path(); } ~imgproc() {} // load data public: int load_raw_data(std::shared_ptr buff) { int ret = SCANNER_ERR_INSUFFICIENT_MEMORY; buffer_.reset(new std::vector(buff->size())); if (buffer_.get()) { unsigned int total = buff->size(), off = 0, size = total; unsigned char* mem = buff->data(off, &size); while (mem) { memcpy(buffer_->data(), mem, size); off += size; if (off >= total) { ret = SCANNER_ERR_OK; break; } size = total - off; mem = buff->data(off, &size); } } mats_.clear(); return ret; } int load_file(const char* path_file) { mats_.clear(); FILE* src = fopen(path_file, "rb"); if (!src) return SCANNER_ERR_OPEN_FILE_FAILED; long len = 0; fseek(src, 0, SEEK_END); len = ftell(src); fseek(src, 0, SEEK_SET); if (len > 1 * 1024 * 1024 * 1024) { fclose(src); return SCANNER_ERR_INSUFFICIENT_MEMORY; } raw_data_.reset(new std::string()); raw_data_->resize(len); fread(&(*raw_data_)[0], 1, len, src); fclose(src); return SCANNER_ERR_OK; } // image-processing public: int decode(int pid) { if (!buffer_) return SCANNER_ERR_NO_DATA; size_t origin = buffer_->size(); std::vector>> buffs; if(pid == 0x100 || pid == 0x200) buffs = G200Decode(buffer_,img_conf_.is_duplex,img_conf_.is_switchfrontback).getImageBuffs(); else if(pid == 0x139 || pid == 0x239) buffs = GRawDecode(buffer_).getImageBuffs(); else if(pid == 0x300 || pid == 0x400) buffs = G400Decode(buffer_,img_conf_.is_duplex).getImageBuffs(); if(buffs.empty()) return -1; buffer_.reset(new std::vector()); int i=0; for (auto& buf : buffs) { i++; cv::ImreadModes rmc = param_.channels > 1 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE; try { if (buf->at(0) == -119 && buf->at(1) == 0x50 && buf->at(2) == 0x4e && buf->at(3) == 0x47) { rmc = cv::IMREAD_GRAYSCALE; param_.black_white = true; } else param_.black_white = false; if((pid == 0x100 || pid == 0x200 || pid == 0x300 || pid == 0x400) && (img_conf_.filter != 3 || img_conf_.multiOutput == 1 || img_conf_.multiOutput == 2 || img_conf_.multiOutput == 0)) { rmc = cv::IMREAD_COLOR; } cv::Mat mat(cv::imdecode(*buf, rmc)); //("/home/huagao/Desktop/1.jpg",mat); if (mat.empty()) { LOG_INFO(LOG_LEVEL_FATAL, "decode image data error\n"); continue; } if(pid == 0x100 || pid == 0x200 || pid == 0x139 || pid == 0x239) { mats_.push_back(mat); //cv::imwrite(std::to_string(i)+"_decode.jpg",mat); } else if(pid == 0x300 || pid == 0x400) { cv::Mat back = mat(cv::Rect(0, 0, mat.cols / 2, mat.rows)); cv::Mat front = mat(cv::Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows)); if(img_conf_.is_duplex) { mats_.push_back(img_conf_.is_switchfrontback ? back :front); mats_.push_back(img_conf_.is_switchfrontback ? front :back); } else { mats_.push_back(front); } back.release(); front.release(); } //#ifndef mips64 buffer_.reset(new std::vector()); //#endif } catch (const std::exception& e) { LOG_INFO(LOG_LEVEL_FATAL, e.what()); } } buffs.clear(); VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Decode %u bytes to %u picture(s)\n", origin, mats_.size()); if(mats_.size() == 0) { return SCANNER_ERR_NO_DATA; } return SCANNER_ERR_OK; } public: int correct_text(void) { std::string sample(my_path_ + "/data/img/osd.traineddata"); CImageApplyRotation rot(CImageApplyRotation::RotationType::AutoTextOrientation, false, param_.dpi, sample.c_str()); rot.apply(mats_, img_conf_.is_duplex); return SCANNER_ERR_OK; } int split(int multioutputtype,bool is_msplit,bool is_multiout_red,int colortype,bool is_duplex,int split3399) { std::vector mats(mats_); CImageApplySplit split(multioutputtype, is_msplit, is_multiout_red, colortype);; mats_.clear(); auto matexs = split.SplitMats(mats,is_duplex); std::string filename ; int rotation01_ = 1; int rotation02_ = 1; if((pid_ == 0x139 || pid_ == 0x239 || pid_ == 0x100 || pid_ == 0x200) && (split3399 % 2 ==0) && img_conf_.is_duplex) { rotation01_ = 0; rotation02_ = 1; } for(auto &matex : matexs) { cv::flip(matex.mat,matex.mat,rotation01_); cv::flip(matex.mat,matex.mat,rotation02_); if(!matex.mat.empty()) mats_.push_back(matex.mat); } return SCANNER_ERR_OK; } int fadeback(int range,bool is_duplex) { std::vector mats(mats_); mats_.clear(); CImageApplyFadeBackGroudColor fade(100,0,range); for(size_t i = 0; i < mats.size();i++) { fade.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); // std::string filename = "/home/huagao/Desktop/fadeback("+std::to_string(num++)+").jpg"; // cv::imwrite(filename,mats_[i]); // printf("fadeback.size :%d ,filename is =%s\r\n",mats_.size(),filename.c_str()); } return SCANNER_ERR_OK; } int multi_out(void) { std::vector mats(mats_); mats_.clear(); for (size_t i = 0; i < mats.size(); ++i) { if (mats[i].empty()) continue; vector retmats; std::vector> m_multiprc_list; int multiout = 1, colormode = 1; //if (m_param.imageProcess.filter == ColorFilter::FILTER_NONE) //{ // colormode = m_param.pixelType; //} if (param_.channels > 1) m_multiprc_list.push_back(shared_ptr(new ImageMultiOutputRed(2))); m_multiprc_list.push_back(shared_ptr(new IMageMulti(multiout))); for (int j = 0; j < m_multiprc_list.size(); j++) { retmats = m_multiprc_list[j]->apply(mats[i]); } CImageApplySplit isp(multiout, false, 1, colormode); if (!retmats.size()) { std::vector matse; matse.push_back(mats[i]); auto matexs = isp.SplitMats(matse, img_conf_.is_duplex); for (auto& matex : matexs) { mats_.push_back(matex.mat); } break; } else { auto matexs = isp.SplitMats(retmats, img_conf_.is_duplex); for (auto& matex : matexs) { mats_.push_back(matex.mat); } } } return SCANNER_ERR_OK; } int multi_out(int out_type) { std::vector mats(mats_); std::vector mat; mats_.clear(); IMageMulti output(out_type); for(size_t i = 0;i < mats.size();i++) { mat = output.apply(mats[i]); for(size_t j = 0;j < mat.size();j++) { mats_.push_back(mat[j]); // std::string filename = "multi_out("+std::to_string(num++)+").jpg"; // cv::imwrite(filename,mat[j]); } } return SCANNER_ERR_OK; } int multi_out_red() { std::vector mats(mats_); std::vector mat; mats_.clear(); mat.clear(); ImageMultiOutputRed outred(2); for(size_t i = 0;i < mats.size();i++) { mat = outred.apply(mats[i]); for(size_t j = 0;j < mat.size();j++) { mats_.push_back(mat[j]); } // std::string filename = "/home/huagao/Desktop/multi_out_red("+std::to_string(num++)+").jpg"; // cv::imwrite(filename,mats_[i]); // printf("fadeback.size :%d ,filename is =%s\r\n",mats_.size(),filename.c_str()); } return SCANNER_ERR_OK; } int auto_matic_color(int color_type) { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); for(size_t i = 0;i < mats.size();i++) { CImageApplyColorRecognition ColorRecognition(color_type==1? CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray : CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono); ColorRecognition.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } /*pixtype 0 colcor; 1 gray; 2 bw*/ int auto_crop() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); SIZE temp_Size = papersize_.GetPaperSize(img_conf_.papertype,200,img_conf_.paperAlign); cv::Size cvSize(temp_Size.cx, temp_Size.cy); CImageApplyAutoCrop crop(img_conf_.is_autocrop,img_conf_.autodescrew,img_conf_.fillbackground,cvSize,img_conf_.is_convex,img_conf_.isfillcolor); crop.apply(mats,img_conf_.is_duplex); mats_ = mats; //cv::imwrite("/home/huagao/Desktop/mats_.jpg",mats_[0]); return ret; } int fillhole() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); float scale = img_conf_.fillhole.fillholeratio / 100.0; CImageApplyOutHole outh(200,scale,50); outh.apply(mats,img_conf_.is_duplex); mats_ = mats; return ret; } int resolution_change() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyResize::ResizeType resizeType; double ratio = 1.0; SIZE reSize = papersize_.GetPaperSize(img_conf_.papertype, img_conf_.resolution_dst,img_conf_.paperAlign); cv::Size cvSize(reSize.cx, reSize.cy); if (img_conf_.is_autocrop || img_conf_.cropRect.enable) { resizeType = CImageApplyResize::ResizeType::RATIO; ratio = img_conf_.resolution_dst / (float)img_conf_.resolution_native; } else resizeType = CImageApplyResize::ResizeType::DSIZE; CImageApplyResize resize(resizeType,cvSize,ratio,ratio); resize.apply(mats,img_conf_.is_duplex); if(!mats.empty()) mats_ = mats; return ret; } int croprect() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyCustomCrop rect(cv::Rect(img_conf_.cropRect.x, img_conf_.cropRect.y, img_conf_.cropRect.width, img_conf_.cropRect.height)); for (size_t i = 0; i < mats.size(); ++i) { rect.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } int channel() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyChannel chl((CImageApplyChannel::channel)(img_conf_.filter)); for (size_t i = 0; i < mats.size(); i++) { chl.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } int adjust_color(unsigned char* gamma_table = nullptr, int tableLength = 0) { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "adjust_color: table len = %d, brightness = %f, contrast = %f, gamma = %f\n", tableLength , img_conf_.brightness, img_conf_.contrast, img_conf_.gamma); if(gamma_table && tableLength) { CImageApplyCustomGamma gamme(gamma_table, tableLength); gamme.apply(mats, img_conf_.is_duplex); } else { if (img_conf_.brightness != 128 ||img_conf_.contrast != 4 || ((img_conf_.gamma < (1.0f - 1e-2)) || (img_conf_.gamma > (1.0f + 1e-2))) ) { int temp_contrast = (img_conf_.contrast - 4) * 12; CImageApplyAdjustColors justColors(img_conf_.brightness - 128, temp_contrast, img_conf_.gamma); for (size_t i = 0; i < mats.size(); ++i) { justColors.apply(mats[i],img_conf_.is_duplex); } } //cv::imwrite("/home/huagao/Desktop/customgamma2.jpg",mats_[0]); } mats_ = mats; return ret; } //防止渗�? int antiInflow(int permeate_lv) { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyRefuseInflow Inflow(permeate_lv); for (size_t i = 0; i < mats.size(); ++i) { Inflow.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } //色彩校正 int colorCorrection() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyAutoContrast con; con.apply(mats,img_conf_.is_duplex); mats_= mats; return ret; } //图像旋转 int orentation() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); mats_.resize(mats.size()); CImageApplyRotation::RotationType rotatetype = CImageApplyRotation::RotationType::Invalid; switch ((CImageApplyRotation::RotationType)img_conf_.imageRotateDegree) { case CImageApplyRotation::RotationType::Rotate_90_clockwise: rotatetype = CImageApplyRotation::RotationType::Rotate_90_clockwise; break; case CImageApplyRotation::RotationType::Rotate_180: rotatetype = CImageApplyRotation::RotationType::Rotate_180; break; case CImageApplyRotation::RotationType::Rotate_90_anti_clockwise: rotatetype = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise; break; default: break; } if (img_conf_.is_autotext) rotatetype = CImageApplyRotation::RotationType::AutoTextOrientation; #ifdef WIN32 char szIniFile[MAX_PATH] = {0}; SHGetSpecialFolderPathA(NULL, szIniFile, CSIDL_WINDOWS, TRUE); strcat(szIniFile, "\\twain_32\\HuaGoScan\\tessdata"); // m_iaList.push_back(shared_ptr(new CImageApplyRotation(rotatetype, imgparams.BackRotate180, imgparams.DestResulution, szIniFile))); #else // WIN32 CImageApplyRotation Rotation(rotatetype,img_conf_.is_backrotate180,img_conf_.resolution_native,"./tessdata"); Rotation.apply(mats,img_conf_.is_duplex); mats_ = mats; #endif return ret; } //除网? int textureRemove() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyTextureRemoval Removal; Removal.apply(mats,img_conf_.is_duplex); mats_ = mats; return ret; } //锐化 int sharpenType() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyFilter::FilterMode sharpenType = (CImageApplyFilter::FilterMode)img_conf_.sharpen; CImageApplyFilter Filte(sharpenType); for (size_t i = 0; i < mats.size(); ++i) { Filte.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } //黑白降噪 int nosieDetach() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyDetachNoise Noise(img_conf_.detachnoise.detachnoise); for (size_t i = 0; i < mats.size(); ++i) { Noise.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } //错误扩散 int errorextention() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyBWBinaray::ThresholdType thrtype; if(img_conf_.errorExtention) thrtype = CImageApplyBWBinaray::ThresholdType::ERROR_DIFFUSION; else thrtype = CImageApplyBWBinaray::ThresholdType::THRESH_BINARY; CImageApplyBWBinaray BWBinaray(thrtype); for (size_t i = 0; i < mats.size(); ++i) { BWBinaray.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } int discardBlank() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); double threshold = 40; int edge = 150; CImageApplyDiscardBlank(threshold,edge,img_conf_.discardblank_percent); for (size_t i = 0; i < mats.size(); ++i) { bool b = CImageApplyDiscardBlank::apply(mats[i]); if (b) mats[i].release(); else mats_.push_back(mats[i]); } return ret; } //答题卡出? int answerSheetFilterRed() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyHSVCorrect correct((CImageApplyHSVCorrect::Red_Removal)); for (size_t i = 0; i < mats.size(); ++i) { correct.apply(mats[i],img_conf_.is_duplex); mats_.push_back(mats[i]); } return ret; } //对折 int fold() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplyConcatenation fold(CImageApplyConcatenation::horizontal); fold.apply(mats,img_conf_.is_duplex); mats_= mats; return ret; } //画质 int quality(int dpi_dst) { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); //mats_.resize(mats.size()); float xy = (float)dpi_dst/200.0; for (size_t i = 0; i < mats.size(); ++i) { cv::Mat out; cv::resize(mats[i],out, cv::Size(),xy,xy); mats_.push_back(out); } return SCANNER_ERR_OK; } int ocr_auto_txtdirect() { int pDirect = -1; int ret = SCANNER_ERR_OK; void *pHanld = NULL; #ifndef x86_64 //linux x86_64 暂时没有OCR三方 std::vector mats(mats_); mats_.clear(); ret = HWOCR_SDKInitialize(&pHanld); for (size_t i = 0; i < mats.size(); i++) { ret = HWOCR_GetFileDirectImage(const_cast(mats[i].data),mats[i].cols,mats[i].rows,mats[i].channels()== 1 ? TColorType::EGray256:TColorType::EColor16M,pHanld,&pDirect); if(ret != 0) { return SCANNER_ERR_NO_DATA; } if(pDirect == 1) pDirect = 3; else if(pDirect == 3) pDirect = 1; CImageApplyRotation(CImageApplyRotation::RotationType(pDirect)).apply(mats[i],false); mats_.push_back(mats[i]); } HWOCR_SDKExit(pHanld); #endif return ret; } int size_detection() { int ret = SCANNER_ERR_OK; std::vector mats(mats_); mats_.clear(); CImageApplySizeDetection paper(img_conf_.papertype); for (size_t i = 0; i < mats.size(); ++i) { ret = paper.apply(mats[i]); mats_.push_back(mats[i]); } if(ret == 1) { return SCANNER_ERR_DEVICE_SIZE_CHECK; } return SCANNER_ERR_OK; } // final public: int final(void) { std::vector mats(mats_); mats_.clear(); for (size_t i = 0; i < mats.size(); ++i) { if (mats[i].empty()) continue; int bpp = param_.black_white ? 8 : param_.bits * param_.channels; MatEx out(mats[i], bpp); if (out.mat.channels() == 3) swap_rgb(out.mat); mats_.push_back(out.mat); //cv::imwrite(std::to_string(i++)+"_final.jpg",out.mat); } return SCANNER_ERR_OK; } int get_final_data(LPIMGHEAD pimh, void** buf, int index) { if ((index < 0 || index >= mats_.size())) return SCANNER_ERR_NO_DATA; pimh->width = mats_[index].cols; pimh->height = mats_[index].rows; pimh->bits = 8; //mats_[index].depth pimh->channels = mats_[index].channels(); pimh->total_bytes = mats_[index].total() * pimh->channels; pimh->line_bytes = pimh->height ? pimh->total_bytes / pimh->height : pimh->width * pimh->channels; *buf = mats_[index].data; //printf("pimh->channels = %d \r\n",pimh->channels); return SCANNER_ERR_OK; } int get_final_data(LPIMGHEAD pimh, std::vector* buf, int index) { if ((index < 0 || index >= mats_.size())) return SCANNER_ERR_NO_DATA; pimh->width = mats_[index].cols; pimh->height = mats_[index].rows; pimh->bits = 8; //mats_[index].depth pimh->channels = mats_[index].channels(); if((pimh->width * pimh->channels) % 4) { int len = pimh->width * pimh->channels; pimh->line_bytes = (len + 3) / 4 * 4; pimh->total_bytes = pimh->line_bytes * pimh->height; buf->resize(pimh->total_bytes); //printf("pimh->total_bytes=%d pimh->line_bytes=%d\r\n",pimh->total_bytes,pimh->line_bytes); unsigned char* src = mats_[index].data, *dst = buf->data(); for(int i = 0; i < pimh->height; ++i) { memcpy(dst, src, len); dst += pimh->line_bytes; src += len; } } else { pimh->total_bytes = mats_[index].total() * pimh->channels; pimh->line_bytes = pimh->height ? pimh->total_bytes / pimh->height : pimh->width * pimh->channels; buf->resize(pimh->total_bytes); memcpy(buf->data(), mats_[index].data, pimh->total_bytes); //cv::imwrite(to_string(index)+"_final.jpg",mats_[index]); } //printf("pimh->channels_01 = %d \r\n",pimh->channels); return SCANNER_ERR_OK; } int imgtypechange(std::string img_type_,void *buf,std::vector &bmpdata) { int ret = SCANNER_ERR_OK; if(!buf) { return SCANNER_ERR_NO_DATA; } cv::imencode(img_type_,*((cv::Mat*)buf),bmpdata); return ret; } }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // api ... HIMGPRC init(LPSCANCONF parameter,LPIMGPRCPARAM param,int pid) { imgproc* obj = new imgproc(parameter,param,pid); return (HIMGPRC)obj; } int load_buffer(HIMGPRC himg, std::shared_ptr buff) { return ((imgproc*)himg)->load_raw_data(buff); } int load_file(HIMGPRC himg, const char* path_file) { return ((imgproc*)himg)->load_file(path_file); } int decode(HIMGPRC himg,int pid) { return ((imgproc*)himg)->decode(pid); } int correct_text(HIMGPRC himg) { return ((imgproc*)himg)->correct_text(); } int split(HIMGPRC himg,int multioutputtype,bool is_msplit,bool is_multiout_red,int colortype,bool is_duplex,int split3399) { return ((imgproc*)himg)->split( multioutputtype, is_msplit, is_multiout_red, colortype,is_duplex,split3399); } int fadeback(HIMGPRC himg,int range,bool is_duplex) { return ((imgproc*)himg)->fadeback(range,is_duplex); } int multi_out(HIMGPRC himg) { return ((imgproc*)himg)->multi_out(); } int multi_out(HIMGPRC himg,int out_type) { return ((imgproc*)himg)->multi_out(out_type); } int multi_out_red(HIMGPRC himg) { return ((imgproc*)himg)->multi_out_red(); } int auto_matic_color(HIMGPRC himg,int color_type) { return ((imgproc*)himg)->auto_matic_color(color_type); } int auto_crop(HIMGPRC himg) { return ((imgproc*)himg)->auto_crop(); } int fillhole(HIMGPRC himg) { return ((imgproc*)himg)->fillhole(); } int resolution_change(HIMGPRC himg) { return ((imgproc*)himg)->resolution_change(); } int croprect(HIMGPRC himg) { return ((imgproc*)himg)->croprect(); } int channel(HIMGPRC himg) { return ((imgproc*)himg)->channel(); } int adjust_color(HIMGPRC himg, unsigned char* table, int tableLength) { return ((imgproc*)himg)->adjust_color(table, tableLength); } int antiInflow(HIMGPRC himg,int permeate_lv) { return ((imgproc*)himg)->antiInflow(permeate_lv); } int colorCorrection(HIMGPRC himg) { return ((imgproc*)himg)->colorCorrection(); } int orentation(HIMGPRC himg) { return ((imgproc*)himg)->orentation(); } int textureRemove(HIMGPRC himg) { return ((imgproc*)himg)->textureRemove(); } int sharpenType(HIMGPRC himg) { return ((imgproc*)himg)->sharpenType(); } int nosieDetach(HIMGPRC himg) { return ((imgproc*)himg)->nosieDetach(); } int errorextention(HIMGPRC himg) { return ((imgproc*)himg)->errorextention(); } int discardBlank(HIMGPRC himg) { return ((imgproc*)himg)->discardBlank(); } int answerSheetFilterRed(HIMGPRC himg) { return ((imgproc*)himg)->answerSheetFilterRed(); } //img_type_ = jpg png bmp int imgtypechange(HIMGPRC himg,std::string img_type_,void *buf,std::vector &bmpdata) { return ((imgproc*)himg)->imgtypechange(img_type_,buf,bmpdata); } int fold(HIMGPRC himg) { return ((imgproc*)himg)->fold(); } int quality(HIMGPRC himg,int dpi) { return ((imgproc*)himg)->quality(dpi); } int ocr_auto_txtdirect(HIMGPRC himg) { return ((imgproc*)himg)->ocr_auto_txtdirect(); } int size_detection(HIMGPRC himg) { return ((imgproc*)himg)->size_detection(); } int final(HIMGPRC himg) { return ((imgproc*)himg)->final(); } int get_final_data(HIMGPRC himg, LPIMGHEAD pimh, void** buf, int index) { return ((imgproc*)himg)->get_final_data(pimh, buf, index); } int get_final_data(HIMGPRC himg, LPIMGHEAD pimh, std::vector* buf, int index) { return ((imgproc*)himg)->get_final_data(pimh, buf, index); } void release(HIMGPRC himg) { imgproc* obj = (imgproc*)himg; delete obj; } // seperate utilites ... #include #define CV_MAT_DEPTH_SET(flags, depth) (((flags) & ~(CV_MAT_DEPTH_MASK)) | (depth & CV_MAT_DEPTH_MASK)) static cv::Mat from_bmp_file_bits(const BITMAPINFOHEADER& bih, unsigned char* data, bool tiff) { cv::Mat m; int bytes = 0, align = 0; unsigned char *dst = NULL; m.create(bih.biHeight, bih.biWidth, bih.biBitCount > 8 ? CV_8UC3 : CV_8UC1); dst = m.ptr(); bytes = (bih.biBitCount + 7) / 8; bytes *= bih.biWidth; align = (bytes + 3) / 4 * 4; if (tiff) { data += align * (bih.biHeight - 1); align *= -1; } for (int i = 0; i < bih.biHeight; ++i) { memcpy(dst, data, bytes); dst += bytes; data += align; } return m; } int convert_image_file(SANE_ImageFormatConvert* conv) { if (conv->src.fmt.img_format != SANE_IMAGE_TYPE_BMP && conv->src.fmt.compress.compression != SANE_COMPRESSION_NONE) return SCANNER_ERR_DEVICE_NOT_SUPPORT; if(conv->dst.fmt.img_format != SANE_IMAGE_TYPE_JFIF && conv->dst.fmt.img_format != SANE_IMAGE_TYPE_TIFF && conv->dst.fmt.compress.compression != SANE_COMPRESSION_NONE && conv->dst.fmt.compress.compression != SANE_COMPRESSION_GROUP4) return SCANNER_ERR_DEVICE_NOT_SUPPORT; int fh = sizeof(BITMAPFILEHEADER); BITMAPINFOHEADER bih = { 0 }; unsigned char *bits = NULL; std::shared_ptr> data; if (conv->src.is_file) { FILE* src = fopen(conv->src.data, "rb"); long len = 0; if (!src) return SCANNER_ERR_OPEN_FILE_FAILED; fseek(src, 0, SEEK_END); len = ftell(src) - fh; if (len <= 0) { fclose(src); return SCANNER_ERR_DATA_DAMAGED; } fseek(src, fh, SEEK_SET); fread(&bih, sizeof(bih), 1, src); len -= sizeof(bih); data.reset(new std::vector(len)); fread(&(*data.get())[0], 1, len, src); fclose(src); bits = data.get()->data(); } else { memcpy(&bih, conv->src.data + fh, sizeof(bih)); bits = (unsigned char*)conv->src.data + fh + sizeof(bih); } bool tiff = conv->dst.fmt.img_format == SANE_IMAGE_TYPE_TIFF; int resolution = bih.biXPelsPerMeter / 39.37f + .5f, threshold = (int)(long)conv->dst.fmt.compress.detail; cv::Mat imsg = from_bmp_file_bits(bih, data->data(), tiff); data.reset(); if (tiff) { if (bih.biBitCount == 24) { if (conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4) cvtColor(imsg, imsg, cv::COLOR_RGB2GRAY); else { for (int y = 0; y < bih.biHeight; ++y) { uint8_t* row = imsg.ptr(y); for (int x = 0; x < bih.biWidth; ++x) { uint8_t t = row[x * 3 + 0]; row[x * 3 + 0] = row[x * 3 + 2]; row[x * 3 + 2] = t; } } } } int compression = conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4 ? COMPRESSION_CCITT_T6 : COMPRESSION_NONE; if (conv->dst.is_file) { G4Tiff tiff(imsg, G4Tiff::Mode::FileMode, conv->dst.data, threshold, resolution, compression); tiff.SaveG4Tiff(); } else { G4Tiff tiff(imsg, G4Tiff::Mode::MemoryMode, "", threshold, resolution, compression); size_t bytes = 0; conv->dst.data = (SANE_String_Const)tiff.get_compressed_data(&bytes, allocate_memory); conv->dst.data_len = bytes; } } else if (conv->dst.fmt.img_format == SANE_IMAGE_TYPE_JFIF) { std::vector cpr; cpr.push_back(CV_IMWRITE_JPEG_QUALITY); cpr.push_back((int)(long)conv->dst.fmt.detail); if (conv->dst.is_file) cv::imwrite(conv->dst.data, imsg, cpr); else { std::string tmpf(hg_log::temporary_path() + PATH_SEPARATOR + "imgtrans.tmp"); cv::imwrite(tmpf.c_str(), imsg, cpr); size_t bytes = 0; conv->dst.data = (SANE_String_Const)G4Tiff::load_mini_file(tmpf.c_str(), &bytes, allocate_memory); conv->dst.data_len = bytes; remove(tmpf.c_str()); } } else if (conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4) { std::vector cmp; if (bih.biBitCount == 24) cvtColor(imsg, imsg, cv::COLOR_RGB2GRAY); if (conv->dst.is_file) { G4Tiff tiff(imsg, G4Tiff::Mode::FileMode, conv->dst.data, threshold, resolution); tiff.SaveG4Tiff(); } else { G4Tiff tiff(imsg, G4Tiff::Mode::MemoryMode, "", threshold, resolution); size_t bytes = 0; conv->dst.data = (SANE_String_Const)tiff.get_compressed_data(&bytes, allocate_memory); conv->dst.data_len = bytes; } } return SCANNER_ERR_OK; } int save_2_bmp_file(const char* bmp_file, LPIMGHEAD head, void* buf, int resolution) { BITMAPINFOHEADER bih = { 0 }; BITMAPFILEHEADER fh = { 0 }; int pal_size = 0, line_len = (head->channels * head->bits * head->width + 31) / 32 * 4; FILE *dst = fopen(bmp_file, "wb"); if (!dst) return errno; bih.biSize = sizeof(bih); bih.biWidth = head->width; bih.biBitCount = head->channels * head->bits; bih.biSizeImage = head->height * line_len; bih.biPlanes = 1; bih.biHeight = head->height; bih.biCompression = BI_RGB; bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f; if (bih.biBitCount == 1) pal_size = 2 * sizeof(int); else if (bih.biBitCount == 8) pal_size = 256 * sizeof(int); fh.bfType = MAKEWORD('B', 'M'); fh.bfSize = sizeof(fh) + bih.biSizeImage + sizeof(bih); fh.bfOffBits = sizeof(fh) + sizeof(bih) + pal_size; fwrite(&fh, sizeof(fh), 1, dst); fwrite(&bih, sizeof(bih), 1, dst); if (bih.biBitCount == 1) { int pal[] = { 0, 0x0ffffff }; fwrite(pal, sizeof(pal), 1, dst); } else if (bih.biBitCount == 8) { static unsigned int g_bmp8_pallete[256] = { 0 }; if (g_bmp8_pallete[1] == 0) { for (int i = 1; i < _countof(g_bmp8_pallete); ++i) g_bmp8_pallete[i] = MAKELONG(MAKEWORD(i, i), MAKEWORD(i, 0)); } fwrite(g_bmp8_pallete, sizeof(g_bmp8_pallete), 1, dst); } if (line_len == head->line_bytes) fwrite(buf, 1, head->total_bytes, dst); else { unsigned char* ptr = (unsigned char*)buf; unsigned int pad = 0; int pad_l = 4 - (head->line_bytes % 4), step = head->line_bytes; if (1) { ptr += head->total_bytes - head->line_bytes; step *= -1; } for (int i = 0; i < head->height; ++i) { fwrite(ptr, head->line_bytes, 1, dst); fwrite(&pad, 1, pad_l, dst); ptr += step; } } fclose(dst); return 0; } }