添加黑白图像转换处理

This commit is contained in:
gb 2022-05-30 14:46:37 +08:00
parent e3d672a666
commit 0439185933
2 changed files with 86 additions and 7 deletions

View File

@ -13,6 +13,73 @@ static int ui_default_callback(scanner_handle, int, void*, unsigned int*, void*)
{
return 0;
}
static std::string bmp_821(unsigned char* bits/*bits data*/, int w, int h, int* lbytes, bool line_align_4)
{
static unsigned int g_bmp8_pallete[] = {
0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0, 0x00c0dcc0, 0x00a6caf0, 0x00402000, 0x00602000, 0x00802000, 0x00a02000, 0x00c02000, 0x00e02000
, 0x00004000, 0x00204000, 0x00404000, 0x00604000, 0x00804000, 0x00a04000, 0x00c04000, 0x00e04000, 0x00006000, 0x00206000, 0x00406000, 0x00606000, 0x00806000, 0x00a06000, 0x00c06000, 0x00e06000
, 0x00008000, 0x00208000, 0x00408000, 0x00608000, 0x00808000, 0x00a08000, 0x00c08000, 0x00e08000, 0x0000a000, 0x0020a000, 0x0040a000, 0x0060a000, 0x0080a000, 0x00a0a000, 0x00c0a000, 0x00e0a000
, 0x0000c000, 0x0020c000, 0x0040c000, 0x0060c000, 0x0080c000, 0x00a0c000, 0x00c0c000, 0x00e0c000, 0x0000e000, 0x0020e000, 0x0040e000, 0x0060e000, 0x0080e000, 0x00a0e000, 0x00c0e000, 0x00e0e000
, 0x00000040, 0x00200040, 0x00400040, 0x00600040, 0x00800040, 0x00a00040, 0x00c00040, 0x00e00040, 0x00002040, 0x00202040, 0x00402040, 0x00602040, 0x00802040, 0x00a02040, 0x00c02040, 0x00e02040
, 0x00004040, 0x00204040, 0x00404040, 0x00604040, 0x00804040, 0x00a04040, 0x00c04040, 0x00e04040, 0x00006040, 0x00206040, 0x00406040, 0x00606040, 0x00806040, 0x00a06040, 0x00c06040, 0x00e06040
, 0x00008040, 0x00208040, 0x00408040, 0x00608040, 0x00808040, 0x00a08040, 0x00c08040, 0x00e08040, 0x0000a040, 0x0020a040, 0x0040a040, 0x0060a040, 0x0080a040, 0x00a0a040, 0x00c0a040, 0x00e0a040
, 0x0000c040, 0x0020c040, 0x0040c040, 0x0060c040, 0x0080c040, 0x00a0c040, 0x00c0c040, 0x00e0c040, 0x0000e040, 0x0020e040, 0x0040e040, 0x0060e040, 0x0080e040, 0x00a0e040, 0x00c0e040, 0x00e0e040
, 0x00000080, 0x00200080, 0x00400080, 0x00600080, 0x00800080, 0x00a00080, 0x00c00080, 0x00e00080, 0x00002080, 0x00202080, 0x00402080, 0x00602080, 0x00802080, 0x00a02080, 0x00c02080, 0x00e02080
, 0x00004080, 0x00204080, 0x00404080, 0x00604080, 0x00804080, 0x00a04080, 0x00c04080, 0x00e04080, 0x00006080, 0x00206080, 0x00406080, 0x00606080, 0x00806080, 0x00a06080, 0x00c06080, 0x00e06080
, 0x00008080, 0x00208080, 0x00408080, 0x00608080, 0x00808080, 0x00a08080, 0x00c08080, 0x00e08080, 0x0000a080, 0x0020a080, 0x0040a080, 0x0060a080, 0x0080a080, 0x00a0a080, 0x00c0a080, 0x00e0a080
, 0x0000c080, 0x0020c080, 0x0040c080, 0x0060c080, 0x0080c080, 0x00a0c080, 0x00c0c080, 0x00e0c080, 0x0000e080, 0x0020e080, 0x0040e080, 0x0060e080, 0x0080e080, 0x00a0e080, 0x00c0e080, 0x00e0e080
, 0x000000c0, 0x002000c0, 0x004000c0, 0x006000c0, 0x008000c0, 0x00a000c0, 0x00c000c0, 0x00e000c0, 0x000020c0, 0x002020c0, 0x004020c0, 0x006020c0, 0x008020c0, 0x00a020c0, 0x00c020c0, 0x00e020c0
, 0x000040c0, 0x002040c0, 0x004040c0, 0x006040c0, 0x008040c0, 0x00a040c0, 0x00c040c0, 0x00e040c0, 0x000060c0, 0x002060c0, 0x004060c0, 0x006060c0, 0x008060c0, 0x00a060c0, 0x00c060c0, 0x00e060c0
, 0x000080c0, 0x002080c0, 0x004080c0, 0x006080c0, 0x008080c0, 0x00a080c0, 0x00c080c0, 0x00e080c0, 0x0000a0c0, 0x0020a0c0, 0x0040a0c0, 0x0060a0c0, 0x0080a0c0, 0x00a0a0c0, 0x00c0a0c0, 0x00e0a0c0
, 0x0000c0c0, 0x0020c0c0, 0x0040c0c0, 0x0060c0c0, 0x0080c0c0, 0x00a0c0c0, 0x00fffbf0, 0x00a0a0a4, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00, 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
};
int l = (w + 31) / 32 * 4,
size = l * h,
line_bytes = (w + 3) / 4 * 4;
std::string f("");
unsigned char* data = nullptr;
unsigned int* pallete = g_bmp8_pallete;
if (!line_align_4)
{
l = (w + 7) / 8;
size = l * h;
}
if (lbytes && *lbytes)
line_bytes = *lbytes;
f.resize(size);
data = (unsigned char*)&f[0];
for (int i = 0; i < h; ++i)
{
unsigned char v = 0,
*dst = data;
for (int j = 0; j < w; ++j)
{
v <<= 1;
unsigned char pixel = ((pallete[bits[j]] & 0x0ff) + ((pallete[bits[j]] >> 8) & 0x0ff) + ((pallete[bits[j]] >> 16) & 0x0ff)) / 3;
if (pixel >= 128)
v |= 1;
if ((j + 1) % 8 == 0)
{
*dst++ = v;
v = 0;
}
}
if (v)
{
v <<= 8 - (w % 8);
*dst++ = v;
}
data += l;
bits += line_bytes;
}
if (lbytes)
*lbytes = l;
return f;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hg_scanner
@ -1737,14 +1804,14 @@ bool hg_scanner::waiting_for_memory_enough(unsigned need_bytes)
return ret;
}
void hg_scanner::copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels)
void hg_scanner::copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels, int bits)
{
if (channels == 3)
header->format = SANE_FRAME_RGB;
else
header->format = SANE_FRAME_GRAY;
header->depth = 8; // 此处指每一个颜色分量的位深我们的扫描仪固定为“8”
header->last_frame = SANE_TRUE; // 一幅图片如果各个分量相互分离则最后一个分量的时候设置为true。彩色图像RGB时也只有一“帧”所以也为true
header->depth = bits >= 8 ? 8 : bits; // 此处指每一个颜色分量的位深我们的扫描仪固定为“8”
header->last_frame = SANE_TRUE; // 一幅图片如果各个分量相互分离则最后一个分量的时候设置为true。彩色图像RGB时也只有一“帧”所以也为true
header->pixels_per_line = w;
header->lines = h;
header->bytes_per_line = line_bytes;
@ -1778,11 +1845,23 @@ int hg_scanner::save_usb_data(std::shared_ptr<std::vector<char>> data)
}
int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
{
std::string bw("");
final_img_index_++;
if (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE)
{
int old = head->line_bytes;
bw = bmp_821((unsigned char*)buf, head->width, head->height, &head->line_bytes, async_io_);
buf = &bw[0];
head->channels = head->bits = 1;
head->total_bytes = head->line_bytes * head->height;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "convert to 1-bit bmp(%d * %d), total = %u, len = %u\n", head->width, head->height, head->total_bytes, bw.length());
}
if (async_io_)
{
SANE_Image img;
copy_to_sane_image_header(&img.header, head->width, head->height, head->line_bytes, head->channels);
copy_to_sane_image_header(&img.header, head->width, head->height, head->line_bytes, head->channels, head->bits);
img.data = (unsigned char*)buf;
img.bytes = head->total_bytes;
@ -2153,7 +2232,7 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
if (!final_imgs_.front(&imh))
ret = SCANNER_ERR_NO_DATA;
else
copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels);
copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels, imh.bits);
}
if (ret == SCANNER_ERR_NO_DATA /*&& final_img_index_ == 0*/)
@ -2162,7 +2241,7 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
ret = SCANNER_ERR_NO_DATA;
else
{
ii->depth = 8;
ii->depth = image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE ? 1 : 8;
ii->last_frame = SANE_TRUE;
ii->format = image_prc_param_.bits.color_mode == COLOR_MODE_24_BITS || image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ?
SANE_FRAME_RGB : SANE_FRAME_GRAY;

View File

@ -268,7 +268,7 @@ protected:
int notify_ui_working_status(const char* msg, int ev = SANE_EVENT_STATUS, int status = SCANNER_ERR_OK);
bool waiting_for_memory_enough(unsigned need_bytes);
void copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels);
void copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels, int bits);
int save_usb_data(std::shared_ptr<std::vector<char>> data);
int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf);