code_device/hgdriver/hgdev/image_process.cpp

2464 lines
66 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "image_process.h"
#include "../wrapper/hg_log.h"
#include <vector>
#include <string.h>
#if !defined(WIN32) && !defined(_WIN64)
#include <unistd.h>
#define BI_RGB 0
#define MAKEWORD(a, b) (((a) & 0x0ff) | (((b) & 0x0ff) << 8))
#define MAKELONG(a, b) (((a) & 0x0ffff) | (((b) & 0x0ffff) << 16))
#else
#include <Windows.h>
#include <shlobj.h>
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "hanwangOCRdetect.lib")
#endif
#include <memory>
#include "ImageMatQueue.h"
#include "ImageMultiOutput.h"
#include "PaperSize.h"
#include "imgproc/HGOCR.h"
#if defined(WIN32) || defined(_WIN64)
#include "scanner_manager.h"
#include "ocr/hanwangOCRdetect.h"
#else
#include <dlfcn.h>
extern "C"
{
#include "ocr/hanwangOCRdetect.h"
}
#endif
#include "hg_ipc.h"
#include "../ImageProcess/G4Tiff.h"
#include "base/HGImage.h"
#include <opencv2/imgcodecs.hpp>
#define CV_MAT_DEPTH_SET(flags, depth) (((flags) & ~(CV_MAT_DEPTH_MASK)) | (depth & CV_MAT_DEPTH_MASK))
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 ...
////////////////////////////////////////////////////////////////////////////////
//
#ifndef WIN32
#define __stdcall
#endif
#define SAFE_DELETE(p){ \
if (NULL != (p)) {delete []p; \
(p) = NULL; \
}\
}
#if defined(WIN32) || defined(_WIN64)
static int load_dll(const wchar_t* path_dll, HMODULE* dll)
{
HMODULE h = LoadLibraryW(path_dll);
int ret = GetLastError();
wchar_t info[128] = { 0 };
swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret);
OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str());
if (!h && ret == ERROR_MOD_NOT_FOUND)
{
std::wstring dir(path_dll);
size_t pos = dir.rfind(L'\\');
wchar_t path[MAX_PATH] = { 0 };
GetDllDirectoryW(_countof(path) - 1, path);
if (pos != std::wstring::npos)
dir.erase(pos);
OutputDebugStringW((L"[TWAIN]Load: try change directory to " + dir + L"\r\n").c_str());
SetDllDirectoryW(dir.c_str());
h = LoadLibraryW(path_dll);
ret = GetLastError();
swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret);
OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str());
OutputDebugStringW((L"[TWAIN]Load: restore directory to " + std::wstring(path) + L"\r\n").c_str());
SetDllDirectoryW(path);
}
if (dll)
*dll = h;
return ret;
}
static int strToWchar(string str, wchar_t* s)
{
if (str.empty() || !s)
{
return -1;
}
size_t size = str.length();
//閼惧嘲褰囩紓鎾冲暱閸栧搫銇囩亸蹇ョ礉楠炲墎鏁电拠椋庘敄闂傝揪绱濈紓鎾冲暱閸栧搫銇囩亸蹇斿瘻鐎涙顑佺拋锛勭暬
int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), size, NULL, 0);
wchar_t* buffer = new wchar_t[size + 1];
MultiByteToWideChar(CP_ACP, 0, str.c_str(), size, buffer, len);
buffer[len] = '\0';
wcscpy(s, buffer);
if (!buffer || !s)
return -1;
delete []buffer;
buffer = NULL;
return 0;
}
#endif
namespace hg_imgproc
{
typedef union
{
unsigned char ch;
struct
{
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
}bits;
}BITS;
class bit_stream
{
unsigned char* byte_stream_;
bool lsb_first_; // whether the Lowest_bit is first pop ...
int offset_;
public:
bit_stream(unsigned char* data, bool lsb_first = true) : byte_stream_(data), lsb_first_(lsb_first)
, offset_(0)
{}
~bit_stream()
{}
public:
void reset(int off = 0)
{
offset_ = off;
}
unsigned char get(void)
{
unsigned char ret = 0;
if (lsb_first_)
ret = (byte_stream_[offset_ / 8] >> (offset_ % 8)) & 1;
else
ret = (byte_stream_[offset_ / 8] >> (7 - (offset_ % 8))) & 1;
offset_++;
return ret;
}
};
typedef unsigned int (__stdcall *SDKHGImgProc_InitOCR_)(unsigned int ocrtype, void** pstOcrHandle);
typedef unsigned int (__stdcall *SDKHGImgProc_FreeImage_)(void* pstOcrHandle);
typedef unsigned int (__stdcall *SDKHGImgProc_GetTextDir_)(void* pstOcrHandle, void* image, unsigned int* pDirect);
typedef unsigned int (__stdcall *SDKHGBase_CreateImage_)(void* data, void* imageinfo, void* image);
typedef unsigned int (__stdcall *SDKHGBase_FreeImage_)(void* image);
class imgproc
{
bool isx86_Advan_ = true;
std::string my_path_;
IMGPRCPARAM param_;
SCANCONF img_conf_;
std::shared_ptr<std::string> raw_data_;
std::shared_ptr<vector<char>> buffer_;
std::vector<cv::Mat> mats_;
int pid_;
Device::PaperSize papersize_;
SANE_Image_Statu img_statu_;
SDKHGImgProc_InitOCR_ ocrinit_;
SDKHGImgProc_GetTextDir_ ocrgetdirectimage_;
SDKHGImgProc_FreeImage_ ocrexit_;
SDKHGBase_CreateImage_ HGBase_CreatImg;
SDKHGBase_FreeImage_ HGBase_FreeImg;
void* Auto_Txt_pHanld;
#ifndef WIN32
void *Dynamicopen_HGBase_pHandle_;
void *Dynamicopen_HGImageprc_pHandle_;
#else
HINSTANCE Dynamicopen_HGBase_pHandle_;
HINSTANCE Dynamicopen_HGImageprc_pHandle_;
#endif
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(int pid, bool isx86_Advan) : pid_(pid),papersize_(pid_)
, img_statu_(IMG_STATUS_OK)
, my_path_(hg_log::pe_path())
,ocrinit_(NULL),ocrgetdirectimage_(NULL)
,ocrexit_(NULL),HGBase_CreatImg(NULL)
,HGBase_FreeImg(NULL),Auto_Txt_pHanld(NULL)
,Dynamicopen_HGBase_pHandle_(NULL)
,Dynamicopen_HGImageprc_pHandle_(NULL),isx86_Advan_(isx86_Advan)
{
if(!isx86_Advan_ || hg_log::ini_get("opencv", "speed-first") == "1")
cv::setUseOptimized(isx86_Advan_);
}
~imgproc()
{
free_auto_txt_hanld();
#ifdef FREE_GLOBAL_OBJECTS
cv::unload();
#endif
}
// load data
public:
int load_raw_data(std::shared_ptr<tiny_buffer> buff)
{
int ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
buffer_.reset(new std::vector<char>(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();
img_statu_ = (SANE_Image_Statu)buff->get_image_statu();
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 init_auto_txt_hanld()
{
int ret = 0;
#ifndef WIN32
#ifdef OEM_HANWANG
string libname = "libhwdriver.so";
#elif defined(OEM_LISICHENG)
string libname = "liblscdriver.so";
#elif defined(OEM_CANGTIAN)
string libname = "libctsdriver.so";
#elif defined(OEM_ZHONGJING)
string libname = "libzjdriver.so";
#elif defined(OEM_ZIGUANG)
string libname = "libzgdriver.so";
#elif defined(OEM_DELI)
string libname = "libdldriver.so";
#elif defined(OEM_NEUTRAL)
string libname = "libneudriver.so";
#else
string libname = "libhgdriver.so";
#endif
string scanner_path = hg_log::get_module_full_path(libname.c_str());
if (scanner_path.empty())
{
return SCANNER_ERR_OUT_OF_RANGE;
}
scanner_path = scanner_path.substr(0, scanner_path.size() - libname.size());
string HGImagePrclib_path = scanner_path + IMGPRC_LIBNANE;
string HGBaselib_path = scanner_path + HGBASE_LIBNAME;
printf("get auto txt path is:%s\r\n", scanner_path.c_str());
if (access(HGBaselib_path.c_str(), F_OK) != 0 && access(HGImagePrclib_path.c_str(), F_OK) != 0)
{
return SCANNER_ERR_OUT_OF_RANGE;
}
printf("HGBaselib_path閿?s HGImagePrclib_path:%s\r\n",HGBaselib_path.c_str(),HGImagePrclib_path.c_str());
Dynamicopen_HGImageprc_pHandle_ = dlopen(HGImagePrclib_path.c_str(), RTLD_LAZY);
Dynamicopen_HGBase_pHandle_ = dlopen(HGBaselib_path.c_str(), RTLD_LAZY);
if (!Dynamicopen_HGBase_pHandle_ || !Dynamicopen_HGImageprc_pHandle_)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "auto txt open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
ocrinit_ = (SDKHGImgProc_InitOCR_)dlsym(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_CreateOCRMgr");
ocrgetdirectimage_ = (SDKHGImgProc_GetTextDir_)dlsym(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_ImageTextDirectOCR");
ocrexit_ = (SDKHGImgProc_FreeImage_)dlsym(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_DestroyOCRMgr");
HGBase_CreatImg = (SDKHGBase_CreateImage_)dlsym(Dynamicopen_HGBase_pHandle_,"HGBase_CreateImageWithData");
HGBase_FreeImg = (SDKHGBase_FreeImage_)dlsym(Dynamicopen_HGBase_pHandle_,"HGBase_DestroyImage");
#else
string scanner_path = hg_log::get_module_full_path(MODULE_NAME_SCANNER);
scanner_path = scanner_path.substr(0, scanner_path.size() - strlen(MODULE_NAME_SCANNER));
string HGImagePrclib_path = scanner_path + IMGPRC_LIBNANE;
string HGBaselib_path = scanner_path + HGBASE_LIBNAME;
wchar_t* Prclibbuffer = new wchar_t[HGImagePrclib_path.length() + 1];
wchar_t* Baselibbuffer = new wchar_t[HGBaselib_path.length() + 1];
ret = strToWchar(HGImagePrclib_path, Prclibbuffer);
if (ret == -1 )
return SCANNER_ERR_INSUFFICIENT_MEMORY;
ret = strToWchar(HGBaselib_path, Baselibbuffer);
if (ret == -1)
return SCANNER_ERR_INSUFFICIENT_MEMORY;
load_dll(Baselibbuffer, &Dynamicopen_HGBase_pHandle_); //閸忓牆濮炴潪钘夋倵闁插﹥鏂?
load_dll(Prclibbuffer, &Dynamicopen_HGImageprc_pHandle_); //windows娑撳褰查懗鎴掔窗閹靛彞绗夐崚棰佺铂閹碘偓閸︺劎娈戞笟婵婄鎼存挸顕遍懛瀵告纯閹恒儲澧﹀鈧崝銊︹偓浣哥氨閻ㄥ嫭妞傞崐娆愬娑撳秴鍩屽Ο鈥虫健
SAFE_DELETE(Prclibbuffer);
SAFE_DELETE(Baselibbuffer);
//int l = GetLastError();
if (!Dynamicopen_HGBase_pHandle_ || !Dynamicopen_HGImageprc_pHandle_)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "auto txt open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
ocrinit_ = (SDKHGImgProc_InitOCR_)GetProcAddress(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_CreateOCRMgr");
ocrgetdirectimage_ = (SDKHGImgProc_GetTextDir_)GetProcAddress(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_ImageTextDirectOCR");
ocrexit_ = (SDKHGImgProc_FreeImage_)GetProcAddress(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_DestroyOCRMgr");
HGBase_CreatImg = (SDKHGBase_CreateImage_)GetProcAddress(Dynamicopen_HGBase_pHandle_, "HGBase_CreateImageWithData");
HGBase_FreeImg = (SDKHGBase_FreeImage_)GetProcAddress(Dynamicopen_HGBase_pHandle_, "HGBase_DestroyImage");
#endif
ocrinit_(HGIMGPROC_OCRALGO_TESSERACT, &Auto_Txt_pHanld);
return ret;
}
int free_auto_txt_hanld()
{
int ret = 0;
if (Auto_Txt_pHanld)
{
int ret = ocrexit_(Auto_Txt_pHanld);
Auto_Txt_pHanld = NULL;
}
if (Dynamicopen_HGImageprc_pHandle_)
{
#if (!defined WIN32)
ret = dlclose(Dynamicopen_HGImageprc_pHandle_);
#else
ret = FreeLibrary(Dynamicopen_HGImageprc_pHandle_);
#endif
Dynamicopen_HGImageprc_pHandle_ = NULL;
}
if (Dynamicopen_HGBase_pHandle_)
{
#if (!defined WIN32)
ret = dlclose(Dynamicopen_HGBase_pHandle_);
#else
ret = FreeLibrary(Dynamicopen_HGBase_pHandle_); //鐠ㄥ奔鎶€閸旂姾娴囨い鍝勭碍娑撳秴顕敍灞肩窗鐎佃壈鍤ф潻娆庨嚋閸︾増鏌熼惃鍕劥闁夸緤绱甸敍鐕傜吹
#endif
Dynamicopen_HGBase_pHandle_ = NULL;
}
return ret;
}
int fillhole1(std::vector<cv::Mat>& v, float top, float low, float l, float r)
{
int ret = SCANNER_ERR_OK;
float scale = img_conf_.fillhole.fillholeratio / 100.0;
int dpi = img_conf_.resolution_dst;
if (!param_.is_sup_real_300dpi_ && !param_.is_sup_real_600dpi_)
{
dpi = 200;
}
else if (param_.is_sup_real_300dpi_ && !param_.is_sup_real_600dpi_)
{
if (dpi >= 300)
dpi = 300;
}
float val = dpi / 10;
cv::Vec4f edgeScale;
edgeScale[0] = top;
edgeScale[1] = low;
edgeScale[2] = l;
edgeScale[3] = r;
CImageApplyOutHole outh(val, edgeScale, 20);
outh.apply(v, true);
if (v.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int decode(int pid, LPSCANCONF img_param, LPIMGPRCPARAM param, std::map<int, setting3288dsp::FLAT_INFO_IMAGE>& correction_image_map_)
{
if (!buffer_)
return SCANNER_ERR_NO_DATA;
pid_ = pid;
img_conf_ = *img_param;
param_ = *param;
size_t origin = buffer_->size();
std::vector<std::shared_ptr<std::vector<char>>> buffs;
if(pid == 0x100 || pid == 0x200)
buffs = G200Decode(buffer_,img_conf_.is_duplex,img_conf_.is_switchfrontback).getImageBuffs();
else if(pid == 0x139 || pid == 0x239 ||pid == 0x439)
buffs = GRawDecode(buffer_).getImageBuffs();
else if(pid == 0x300 || pid == 0x400 ||pid == 0x402 || pid == 0x302)
buffs = G400Decode(buffer_,img_conf_.is_duplex).getImageBuffs();
if(buffs.empty())
return -1;
buffer_.reset(new std::vector<char >());
int i=0;
vector<cv::Mat >Temp_mat;
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|| pid == 0x402 ||pid == 0x302)
&& (img_conf_.filter != 3
|| img_conf_.multiOutput == 1
|| img_conf_.multiOutput == 2
|| img_conf_.multiOutput == 0)&& img_conf_.pixtype == COLOR_MODE_24_BITS)
{
rmc = cv::IMREAD_COLOR;
}
cv::Mat mat;
bool f = true;
if (!param_.device_7010)/////只有7010需要从设备获取校正数据
mat = cv::imdecode(*buf, rmc);
else
{
static int img_idx = 0;
cv::Mat ds(param_.height, param_.width, CV_8UC1, buf->data(), cv::Mat::AUTO_STEP);
//cv::imwrite("C:\\image\\imdecode"+std::to_string(img_idx++) + ".jpg", ds);
cv::Mat m_dst(ds(cv::Rect(0, 2, ds.cols, ds.rows - 2))); //删除前几行 一定按照实际测试来,因为最上面会有白边影响校正裁切等
cv::Mat d;
if (param_.channels == 3)
{
int mat_width = m_dst.cols / 3;
int mat_height = m_dst.rows;
d = cv::Mat(mat_width, mat_height, CV_8UC3);
std::vector<cv::Mat> m_items;
std::vector <int> list = { 0,2,1 }; //调整RGB顺序 opencv顺序是BRG
for (size_t i = 0; i < 3; i++)
{
cv::Mat t_item(m_dst(cv::Rect(mat_width * list[i], 0, mat_width, mat_height)));
m_items.push_back(t_item);
}
cv::merge(m_items, d);
mat = d.clone();
}
else
mat = m_dst.clone();
float vratio = 0.0;
float hratio = 0.0;
//cv::imwrite("C:\\image\\imdecode" + std::to_string(img_idx++) + ".jpg", mat);
int dpi = param_.dpi == 600 ? 3 : (param_.dpi < 599 && param_.dpi >= 300) ? 2 : 1;
int mode = param_.color_mode == COLOR_MODE_24_BITS ? 1 : 0;
for (auto it : correction_image_map_)
{
if (img_conf_.removeMorr && param_.dpi != 600) //除摩尔纹 使用300dpi校正数据
{
if (it.second.info.params.dpi == 2 && it.second.info.params.colormode == mode)
{
if (it.second.info.params.status != 100)
break;
vratio = it.second.vratio;
hratio = it.second.hratio;
correctColor(mat, it.second.flat_lut);
break;
}
continue;
}
if (it.second.info.params.colormode == mode && it.second.info.params.dpi == dpi)
{
if (it.second.info.params.status != 100)
{
break;
}
vratio = it.second.vratio;
hratio = it.second.hratio;
correctColor(mat, it.second.flat_lut);//校正
break;
}
}
if (!(vratio >= 0.8f && vratio <= 1.20f && hratio > 0.8f && hratio < 1.2f))
vratio = hratio = 1.0f;
if (dpi == 1 && img_conf_.removeMorr)
hratio = (200.0 / 300.0) * hratio;
if (img_conf_.removeMorr && dpi != 3)
vratio = dpi == 1 ? vratio * 0.5 : vratio * 0.75; //0.5 = 200/400 0.75= 300/400
if (img_conf_.removeMorr)
resize(mat, mat, cv::Size(0, 0), hratio, vratio, cv::InterpolationFlags::INTER_AREA);
else
resize(mat, mat, cv::Size(0, 0), hratio, vratio);
}
//cv::imwrite("C:\\image\\imdecode4.png", mat);
//cv::imwrite("C:\\image\\imdecode2.jpg",mat);
if (mat.empty())
{
LOG_INFO(LOG_LEVEL_FATAL, "decode image data error\n");
continue;
}
if (param_.cis_image)
{
Temp_mat.push_back(mat);
}
else if (pid == 0x100 || pid == 0x200 || pid == 0x139 || pid == 0x239 || pid_ == 0x439)
{
Temp_mat.push_back(mat);
//cv::imwrite("C:\\Users\\modehua\\Desktop\\image\\decode1.jpg",mat);
}
else if (pid == 0x300 || pid == 0x400 || pid == 0x402 || pid == 0x302)
{
Temp_mat.push_back(mat(cv::Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows))); //front
Temp_mat.push_back(mat(cv::Rect(0, 0, mat.cols / 2, mat.rows))); //back
}
buffer_.reset(new std::vector<char >());
}
catch (const std::exception& e)
{
LOG_INFO(LOG_LEVEL_FATAL, e.what());
throw(e);
}
}
buffs.clear();
if (Temp_mat.empty())
{
return SCANNER_ERR_NO_DATA;
}
if (pid_ == 0x100 || pid_ == 0x200 || pid_ == 0x300 || pid_ == 0x400 || pid == 0x402 || pid == 0x302)
{
double left = img_conf_.fillholeratio_left / 100.0;
double right = img_conf_.fillholeratio_right / 100.0;
double top = img_conf_.fillholeratio_up / 100.0;
double low = img_conf_.fillholeratio_down / 100.0;
if (left > 0 || right > 0 || top > 0 || low > 0)
fillhole1(Temp_mat, top, low, left, right);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Remove hole is '%s',Hole image buffer size is:%d\n", !Temp_mat.empty() ? "enable" : "close", Temp_mat.size());
if (param_.cis_image)
{
mats_ = Temp_mat;
}
else
{
if (img_conf_.is_duplex)
{
mats_.push_back(img_conf_.is_switchfrontback ? Temp_mat[1] : Temp_mat[0]);
mats_.push_back(img_conf_.is_switchfrontback ? Temp_mat[0] : Temp_mat[1]);
}
else
mats_.push_back(Temp_mat[0]);
}
if (mats_.size() % 2 == 0
&& ((CImageApplyRotation::RotationType)img_conf_.imageRotateDegree == CImageApplyRotation::RotationType::Rotate_90_clockwise
|| (CImageApplyRotation::RotationType)img_conf_.imageRotateDegree == CImageApplyRotation::RotationType::Rotate_90_anti_clockwise))
{
cv::flip(mats_[1], mats_[1], 0);
cv::flip(mats_[1], mats_[1], 1);
}
}
else
{
mats_ = Temp_mat;
}
Temp_mat.clear();
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Decode %u bytes to %u picture(s)\n", origin, mats_.size());
if (mats_.empty())
{
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);
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int split(int split3399)
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
int colormode = 1;
if (img_conf_.filter == 3)
colormode = img_conf_.pixtype;
CImageApplySplit split(img_conf_.multiOutput, img_conf_.splitImage, img_conf_.multi_output_red, colormode);
auto matexs = split.SplitMats(mats, img_conf_.is_duplex);
std::string filename ;
int rotation01_ = 1;
int rotation02_ = 1;
if(((pid_ == 0x139 || pid_ == 0x239 || pid_ == 0x439) && (split3399 % 2 ==0) && img_conf_.is_duplex ) || pid_ == 0x200 || pid_== 0x100)
{
rotation01_ = 0;
rotation02_ = 1;
}
int i = 0;
for(auto &matex : matexs)
{
cv::flip(matex.mat, matex.mat, rotation01_);
cv::flip(matex.mat,matex.mat,rotation02_);
if (i > 1 && (pid_ == 0x402 || pid_ == 0x100 || pid_ == 0x400 || pid_== 0x302 || pid_ == 0x300))
{
cv::flip(matex.mat,matex.mat,-1);
}
if(!matex.mat.empty())
mats_.push_back(matex.mat);
i++;
}
CImageApplyRotation::RotationType rotatetype = CImageApplyRotation::RotationType::Invalid;
if (pid_ == 0x402 || pid_ == 0x400 || pid_ == 0x239 || pid_ == 0x439 || pid_ == 0x302 || pid_ == 0x300)
rotatetype = CImageApplyRotation::RotationType::Rotate_90_clockwise;
else if(pid_ == 0x100)
rotatetype = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
CImageApplyRotation Rotation(rotatetype,false,img_conf_.resolution_native,"./tessdata");
Rotation.apply(mats_,img_conf_.is_duplex);
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int fadeback()
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyFadeBackGroudColor fade(20, 255, img_conf_.fadebackrange);
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());
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int multi_out(int out_type, int bw_threshold)
{
std::vector<cv::Mat> mats(mats_);
std::vector<cv::Mat> mat;
mats_.clear();
IMageMulti output(out_type, bw_threshold);
for(size_t i = 0;i < mats.size();i++)
{
mat = output.apply(mats[i]);
for(size_t j = 0;j < mat.size();j++)
{
//if (out_type != MULTI_COLOR_AND_GRAY && i == mats.size() - 1)
// mats_.push_back(convert_8bit_2_1bit(mat[j], 127, false, false));
//else
mats_.push_back(mat[j]);
// std::string filename = "multi_out("+std::to_string(num++)+").jpg";
// cv::imwrite(filename,mat[j]);
}
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int multi_out_red()
{
std::vector<cv::Mat> mats(mats_);
std::vector<cv::Mat> 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());
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int auto_matic_color(int color_type)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
/*pixtype 0 colcor; 1 gray; 2 bw*/
int auto_crop(float dpi)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
SIZE temp_Size = papersize_.GetPaperSize(img_conf_.papertype, dpi,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, 30,img_conf_.noise,img_conf_.indent);
crop.apply(mats,img_conf_.is_duplex);
mats_ = mats;
//cv::imwrite("/home/huagao/Desktop/mats_.jpg",mats_[0]);
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int dispersion()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyDispersion disp;
for (int i = 0; i < mats.size(); ++i)
{
disp.apply(mats[i], 0);
mats_.push_back(mats[i]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int fillhole(float top,float low,float l,float r)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
float scale = img_conf_.fillhole.fillholeratio / 100.0;
float val = img_conf_.resolution_dst / 10;
cv::Vec4f edgeScale;
edgeScale[0] = top;
edgeScale[1] = low;
edgeScale[2] = l;
edgeScale[3] = r;
CImageApplyOutHole outh(val, edgeScale, 20);
outh.apply(mats,img_conf_.is_duplex);
mats_ = mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int resolution_change(float dpi3288)
{
int ret = SCANNER_ERR_OK;
CImageApplyFilter::FilterMode sharpenType = CImageApplyFilter::FilterMode::None;
std::vector<cv::Mat> 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 / dpi3288;
}
else
resizeType = CImageApplyResize::ResizeType::DSIZE;
CImageApplyResize resize(resizeType,cvSize,ratio,ratio);
resize.apply(mats,img_conf_.is_duplex);
if (mats.empty())
{
return SCANNER_ERR_NO_DATA;
}
mats_ = mats;
return SCANNER_ERR_OK;
}
int croprect()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int channel()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int adjust_color(unsigned char* gamma_table = nullptr, int tableLength = 0)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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 && img_conf_.pixtype != COLOR_MODE_AUTO_MATCH)
{
CImageApplyCustomGamma gamme(gamma_table, tableLength);
gamme.apply(mats, img_conf_.is_duplex);
}
else if (pid_ != 0x0239 && pid_ != 0x439 && pid_ != 0x0139)
{
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;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int antiInflow(int permeate_lv)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyRefuseInflow Inflow(20, permeate_lv);
for (size_t i = 0; i < mats.size(); ++i)
{
Inflow.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int colorCorrection()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyAutoContrast con;
con.apply(mats,img_conf_.is_duplex);
mats_= mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int orentation()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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;
unsigned char back180 = false;
if (img_conf_.splitImage)
unsigned char back180 = false;
else
back180 = img_conf_.is_backrotate180;
CImageApplyRotation Rotation(rotatetype, back180,img_conf_.resolution_native,"./tessdata");
Rotation.apply(mats,img_conf_.is_duplex);
mats_ = mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int textureRemove()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyTextureRemoval Removal;
Removal.apply(mats,img_conf_.is_duplex);
mats_ = mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int remove_morr()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyFilter::FilterMode sharpenType = CImageApplyFilter::FilterMode::BilateralFilter;
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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int sharpenType()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int nosieDetach()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int errorextention(int bw_threshold)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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, bw_threshold);
for (size_t i = 0; i < mats.size(); ++i)
{
BWBinaray.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int discardBlank()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
double threshold = 40;
int edge = 100;
int dis = img_conf_.discardblank_percent;
if (img_conf_.is_autodiscradblank_vince)
dis *= 1.5;
CImageApplyDiscardBlank discardblank(threshold, edge, dis);
discardblank.apply(mats, mats.size());
for (size_t i = 0; i < mats.size(); ++i)
{
if (!mats[i].empty())
mats_.push_back(mats[i]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int answerSheetFilterRed()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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]);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int fold()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyConcatenation fold((CImageApplyConcatenation::ConcatMode)img_conf_.fold_concatmode, cv::Scalar(255, 255, 255));
fold.apply(mats,img_conf_.is_duplex);
mats_= mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int quality(int dpi_dst)
{
int ret = SCANNER_ERR_OK;
//std::vector<cv::Mat> 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], mats_[i], cv::Size(),xy,xy);
//mats_.push_back(out);
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int ocr_auto_txtdirect()
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
int pDirect = -1,
ret = SCANNER_ERR_OK;
void* pHanld = NULL;
typedef int (* SDKInitialize)(void** ppstOcrHandle);
typedef void(* SDKExit)(void* pstOcrHandle);
typedef int (* SDKGetFileDirectImage)(BYTE* pbImage, int nWidth, int nHeight, TColorType nColorType, void* pstHandle, int* pDirect);
SDKInitialize ocrinit = NULL;
SDKGetFileDirectImage ocrgetdirectimage = NULL;
SDKExit ocrexit = NULL;
#ifndef WIN32
#ifdef OEM_HANWANG
string libname = "libhwdriver.so";
#elif defined(OEM_LISICHENG)
string libname = "liblscdriver.so";
#else
string libname = "libhgdriver.so";
#endif
string scanner_path = hg_log::get_module_full_path(libname.c_str());
if(scanner_path.empty())
{
return SCANNER_ERR_OUT_OF_RANGE;
}
scanner_path = scanner_path.substr(0,scanner_path.size() - libname.size());
scanner_path+="libhwocrdetect.so";
printf("hwlib path:%s\r\n",scanner_path.c_str());
if(access(scanner_path.c_str(),F_OK) != 0)
{
return SCANNER_ERR_OUT_OF_RANGE;
}
#endif
#if ((!defined x86_64) && (!defined WIN32))
//linux x86_64
void *hanlde = dlopen(scanner_path.c_str(),RTLD_LAZY);
if(!hanlde)
{
return SCANNER_ERR_OUT_OF_RANGE;
}
ocrinit = (SDKInitialize)dlsym(hanlde , "HWOCR_SDKInitialize");
ocrgetdirectimage = (SDKGetFileDirectImage)dlsym(hanlde , "HWOCR_GetFileDirectImage");
ocrexit= (SDKExit)dlsym(hanlde , "HWOCR_SDKExit");
#else
#ifdef _WIN32
HINSTANCE handle = LoadLibrary(L"hanwangOCRdetect.dll");
if (handle)
{
ocrinit = (SDKInitialize)GetProcAddress(handle, "HWOCR_SDKInitialize");
ocrgetdirectimage = (SDKGetFileDirectImage)GetProcAddress(handle, "HWOCR_GetFileDirectImage");
ocrexit = (SDKExit)GetProcAddress(handle, "HWOCR_SDKExit");
}
#endif // WIN32
#endif
int r = ocrinit(&pHanld);
for (size_t i = 0; i < mats.size(); i++)
{
r = ocrgetdirectimage(const_cast<uchar*>(mats[i].data), mats[i].cols, mats[i].rows, mats[i].channels() == 1 ? TColorType::EGray256 : TColorType::EColor16M, pHanld, &pDirect);
if (pDirect == 1)
pDirect = 3;
else if (pDirect == 3)
pDirect = 1;
CImageApplyRotation(CImageApplyRotation::RotationType(pDirect)).apply(mats[i], false);
mats_.push_back(mats[i]);
}
ocrexit(pHanld);
#if ((!defined x86_64) && (!defined WIN32))
dlclose(hanlde);
#else
#endif
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int tesseract_auto_txtdirect()
{
if (!Auto_Txt_pHanld)
{
return SCANNER_ERR_NO_DATA;
}
std::vector<cv::Mat> mats(mats_);
mats_.clear();
unsigned int pDirect = 0,
ret = SCANNER_ERR_OK;
HGImage image;
if (ocrinit_ && ocrgetdirectimage_ && ocrexit_)
{
for (size_t i = 0; i < mats.size(); i++)
{
HGImage b = opencv_to_hgbase_image(mats[i]);
ret = ocrgetdirectimage_(Auto_Txt_pHanld, b, &pDirect);
HGBase_FreeImg(b);
//HGBase_DestroyImage(b);
switch (pDirect)
{
case HGIMGPROC_OCRTEXTDIRECT_ORI:
pDirect = (unsigned int)CImageApplyRotation::RotationType::Invalid;
break;
case HGIMGPROC_OCRTEXTDIRECT_RIGHT:
pDirect = (unsigned int)CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
break;
case HGIMGPROC_OCRTEXTDIRECT_LEFT:
pDirect = (unsigned int)CImageApplyRotation::RotationType::Rotate_90_clockwise;
break;
case HGIMGPROC_OCRTEXTDIRECT_180:
pDirect = (unsigned int)CImageApplyRotation::RotationType::Rotate_180;
break;
default:
pDirect = (int)CImageApplyRotation::RotationType::Invalid;
break;
}
CImageApplyRotation(CImageApplyRotation::RotationType(pDirect)).apply(mats[i], false);
mats_.push_back(mats[i]);
}
}
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return SCANNER_ERR_OK;
}
int size_detection()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> 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;
}
int cis_test_image(CISTestImageProcess::CISTestResult &res)
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
for (size_t i = 0; i < mats.size(); ++i)
{
//cv::imwrite(to_string(i) + "cis_test_image.jpg", mats[i]);
CISTestImageProcess::test(mats[i], res);
mats_.push_back(mats[i]);
//cv::imwrite("CISTestImageProcess.jpg",mats[i]);
return ret;
}
}
int color_cast_correction()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
int tmp = -1;
CImageApplyColorCastCorrect::PreScheme deviceType = (CImageApplyColorCastCorrect::PreScheme)tmp;
if (param_.device_7010)
deviceType = CImageApplyColorCastCorrect::G300_7010;
if (0x300 == pid_)
{
deviceType = CImageApplyColorCastCorrect::G300_D8;
}
else if (0x400 == pid_)
{
deviceType = CImageApplyColorCastCorrect::G400_3288;
}
else if (0x402 == pid_)
{
deviceType = CImageApplyColorCastCorrect::G400_402;
}
else if (0x302 == pid_)
{
deviceType = CImageApplyColorCastCorrect::Android302;
}
CImageApplyColorCastCorrect ColorCastCorrect(deviceType);
ColorCastCorrect.apply(mats, true);
//cv::imwrite(to_string(i) + "cis_test_image.jpg", mats[i]);
mats_ = mats;
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return ret;
//cv::imwrite("CISTestImageProcess.jpg",mats[i]);
}
int lost_frame_test()
{
if (mats_.empty())
{
return SCANNER_ERR_NO_DATA;
}
return LineContinuityDetection::isContinuous(mats_[0], 100); //妫€娴嬩竴闈㈠氨琛?
}
int correction_image(cv::Mat &flat_lut, cv::Mat black_mat, cv::Mat white_mat)
{
flat_lut = creatLUTData(black_mat, white_mat);//计算LUT 查值表
return 0;
}
HGImage opencv_to_hgbase_image(const cv::Mat& mats)
{
HGImage image;
HGImageInfo info;
info.height = mats.rows;
info.width = mats.cols;
info.origin = HGBASE_IMGORIGIN_TOP;
int bits = mats.channels() == 1 ? 8 : 24;
info.widthStep = mats.step; //opencv閸樼喎顫愰崐?
info.type = mats.channels() == 1 ? HGBASE_IMGTYPE_GRAY : HGBASE_IMGTYPE_BGR;
int ret = HGBase_CreatImg(const_cast<uchar*>(mats.data), &info, &image);
//int ret = HGBase_CreateImageWithData(const_cast<uchar*>(mats.data), &info, &image);
return image;
}
/// <summary>
/// 8娴秴娴樻潪?娴e秴娴?
/// </summary>
/// <param name="image">8bit閸?/param>
/// <param name="threshold">闂冨牆鈧》绱濆楦款唴姒涙顓?27</param>
/// <param name="reverse">true娑撳搫寮介懝璇х礉閸楁娊绮?閻?閿涙稑寮芥稊瀣╁閻?/param>
/// <param name="align">true娑撳搫娲撶€涙濡€靛綊缍?/param>
/// <returns>1娴秴娴?/returns>
///
static cv::Mat convert_8bit_2_1bit(const cv::Mat& image, uchar threshold, bool reverse, bool align)
{
if (image.channels() != 1)
return cv::Mat();
int cols = align ? (((image.cols + 7) / 8 + 3) / 4 * 4) : ((image.cols + 7) / 8);
int rows = image.rows;
uchar tableData[256];
memset(tableData, reverse ? 0 : 1, 256);
memset(tableData, reverse ? 1 : 0, threshold);
int* index_dst = new int[image.cols];
int* index_carry = new int[image.cols];
for (size_t i = 0; i < image.cols; i++)
{
index_dst[i] = i / 8;
index_carry[i] = 7 - (i % 8);
}
cv::Mat dst = cv::Mat::zeros(rows, cols, CV_8UC1);
uchar* ptr_src, * ptr_dst;
for (size_t y = 0; y < rows; y++)
{
ptr_dst = dst.ptr<uchar>(y);
ptr_src = const_cast<uchar*>(image.ptr<uchar>(y));
for (size_t x = 0; x < image.cols; x++)
ptr_dst[index_dst[x]] += tableData[ptr_src[x]] << index_carry[x];
}
delete[] index_dst;
delete[] index_carry;
return dst;
}
// final
public:
int final(void)
{
std::vector<cv::Mat> 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;
pimh->statu = img_statu_;
//printf("pimh->channels = %d \r\n",pimh->channels);
return SCANNER_ERR_OK;
}
int get_final_data(LPIMGHEAD pimh, std::vector<unsigned char>* 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->statu = img_statu_;
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<unsigned char> &bmpdata)
{
int ret = SCANNER_ERR_OK;
if(!buf)
{
return SCANNER_ERR_NO_DATA;
}
cv::imencode(img_type_,*((cv::Mat*)buf),bmpdata);
return ret;
}
void dump_2_file(const char* local_file)
{
if (mats_.size())
{
cv::imwrite(local_file, mats_[0]);
if (mats_.size() > 1)
{
std::string path(local_file), name(""), ext("");
size_t pos = path.rfind(PATH_SEPARATOR[0]);
char sn[20] = { 0 };
if (pos++ != std::string::npos)
{
name = path.substr(pos);
path.erase(pos);
pos = name.rfind('.');
if (pos != std::string::npos)
{
ext = name.substr(pos);
name.erase(pos);
}
}
for (size_t i = 1; i < mats_.size(); ++i)
{
sprintf(sn, "(%d)", i);
cv::imwrite((path + name + sn + ext).c_str(), mats_[i]);
}
}
}
else
{
LOG_INFO(LOG_LEVEL_ALL, "No image output in image_process!\n");
}
}
float gamma(float value, float ex)
{
return cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f;
}
std::vector<double> caculate(const std::vector<double>& points_x, const std::vector<double>& points_y)
{
int MaxElement = points_x.size() - 1;
//计算常数f
double f = points_y[0];
//求解
int n, m;
// double a[MaxElement][MaxElement+1];
std::vector<std::vector<double>> a;
// a.resize(MaxElement);
for (int i = 0; i < MaxElement; i++)
{
std::vector<double> b;
b.resize(MaxElement + 1);
a.push_back(b);
}
for (int i = 0; i < MaxElement; i++)
{
for (int j = 0; j < MaxElement; j++)
a[i][j] = cv::pow(points_x[i + 1], MaxElement - j);
a[i][MaxElement] = points_y[i + 1] - f;
}
int i, j;
n = MaxElement;
for (j = 0; j < n; j++)
{
double max = 0;
double imax = 0;
for (i = j; i < n; i++)
{
if (imax < cv::abs(a[i][j]))
{
imax = cv::abs(a[i][j]);
max = a[i][j]; //得到各行中所在列最大元素
m = i;
}
}
if (cv::abs(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.0)
continue;
for (int s = j; s < n + 1; 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];
}
}
std::vector<double> result;
for (int k = 0; k < n; k++)
result.push_back(a[k][n]);
result.push_back(f);
return result;
}
//设置一面的offset值
void setOffset(int* config, int step)
{
for (int i = 0; i < 6; i++)
{
int* offset = config + i;
*offset += step;
if (*offset < 0)
*offset = 1;
if (*offset > 255)
*offset = 255;
}
}
cv::Mat extractRepresentRow2(const cv::Mat& src)
{
cv::Mat BWbalenceSrc(1, src.cols * src.channels(), CV_8UC1);
cv::Mat temp_imageBW(src.rows, src.cols * src.channels(), CV_8UC1, src.data);
for (size_t i = 0; i < BWbalenceSrc.cols; i++)
BWbalenceSrc.at<unsigned char>(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0];
return BWbalenceSrc;
}
#define GAMMA_EX 1.7f
#define BLACK_OFFSET 8
void fittingLUT(const std::vector<unsigned char>& points, unsigned char min_value, unsigned char max_value, unsigned char* data)
{
float step = max_value - min_value + 1;
memset(data, min_value, 127);
memset(data + 127, max_value, 129);
int b = points[0];
int w = points[1];
int tb = min_value;
int tw = max_value;
step = (cv::max)((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f);
float temp;
for (int j = 0, length = (255 - b + 1); j < length; j++)
{
temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET;//tb + step * j;//
data[j + b] = (cv::min)(255, (cv::max)(0, static_cast<int>(temp)));
}
}
cv::Mat createLUT(const std::vector<cv::Mat>& mats, bool isTextCorrect)
{
int rows = mats[0].cols;
cv::Mat lut(rows, 256, CV_8UC1);
double max_val, min_val;
cv::minMaxIdx(mats[0], &min_val, nullptr);
cv::minMaxIdx(mats[1], nullptr, &max_val);
for (size_t i = 0; i < rows; i++)
{
std::vector<unsigned char> grayPoints;
for (size_t j = 0; j < mats.size(); j++)
grayPoints.push_back(mats[j].data[i]);
fittingLUT(grayPoints, static_cast<unsigned char>(min_val), static_cast<unsigned char>(max_val), lut.data + i * 256);
}
if (isTextCorrect)
{
std::vector<double> points_x = { 0, 25, 205, 255 }, points_y = { 0, 0, 230, 255 };
std::vector<double> coefficient = caculate(points_x, points_y);
unsigned char buffer[256];
for (int i = 0; i < 256; i++)
{
int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3];
buffer[i] = static_cast<unsigned char>((cv::min)(255, (cv::max)(0, temp)));
}
cv::Mat lut_lut(256, 1, CV_8UC1, buffer);
cv::LUT(lut, lut_lut, lut);
}
return lut;
}
#define CHANNEL 432
cv::Mat calcLUT(const cv::Mat& black, const cv::Mat& white, bool isTextCorrection)
{
static int lut_idx = 0;
std::vector<cv::Mat> w;
w.push_back(black);
w.push_back(white);
cv::Mat lut = createLUT(w, isTextCorrection);
for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++)
{
cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL));
cv::Mat tran;
cv::transpose(lutROI, tran);
memcpy(lutROI.data, tran.data, tran.total());
}
//cv::imwrite("C:\\image\\" + std::to_string(lut_idx++) + ".bmp", lut);
return lut;
}
cv::Mat loadLUT(const std::string& file)
{
cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR);
long total = dataFile.total();
int step = total / 256;
int channel = 432;
cv::Mat lut(step / channel, 256, CV_8UC(channel));
memcpy(lut.data, dataFile.data, total);
return lut;
}
void correctColor(cv::Mat& src, cv::Mat lut)
{
cv::Mat image_temp(src.rows, src.cols * src.channels() / lut.channels(), CV_8UC(lut.channels()), src.data);
for (size_t i = 0; i < image_temp.cols; i++)
cv::LUT(image_temp(cv::Rect(i, 0, 1, image_temp.rows)), lut(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows)));
}
cv::Mat creatLUTData(cv::Mat black, cv::Mat white)
{
printf("eneter creatLUTData \n");
cv::Mat lut;
cv::Mat twMat = white;// cv::imread(whitePath, colormode);
cv::Mat tbMat = black;// cv::imread(blackPath, colormode);
cv::Mat wMat, bMat;
if (black.channels() == 3 && white.channels() == 3)
{
wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data);
bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data);
}
else
{
wMat = twMat;
bMat = tbMat;
}
lut = calcLUT(bMat, wMat, true);
long total = lut.total();
int step = total / 256;
int channel = 432;
cv::Mat ret = cv::Mat::zeros(step / channel, 256, CV_8UC(channel));
memcpy(ret.data, lut.data, total);
return ret;
}
cv::Mat create_lut(const cv::Mat& black, const cv::Mat& white, int dpi, bool colormode)
{
return calcLUT(black, white, false);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// api ...
HIMGPRC init(int pid,bool isx86_Advan_)
{
imgproc* obj = new imgproc(pid, isx86_Advan_);
return (HIMGPRC)obj;
}
int load_buffer(HIMGPRC himg, std::shared_ptr<tiny_buffer> 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, LPSCANCONF img_param, LPIMGPRCPARAM param, std::map<int, setting3288dsp::FLAT_INFO_IMAGE>& correction_image_map_)
{
return ((imgproc*)himg)->decode(pid, img_param, param, correction_image_map_);
}
int init_auto_txt_hanld(HIMGPRC himg)
{
return ((imgproc*)himg)->init_auto_txt_hanld();
}
int free_auto_txt_hanld(HIMGPRC himg)
{
return ((imgproc*)himg)->free_auto_txt_hanld();
}
int correct_text(HIMGPRC himg)
{
return ((imgproc*)himg)->correct_text();
}
int split(HIMGPRC himg,int split3399)
{
return ((imgproc*)himg)->split(split3399);
}
int fadeback(HIMGPRC himg)
{
return ((imgproc*)himg)->fadeback();
}
int multi_out(HIMGPRC himg, int out_type, int bw_threshold)
{
return ((imgproc*)himg)->multi_out(out_type, bw_threshold);
}
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,float dpi)
{
return ((imgproc*)himg)->auto_crop(dpi);
}
int dispersion(HIMGPRC himg)
{
return ((imgproc*)himg)->dispersion();
}
int fillhole(HIMGPRC himg, float top, float low, float l, float r)
{
return ((imgproc*)himg)->fillhole(top, low, l,r);
}
int resolution_change(HIMGPRC himg,float dpi3288)
{
return ((imgproc*)himg)->resolution_change(dpi3288);
}
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 remove_morr(HIMGPRC himg)
{
return ((imgproc*)himg)->remove_morr();
}
int sharpenType(HIMGPRC himg)
{
return ((imgproc*)himg)->sharpenType();
}
int nosieDetach(HIMGPRC himg)
{
return ((imgproc*)himg)->nosieDetach();
}
int errorextention(HIMGPRC himg, int bw_threshold)
{
return ((imgproc*)himg)->errorextention(bw_threshold);
}
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<unsigned char> &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 tesseract_auto_txtdirect(HIMGPRC himg)
{
return ((imgproc*)himg)->tesseract_auto_txtdirect();
}
int size_detection(HIMGPRC himg)
{
return ((imgproc*)himg)->size_detection();
}
int cis_test_image(HIMGPRC himg, CISTestImageProcess::CISTestResult &res)
{
return ((imgproc*)himg)->cis_test_image(res);
}
int color_cast_correction(HIMGPRC himg)
{
return ((imgproc*)himg)->color_cast_correction();
}
int lost_frame_test(HIMGPRC himg)
{
return ((imgproc*)himg)->lost_frame_test();
return 0;
}
int final(HIMGPRC himg)
{
return ((imgproc*)himg)->final();
}
int correction_image(HIMGPRC himg, cv::Mat& flat_lut, cv::Mat black_mat, cv::Mat white_mat)
{
return ((imgproc*)himg)->correction_image(flat_lut, black_mat, white_mat);
}
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<unsigned char>* buf, int index)
{
return ((imgproc*)himg)->get_final_data(pimh, buf, index);
}
void dump_2_file(HIMGPRC himg, const char* local_file)
{
((imgproc*)himg)->dump_2_file(local_file);
}
void release(HIMGPRC himg)
{
imgproc* obj = (imgproc*)himg;
delete obj;
}
// seperate utilites ...
static cv::Mat from_bmp_file_bits(const BITMAPINFOHEADER& bih, unsigned char* data, bool line_reverse, bool bw_reverse)
{
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 * bih.biWidth + 7) / 8;
align = (bytes + 3) / 4 * 4;
if (line_reverse)
{
data += align * (bih.biHeight - 1);
align *= -1;
}
if (bih.biBitCount >= 8)
{
if (bih.biBitCount == 8 && bw_reverse)
{
for (int i = 0; i < bih.biHeight; ++i)
{
for (int j = 0; j < bytes; ++j)
dst[j] = data[j] ^ 0x0ff;
dst += bytes;
data += align;
}
}
else
{
for (int i = 0; i < bih.biHeight; ++i)
{
memcpy(dst, data, bytes);
dst += bytes;
data += align;
}
}
}
else // if (bih.biBitCount == 1)
{
unsigned char bw[] = { !bw_reverse - 1, bw_reverse - 1};
bytes = bih.biWidth;
for (int i = 0; i < bih.biHeight; ++i)
{
bit_stream bs(data, false);
for (int j = 0; j < bih.biWidth; ++j)
dst[j] = bw[bs.get()];
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<std::vector<unsigned char>> data;
if (conv->src.is_file)
{
BITMAPFILEHEADER bfh = { 0 };
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);
if (len <= fh + sizeof(bih))
{
fclose(src);
return SCANNER_ERR_DATA_DAMAGED;
}
fseek(src, 0, SEEK_SET);
fread(&bfh, sizeof(bfh), 1, src);
fread(&bih, sizeof(bih), 1, src);
if (len < bfh.bfOffBits || len < bfh.bfSize)
{
fclose(src);
return SCANNER_ERR_DATA_DAMAGED;
}
// we consider pallete as gray, discard pallete here ...
fseek(src, bfh.bfOffBits, SEEK_SET);
// len -= bfh.bfOffBits;
data.reset(new std::vector<unsigned char>(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 + ((BITMAPFILEHEADER*)conv->src.data)->bfOffBits;
}
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 || conv->dst.fmt.img_format == SANE_IMAGE_TYPE_JFIF, tiff && conv->dst.fmt.compress.compression != SANE_COMPRESSION_GROUP4);
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)
{
// MSB word[7] and word[8] are x and y resolutions
std::vector<int> cpr;
unsigned short jpeg_r = (resolution << 8) | ((resolution >> 8) & 0x0ff);
int resolution_y = bih.biYPelsPerMeter / 39.37f + .5f;
cpr.push_back(CV_IMWRITE_JPEG_QUALITY);
cpr.push_back((int)(long)conv->dst.fmt.detail);
cpr.push_back(CV_IMWRITE_JPEG_RESOLUTION_UNIT);
cpr.push_back(1);
cpr.push_back(CV_IMWRITE_JPEG_RESOLUTION_X);
cpr.push_back(resolution);
cpr.push_back(CV_IMWRITE_JPEG_RESOLUTION_Y);
cpr.push_back(resolution_y);
if (conv->dst.is_file)
{
std::string tmp(conv->dst.data);
cv::imwrite((tmp + ".jpg").c_str(), imsg, cpr);
rename((tmp + ".jpg").c_str(), tmp.c_str());
//FILE* f = fopen(conv->dst.data, "rb+");
//if (f)
//{
// fseek(f, 0x0e, SEEK_SET);
// fwrite(&jpeg_r, sizeof(jpeg_r), 1, f);
// fwrite(&jpeg_r, sizeof(jpeg_r), 1, f);
// fclose(f);
//}
}
else
{
std::string tmpf(hg_log::temporary_path() + PATH_SEPARATOR + "imgtrans.jpg");
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());
//if (conv->dst.data_len > 0x20)
// ((unsigned short*)conv->dst.data)[7] = ((unsigned short*)conv->dst.data)[8] = jpeg_r;
}
}
else if (conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4)
{
std::vector<uchar> 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.bfOffBits = sizeof(fh) + sizeof(bih) + pal_size;
fh.bfSize = fh.bfOffBits + bih.biSizeImage;
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;
}
static unsigned char reverse_bit(unsigned char v)
{
unsigned char r = 0;
for (int i = 0; i < 8; ++i)
{
r <<= 1;
r |= v & 1;
v >>= 1;
}
return r;
}
std::string bmp8_2_1bit(const unsigned char* data, int w, int h, int line_len, int threshold, bool reverse, bool align)
{
cv::Mat m;
unsigned char* dst = NULL;
m.create(h, w, CV_8UC1);
dst = m.ptr();// +w * (h - 1);
for (int i = 0; i < h; ++i)
{
memcpy(dst, data, w);
dst += w;
data += line_len;
}
cv::Mat bw = imgproc::convert_8bit_2_1bit(m, threshold, reverse, align);
//std::string ret("");
//dst = bw.ptr();
//for (int i = 0; i < bw.total(); ++i)
// dst[i] = reverse_bit(dst[i]);
return std::string((char*)bw.ptr(), bw.total());
}
}