code_device/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp

999 lines
30 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
#define FX 0.5
#define FY 0.5
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh, int dilate)
: m_threshold(threshold)
, m_edge(edge)
, m_devTh(devTh)
, m_meanTh(meanTh)
, m_dilate(dilate)
{
}
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
{
}
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
{
if (apply(pDib, m_threshold, m_edge, m_devTh, m_meanTh, m_dilate))
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)
{
if (pDib.empty())
return true;
cv::Mat img_resize;
cv::resize(pDib, img_resize, cv::Size(), FX, FY);
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);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h1;
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
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);
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)
{
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;
}
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;
}
}