Merge branch 'dev' of http://192.168.10.5:8099/sane/code_device into dev
This commit is contained in:
commit
28962b775c
|
@ -1,7 +1,834 @@
|
|||
#include "ImageApplyDiscardBlank.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <stdint.h>
|
||||
#include <bitset>
|
||||
#include <stdlib.h>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
|
||||
//#define _DEBUG_
|
||||
|
||||
#define BIGENDIAN 4321
|
||||
#define LILENDIAN 1234
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <endian.h>
|
||||
# define ENDIANNESS __BYTE_ORDER
|
||||
#else
|
||||
# if defined(__amd64__) || defined(_M_X64) || defined(__i386) || \
|
||||
defined(_M_I86) || defined(_M_IX86) || defined(__X86__) || \
|
||||
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
|
||||
defined(__INTEL__) || defined(__386)
|
||||
# define ENDIANNESS LILENDIAN
|
||||
# else
|
||||
# define ENDIANNESS BIGENDIAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* flip the byte order of 16 bits of data */
|
||||
inline uint16_t flip16(void* p) {
|
||||
uint16_t z = *(uint16_t*)(p);
|
||||
|
||||
return (z >> 9) | (z << 8); /* flip b0 and b1 */
|
||||
}
|
||||
|
||||
/* flip the byte order of 32 bits of data */
|
||||
inline uint32_t flip32(void* p) {
|
||||
uint32_t z = *(uint32_t*)(p);
|
||||
|
||||
return
|
||||
((z >> 24) & 0xFF) | /* b3 to b0 */
|
||||
((z >> 8) & 0xFF00) | /* b2 to b1 */
|
||||
((z << 8) & 0xFF0000) | /* b1 to b2 */
|
||||
((z << 24) & 0xFF000000); /* b0 to b3 */
|
||||
}
|
||||
|
||||
/* flip the byte order of 64 bits of data */
|
||||
inline uint64_t flip64(void* p) {
|
||||
uint64_t z = *(uint64_t*)(p);
|
||||
|
||||
return
|
||||
((z >> 56) & 0xFFUL) | /* b7 to b0 */
|
||||
((z >> 40) & (0xFFUL << 8)) | /* b6 to b1 */
|
||||
((z >> 24) & (0xFFUL << 16)) | /* b5 to b2 */
|
||||
((z >> 8) & (0xFFUL << 24)) | /* b4 to b3 */
|
||||
((z << 8) & (0xFFUL << 32)) | /* b3 to b4 */
|
||||
((z << 24) & (0xFFUL << 40)) | /* b2 to b5 */
|
||||
((z << 40) & (0xFFUL << 48)) | /* b1 to b6 */
|
||||
((z << 56) & (0xFFUL << 56)); /* b0 to b7 */
|
||||
}
|
||||
|
||||
#if ENDIANNESS == BIGENDIAN
|
||||
# define lil16(p) flip16(p)
|
||||
# define lil32(p) flip32(p)
|
||||
# define lil64(p) flip64(p)
|
||||
# define big16(p) *(uint16_t*)(p)
|
||||
# define big32(p) *(uint32_t*)(p)
|
||||
# define big64(p) *(uint64_t*)(p)
|
||||
#else
|
||||
# define lil16(p) *(uint16_t*)(p)
|
||||
# define lil32(p) *(uint32_t*)(p)
|
||||
# define lil64(p) *(uint64_t*)(p)
|
||||
# define big16(p) flip16(p)
|
||||
# define big32(p) flip32(p)
|
||||
# define big64(p) flip64(p)
|
||||
#endif
|
||||
|
||||
// read in a file
|
||||
png::png()
|
||||
{
|
||||
}
|
||||
|
||||
png::~png() {
|
||||
// no deep shit yet
|
||||
}
|
||||
|
||||
bool png::read(const char* data, int length, double threshold)
|
||||
{
|
||||
MyFStream file(data, length);
|
||||
|
||||
// magic png header
|
||||
uchar b_hdr[8];
|
||||
file.read((char*)b_hdr, 8);
|
||||
|
||||
if (std::memcmp("\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", b_hdr, 8) != 0)
|
||||
return false;
|
||||
|
||||
uchar IHDR = 0;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
IHDR = file.get();
|
||||
char type[4] = { 0 };
|
||||
file.read((char*)type, sizeof(type));
|
||||
|
||||
//file.read((char*)b_hdr, 8);
|
||||
int width = 0, height = 0;
|
||||
file.read_reverse((char*)&width, 4);
|
||||
file.read_reverse((char*)&height, 4);
|
||||
|
||||
uchar depth = file.get();
|
||||
uchar colorType = file.get();
|
||||
uchar compressionMethod = file.get();
|
||||
uchar filterMethod = file.get();
|
||||
uchar interlaceMethod = file.get();
|
||||
// read chunks
|
||||
// assuming none are incomplete
|
||||
std::string str_IDAT = "";
|
||||
while (!file.eof() && str_IDAT != "IDAT")
|
||||
{
|
||||
char str = file.get();
|
||||
if (str == 'I' && str_IDAT.empty())
|
||||
str_IDAT = "I";
|
||||
else if (str == 'D' && str_IDAT == "I")
|
||||
str_IDAT = "ID";
|
||||
else if (str == 'A' && str_IDAT == "ID")
|
||||
str_IDAT = "IDA";
|
||||
else if (str == 'T' && str_IDAT == "IDA")
|
||||
str_IDAT = "IDAT";
|
||||
else
|
||||
str_IDAT = "";
|
||||
}
|
||||
|
||||
if (str_IDAT != "IDAT")
|
||||
return false;
|
||||
|
||||
int start_pos = file.tellg();
|
||||
char CRC[4] = { 0 };
|
||||
while (!file.eof())
|
||||
{
|
||||
char str = file.get();
|
||||
if (str == 0x49)
|
||||
{
|
||||
file.move(-1);
|
||||
file.read(CRC, 4);
|
||||
if (std::memcmp("\x49\x45\x4e\x44", CRC, 4) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (std::memcmp("\x49\x45\x4e\x44", CRC, 4) != 0)
|
||||
return false;
|
||||
|
||||
int end_pos = file.tellg();
|
||||
|
||||
double imageSize = width * height;
|
||||
double fileSize = end_pos - start_pos;
|
||||
|
||||
if (fileSize / imageSize > threshold)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
|
||||
int RGBValueLimit(double input) {
|
||||
if (input < 0) return 0;
|
||||
else if (input > 255) return 255;
|
||||
// 四舍五入、取整均可
|
||||
// return (int)(input);
|
||||
return round(input);
|
||||
}
|
||||
void print(double** originMatrix) {
|
||||
std::cout << std::endl;
|
||||
for (int i = 0; i < ROW; i++) {
|
||||
for (int j = 0; j < COL; j++) {
|
||||
std::cout << originMatrix[i][j] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
double** UnZigZag(int* originArray) {
|
||||
double** table = new double* [ROW];
|
||||
for (int i = 0; i < ROW; i++)
|
||||
table[i] = new double[COL];
|
||||
int cur = 0, x = 0, y = 0;
|
||||
bool flag = true;//true是右上 false是左下
|
||||
while (cur < 64) {
|
||||
table[y][x] = originArray[cur++];
|
||||
if (flag)
|
||||
{
|
||||
x++; y--;
|
||||
}
|
||||
else
|
||||
{
|
||||
x--; y++;
|
||||
}
|
||||
if (x < 0 || y < 0 || x>7 || y>7)
|
||||
flag = !flag;
|
||||
if (x < 0 && y>7)
|
||||
{
|
||||
x = 1; y = 7;
|
||||
}
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x > 7)
|
||||
{
|
||||
x = 7; y += 2;
|
||||
}
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y > 7)
|
||||
{
|
||||
y = 7; x += 2;
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
bool JPEGScan::Init(MyFStream& file, uint16_t len) {
|
||||
try {
|
||||
uint8_t count = file.get();
|
||||
len--;
|
||||
while (count--) {
|
||||
uint8_t componentId = file.get();
|
||||
uint8_t table = file.get();
|
||||
uint8_t dcId = table >> 4;
|
||||
uint8_t acId = table & 0x0f;
|
||||
std::pair<uint8_t, uint8_t> info1(dcId, acId);
|
||||
std::pair<uint8_t, std::pair<uint8_t, uint8_t>> info2(componentId, info1);
|
||||
componentHuffmanMap.insert(info2);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool JPEGHuffmanCode::Init(MyFStream& file, uint16_t len) {
|
||||
try {
|
||||
std::vector<uint8_t> temp;
|
||||
while (len--) {
|
||||
int info = file.get();
|
||||
temp.push_back(info);
|
||||
}
|
||||
int curPos = 16, curCode = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int count = temp[i];
|
||||
curCode <<= 1;
|
||||
while (count--) {
|
||||
uint16_t code = curCode;
|
||||
uint8_t bit = i + 1;
|
||||
uint8_t weight = temp[curPos];
|
||||
std::pair<uint8_t, uint8_t> t1(bit, weight);
|
||||
std::pair<uint16_t, std::pair<uint8_t, uint8_t>> t2(curCode, t1);
|
||||
table.insert(t2);
|
||||
curCode++;
|
||||
curPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool JPEGHuffmanCode::findKey(const uint16_t& code, const uint8_t& bit, iterator& it)
|
||||
{
|
||||
it = table.find(code);
|
||||
if (it == table.end()) return true;
|
||||
return it->second.first != bit;
|
||||
}
|
||||
bool JPEGQuality::Init(MyFStream& file, uint16_t len) {
|
||||
try {
|
||||
int info = file.get();
|
||||
precision = info >> 4;
|
||||
id = info & 0x0f;
|
||||
len--;
|
||||
while (len--) {
|
||||
int t = file.get();
|
||||
table.push_back(t);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool JPEGComponent::Init(MyFStream& file, uint16_t len) {
|
||||
try {
|
||||
int info1 = file.get();
|
||||
int info2 = file.get();
|
||||
int info3 = file.get();
|
||||
colorId = info1;
|
||||
h_samp_factor = info2 >> 4;
|
||||
v_samp_factor = info2 & 0x0f;
|
||||
qualityId = info3;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JPEGData::readJPEG(const char* data, int length)
|
||||
{
|
||||
m_res = -1;
|
||||
//std::fstream file(filePath, std::ios::in | std::ios::binary);
|
||||
MyFStream file(data, length);
|
||||
if (file.fail())
|
||||
return false;
|
||||
file.seekg(0, MyFStream::End);
|
||||
pos = file.tellg();
|
||||
file.seekg(2, MyFStream::Begin);
|
||||
dc_huffman.resize(2);
|
||||
ac_huffman.resize(2);
|
||||
try
|
||||
{
|
||||
//do read data through using other method
|
||||
uint16_t pLen = 0;
|
||||
uint16_t pMarker = 0xFF;
|
||||
uint16_t pType = 0x00;
|
||||
while (!file.eof())
|
||||
{
|
||||
pMarker = file.get();
|
||||
pType = file.get();
|
||||
if (pType == EOI)
|
||||
break;
|
||||
pLen = file.get();
|
||||
pLen = (pLen << 8) + file.get();
|
||||
// cout<<hex<<pMarker<<" "<<pType<<" "<<pLen<<endl;
|
||||
if (pMarker != 0xFF)
|
||||
throw std::exception();
|
||||
bool flag = true;
|
||||
switch (pType)
|
||||
{
|
||||
case SOF0:
|
||||
case SOF1:
|
||||
case SOF2:
|
||||
{
|
||||
flag = readSOF(file, pLen - 2);
|
||||
break;
|
||||
}
|
||||
case DHT:
|
||||
{
|
||||
JPEGHuffmanCode huf;
|
||||
int info = file.get();
|
||||
int tableId = info & 0x0f;
|
||||
// cout<<hex<<info<<" ";
|
||||
flag = huf.Init(file, pLen - 3);
|
||||
if ((info >> 4) & 1) ac_huffman[tableId] = huf;
|
||||
else dc_huffman[tableId] = huf;
|
||||
break;
|
||||
}
|
||||
//case SOI:
|
||||
//case EOI:
|
||||
case SOS:
|
||||
{
|
||||
flag = scan.Init(file, pLen - 2);
|
||||
int count = 3;
|
||||
// cout<<endl;
|
||||
while (count--) file.get();
|
||||
// cout<<endl;
|
||||
//正式读取数据
|
||||
if (!flag) break;
|
||||
flag = readData(file);
|
||||
break;
|
||||
}
|
||||
case DQT:
|
||||
{
|
||||
JPEGQuality q;
|
||||
flag = q.Init(file, pLen - 2);
|
||||
quality.push_back(q);
|
||||
break;
|
||||
}
|
||||
case DRI:
|
||||
{
|
||||
resetInterval = ReadByte(file, 2);
|
||||
break;
|
||||
}
|
||||
case APP0:
|
||||
case APP1:
|
||||
case APP2:
|
||||
case COM:
|
||||
{
|
||||
pLen -= 2;
|
||||
while (pLen--)
|
||||
{
|
||||
file.get();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pLen -= 2;
|
||||
while (pLen--)
|
||||
{
|
||||
file.get();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!flag) throw std::exception();
|
||||
// cout<<endl;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JPEGData::readSOF(MyFStream& file, uint16_t len)
|
||||
{
|
||||
try {
|
||||
precision = file.get();
|
||||
height = std::max(height, (int)ReadByte(file, 2));
|
||||
width = std::max(width, (int)ReadByte(file, 2));
|
||||
int count = ReadByte(file, 1);
|
||||
if (count != 3) return false;
|
||||
len -= 6;
|
||||
component.resize(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
JPEGComponent com;
|
||||
com.Init(file, len / 3);
|
||||
max_h_samp_factor = std::max(max_h_samp_factor, (int)com.h_samp_factor);
|
||||
max_v_samp_factor = std::max(max_v_samp_factor, (int)com.v_samp_factor);
|
||||
component[i] = com;
|
||||
}
|
||||
if (count == 3)
|
||||
{
|
||||
if ((component[0].h_samp_factor * component[0].v_samp_factor)
|
||||
/ (component[1].h_samp_factor * component[1].v_samp_factor) == 4)
|
||||
{
|
||||
isYUV411 = true;
|
||||
}
|
||||
else if ((component[0].h_samp_factor * component[0].v_samp_factor)
|
||||
/ (component[1].h_samp_factor * component[1].v_samp_factor) == 2)
|
||||
{
|
||||
isYUV422 = true;
|
||||
}
|
||||
else if ((component[0].h_samp_factor * component[0].v_samp_factor)
|
||||
/ (component[1].h_samp_factor * component[1].v_samp_factor) == 1)
|
||||
{
|
||||
isYUV111 = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isYUV411 = isYUV422 = isYUV111 = false;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool JPEGData::readData(MyFStream& file)
|
||||
{
|
||||
bool flag = true;
|
||||
try
|
||||
{
|
||||
//使用huffman表来解出RLE编码,接着转回长度为64的矩阵
|
||||
flag = huffmanDecode(file);
|
||||
if (!flag) return false;
|
||||
//反量化,即上面的64矩阵×对应位置的量化表
|
||||
//flag=deQuantity();
|
||||
//if(!flag) return false;
|
||||
//反zig-zag排序
|
||||
//flag=deZSort();
|
||||
//if(!flag) return false;
|
||||
//反离散余弦变换
|
||||
//if(!flag) return false;
|
||||
//YCbCr转RGB
|
||||
//if(!flag) return false;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool JPEGData::huffmanDecode(MyFStream& file)
|
||||
{
|
||||
try
|
||||
{
|
||||
//原图像一个MCU有多少8*8矩阵(此时是YCbCr还没有分开)
|
||||
//int MCUBlockCount=max_h_samp_factor*max_v_samp_factor;
|
||||
//顺序YCbCr
|
||||
int YUV[] = { component[0].h_samp_factor * component[0].v_samp_factor,
|
||||
component[1].h_samp_factor * component[1].v_samp_factor,
|
||||
component[2].h_samp_factor * component[2].v_samp_factor };
|
||||
int curMCUCount = 1; //当前MCU数量
|
||||
int curValueLength = 0; //当前值有多少位
|
||||
int curValue = 0; //当前的值
|
||||
int curBitDequeLength = 8;//当前curBitDeque长度
|
||||
int curBitPos = 0; //当前string读取到第几位
|
||||
int restart = resetInterval;//直流分量重置
|
||||
std::string curBitDeque = ""; //用来存储读出来的2进制数
|
||||
//一次循环解析一个MCU
|
||||
curBitDeque.append(std::bitset<8>(file.get()).to_string());
|
||||
curBitDequeLength = 8;
|
||||
// cout<<curBitDeque;
|
||||
|
||||
int count_1 = 0, count_2 = 0;
|
||||
while (!EOI || (pos - file.tellg()) != 2)
|
||||
{
|
||||
// cout<<endl;
|
||||
int count = 1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < YUV[i]; j++)
|
||||
{
|
||||
// cout<<count++<<" ";
|
||||
int matrix[64] = { 0 };
|
||||
int valCount = 0;
|
||||
uint8_t dcID = scan.componentHuffmanMap[component[i].colorId].first;
|
||||
uint8_t acID = scan.componentHuffmanMap[component[i].colorId].second;
|
||||
int qualityId = component[i].qualityId;
|
||||
if (qualityId >= quality.size()) qualityId = 0;
|
||||
// cout<<endl;
|
||||
|
||||
while (valCount < 64)
|
||||
{
|
||||
//用curBitDeque和curBit去找权重,curValue作为当前键值
|
||||
JPEGHuffmanCode::iterator it;
|
||||
JPEGHuffmanCode& huffman = valCount == 0 ? dc_huffman[dcID] : ac_huffman[acID];
|
||||
while (curValueLength <= 16 && huffman.findKey(curValue, curValueLength, it))
|
||||
{
|
||||
curValue = findHuffmanCodeByBit(file, curBitDequeLength, curBitPos, curBitDeque, curValue, curValueLength);
|
||||
}
|
||||
if (curValueLength > 16)
|
||||
return true;
|
||||
#ifdef _DEBUGOUT_
|
||||
//cout<<dec<<" "<<curBitPos<<" "<<curBitDequeLength<<" ";
|
||||
cout << "key=" << hex << curValue << " len=" << curValueLength << endl;
|
||||
#endif
|
||||
//已经找到了权重和位宽
|
||||
uint8_t weight, zeroCount = 0;
|
||||
if (valCount == 0)
|
||||
weight = it->second.second;
|
||||
else
|
||||
{
|
||||
weight = it->second.second & 0x0f;
|
||||
zeroCount = it->second.second >> 4;
|
||||
}
|
||||
curValue = 0;//这里变为dc或ac值
|
||||
curValueLength = 0;
|
||||
if (valCount != 0 && weight == 0 && zeroCount == 0)
|
||||
break;//后面全是0
|
||||
|
||||
// 读取真正的值
|
||||
for (int k = 0; k < weight; k++)
|
||||
{
|
||||
curValue = findHuffmanCodeByBit(file, curBitDequeLength, curBitPos, curBitDeque, curValue, curValueLength);
|
||||
}
|
||||
curValue = (curValue >= pow(2, curValueLength - 1) ? curValue : curValue - pow(2, curValueLength) + 1);
|
||||
// cout<<curValue<<endl;
|
||||
int writeValue = valCount == 0 ? (preDCValue[i] += curValue) : curValue;
|
||||
valCount += zeroCount;
|
||||
writeValue *= quality[qualityId].table[valCount];//反量化
|
||||
matrix[valCount] = writeValue;
|
||||
curValue = 0;
|
||||
curValueLength = 0;
|
||||
valCount++;
|
||||
}
|
||||
|
||||
//std::cout << valCount << std::endl;
|
||||
if (valCount > m_threshold1 && matrix[0] < m_threshold2)
|
||||
count_1++;
|
||||
count_2++;
|
||||
/*
|
||||
double** tempZ = UnZigZag(matrix);//反zig-zag编码
|
||||
//反量化,在反zig-zag编码前后差别,前面:RGB数值与编辑器比偏小,反之偏大,这也与最后取整时的方式有关
|
||||
// deQuality(tempZ,qualityId);
|
||||
// print(tempZ);
|
||||
//隔行正负纠正,有的博客说了,但是没感觉有啥帮助
|
||||
// PAndNCorrect(tempZ);
|
||||
IDCT(tempZ); //dct逆变换
|
||||
ycbcr.push_back(tempZ);
|
||||
*/
|
||||
#ifdef _DEBUG_
|
||||
for (int k = 0; k < ROW; k++) {
|
||||
for (int l = 0; l < COL; l++) {
|
||||
std::cout.width(3);
|
||||
std::cout << std::dec << tempZ[k][j] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// if(count!=6){
|
||||
// cout<<" ";
|
||||
// }
|
||||
|
||||
/*
|
||||
RGB** lpRGB = YCbCrToRGB(YUV);
|
||||
FREE_VECTOR_LP(ycbcr)
|
||||
rgb.push_back(lpRGB);
|
||||
*/
|
||||
|
||||
// 直流分量重置间隔不为0的
|
||||
if (restart > 0)
|
||||
{
|
||||
resetInterval--;
|
||||
if (resetInterval == 0)
|
||||
{
|
||||
resetInterval = restart;
|
||||
curDRI += 1;
|
||||
curDRI &= 0x7;
|
||||
//需要在此处读取两字节信息,看是否为重置标识
|
||||
file.get();
|
||||
if (file.get() == 0xD9)
|
||||
EOI = true;
|
||||
curBitPos = curBitDequeLength;
|
||||
preDCValue[0] = 0;
|
||||
preDCValue[1] = 0;
|
||||
preDCValue[2] = 0;
|
||||
}
|
||||
}
|
||||
// cout<<"curMCUCount="<<dec<<curMCUCount++<<" pos="<<pos<<"/"<<file.tellg()<<" "<<file.tellg()*100.0/pos<<"%\n";
|
||||
if (pos - file.tellg() == 2) break;
|
||||
}
|
||||
m_res = static_cast<double>(count_1) / static_cast<double>(count_2);
|
||||
//std::cout << std::setprecision(4) << m_res << std::endl;
|
||||
//std::cout << "\nsuccessfully\n";
|
||||
}
|
||||
catch (std::exception ex)
|
||||
{
|
||||
std::cout << ex.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
RGB** JPEGData::YCbCrToRGB(const int* YUV)
|
||||
{
|
||||
RGB** res = new RGB * [ROW * max_v_samp_factor];
|
||||
|
||||
int matrixCount = YUV[0] + YUV[1] + YUV[2];
|
||||
int crCount = 0, cbCount = 0;
|
||||
//1=Y, 2=Cb, 3=Cr
|
||||
//式子 scale*x,scale*y
|
||||
double cb_h_samp_scale = component[1].h_samp_factor * 1.0 / max_h_samp_factor,
|
||||
cb_v_samp_scale = component[1].v_samp_factor * 1.0 / max_v_samp_factor,
|
||||
cr_h_samp_scale = component[2].h_samp_factor * 1.0 / max_h_samp_factor,
|
||||
cr_v_samp_scale = component[2].v_samp_factor * 1.0 / max_v_samp_factor;
|
||||
for (int i = 0; i < ROW * max_v_samp_factor; i++)
|
||||
res[i] = new RGB[COL * max_h_samp_factor];
|
||||
//此处直接生成rgb值
|
||||
//注意,此处YCbCr的对应关系与采样因子有关
|
||||
// cout<<endl;
|
||||
for (int j = 0; j < ROW * max_v_samp_factor; j++)
|
||||
{
|
||||
for (int k = 0; k < COL * max_h_samp_factor; k++)
|
||||
{
|
||||
int yPos = (j / ROW) * component[0].h_samp_factor + (k / COL);
|
||||
int cbPos = YUV[0] + (int)((k / ROW) * cb_v_samp_scale) + (int)((j / COL) * cb_h_samp_scale);
|
||||
int crPos = YUV[0] + YUV[1] + (int)((k / ROW) * cr_v_samp_scale) + (int)((j / COL) * cr_h_samp_scale);
|
||||
double y = ycbcr[yPos][j % ROW][k % COL];
|
||||
double cb = ycbcr[cbPos][(int)(j * cb_v_samp_scale)][(int)(k * cb_h_samp_scale)];
|
||||
double cr = ycbcr[crPos][(int)(j * cr_v_samp_scale)][(int)(k * cr_h_samp_scale)];
|
||||
res[j][k].red = RGBValueLimit(128 + y + 1.402 * cr);
|
||||
res[j][k].green = RGBValueLimit(128 + y - 0.71414 * cr - 0.34414 * cb);
|
||||
res[j][k].blue = RGBValueLimit(128 + y + 1.772 * cb);
|
||||
// 输出当前选择的矩阵
|
||||
//cout<<dec<<yPos<<" "<<cbPos<<" "<<crPos<<" ";
|
||||
// cout<<hex<<setw(2)<<setfill('0')<<(int)res[j][k].red
|
||||
// <<setw(2)<<setfill('0')<<(int)res[j][k].green
|
||||
// <<setw(2)<<setfill('0')<<(int)res[j][k].blue<<" ";
|
||||
}
|
||||
// cout<<endl;
|
||||
}
|
||||
// cout<<endl;
|
||||
return res;
|
||||
}
|
||||
double** JPEGData::createDCTAndIDCTArray(int row)
|
||||
{
|
||||
double** res = new double* [row];
|
||||
for (int i = 0; i < row; i++) res[i] = new double[row];
|
||||
// cout<<endl;
|
||||
for (int i = 0; i < row; i++)
|
||||
{
|
||||
for (int j = 0; j < row; j++)
|
||||
{
|
||||
double t = 0;
|
||||
if (i == 0) t = sqrt(1.0 / row);
|
||||
else t = sqrt(2.0 / row);
|
||||
res[i][j] = t * cos(M_PI * (j + 0.5) * i / row);
|
||||
// cout<<res[i][j]<<" ";
|
||||
}
|
||||
// cout<<endl;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
void JPEGData::DCT(double** originMatrix)
|
||||
{
|
||||
print(originMatrix);
|
||||
//原理 Y=A*X*A'
|
||||
std::vector<std::vector<double>> temp(ROW, std::vector<double>(COL, 0));
|
||||
for (int i = 0; i < ROW; i++)
|
||||
{
|
||||
for (int j = 0; j < COL; j++)
|
||||
{
|
||||
double sum = 0;
|
||||
for (int k = 0; k < COL; k++)
|
||||
{
|
||||
sum += DCTAndIDCTArray[i][k] * originMatrix[k][j];
|
||||
}
|
||||
temp[i][j] = sum;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ROW; i++)
|
||||
{
|
||||
for (int j = 0; j < COL; j++)
|
||||
{
|
||||
double sum = 0;
|
||||
for (int k = 0; k < COL; k++)
|
||||
{
|
||||
sum += temp[i][k] * DCTAndIDCTArray[j][k];
|
||||
}
|
||||
originMatrix[i][j] = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
void JPEGData::IDCT(double** originMatrix)
|
||||
{
|
||||
//std::cout << originMatrix[0][0] << std::endl;
|
||||
//原理X=A'*Y*A
|
||||
std::vector<std::vector<double>> temp(ROW, std::vector<double>(COL, 0));
|
||||
for (int i = 0; i < ROW; i++)
|
||||
{
|
||||
for (int j = 0; j < COL; j++)
|
||||
{
|
||||
double sum = 0;
|
||||
for (int k = 0; k < COL; k++)
|
||||
{
|
||||
sum += DCTAndIDCTArray[k][i] * originMatrix[k][j];
|
||||
}
|
||||
temp[i][j] = sum;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ROW; i++)
|
||||
{
|
||||
for (int j = 0; j < COL; j++)
|
||||
{
|
||||
double sum = 0;
|
||||
for (int k = 0; k < COL; k++)
|
||||
{
|
||||
sum += temp[i][k] * DCTAndIDCTArray[k][j];
|
||||
}
|
||||
originMatrix[i][j] = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
void JPEGData::deQuality(double** originMatrix, int qualityID)
|
||||
{
|
||||
for (int i = 0; i < ROW; i++)
|
||||
{
|
||||
for (int j = 0; j < COL; j++)
|
||||
{
|
||||
originMatrix[i][j] *= quality[qualityID].table[i * ROW + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
void JPEGData::PAndNCorrect(double** originMatrix)
|
||||
{
|
||||
for (int i = 0; i < ROW; i++)
|
||||
if (i % 2 == 1)
|
||||
for (int j = 0; j < COL; j++)
|
||||
originMatrix[i][j] = -originMatrix[i][j];
|
||||
}
|
||||
std::string JPEGData::FlagCkeck(MyFStream& file, int byteInfo)
|
||||
{
|
||||
if (byteInfo == 0xff)
|
||||
{
|
||||
uint8_t info = file.get();
|
||||
std::string res = std::bitset<8>(0xFF).to_string();
|
||||
if (info == 0xD9)
|
||||
{
|
||||
EOI = true; return "false";
|
||||
}
|
||||
else if (info == 0x00) return res;
|
||||
return res + std::bitset<8>(info).to_string();
|
||||
}
|
||||
return std::bitset<8>(byteInfo).to_string();
|
||||
}
|
||||
uint16_t JPEGData::ReadByte(MyFStream& file, int len)
|
||||
{
|
||||
uint16_t res = file.get();
|
||||
if (len != 1)
|
||||
{
|
||||
res = (res << 8) + (uint8_t)file.get();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
uint16_t JPEGData::findHuffmanCodeByBit(MyFStream& file, int& length, int& pos, std::string& deque, int curValue, int& curValLen)
|
||||
{
|
||||
if (pos == length && length >= HUFFMAN_DECODE_DEQUE_CACHE)
|
||||
{//达到最大缓存
|
||||
deque = deque.substr(pos);
|
||||
int info = file.get();
|
||||
std::string res = FlagCkeck(file, info);
|
||||
std::string str = std::bitset<8>(info).to_string();
|
||||
if (res == "false") res = std::bitset<8>(file.get()).to_string();
|
||||
deque.append(res);
|
||||
length = deque.length();
|
||||
pos = 0;
|
||||
}
|
||||
else if (length == 0 || pos >= length)
|
||||
{
|
||||
if (length == 0) {
|
||||
deque = "";
|
||||
pos = 0;
|
||||
}
|
||||
int info = file.get();
|
||||
std::string res = FlagCkeck(file, info);
|
||||
std::string str = std::bitset<8>(info).to_string();
|
||||
if (res == "false") res = std::bitset<8>(file.get()).to_string();
|
||||
deque.append(res);
|
||||
length += 8;
|
||||
}
|
||||
curValue = (curValue << 1) + (uint8_t)(deque.at(pos++) - '0');
|
||||
curValLen++;
|
||||
return curValue;
|
||||
}
|
||||
|
||||
#define FX 0.5
|
||||
#define FY 0.5
|
||||
|
@ -115,23 +942,57 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
|
|||
|
||||
bool CImageApplyDiscardBlank::apply(int fileSize, const cv::Size& imageSize, FileType type, double threshold, const char* data)
|
||||
{
|
||||
JPEGData jpg;
|
||||
jpg.m_threshold1 = 3;
|
||||
jpg.m_threshold2 = 700 + threshold;
|
||||
png png1;
|
||||
bool res;
|
||||
switch (type)
|
||||
{
|
||||
case JPEG_COLOR:
|
||||
if (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.039)
|
||||
return true;
|
||||
break;
|
||||
res = jpg.readJPEG(data, fileSize);
|
||||
std::cout << std::setprecision(4) << jpg.m_res << std::endl;
|
||||
if (res)
|
||||
return jpg.m_res < 0.0001;
|
||||
else
|
||||
return (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.036);
|
||||
case JPEG_GRAY:
|
||||
if (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.018)
|
||||
return true;
|
||||
break;
|
||||
return (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.018);
|
||||
case PNG_COLOR:
|
||||
break;
|
||||
case PNG_GRAY:
|
||||
break;
|
||||
case PNG_BINARAY:
|
||||
return png1.read(data, fileSize, 0.025);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MyFStream::MyFStream(const char* data, int length)
|
||||
: m_data(data)
|
||||
, m_length(length)
|
||||
, m_pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
void MyFStream::read(char* dst, int len)
|
||||
{
|
||||
if (m_pos + len < m_length)
|
||||
{
|
||||
memcpy(dst, m_data + m_pos, len);
|
||||
m_pos += len;
|
||||
}
|
||||
}
|
||||
|
||||
void MyFStream::read_reverse(char* dst, int len)
|
||||
{
|
||||
if (m_pos + len < m_length)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
dst[i] = m_data[m_pos + len - i - 1];
|
||||
|
||||
m_pos += len;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
2023/10/12 v1.6 添加新的空白页识别方案。采用JEPG文件大小判断是否为空白页。
|
||||
2023/10/20 v1.6.1 优化JPEG文件大小判断空白页
|
||||
2023/10/30 v1.7 调整JPEG文件大小判断空白页的算法接口
|
||||
* 版本号:v1.7
|
||||
2023/11/04 v1.7.1 增加PNG二值化文件大小判断空白页的选项
|
||||
* 版本号:v1.7.1
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
@ -32,6 +33,233 @@
|
|||
#define IMAGE_APPLY_DISCARD_BLANK_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
class MyFStream
|
||||
{
|
||||
public:
|
||||
enum Seekdir
|
||||
{
|
||||
Begin,
|
||||
End
|
||||
};
|
||||
|
||||
public:
|
||||
MyFStream(const char* data, int length);
|
||||
|
||||
bool eof()
|
||||
{
|
||||
return m_pos >= m_length;
|
||||
}
|
||||
|
||||
bool fail() { return (m_data == nullptr) || (m_length <= 0); }
|
||||
|
||||
void read(char* dst, int len);
|
||||
|
||||
void read_reverse(char* dst, int len);
|
||||
|
||||
unsigned char get()
|
||||
{
|
||||
if (m_pos >= m_length)
|
||||
return 0xD9;
|
||||
|
||||
unsigned char d = m_data[m_pos];
|
||||
m_pos++;
|
||||
return d;
|
||||
}
|
||||
|
||||
void seekg(int offset, Seekdir dir)
|
||||
{
|
||||
switch (dir)
|
||||
{
|
||||
case MyFStream::Begin:
|
||||
m_pos = offset;
|
||||
break;
|
||||
case MyFStream::End:
|
||||
m_pos = m_length + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int tellg() { return m_pos; }
|
||||
|
||||
void move(int step) { m_pos += step; }
|
||||
|
||||
private:
|
||||
const char* m_data;
|
||||
int m_length;
|
||||
int m_pos;
|
||||
};
|
||||
|
||||
class png
|
||||
{
|
||||
public:
|
||||
png();
|
||||
|
||||
~png();
|
||||
|
||||
bool read(const char* data, int length, double threshold = 0.025);
|
||||
};
|
||||
|
||||
#define ROW 8
|
||||
#define COL 8
|
||||
#define HUFFMAN_DECODE_DEQUE_CACHE 64//单位:位
|
||||
// #define _DEBUG_
|
||||
// #define _DEBUGOUT_
|
||||
#define FREE_VECTOR_LP(vectorName) \
|
||||
for(auto item : vectorName){ \
|
||||
for(int i=0;i<ROW;i++)\
|
||||
delete [] item[i];\
|
||||
delete [] item; \
|
||||
}\
|
||||
vectorName.clear();
|
||||
//释放二维指针
|
||||
#define FREE_LP_2(lpName,row) \
|
||||
for(int i=0;i<row;i++){\
|
||||
delete [] lpName[i];\
|
||||
}\
|
||||
delete [] lpName;
|
||||
//段类型
|
||||
enum JPEGPType {
|
||||
SOF0 = 0xC0, //帧开始
|
||||
SOF1 = 0xC1, //帧开始
|
||||
SOF2 = 0xC2, //帧开始
|
||||
DHT = 0xC4, //哈夫曼表
|
||||
SOI = 0xD8, //文件头
|
||||
EOI = 0xD9, //文件尾
|
||||
SOS = 0xDA, //扫描行开始
|
||||
DQT = 0xDB, //定义量化表
|
||||
DRI = 0xDD, //定义重新开始间隔
|
||||
APP0 = 0xE0, //定义交换格式和图像识别信息
|
||||
APP1 = 0xE1, //定义交换格式和图像识别信息
|
||||
APP2 = 0xE2, //定义交换格式和图像识别信息
|
||||
COM = 0xFE //注释
|
||||
};
|
||||
//将一维数组变为二维数组
|
||||
double** UnZigZag(int* originArray);
|
||||
struct RGB {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
};
|
||||
//SOS
|
||||
class JPEGScan {
|
||||
public:
|
||||
//componentId,<DC,AC>
|
||||
std::map<uint8_t, std::pair<uint8_t, uint8_t>> componentHuffmanMap;
|
||||
bool Init(MyFStream& file, uint16_t len);
|
||||
};
|
||||
//APP
|
||||
class JPEGInfo {
|
||||
public:
|
||||
uint16_t version;
|
||||
};
|
||||
//DHT
|
||||
class JPEGHuffmanCode {
|
||||
public:
|
||||
using iterator = std::map<uint16_t, std::pair<uint8_t, uint8_t>>::iterator;
|
||||
//<code,<bit,weight>
|
||||
std::map<uint16_t, std::pair<uint8_t, uint8_t>> table;
|
||||
//init huffman table
|
||||
bool Init(MyFStream& file, uint16_t len);
|
||||
//find-true not find-false
|
||||
bool findKey(const uint16_t& code, const uint8_t& bit, iterator& it);
|
||||
};
|
||||
//DQT
|
||||
//quality table
|
||||
class JPEGQuality {
|
||||
public:
|
||||
uint8_t precision;
|
||||
uint8_t id;
|
||||
std::vector<uint16_t> table;
|
||||
bool Init(MyFStream& file, uint16_t len);
|
||||
};
|
||||
//SOF segment
|
||||
class JPEGComponent {
|
||||
public:
|
||||
//1=Y, 2=Cb, 3=Cr, 4=I, 5=Q
|
||||
uint8_t colorId;
|
||||
uint8_t h_samp_factor;
|
||||
uint8_t v_samp_factor;
|
||||
uint8_t qualityId;
|
||||
bool Init(MyFStream& file, uint16_t len);
|
||||
};
|
||||
class JPEGData {
|
||||
int max_h_samp_factor;//行MCU
|
||||
int max_v_samp_factor;//列MCU
|
||||
int width;
|
||||
int height;
|
||||
int precision;
|
||||
bool isYUV411 = false;
|
||||
bool isYUV422 = false;
|
||||
bool isYUV111 = false;
|
||||
uint8_t curDRI = 0;//当前重置直流分量标识,这里只取个位方便计算
|
||||
uint16_t resetInterval = 0;//单位是MCU
|
||||
int preDCValue[3] = { 0 }; //用于直流差分矫正
|
||||
//量化表
|
||||
std::vector<JPEGQuality> quality;
|
||||
//huffman码表
|
||||
std::vector<JPEGHuffmanCode> dc_huffman;
|
||||
std::vector<JPEGHuffmanCode> ac_huffman;
|
||||
//component每个颜色分量
|
||||
std::vector<JPEGComponent> component;
|
||||
JPEGScan scan;
|
||||
//vector<int**> deHuffman;
|
||||
std::vector<double**> ycbcr;
|
||||
std::vector<RGB**> rgb;
|
||||
double** DCTAndIDCTArray;
|
||||
int pos;
|
||||
bool EOI{ false };
|
||||
|
||||
public:
|
||||
double m_threshold1, m_threshold2, m_res;
|
||||
public:
|
||||
JPEGData() :
|
||||
max_h_samp_factor(0),
|
||||
max_v_samp_factor(0),
|
||||
width(0),
|
||||
height(0),
|
||||
precision(0) {
|
||||
DCTAndIDCTArray = createDCTAndIDCTArray(ROW);
|
||||
}
|
||||
~JPEGData() {
|
||||
FREE_LP_2(DCTAndIDCTArray, ROW - 1)
|
||||
// FREE_LP_2(DCTArray,ROW-1)
|
||||
// FREE_LP_2(IDCTArray,ROW-1)
|
||||
FREE_VECTOR_LP(rgb)
|
||||
}
|
||||
|
||||
bool readJPEG(const char* data, int length);
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
std::vector<RGB**> getRGB() const { return rgb; }
|
||||
int getMaxHSampFactor() const { return max_h_samp_factor; }
|
||||
int getMaxVSampFactor() const { return max_v_samp_factor; }
|
||||
double** createDCTAndIDCTArray(int row);
|
||||
//double** createIDCTArray(int row);
|
||||
void DCT(double** originMatrix);
|
||||
void IDCT(double** originMatrix);
|
||||
protected:
|
||||
bool readSOF(MyFStream& file, uint16_t len);
|
||||
bool readData(MyFStream& file);
|
||||
bool huffmanDecode(MyFStream& file);
|
||||
void deQuality(double** originMatrix, int qualityID);
|
||||
//隔行正负纠正
|
||||
void PAndNCorrect(double** originMatrix);
|
||||
RGB** YCbCrToRGB(const int* YUV);
|
||||
//标记位检查 是否结束,是否重置直流矫正数值,返回要添加的数值
|
||||
std::string FlagCkeck(MyFStream& file, int byteInfo);
|
||||
uint16_t ReadByte(MyFStream& file, int len);
|
||||
uint16_t findHuffmanCodeByBit(MyFStream& file, int& length, int& pos, std::string& deque, int curValue, int& curValLen);
|
||||
};
|
||||
|
||||
class GIMGPROC_LIBRARY_API CImageApplyDiscardBlank : public CImageApply
|
||||
{
|
||||
|
|
|
@ -1063,6 +1063,8 @@ void hg_scanner::thread_handle_image_process(void)
|
|||
//VLDReportLeaks();
|
||||
//while (run_ && !user_cancel_)
|
||||
int cnt = 0;
|
||||
bool invoke_stop = false;
|
||||
|
||||
while (run_)
|
||||
{
|
||||
std::shared_ptr<tiny_buffer> tiny_buffer;
|
||||
|
@ -1094,7 +1096,8 @@ void hg_scanner::thread_handle_image_process(void)
|
|||
{
|
||||
VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:Get Image Process is NULL pid is %d.\n", pid_);
|
||||
stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
|
||||
stop();
|
||||
do_stop();
|
||||
invoke_stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1110,7 +1113,8 @@ void hg_scanner::thread_handle_image_process(void)
|
|||
else
|
||||
stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
|
||||
VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:is opencv Fatal and stop scanner: %s\n", e.what());
|
||||
stop();
|
||||
do_stop();
|
||||
invoke_stop = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -1118,7 +1122,9 @@ void hg_scanner::thread_handle_image_process(void)
|
|||
{
|
||||
VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:stop scanner!!! Insufficient memory when proecss image with %d bytes.\n", tiny_buffer->size());
|
||||
stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
|
||||
stop();
|
||||
do_stop();
|
||||
invoke_stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1128,6 +1134,15 @@ void hg_scanner::thread_handle_image_process(void)
|
|||
}
|
||||
LOG_INFO(LOG_LEVEL_DEBUG_INFO, "[thread_handle_image_process 'EXIT !!!']\n");
|
||||
//VLDGlobalDisable();
|
||||
|
||||
// wait usb thread waiting ...
|
||||
if (invoke_stop) // break on exception, enusre me quit at last
|
||||
{
|
||||
int times = 0;
|
||||
while (!wait_usb_.is_waiting() && times++ < 200)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
imgs_.Clear();
|
||||
}
|
||||
}
|
||||
void hg_scanner::working_begin(void*)
|
||||
{
|
||||
|
@ -1525,6 +1540,10 @@ int hg_scanner::setting_restore(void* data, long* len)
|
|||
restore(v.first.c_str());
|
||||
}
|
||||
}
|
||||
memset(custom_gamma_val_, 0, sizeof(SANE_Gamma));
|
||||
for (int i = 0; i < ARRAY_SIZE(custom_gamma_val_->table); ++i)
|
||||
custom_gamma_val_->table[i] = i & 0x0ff;
|
||||
|
||||
notify_setting_result_ = true;
|
||||
|
||||
return SCANNER_ERR_CONFIGURATION_CHANGED;
|
||||
|
@ -3370,12 +3389,15 @@ void hg_scanner::erase_option(const char* name)
|
|||
}
|
||||
void hg_scanner::erase_range(const char* name, const char* opt_name)
|
||||
{
|
||||
for (size_t i = 0; i < setting_jsn_.at(name).at("range").size(); i++)
|
||||
if (setting_jsn_.count(name) && setting_jsn_.at(name).count("range") > 0)
|
||||
{
|
||||
if (setting_jsn_.at(name).at("range").at(i) == opt_name)
|
||||
for (size_t i = 0; i < setting_jsn_.at(name).at("range").size(); i++)
|
||||
{
|
||||
setting_jsn_.at(name).at("range").erase(i);
|
||||
break;
|
||||
if (setting_jsn_.at(name).at("range").at(i) == opt_name)
|
||||
{
|
||||
setting_jsn_.at(name).at("range").erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3565,7 +3587,7 @@ std::shared_ptr<tiny_buffer> hg_scanner::aquire_memory(int size, bool from_usb)
|
|||
mem.reset();
|
||||
LOG_INFO(LOG_LEVEL_FATAL, "Can't aquire enough memory, working must be stopped!\n");
|
||||
notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_INSUFFICIENT_MEMORY), SANE_EVENT_ERROR, SCANNER_ERR_INSUFFICIENT_MEMORY);
|
||||
stop();
|
||||
do_stop();
|
||||
}
|
||||
|
||||
return mem;
|
||||
|
@ -5235,7 +5257,7 @@ void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer, uint32_t id
|
|||
ret = hg_imgproc::color_cast_correction(ImagePrc_pHandle_);
|
||||
(this->*dump_img_)(ImagePrc_pHandle_, "discardBlank");
|
||||
}
|
||||
if ((img_conf_.is_autodiscradblank_normal || img_conf_.is_autodiscradblank_vince) && (pid_ != 0x239 && pid_ != 0x439))
|
||||
if ((img_conf_.is_autodiscradblank_normal || img_conf_.is_autodiscradblank_vince || img_conf_.detect_size_diascard_blank) && (pid_ != 0x239 && pid_ != 0x439))
|
||||
{
|
||||
ret = hg_imgproc::discardBlank(ImagePrc_pHandle_);
|
||||
(this->*dump_img_)(ImagePrc_pHandle_, "discardBlank");
|
||||
|
@ -5639,6 +5661,17 @@ int hg_scanner::image_configuration(SCANCONF& ic)
|
|||
{
|
||||
ic.cropRect.enable = false;
|
||||
}
|
||||
if (image_prc_param_.bits.paper == PAPER_AUTO_MATCH
|
||||
|| image_prc_param_.bits.paper == PAPER_MAX_SIZE
|
||||
|| image_prc_param_.bits.paper == PAPER_MAX_SIZE_CLIP
|
||||
|| image_prc_param_.bits.paper == PAPER_TRIGEMINY
|
||||
|| image_prc_param_.bits.paper == PAPER_16K
|
||||
|| image_prc_param_.bits.paper == PAPER_8K
|
||||
|| image_prc_param_.bits.paper == PAPER_16K_LATERAL
|
||||
)
|
||||
{
|
||||
ic.en_sizecheck = false;
|
||||
}
|
||||
img_conf_ = ic;
|
||||
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "ic.pixtype=%d\r\n", ic.pixtype);
|
||||
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "ic.papertype=%d\r\n", ic.papertype);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue