添加G402图像处理

This commit is contained in:
gb 2022-07-14 14:21:53 +08:00
parent eb50f63e64
commit 9962ac5d7d
3 changed files with 343 additions and 91 deletions

View File

@ -460,7 +460,11 @@ std::string hg_scanner_402::control_fetch(int addr, int val, int size)
data.resize(size + 2);
bzero(&data[0], size + 2);
ret = io_->read_bulk(&data[0], &l);
if (ret)
if (ret == SCANNER_ERR_OK)
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "control_fetch(%d, %d) - read_bulk %d bytes\n", addr, val, l);
}
else
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "control_fetch(%d, %d) - read_bulk = %s\n", addr, val, hg_scanner_err_name(ret));
data.clear();
@ -669,6 +673,159 @@ void hg_scanner_402::image_process(std::shared_ptr<tiny_buffer>& buff)
err = hg_imgproc::load_buffer(handle, buff);
err = hg_imgproc::decode(handle,pid_);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Image process parameter: 0x%x%08x, multi out: %s\n", ((unsigned int*)&image_prc_param_.value)[1], ((unsigned int*)&image_prc_param_.value)[0], is_multiout ? "true" : "false");
if (img_conf_.fillhole.is_fillhole)
{
err = hg_imgproc::fillhole(handle);
//printf("填穿孔开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "填穿孔开启:%s\n",hg_scanner_err_name(ret));
}
/////////////////////////////////////111111111111111111111111111//////////////////////////////////
err = hg_imgproc::auto_crop(handle);
if (img_conf_.is_autodiscradblank_normal || img_conf_.is_autodiscradblank_vince)
{
err = hg_imgproc::discardBlank(handle);
printf("丢弃空白页开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "丢弃空白页开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.fadeback)
{
hg_imgproc::fadeback(handle, img_conf_.fadebackrange, param.double_side);
//printf("背景除色开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "背景除色开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.resolution_dst != img_conf_.resolution_native)
{
hg_imgproc::resolution_change(handle);
//printf("dpi改变开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "dpi改变开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.cropRect.enable && !img_conf_.is_autocrop)
{
hg_imgproc::croprect(handle);
//printf("手动裁图开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "手动裁图开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.filter != ColorFilter::FILTER_NONE && (img_conf_.pixtype == COLOR_MODE_BLACK_WHITE || img_conf_.pixtype == COLOR_MODE_256_GRAY))
{
printf("除色开启\r\n");
hg_imgproc::channel(handle);
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "除色开启:%s\n",hg_scanner_err_name(ret));
}
/////////////////////////////////////2222222222222222222222222222222222222//////////////////////////////////
int tableLength;//= sizeof(custom_gamma_val_->table)/sizeof(custom_gamma_val_->table[0]);
unsigned char buffer1[256 * 3];
if (img_conf_.pixtype == COLOR_MODE_BLACK_WHITE || img_conf_.pixtype == COLOR_MODE_256_GRAY)
tableLength = 256;
else
{
tableLength = 768;
int index = 0;
const int buffersize = 256;
unsigned char buf_01[buffersize];
memcpy(buf_01, custom_gamma_val_->table + index, buffersize);
index += buffersize;
unsigned char buf_02[buffersize];
memcpy(buf_02, custom_gamma_val_->table + index, buffersize);
index += buffersize;
unsigned char buf_03[buffersize];
memcpy(buf_03, custom_gamma_val_->table + index, buffersize);
index += buffersize;
int j = 0;
for (size_t i = 0; i < buffersize; i++)
{
memcpy(buffer1 + j, buf_01 + i, 1);
memcpy(buffer1 + (++j), buf_02 + i, 1);
memcpy(buffer1 + (++j), buf_03 + i, 1);
++j;
}
}
hg_imgproc::customgamma(handle, custom_gamma_, buffer1, tableLength);
if (img_conf_.pixtype == COLOR_MODE_24_BITS && img_conf_.hsvcorrect)
{
hg_imgproc::answerSheetFilterRed(handle);
//printf("答题卡出红开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "答题卡出红开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.refuseInflow)
{
int lv = 5;
if (image_prc_param_.bits.is_permeate_lv_ == 0)
lv = 5;
else if (image_prc_param_.bits.is_permeate_lv_ == 1)
lv = 15;
else if (image_prc_param_.bits.is_permeate_lv_ == 2)
lv = 25;
else if (image_prc_param_.bits.is_permeate_lv_ == 3)
lv = 35;
else if (image_prc_param_.bits.is_permeate_lv_ == 4)
lv = 45;
hg_imgproc::antiInflow(handle, lv);
}
if (img_conf_.colorCorrection && img_conf_.pixtype != COLOR_MODE_BLACK_WHITE)
{
hg_imgproc::colorCorrection(handle);
//printf("颜色校正开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "颜色校正开启:%s\n",hg_scanner_err_name(ret));
}
if ((img_conf_.imageRotateDegree != TEXT_DIRECTION_0 || img_conf_.is_backrotate180) && (!img_conf_.is_autotext))
{
printf("手动旋转开启\r\n");
hg_imgproc::orentation(handle);
}
if (img_conf_.removeMorr)
{
hg_imgproc::textureRemove(handle);
//printf("除摩尔纹开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "除摩尔纹开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.detachnoise.is_detachnoise)
{
hg_imgproc::nosieDetach(handle);
//printf("噪点优化开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "噪点优化开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.pixtype == COLOR_MODE_BLACK_WHITE)
{
hg_imgproc::errorextention(handle);
//printf("黑白图处理开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "黑白图处理开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.en_fold)
{
hg_imgproc::fold(handle);
//printf("对折开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "对折开启:%s\n",hg_scanner_err_name(ret));
}
///////////////////////////////////
if (image_prc_param_.bits.rid_red && img_conf_.pixtype == COLOR_MODE_24_BITS)
{
err = hg_imgproc::multi_out_red(handle);
//printf("多流出红开启\r\n");
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "多流出红开启:%s\n",hg_scanner_err_name(ret));
}
if (img_conf_.sharpen)
{
hg_imgproc::sharpenType(handle);
}
if(image_prc_param_.bits.erase_bakground && !user_cancel_)
{
err = hg_imgproc::fadeback(handle,img_conf_.fadebackrange,img_conf_.is_duplex);
@ -781,58 +938,59 @@ int hg_scanner_402::writedown_device_configuration(HGSCANCONF *dev_conf)
int hg_scanner_402::writedown_image_configuration(void)
{
int ret = write_register(SR_CONFIF_IMGPROCPARAM, sizeof(SCANCONF));
if (ret != SCANNER_ERR_OK)
return ret;
//int ret = write_register(SR_CONFIF_IMGPROCPARAM, sizeof(SCANCONF));
//if (ret != SCANNER_ERR_OK)
// return ret;
int ret = SCANNER_ERR_OK;
SCANCONF ic;
int len = sizeof(ic);
int len = sizeof(ic);
bzero(&ic, len);
ic.papertype = paper_size_;
if (is_lateral(image_prc_param_.bits.paper))
ic.paperAlign = Rot270;
// else if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO)
// ic.paperAlign = AutoTextOrientation;
else
ic.paperAlign = Rot0;
if (is_lateral(image_prc_param_.bits.paper))
ic.paperAlign = Rot270;
// else if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO)
// ic.paperAlign = AutoTextOrientation;
else
ic.paperAlign = Rot0;
ic.en_sizecheck = dev_conf_.g200params.enable_sizecheck;
ic.en_sizecheck = dev_conf_.g200params.enable_sizecheck;
if (image_prc_param_.bits.text_direction != TEXT_DIRECTION_AUTO)
ic.imageRotateDegree = (float)image_prc_param_.bits.text_direction;
else
ic.imageRotateDegree = 0;
if (image_prc_param_.bits.text_direction != TEXT_DIRECTION_AUTO)
ic.imageRotateDegree = (float)image_prc_param_.bits.text_direction;
else
ic.imageRotateDegree = 0;
ic.imageRotateDegree *= 90.0f;
ic.imageRotateDegree *= 90.0f;
ic.is_duplex = (image_prc_param_.bits.page == PAGE_DOUBLE
|| image_prc_param_.bits.page == PAGE_OMIT_EMPTY
|| image_prc_param_.bits.page == PAGE_OMIT_EMPTY_RECEIPT
|| image_prc_param_.bits.page ==PAGE_FOLIO);
ic.is_duplex = (image_prc_param_.bits.page == PAGE_DOUBLE
|| image_prc_param_.bits.page == PAGE_OMIT_EMPTY
|| image_prc_param_.bits.page == PAGE_OMIT_EMPTY_RECEIPT
|| image_prc_param_.bits.page ==PAGE_FOLIO);
ic.en_fold = (image_prc_param_.bits.page == PAGE_FOLIO);
ic.pixtype = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? 2 : image_prc_param_.bits.color_mode;
ic.automaticcolor = is_auto_matic_color;
ic.en_fold = (image_prc_param_.bits.page == PAGE_FOLIO);
ic.pixtype = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? 2 : image_prc_param_.bits.color_mode;
ic.automaticcolor = is_auto_matic_color;
ic.automaticcolortype = 1;// ic.pixtype; //存疑
if (resolution_ >= 300)
{
if(is_quality_ == IMG_SPEED)
ic.automaticcolortype = 1;// ic.pixtype; //存疑
if (resolution_ >= 300)
{
ic.resolution_dst = 200;
if(is_quality_ == IMG_SPEED)
{
ic.resolution_dst = 200;
}
else if(is_quality_ ==IMG_QUALITY)
{
ic.resolution_dst = resolution_;
}
}
else if(is_quality_ ==IMG_QUALITY)
else
{
ic.resolution_dst = resolution_;
}
}
else
{
ic.resolution_dst = resolution_;
}
ic.resolution_native = 200.0f;
ic.gamma = (float)gamma_;
@ -956,14 +1114,14 @@ else
ic.cropRect.enable = false;
}
{
std::lock_guard<std::mutex> lock(io_lock_);
ret = io_->write_bulk(&ic, &len);
this_thread::sleep_for(chrono::milliseconds(500));
io_->set_timeout(2000);//必要延时
}
//{
// std::lock_guard<std::mutex> lock(io_lock_);
//
// ret = io_->write_bulk(&ic, &len);
//
// this_thread::sleep_for(chrono::milliseconds(500));
// io_->set_timeout(2000);//必要延时
//}
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Write-down 0x%x bytes image process parameters\n", len);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO,"\n ic.pixtype=%d", ic.pixtype);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO,"\n ic.papertype=%d", ic.papertype);
@ -1037,6 +1195,7 @@ int hg_scanner_402::read_one_image_from_usb(void)
off = 0,
ret = SCANNER_ERR_OK;
VLOG_MINI_1(LOG_LEVEL_ALL, "New image size: %u\n", total);
if (!waiting_for_memory_enough(total))
{
status_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
@ -1063,63 +1222,45 @@ int hg_scanner_402::read_one_image_from_usb(void)
r = total;
{
std::lock_guard<std::mutex> lock(io_lock_);
void* buff = buf->data(off, (unsigned int*)&r);
unsigned int size = r;
void* buff = buf->data(off, &size);
int block = 0;
if (!buff)
ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
while (buff)
{
VLOG_MINI_3(LOG_LEVEL_FATAL, "memory(0x%08x + %u) fatal when read USB image %d !!!\n", off, r, usb_img_index_);
ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
}
else
{
r = size;
while (r > 0)
{
block = 512 * 1024;
if (r < block)
block = r;
ret = io_->read_bulk(buff, &r);
if (ret != SCANNER_ERR_OK)
break;
unsigned int size = block;
void* buff = buf->data(off, &size);
if (!buf)
{
//VLOG_MINI_3(LOG_LEVEL_FATAL, "memory(0x%08x + %u) fatal when read USB image %d !!!\n", index, block, usb_img_index_);
ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
break;
}
block = size;
ret = io_->read_bulk(buff, &block);
if (ret != SCANNER_ERR_OK)
break;
off += r;
if (off >= total)
break;
off += block;
r -= block;
}
r = total - off;
buff = buf->data(off, (unsigned int*)&r);
}
}
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Read image from USB = %s\n", hg_scanner_err_name(ret));
if (ret == SCANNER_ERR_OK)
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Read image from USB = %s\n", hg_scanner_err_name(ret));
ret = save_usb_data(buf);
if (ret == SCANNER_ERR_OK)
{
pop_first_image();
//if(image_prc_param_.bits.page == PAGE_SINGLE)
// pop_first_image();
}
else
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "save usb data failed: %s\n", hg_scanner_err_name(ret));
}
}
else
{
char msg[128];
sprintf(msg, "Read image data from USB err: %s\n", hg_scanner_err_name(ret));
LOG_INFO(LOG_LEVEL_DEBUG_INFO, msg);
notify_ui_working_status(msg);
notify_ui_working_status(STATU_DESC_SCANNER_ERR_TIMEOUT, SANE_EVENT_ERROR);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Read image data from USB err: %s\n", hg_scanner_err_name(ret));
}
}
else
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "write command SR_IM_TX failed: %s\n", hg_scanner_err_name(ret));
}
}
return ret;
@ -1428,8 +1569,8 @@ void hg_scanner_402::thread_handle_usb_read(void)
ret = io_->read_interrupt(buf, &size);
io_->set_timeout(1000);
}
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "read-INT = %s: From(%d), Code(%d), Index(%d)\n", hg_scanner_err_name(ret),
info->From, info->Code, info->Img_Index);
VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "read-INT = %s: From(%d), Code(%d), Index(%d), size = %d\n", hg_scanner_err_name(ret),
info->From, info->Code, info->Img_Index, size);
if (ret != SCANNER_ERR_OK)
{
if (ret == SCANNER_ERR_TIMEOUT)
@ -1437,11 +1578,13 @@ void hg_scanner_402::thread_handle_usb_read(void)
if (to_cnt++ < 30)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if ((get_status() & 0x03) == 0)
{
status_ = SCANNER_ERR_OK;
break;
}
//int statu = get_status();
//if ((statu & 0x03) == 0)
//{
// VLOG_MINI_1(LOG_LEVEL_FATAL, "USB thread over with status: 0x%x\n", statu);
// status_ = SCANNER_ERR_OK;
// break;
//}
continue;
}
}
@ -1459,6 +1602,10 @@ void hg_scanner_402::thread_handle_usb_read(void)
{
read_one_image_from_usb();
}
else
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "receive IMG event but no image count(%d)!", get_image_count());
}
break;
case V4L2:
VLOG_MINI_1(LOG_LEVEL_FATAL, "V4L2 error: %d\n", info->Code);
@ -1469,9 +1616,35 @@ void hg_scanner_402::thread_handle_usb_read(void)
go = false;
}
break;
case STOPSCAN:
go = false;
LOG_INFO(LOG_LEVEL_ALL, "Received STOPSCAN event ...\n");
std::this_thread::sleep_for(std::chrono::milliseconds(500));
{
std::lock_guard<std::mutex> lock(io_lock_);
size = sizeof(buf);
ret = io_->read_interrupt(buf, &size);
io_->set_timeout(1000);
if (ret == SCANNER_ERR_OK && info->From == IMG)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (get_image_count() > 0)
{
read_one_image_from_usb();
}
else
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "receive IMG event but no image count(%d) after STOPSCAN!", get_image_count());
}
}
}
break;
default:
break;
}
if (!go)
break;
}
else
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "read %d bytes, sizeof(buf) = %d\n", size, sizeof(buf));
@ -1502,6 +1675,7 @@ int hg_scanner_402::start(void)
get_roller_num();
notify_ui_working_status(STATU_DESC_REWRITE_CONFIGURATION);
writedown_device_configuration();
writedown_image_configuration();
ret = read_register(/*SR_GET_ANDROID_STATE*/0x1001, &val);
if (val)
{
@ -1514,6 +1688,7 @@ int hg_scanner_402::start(void)
else
ret = status_ = SCANNER_ERR_IO;
VLOG_MINI_1(LOG_LEVEL_WARNING, "SR_GET_ANDROID_STATE result: %s\n", hg_scanner_err_name(ret));
return ret;
}
write_register(0x1000, scan_count_);

View File

@ -5,6 +5,8 @@
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#pragma pack(push)
#pragma pack(1)
typedef struct BITMAPFILEHEADER
{
u_int16_t bfType;
@ -28,6 +30,11 @@ typedef struct BITMAPINFOHEADER
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 <Windows.h>
#include <shlobj.h>
@ -611,7 +618,7 @@ namespace hg_imgproc
#endif
return ret;
}
//除网<EFBFBD>?
//除网�
int textureRemove()
{
int ret = SCANNER_ERR_OK;
@ -701,7 +708,7 @@ namespace hg_imgproc
}
return ret;
}
//答题卡出<EFBFBD>?
//答题å<EFBFBD>¡å‡ºï¿?
int answerSheetFilterRed()
{
int ret = SCANNER_ERR_OK;
@ -1199,7 +1206,76 @@ namespace hg_imgproc
}
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;
}
}

View File

@ -214,4 +214,5 @@ namespace hg_imgproc
// seperate utilites ...
int convert_image_file(SANE_ImageFormatConvert* conv);
int save_2_bmp_file(const char* bmp_file, LPIMGHEAD head, void* buf, int resolution);
}