diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index a95848c..64cb7b9 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -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> 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; diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index 8d0b467..dfbdf44 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -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> data); int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf);