code_device/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp

999 lines
30 KiB
C++
Raw Normal View History

2022-07-29 08:41:34 +00:00
#include "ImageApplyDiscardBlank.h"
#include "ImageProcess_Public.h"
#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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롢ȡ<EBA1A2><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 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<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD> false<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
//<2F><>ʽ<EFBFBD><CABD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
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
{
//ʹ<><CAB9>huffman<61><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>RLE<4C><45><EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD>ת<EFBFBD>س<EFBFBD><D8B3><EFBFBD>Ϊ64<36>ľ<EFBFBD><C4BE><EFBFBD>
flag = huffmanDecode(file);
if (!flag) return false;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>64<36><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧλ<D3A6>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//flag=deQuantity();
//if(!flag) return false;
//<2F><>zig-zag<61><67><EFBFBD><EFBFBD>
//flag=deZSort();
//if(!flag) return false;
//<2F><><EFBFBD><EFBFBD>ɢ<EFBFBD><C9A2><EFBFBD>ұ任
//if(!flag) return false;
//YCbCrתRGB
//if(!flag) return false;
}
catch (...) {
return false;
}
return true;
}
bool JPEGData::huffmanDecode(MyFStream& file)
{
try
{
//ԭͼ<D4AD><CDBC>һ<EFBFBD><D2BB>MCU<43>ж<EFBFBD><D0B6><EFBFBD>8*8<><38><EFBFBD>󣨴<EFBFBD>ʱ<EFBFBD><CAB1>YCbCr<43><72>û<EFBFBD>зֿ<D0B7><D6BF><EFBFBD>
//int MCUBlockCount=max_h_samp_factor*max_v_samp_factor;
//˳<><CBB3>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; //<2F><>ǰMCU<43><55><EFBFBD><EFBFBD>
int curValueLength = 0; //<2F><>ǰֵ<C7B0>ж<EFBFBD><D0B6><EFBFBD>λ
int curValue = 0; //<2F><>ǰ<EFBFBD><C7B0>ֵ
int curBitDequeLength = 8;//<2F><>ǰcurBitDeque<75><65><EFBFBD><EFBFBD>
int curBitPos = 0; //<2F><>ǰstring<6E><67>ȡ<EFBFBD><C8A1><EFBFBD>ڼ<EFBFBD>λ
int restart = resetInterval;//ֱ<><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::string curBitDeque = ""; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//һ<><D2BB>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>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)
{
//<2F><>curBitDeque<75><65>curBitȥ<74><C8A5>Ȩ<EFBFBD>أ<EFBFBD>curValue<75><65>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0>ֵ
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
//<2F>Ѿ<EFBFBD><D1BE>ҵ<EFBFBD><D2B5><EFBFBD>Ȩ<EFBFBD>غ<EFBFBD>λ<EFBFBD><CEBB>
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;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊdc<64><63>acֵ
curValueLength = 0;
if (valCount != 0 && weight == 0 && zeroCount == 0)
break;//<2F><><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>0
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
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];//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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);//<2F><>zig-zag<61><67><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD>zig-zag<61><67><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>棺RGB<47><42>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><E0BCAD><EFBFBD><EFBFBD>ƫС<C6AB><D0A1><EFBFBD><EFBFBD>֮ƫ<D6AE><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʱ<EFBFBD>ķ<EFBFBD>ʽ<EFBFBD>й<EFBFBD>
// deQuality(tempZ,qualityId);
// print(tempZ);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еIJ<D0B5><C4B2><EFBFBD>˵<EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>о<EFBFBD><D0BE><EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD>
// PAndNCorrect(tempZ);
IDCT(tempZ); //dct<63><74><EFBFBD>
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);
*/
// ֱ<><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>Ϊ0<CEAA><30>
if (restart > 0)
{
resetInterval--;
if (resetInterval == 0)
{
resetInterval = restart;
curDRI += 1;
curDRI &= 0x7;
//<2F><>Ҫ<EFBFBD>ڴ˴<DAB4><CBB4><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ñ<EFBFBD>ʶ
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<><31>Y, 2<><32>Cb, 3<><33>Cr
//ʽ<><CABD> 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];
//<2F>˴<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>rgbֵ
//ע<><EFBFBD>˴<EFBFBD>YCbCr<43>Ķ<EFBFBD>Ӧ<EFBFBD><D3A6>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>
// 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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰѡ<C7B0><D1A1><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
//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);
//ԭ<><D4AD> 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;
//ԭ<><D4AD>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)
{//<2F><EFBFBD><EFB5BD><EFBFBD>󻺴<EFBFBD>
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;
}
2022-07-29 08:41:34 +00:00
#define FX 0.5
#define FY 0.5
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh, int dilate)
2022-07-29 08:41:34 +00:00
: m_threshold(threshold)
, m_edge(edge)
, m_devTh(devTh)
, m_meanTh(meanTh)
, m_dilate(dilate)
2022-07-29 08:41:34 +00:00
{
}
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
{
}
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
{
if (apply(pDib, m_threshold, m_edge, m_devTh, m_meanTh, m_dilate))
2022-07-29 08:41:34 +00:00
pDib.release();
}
void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh)
{
double min, max;
cv::minMaxLoc(img, &min, &max, 0, 0, mask);
if (cv::mean(img, mask)[0] < meanTh)
return false;
return (max - min) < devTh;
}
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, double devTh, double meanTh, int dilate)
2022-07-29 08:41:34 +00:00
{
if (pDib.empty())
return true;
cv::Mat img_resize;
cv::resize(pDib, img_resize, cv::Size(), FX, FY);
2022-07-29 08:41:34 +00:00
if (img_resize.channels() == 3)
cv::cvtColor(img_resize, img_resize, cv::COLOR_BGR2GRAY);
if (dilate > 2)
{
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, dilate));
cv::Mat img_temp1;
cv::morphologyEx(img_resize, img_temp1, cv::MORPH_DILATE, element);
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilate, 1));
cv::Mat img_temp2;
cv::morphologyEx(img_resize, img_temp2, cv::MORPH_DILATE, element);
img_resize = img_temp1 & img_temp2;
}
cv::Mat threshold_img;
cv::threshold(img_resize, threshold_img, threshold, 255, cv::THRESH_BINARY);
2022-07-29 08:41:34 +00:00
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h1;
2022-11-28 08:03:11 +00:00
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
2022-07-29 08:41:34 +00:00
std::vector<cv::Point> contour;
for (const std::vector<cv::Point>& sub : contours)
for (const cv::Point& p : sub)
contour.push_back(p);
cv::RotatedRect rect = hg::getBoundingRect(contour);
rect.size = cv::Size2f(rect.size.width - edge * FX, rect.size.height - edge * FX);
2022-07-29 08:41:34 +00:00
cv::Point2f box[4];
rect.points(box);
contour.clear();
contours.clear();
for (size_t i = 0; i < 4; i++)
contour.push_back(box[i]);
contours.push_back(contour);
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
hg::fillPolys(mask, contours, cv::Scalar::all(255));
bool b = true;
if (img_resize.channels() == 3)
{
cv::Mat bgr[3];
cv::split(img_resize, bgr);
for (size_t i = 0; i < 3; i++)
{
b &= maxMinCompare(bgr[i], mask, devTh, meanTh);
if (!b) break;
}
}
else
b &= maxMinCompare(img_resize, mask, devTh, meanTh);
return b;
}
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)
2022-07-29 08:41:34 +00:00
{
case JPEG_COLOR:
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:
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;
2022-07-29 08:41:34 +00:00
}
return false;
2022-07-29 08:41:34 +00:00
}
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;
}
}