添加图像压缩算法
This commit is contained in:
parent
a040422b7b
commit
a0461ff354
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"img-fmt": {
|
||||
"cat": "imgp",
|
||||
"group": "output",
|
||||
"title": "图片格式",
|
||||
"desc": "设备输出的图片文件格式",
|
||||
"type": "string",
|
||||
"ver": 1,
|
||||
"pos": 9900,
|
||||
"ui-pos": 10,
|
||||
"auth": 0,
|
||||
"visible": 0,
|
||||
"size": 16,
|
||||
"cur": "JPEG",
|
||||
"default": "JPEG",
|
||||
"range": ["JPEG", "PNG", "BMP"]
|
||||
},
|
||||
"jpeg-quality": {
|
||||
"cat": "imgp",
|
||||
"group": "output",
|
||||
"title": "JPEG质量",
|
||||
"desc": "设置JPEG压缩质量,质量越高,压缩率越低",
|
||||
"type": "int",
|
||||
"ver": 1,
|
||||
"pos": 9901,
|
||||
"ui-pos": 11,
|
||||
"auth": 0,
|
||||
"affect": 4,
|
||||
"unit": "%",
|
||||
"visible": 0,
|
||||
"size": 4,
|
||||
"cur": 100,
|
||||
"default": 100,
|
||||
"range": {
|
||||
"min": 10,
|
||||
"max": 100,
|
||||
"step": 1
|
||||
},
|
||||
"depend": "img-fmt==JPEG"
|
||||
}
|
||||
}
|
|
@ -382,14 +382,14 @@ void scanner_hw::thread_image_capture(bool paper_ready)
|
|||
scanstream.err = 0;
|
||||
devui::send_message(devui::UI_STATUS_SCANNING, (uint8_t*)&scanstream, sizeof(scanstream));
|
||||
while(scanning_) // auto scan cycle ...
|
||||
{
|
||||
// scanning ONE turn ...
|
||||
if(paper_ready) // auto_scan_ ignore no paper
|
||||
{
|
||||
err = start_and_wait_lifter(to_lifter_, &over_msg_id);
|
||||
if(err)
|
||||
break;
|
||||
|
||||
// scanning ONE turn ...
|
||||
if(paper_ready) // auto_scan_ ignore no paper
|
||||
{
|
||||
motor_->pick_paper();
|
||||
err = scan_one_turn(&img, &avail_mem, &used_v4l2_mem, &over_msg_id);
|
||||
if(err || !auto_scan_ || !scanning_)
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
#include "image_encoder.h"
|
||||
|
||||
#include <huagao/hgscanner_error.h>
|
||||
#include <sane/sane_ex.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// img_encoder
|
||||
static std::string device_opt_json[] = {
|
||||
"{\"img-fmt\":{\"cat\":\"imgp\",\"group\":\"output\",\"title\":\"\\u56fe\\u7247\\u683c\\u5f0f\",\"desc\":\"\\u8bbe\\u5907\\u8f93\\u51fa\\u7684\\u56fe\\u7247\\u6587\\u4ef6\\u683c\\u5f0f\",\"type\":\"string\",\"ver\":1,\"pos\":9900,\"ui-pos\":10,\"auth\":0,\"visible\":0,\"size\":16,\"cur\":\"JPEG\",\"default\":\"JPEG\",\"range\":[\"JPEG\",\"PNG\",\"BMP\"]},\"jpeg-quality\":{\"cat\":\"imgp\",\"group\":\"output\",\"title\":\"JPEG\\u8d28\\u91cf\",\"desc\":\"\\u8bbe\\u7f6eJPEG\\u538b\\u7f29\\u8d28\\u91cf\\uff0c\\u8d28\\u91cf\\u8d8a\\u9ad8\\uff0c\\u538b\\u7f29\\u7387\\u8d8a\\u4f4e\",\"type\":\"int\",\"ver\":1,\"pos\":9901,\"ui-pos\":11,\"auth\":0,\"affect\":4,\"unit\":\"%\",\"visible\":0,\"size\":4,\"cur\":100,\"default\":100,\"range\":{\"min\":10,\"max\":100,\"step\":1},\"depend\":\"img-fmt==JPEG\"}}"
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// img_encoder
|
||||
img_encoder::img_encoder() : image_processor("img_encoder")
|
||||
{
|
||||
ADD_THIS_JSON();
|
||||
// if (!bwimg)
|
||||
// {
|
||||
// compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||||
// compression_params.push_back(100);
|
||||
// }
|
||||
// else{
|
||||
// compression_params.push_back(CV_IMWRITE_PNG_STRATEGY);
|
||||
// compression_params.push_back(cv::IMWRITE_PNG_STRATEGY_FIXED);
|
||||
// }
|
||||
param_.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||||
param_.push_back(jpeg_quality_);
|
||||
}
|
||||
img_encoder::~img_encoder()
|
||||
{}
|
||||
|
||||
int img_encoder::set_value(const char* name, void* val)
|
||||
{
|
||||
int ret = SCANNER_ERR_OK;
|
||||
|
||||
if(strcmp(name, SANE_OPT_NAME(OUT_FORMAT)) == 0)
|
||||
{
|
||||
fmt_ = (char*)val;
|
||||
if(fmt_ == "JPEG")
|
||||
{
|
||||
fmt_ = ".jpg";
|
||||
|
||||
param_.clear();
|
||||
param_.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||||
param_.push_back(jpeg_quality_);
|
||||
}
|
||||
else if(fmt_ == "PNG")
|
||||
{
|
||||
fmt_ = ".png";
|
||||
|
||||
param_.clear();
|
||||
param_.push_back(CV_IMWRITE_PNG_STRATEGY);
|
||||
param_.push_back(cv::IMWRITE_PNG_STRATEGY_FIXED);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt_ = ".bmp";
|
||||
param_.clear();
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, SANE_OPT_NAME(JPEG_QUALITY)) == 0)
|
||||
{
|
||||
jpeg_quality_ = *(int*)val;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
int img_encoder::process(std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out)
|
||||
{
|
||||
for(auto& v: in)
|
||||
{
|
||||
v.info.prc_stage = get_position();
|
||||
v.info.prc_time = 0;
|
||||
|
||||
out.push_back(v);
|
||||
}
|
||||
|
||||
return SCANNER_ERR_OK;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<uchar>> img_encoder::encode(LPPACKIMAGE head, cv::Mat& mat)
|
||||
{
|
||||
std::shared_ptr<std::vector<uchar>> ptr;
|
||||
chronograph watch;
|
||||
|
||||
head->prc_stage = get_position();
|
||||
if(fmt_ == ".bmp")
|
||||
{
|
||||
size_t size = mat.total() * mat.channels();
|
||||
ptr.reset(new std::vector<uchar>(size));
|
||||
memcpy(ptr->data(), mat.data, size);
|
||||
head->prc_time = watch.elapse_ms();
|
||||
head->format = IMG_FMT_BMP;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr.reset(new std::vector<uchar>());
|
||||
head->format = fmt_ == ".jpg" ? IMG_FMT_JPEG : IMG_FMT_PNG;
|
||||
cv::imencode(fmt_.c_str(), mat, *ptr, param_);
|
||||
head->prc_time = watch.elapse_ms();
|
||||
printf("encode to '%s' in %ums: %u\n", fmt_.c_str(), head->prc_time, ptr->size());
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// encoder bmp to given format
|
||||
//
|
||||
// Date: 2024-02-26
|
||||
#pragma once
|
||||
|
||||
#include <imgprc/img_processor.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class img_encoder : public image_processor
|
||||
{
|
||||
std::string fmt_ = ".jpg";
|
||||
int jpeg_quality_ = 100;
|
||||
std::vector<int> param_;
|
||||
|
||||
public:
|
||||
img_encoder();
|
||||
|
||||
protected:
|
||||
~img_encoder();
|
||||
|
||||
public:
|
||||
virtual int set_value(const char* name/*nullptr for all options*/, void* val/*nullptr for restore*/) override;
|
||||
|
||||
public:
|
||||
virtual int process(std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out) override;
|
||||
|
||||
public:
|
||||
std::shared_ptr<std::vector<uchar>> encode(LPPACKIMAGE head, cv::Mat& mat);
|
||||
};
|
|
@ -10,6 +10,7 @@
|
|||
#include "./algs/auto_crop.h"
|
||||
#include "./algs/color_correct.h"
|
||||
#include "./algs/ImageProcess_Public.h"
|
||||
#include "./algs/image_encoder.h"
|
||||
|
||||
|
||||
|
||||
|
@ -54,7 +55,11 @@ imgproc_mgr::imgproc_mgr(std::function<void(data_source_ptr)> sender
|
|||
else
|
||||
opts_ = new device_option(true);
|
||||
load_processor(nullptr);
|
||||
rebuild_.reset(new rebuild());
|
||||
first_.reset(new rebuild());
|
||||
last_.reset(new img_encoder());
|
||||
|
||||
opts_->add(first_.get());
|
||||
opts_->add(last_.get());
|
||||
|
||||
auto thrd = [&](void) -> void
|
||||
{
|
||||
|
@ -96,12 +101,6 @@ data_source_ptr imgproc_mgr::scan_finished_packet(uint32_t scanid, uint32_t err)
|
|||
|
||||
return reply;
|
||||
}
|
||||
image_packet_ptr imgproc_mgr::image_sent_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid, void* info, size_t info_l)
|
||||
{
|
||||
image_packet_ptr pimg = new image_packet(head, img, scanid, info, info_l);
|
||||
|
||||
return pimg;
|
||||
}
|
||||
|
||||
uint32_t imgproc_mgr::add_busy_worker(int inc)
|
||||
{
|
||||
|
@ -148,7 +147,7 @@ void imgproc_mgr::process(RAWIMG* img)
|
|||
|
||||
if(do_rebuild_)
|
||||
{
|
||||
rebuild_->do_rebuild(&img->info, img->data->ptr(), in);
|
||||
first_->do_rebuild(&img->info, img->data->ptr(), in);
|
||||
utils::to_log(LOG_LEVEL_ALL, "Rebuild paper %d spend %llu milliseconds.\n", img->info.pos.paper_ind, watch.elapse_ms());
|
||||
}
|
||||
else
|
||||
|
@ -161,12 +160,15 @@ void imgproc_mgr::process(RAWIMG* img)
|
|||
|
||||
if(dump_img_)
|
||||
{
|
||||
send_image(&img->info, img->data->ptr(), img->info.width * img->info.height);
|
||||
{
|
||||
cv::Mat mat(img->info.width, img->info.height, CV_8UC1, img->data->ptr());
|
||||
send_image(&img->info, mat);
|
||||
}
|
||||
img->data->release();
|
||||
|
||||
for(auto& v: processors_)
|
||||
{
|
||||
send_image(*src, false);
|
||||
send_image(*src);
|
||||
if(v->is_enable())
|
||||
{
|
||||
process(v, src, dst);
|
||||
|
@ -196,7 +198,7 @@ void imgproc_mgr::process(RAWIMG* img)
|
|||
v.info.prc_time = t;
|
||||
}
|
||||
|
||||
send_image(*src, true);
|
||||
send_image(*src);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -234,7 +236,7 @@ void imgproc_mgr::process(image_processor* prc, std::vector<PROCIMGINFO>* in, st
|
|||
throw(exception_ex(msg.c_str()));
|
||||
}
|
||||
}
|
||||
void imgproc_mgr::send_image(LPPACKIMAGE head, uint8_t* data, size_t size, void* info, size_t info_l)
|
||||
void imgproc_mgr::send_image(LPPACKIMAGE head, cv::Mat& mat, void* info, size_t info_l)
|
||||
{
|
||||
auto ovr = [&](uint64_t total, uint64_t cur_size, uint32_t err, void* user_data) -> int
|
||||
{
|
||||
|
@ -244,31 +246,18 @@ void imgproc_mgr::send_image(LPPACKIMAGE head, uint8_t* data, size_t size, void*
|
|||
return 0;
|
||||
};
|
||||
|
||||
dyn_mem_ptr mem(dyn_mem::memory(size));
|
||||
image_packet_ptr ptr = nullptr;
|
||||
PACKIMAGE h(*head);
|
||||
std::shared_ptr<std::vector<uchar>> compd(last_->encode(&h, mat));
|
||||
image_packet_ptr ptr = new image_packet(&h, compd, scan_id_, info, info_l);
|
||||
|
||||
// mem->set_progress_notify(ovr, mem);
|
||||
mem->put(data, size);
|
||||
ptr = imgproc_mgr::image_sent_packet(head, mem, scan_id_, info, info_l);
|
||||
// ptr->set_progress_notify(ovr, ptr);
|
||||
// printf("+dyn_mem(%p)\n+image_packet(%p)\n", mem, ptr);
|
||||
|
||||
mem->release();
|
||||
ptr->set_session_id(session_id_);
|
||||
img_sender_(ptr);
|
||||
ptr->release();
|
||||
}
|
||||
void imgproc_mgr::send_image(std::vector<PROCIMGINFO>& imgs, bool clear_after_send)
|
||||
void imgproc_mgr::send_image(std::vector<PROCIMGINFO>& imgs)
|
||||
{
|
||||
for(auto& v: imgs)
|
||||
{
|
||||
if(clear_after_send)
|
||||
v.info.prc_stage = -1;
|
||||
send_image(&v.info, v.img.ptr(), v.img.total() * v.img.channels()
|
||||
, v.ext_info.empty() ? nullptr : &v.ext_info[0], v.ext_info.length());
|
||||
// if(clear_after_send)
|
||||
// v.img.release();
|
||||
}
|
||||
send_image(&v.info, v.img, v.ext_info.empty() ? nullptr : &v.ext_info[0], v.ext_info.length());
|
||||
}
|
||||
|
||||
int imgproc_mgr::set_value(const char* name, void* val)
|
||||
|
@ -317,6 +306,7 @@ int imgproc_mgr::load_processor(const char* path)
|
|||
ADD_IMG_PROCESSOR(stretch);
|
||||
ADD_IMG_PROCESSOR(auto_crop);
|
||||
ADD_IMG_PROCESSOR(color_correct);
|
||||
// ADD_IMG_PROCESSOR(img_encoder);
|
||||
|
||||
std::sort(processors_.begin(), processors_.end(), &imgproc_mgr::sort_processor_by_pos);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ typedef std::shared_ptr<std::vector<char>> dcptr;
|
|||
|
||||
class device_option;
|
||||
class rebuild;
|
||||
class img_encoder;
|
||||
|
||||
class imgproc_mgr : public sane_opt_provider
|
||||
{
|
||||
|
@ -27,7 +28,8 @@ class imgproc_mgr : public sane_opt_provider
|
|||
bool img;
|
||||
}RAWIMG;
|
||||
|
||||
refer_guard<rebuild> rebuild_;
|
||||
refer_guard<rebuild> first_;
|
||||
refer_guard<img_encoder> last_;
|
||||
image_processor* stretcher_ = nullptr;
|
||||
bool do_rebuild_ = true;
|
||||
volatile bool run_ = true;
|
||||
|
@ -48,14 +50,13 @@ class imgproc_mgr : public sane_opt_provider
|
|||
static bool sort_processor_by_pos(image_processor* l, image_processor* r);
|
||||
static bool sort_image_packet(image_packet_ptr l, image_packet_ptr r);
|
||||
static data_source_ptr scan_finished_packet(uint32_t scanid, uint32_t err = 0);
|
||||
static image_packet_ptr image_sent_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid, void* info = nullptr, size_t info_l = 0);
|
||||
|
||||
uint32_t add_busy_worker(int inc = 1);
|
||||
void thread_worker(void);
|
||||
void process(RAWIMG* img);
|
||||
void process(image_processor* prc, std::vector<PROCIMGINFO>* in, std::vector<PROCIMGINFO>* out);
|
||||
void send_image(LPPACKIMAGE head, uint8_t* data, size_t size, void* info = nullptr, size_t info_l = 0);
|
||||
void send_image(std::vector<PROCIMGINFO>& imgs, bool clear_after_send);
|
||||
void send_image(LPPACKIMAGE head, cv::Mat& mat, void* info = nullptr, size_t info_l = 0);
|
||||
void send_image(std::vector<PROCIMGINFO>& imgs);
|
||||
|
||||
public:
|
||||
imgproc_mgr(std::function<void(data_source_ptr)> sender, device_option* devopts, CHK_RES_FUNC res = CHK_RES_FUNC());
|
||||
|
|
|
@ -928,7 +928,8 @@ uint8_t* file_map::buffer(void)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// image_packet
|
||||
image_packet::image_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid
|
||||
image_packet::image_packet(LPPACKIMAGE head, std::shared_ptr<std::vector<uchar>> img
|
||||
, uint32_t scanid
|
||||
, const void* info, size_t info_size)
|
||||
: img_(img), offset_(0), info_over_(false)
|
||||
{
|
||||
|
@ -936,7 +937,6 @@ image_packet::image_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid
|
|||
LPPACKIMAGE pimg = nullptr;
|
||||
|
||||
paper_ind_ = head->pos.paper_ind;
|
||||
img->add_ref();
|
||||
if(info && info_size)
|
||||
info_ = std::string((const char*)info, info_size);
|
||||
else
|
||||
|
@ -949,7 +949,7 @@ image_packet::image_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid
|
|||
pack->payload_len = sizeof(PACKIMAGE);
|
||||
|
||||
memcpy(pimg, head, sizeof(*pimg));
|
||||
pimg->data_size = img->get_rest();
|
||||
pimg->data_size = img->size();
|
||||
pimg->info_size = info_size;
|
||||
|
||||
head_->set_len(sizeof(PACK_BASE) + sizeof(PACKIMAGE));
|
||||
|
@ -970,7 +970,6 @@ image_packet::image_packet(LPPACKIMAGE head, dyn_mem_ptr img, uint32_t scanid
|
|||
image_packet::~image_packet()
|
||||
{
|
||||
head_->release();
|
||||
img_->release();
|
||||
}
|
||||
|
||||
bool image_packet::is_memory_block(void)
|
||||
|
@ -979,7 +978,7 @@ bool image_packet::is_memory_block(void)
|
|||
}
|
||||
uint32_t image_packet::get_rest(void)
|
||||
{
|
||||
return head_->get_rest() + info_.length() + img_->get_rest() - offset_;
|
||||
return head_->get_rest() + info_.length() + img_->size() - offset_;
|
||||
}
|
||||
|
||||
// following API valid when is_memory_block() return true
|
||||
|
@ -1023,15 +1022,15 @@ int image_packet::fetch_data(void* buf, uint32_t* size)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(*size + offset_ >= img_->get_rest())
|
||||
if(*size + offset_ >= img_->size())
|
||||
{
|
||||
memcpy(buf, img_->ptr() + offset_, img_->get_rest() - offset_);
|
||||
*size = img_->get_rest() - offset_;
|
||||
offset_ = img_->get_rest();
|
||||
memcpy(buf, img_->data() + offset_, img_->size() - offset_);
|
||||
*size = img_->size() - offset_;
|
||||
offset_ = img_->size();
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf, img_->ptr() + offset_, *size);
|
||||
memcpy(buf, img_->data() + offset_, *size);
|
||||
offset_ += *size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <functional>
|
||||
|
||||
#define CLS_PTR(cls) typedef cls* cls##_ptr;
|
||||
#ifndef uchar
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -309,7 +312,8 @@ public:
|
|||
|
||||
class image_packet : public data_source
|
||||
{
|
||||
dyn_mem* img_;
|
||||
// dyn_mem* img_;
|
||||
std::shared_ptr<std::vector<uchar>> img_;
|
||||
dyn_mem* head_;
|
||||
uint32_t offset_;
|
||||
uint32_t paper_ind_ = 0;
|
||||
|
@ -318,7 +322,7 @@ class image_packet : public data_source
|
|||
std::string pos_str_;
|
||||
|
||||
public:
|
||||
image_packet(LPPACKIMAGE head, dyn_mem* img, uint32_t scanid, const void* info = nullptr, size_t info_size = 0);
|
||||
image_packet(LPPACKIMAGE head, std::shared_ptr<std::vector<uchar>> img, uint32_t scanid, const void* info = nullptr, size_t info_size = 0);
|
||||
|
||||
protected:
|
||||
virtual ~image_packet();
|
||||
|
|
|
@ -185,6 +185,9 @@ extern uint64_t GetCurrentThreadId(void);
|
|||
#define pid_t int
|
||||
#define pthread_t HANDLE
|
||||
|
||||
#define _GLIBCXX_TXN_SAFE_DYN
|
||||
#define _GLIBCXX_USE_NOEXCEPT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -298,6 +298,10 @@ public:
|
|||
{
|
||||
return obj_;
|
||||
}
|
||||
T* get(void)
|
||||
{
|
||||
return obj_;
|
||||
}
|
||||
};
|
||||
|
||||
// time utility
|
||||
|
|
|
@ -187,6 +187,9 @@
|
|||
#define SANE_STD_OPT_NAME_LUT_FILE "lut-file"
|
||||
#define SANE_STD_OPT_NAME_PHASE_FRONT "phase-f"
|
||||
#define SANE_STD_OPT_NAME_PHASE_BACK "phase-b"
|
||||
#define SANE_STD_OPT_NAME_OUT_FORMAT "img-fmt"
|
||||
#define SANE_STD_OPT_NAME_JPEG_QUALITY "jpeg-quality"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue