18 template<std::
unsigned_
integral Pixel>
25 template<std::
unsigned_
integral Pixel>
27 FrameSource& src,
unsigned srcStartY,
unsigned srcEndY,
31 unsigned stopDstY = (dstEndY == dstHeight)
32 ? dstEndY : dstEndY - 2;
33 unsigned srcY = srcStartY, dstY = dstStartY;
34 for (; dstY < stopDstY; srcY += 1, dstY += 2) {
39 if (dstY != dstHeight) {
42 assert(nextLineWidth != 1);
43 this->dispatchScale(src, srcY, srcEndY, nextLineWidth,
48 template<std::
unsigned_
integral Pixel>
51 return pixelOps.template blend<1, 1>(p1, p2);
54 template<std::
unsigned_
integral Pixel>
55 void SaI2xScaler<Pixel>::scaleLine1on2(
56 const Pixel* __restrict srcLine0,
const Pixel* __restrict srcLine1,
57 const Pixel* __restrict srcLine2,
const Pixel* __restrict srcLine3,
58 Pixel* __restrict dstUpper,
Pixel* __restrict dstLower,
62 for (
auto x :
xrange(srcWidth)) {
69 unsigned xl =
x ?
x - 1 : 0;
70 unsigned xr =
std::min(
x + 1, srcWidth - 1);
71 unsigned xrr =
std::min(
x + 2, srcWidth - 1);
77 Pixel colorI = srcLine0[xl];
78 Pixel colorE = srcLine0[
x];
79 Pixel colorF = srcLine0[xr];
80 Pixel colorJ = srcLine0[xrr];
82 Pixel colorG = srcLine1[xl];
83 Pixel colorA = srcLine1[
x];
84 Pixel colorB = srcLine1[xr];
85 Pixel colorK = srcLine1[xrr];
87 Pixel colorH = srcLine2[xl];
88 Pixel colorC = srcLine2[
x];
89 Pixel colorD = srcLine2[xr];
90 Pixel colorL = srcLine2[xrr];
92 Pixel colorM = srcLine3[xl];
93 Pixel colorN = srcLine3[
x];
94 Pixel colorO = srcLine3[xr];
97 Pixel product, product1, product2;
98 if (colorA == colorD && colorB != colorC) {
99 product = ((colorA == colorE && colorB == colorL) ||
100 (colorA == colorC && colorA == colorF &&
101 colorB != colorE && colorB == colorJ))
103 : blend(colorA, colorB);
104 product1 = ((colorA == colorG && colorC == colorO) ||
105 (colorA == colorB && colorA == colorH &&
106 colorG != colorC && colorC == colorM))
108 : blend(colorA, colorC);
110 }
else if (colorB == colorC && colorA != colorD) {
111 product = ((colorB == colorF && colorA == colorH) ||
112 (colorB == colorE && colorB == colorD &&
113 colorA != colorF && colorA == colorI))
115 : blend(colorA, colorB);
116 product1 = ((colorC == colorH && colorA == colorF) ||
117 (colorC == colorG && colorC == colorD &&
118 colorA != colorH && colorA == colorI))
120 : blend(colorA, colorC);
122 }
else if (colorA == colorD && colorB == colorC) {
123 if (colorA == colorB) {
124 product = product1 = product2 = colorA;
127 if (colorE == colorG) {
128 if (colorA == colorE) r--;
129 else if (colorB == colorE) r++;
131 if (colorF == colorK) {
132 if (colorA == colorF) r--;
133 else if (colorB == colorF) r++;
135 if (colorH == colorN) {
136 if (colorA == colorH) r--;
137 else if (colorB == colorH) r++;
139 if (colorL == colorO) {
140 if (colorA == colorL) r--;
141 else if (colorB == colorL) r++;
143 product = product1 = blend(colorA, colorB);
144 product2 = r > 0 ? colorA : (r < 0 ? colorB : product);
147 product = (colorA == colorC && colorA == colorF &&
148 colorB != colorE && colorB == colorJ)
150 : ((colorB == colorE && colorB == colorD &&
151 colorA != colorF && colorA == colorI)
153 : blend(colorA, colorB));
154 product1 = (colorA == colorB && colorA == colorH &&
155 colorG != colorC && colorC == colorM)
157 : ((colorC == colorG && colorC == colorD &&
158 colorA != colorH && colorA == colorI)
160 : blend(colorA, colorC));
162 blend(colorA, colorB),
163 blend(colorC, colorD));
166 dstUpper[
x * 2 + 0] = colorA;
167 dstUpper[
x * 2 + 1] = product;
168 dstLower[
x * 2 + 0] = product1;
169 dstLower[
x * 2 + 1] = product2;
173 template<std::
unsigned_
integral Pixel>
174 void SaI2xScaler<Pixel>::scaleLine1on1(
175 const Pixel* __restrict srcLine0,
const Pixel* __restrict srcLine1,
176 const Pixel* __restrict srcLine2,
const Pixel* __restrict srcLine3,
177 Pixel* __restrict dstUpper,
Pixel* __restrict dstLower,
183 dstUpper[0] = srcLine1[0];
184 dstLower[0] = blend(srcLine1[0], srcLine2[0]);
185 for (
auto x :
xrange(1u, srcWidth - 1)) {
192 Pixel colorI = srcLine0[
x - 1];
194 Pixel colorF = srcLine0[
x + 1];
196 Pixel colorG = srcLine1[
x - 1];
197 Pixel colorA = srcLine1[
x];
198 Pixel colorB = srcLine1[
x + 1];
200 Pixel colorH = srcLine2[
x - 1];
201 Pixel colorC = srcLine2[
x];
202 Pixel colorD = srcLine2[
x + 1];
204 Pixel colorM = srcLine3[
x - 1];
206 Pixel colorO = srcLine3[
x + 1];
209 if (colorA == colorD && colorB != colorC) {
210 product1 = ((colorA == colorG && colorC == colorO) ||
211 (colorA == colorB && colorA == colorH &&
212 colorG != colorC && colorC == colorM))
214 : blend(colorA, colorC);
215 }
else if (colorB == colorC && colorA != colorD) {
216 product1 = ((colorC == colorH && colorA == colorF) ||
217 (colorC == colorG && colorC == colorD &&
218 colorA != colorH && colorA == colorI))
220 : blend(colorA, colorC);
221 }
else if (colorA == colorD && colorB == colorC) {
222 product1 = (colorA == colorC)
224 : blend(colorA, colorC);
226 product1 = (colorA == colorB && colorA == colorH &&
227 colorG != colorC && colorC == colorM)
229 : ((colorC == colorG && colorC == colorD &&
230 colorA != colorH && colorA == colorI)
232 : blend(colorA, colorC));
235 dstUpper[
x] = colorA;
236 dstLower[
x] = product1;
238 dstUpper[srcWidth - 1] = srcLine1[srcWidth - 1];
239 dstLower[srcWidth - 1] =
240 blend(srcLine1[srcWidth - 1], srcLine2[srcWidth - 1]);
243 template<std::
unsigned_
integral Pixel>
245 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
248 assert(dst.
getWidth() == srcWidth * 2);
255 int srcY = srcStartY;
256 auto* srcLine0 = src.
getLinePtr(srcY - 1, srcWidth, buf0);
257 auto* srcLine1 = src.
getLinePtr(srcY + 0, srcWidth, buf1);
258 auto* srcLine2 = src.
getLinePtr(srcY + 1, srcWidth, buf2);
260 for (
unsigned dstY = dstStartY; dstY < dstEndY; srcY += 1, dstY += 2) {
261 auto* srcLine3 = src.
getLinePtr(srcY + 2, srcWidth, buf3);
264 scaleLine1on2(srcLine0, srcLine1, srcLine2, srcLine3,
265 dstUpper, dstLower, srcWidth);
271 std::swap(buf0, buf1);
272 std::swap(buf1, buf2);
273 std::swap(buf2, buf3);
277 template<std::
unsigned_
integral Pixel>
279 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
289 int srcY = srcStartY;
290 auto* srcLine0 = src.
getLinePtr(srcY - 1, srcWidth, buf0);
291 auto* srcLine1 = src.
getLinePtr(srcY + 0, srcWidth, buf1);
292 auto* srcLine2 = src.
getLinePtr(srcY + 1, srcWidth, buf2);
294 for (
unsigned dstY = dstStartY; dstY < dstEndY; srcY += 1, dstY += 2) {
295 auto* srcLine3 = src.
getLinePtr(srcY + 2, srcWidth, buf3);
298 scaleLine1on1(srcLine0, srcLine1, srcLine2, srcLine3,
299 dstUpper, dstLower, srcWidth);
305 std::swap(buf0, buf1);
306 std::swap(buf1, buf2);
307 std::swap(buf2, buf3);
Interface for getting lines from a video frame.
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
virtual unsigned getLineWidth(unsigned line) const =0
Gets the number of display pixels on the given line.
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
2xSaI algorithm: edge-detection which produces a rounded look.
SaI2xScaler(const PixelOperations< Pixel > &pixelOps)
void scale1x1to2x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scaleBlank1to2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale1x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Base class for 2x scalers.
virtual Pixel * acquireLine(unsigned y)=0
virtual unsigned getWidth() const =0
virtual unsigned getHeight() const =0
virtual void fillLine(unsigned y, Pixel color)=0
virtual void releaseLine(unsigned y, Pixel *buf)=0
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
This file implemented 3 utility functions:
constexpr KeyMatrixPosition x
Keyboard bindings.
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)