-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdelogo_engine.hpp
163 lines (136 loc) · 4.68 KB
/
delogo_engine.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include "logo.h"
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <assert.h>
#if _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#if !_WIN32
#define __stdcall
// Use standard C11 aligned malloc
#define _aligned_malloc(size, alignment) aligned_alloc(alignment, size)
#define _aligned_free free
#endif
using namespace std;
#define MATH_MIN(a,b) ((a) > (b) ? (b) : (a))
// To support future AVX512, data needs be aligned.
// Logo is 16 bit so mod-32 pixel padding is required.
// Data is 8..16 bit so mod-64 pixel padding is required.
// YUV420 has subsampling so 128 pixel padding is required.
// However we are only supporting SSE4.1 right now.
#define MIN_MODULO 32
enum EOperation { ADD_LOGO, ERASE_LOGO };
template <EOperation EOP>
class DelogoEngine {
protected:
// Store ((1<<30) / real_value) for aligned_Xd
int** logo_yc, ** logo_yd, ** logo_uc, ** logo_ud, ** logo_vc, ** logo_vd;
int _wsubsampling, _hsubsampling;
int _ebpc, _cutoff;
LOGO_HEADER logoheader;
public:
LOGO_HEADER src_logoheader;
DelogoEngine(const char* logofile, const char* logoname, int bitdepth, int wsubsampling, int hsubsampling, int left, int top, bool mono, int cutoff) :
logo_yc(nullptr), logo_yd(nullptr),
logo_uc(nullptr), logo_ud(nullptr),
logo_vc(nullptr), logo_vd(nullptr),
_wsubsampling(wsubsampling), _hsubsampling(hsubsampling),
_ebpc(bitdepth), _cutoff(cutoff)
{
auto data = readLogo(logofile, logoname);
data = shiftLogo(data, left, top);
if (data)
convertLogo(data, mono);
}
~DelogoEngine(void)
{
for (int y = 0; y < logoheader.h; y++) {
_aligned_free(logo_yc[y]);
_aligned_free(logo_yd[y]);
}
int hstep = 1 << _hsubsampling;
for (int i = 0; i < logoheader.h / hstep; i++) {
_aligned_free(logo_uc[i]);
_aligned_free(logo_ud[i]);
_aligned_free(logo_vc[i]);
_aligned_free(logo_vd[i]);
}
delete[] logo_yc;
delete[] logo_yd;
delete[] logo_uc;
delete[] logo_ud;
delete[] logo_vc;
delete[] logo_vd;
}
LOGO_PIXEL* readLogo(const char* logofile, const char* logoname);
LOGO_PIXEL* shiftLogo(LOGO_PIXEL* data, int left, int top);
void convertLogo(LOGO_PIXEL* data, bool mono);
template <typename PIX>
void processImage(unsigned char* ptr, int stride, int maxwidth, int maxheight, int plane, double opacity);
template <typename PIX>
void realProcess(PIX* cellptr, int upbound, int* array_c, int* array_d);
// Old algorithm: AUY2Y((AUY * MAXDP - C * DP) / (MAXDP - DP) + 0.5)
// New algorithm: (Y * MAXDP - n * MAXDP - C * DP * m) / (MAXDP - DP) + n
// \===== offset =====/ \ maxdp_dp / \== bonus
// Where m and n are parameters of AUYtoY, thus
// m = 219/4096, n = 67584/4096
// Y' = (Y * MAXDP + YC) / YDP
int AUYC2YC(int auy_color, int auy_dp) {
// Computing in <<12
const int m = 219;
const int n = 67584;
int maxdp_dp = LOGO_MAX_DP - auy_dp;
int offset = n * LOGO_MAX_DP + auy_color * auy_dp * m;
int bonus = n * maxdp_dp;
return bonus - offset;
}
int YC2FadeYC(int y_color, int y_dp, double opacity) {
// Computing in <<12
// const int m = 219;
const int n = 67584;
if (opacity > 1 - 1e-2)
return y_color;
if (opacity < 1e-2)
return 0;
int auy_dp = LOGO_MAX_DP - y_dp / 4;
int bonus = n * y_dp / 4;
int offset = bonus - y_color;
int cpm = offset - n * LOGO_MAX_DP;
cpm = static_cast<int>(cpm * opacity);
offset = n * LOGO_MAX_DP + cpm;
bonus = static_cast<int>(n * (LOGO_MAX_DP - auy_dp * opacity));
return bonus - offset;
}
int AUCC2CC(int auc_color, int auc_dp) {
// Computing in <<8, storing in <<12
const int m = 14;
const int n = 32896;
int maxdp_dp = LOGO_MAX_DP - auc_dp;
int offset = n * LOGO_MAX_DP + auc_color * auc_dp * m;
int bonus = n * maxdp_dp;
return (bonus - offset) * 16;
}
int CC2FadeCC(int c_color, int c_dp, double opacity) {
// Computing in <<8, storing in <<12
// const int m = 14;
const int n = 32896;
if (opacity > 1 - 1e-2)
return c_color;
if (opacity < 1e-2)
return 0;
int auc_dp = LOGO_MAX_DP - c_dp / 4;
int bonus = n * c_dp / 4;
int offset = bonus - c_color / 16;
int cpm = offset - n * LOGO_MAX_DP;
cpm = static_cast<int>(cpm * opacity);
offset = n * LOGO_MAX_DP + cpm;
bonus = static_cast<int>(n * (LOGO_MAX_DP - auc_dp * opacity));
return (bonus - offset) * 16;
}
};