999 lines
30 KiB
C++
999 lines
30 KiB
C++
#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;
|
||
}
|
||
}
|