16 template <
typename Pixel>
23 template <
class Pixel>
25 FrameSource& src,
unsigned srcStartY,
unsigned srcEndY,
29 unsigned stopDstY = (dstEndY == dstHeight)
30 ? dstEndY : dstEndY - 3;
31 unsigned srcY = srcStartY, dstY = dstStartY;
32 for (; dstY < stopDstY; srcY += 1, dstY += 3) {
34 for (
int i = 0; i < 3; ++i) {
38 if (dstY != dstHeight) {
41 assert(nextLineWidth != 1);
42 this->dispatchScale(src, srcY, srcEndY, nextLineWidth,
47 template <
typename Pixel>
50 return pixelOps.template blend<1, 1>(p1, p2);
53 static const unsigned redblueMask = 0xF81F;
54 static const unsigned greenMask = 0x7E0;
56 template <
typename Pixel>
57 static Pixel bilinear(
unsigned a,
unsigned b,
unsigned x);
64 const unsigned areaB = x >> 11;
65 const unsigned areaA = 0x20 - areaB;
67 a = (a & redblueMask) | ((a & greenMask) << 16);
68 b = (b & redblueMask) | ((b & greenMask) << 16);
69 const unsigned result = ((areaA * a) + (areaB * b)) >> 5;
70 return (result & redblueMask) | ((result >> 16) & greenMask);
78 const unsigned areaB = x >> 8;
79 const unsigned areaA = 0x100 - areaB;
81 const unsigned result0 =
82 ((a & 0x00FF00FF) * areaA + (b & 0x00FF00FF) * areaB) >> 8;
83 const unsigned result1 =
84 ((a & 0xFF00FF00) >> 8) * areaA + ((b & 0xFF00FF00) >> 8) * areaB;
85 return (result0 & 0x00FF00FF) | (result1 & 0xFF00FF00);
88 template <
typename Pixel>
89 static Pixel bilinear4(
90 unsigned a,
unsigned b,
unsigned c,
unsigned d,
unsigned x,
unsigned y );
94 unsigned a,
unsigned b,
unsigned c,
unsigned d,
unsigned x,
unsigned y
98 const unsigned xy = (x * y) >> 5;
100 const unsigned areaA = 0x20 + xy - x - y;
101 const unsigned areaB = x - xy;
102 const unsigned areaC = y - xy;
103 const unsigned areaD = xy;
105 a = (a & redblueMask) | ((a & greenMask) << 16);
106 b = (b & redblueMask) | ((b & greenMask) << 16);
107 c = (c & redblueMask) | ((c & greenMask) << 16);
108 d = (d & redblueMask) | ((d & greenMask) << 16);
110 (areaA * a) + (areaB * b) + (areaC * c) + (areaD * d)
112 return (result & redblueMask) | ((result >> 16) & greenMask);
117 unsigned a,
unsigned b,
unsigned c,
unsigned d,
unsigned x,
unsigned y
121 const unsigned xy = (x * y) >> 8;
123 const unsigned areaA = (1 << 8) + xy - x - y;
124 const unsigned areaB = x - xy;
125 const unsigned areaC = y - xy;
126 const unsigned areaD = xy;
128 const unsigned result0 =
129 ((a & 0x00FF00FF) * areaA + (b & 0x00FF00FF) * areaB +
130 (c & 0x00FF00FF) * areaC + (d & 0x00FF00FF) * areaD) >> 8;
131 const unsigned result1 =
132 ((a & 0xFF00FF00) >> 8) * areaA + ((b & 0xFF00FF00) >> 8) * areaB +
133 ((c & 0xFF00FF00) >> 8) * areaC + ((d & 0xFF00FF00) >> 8) * areaD;
134 return (result0 & 0x00FF00FF) | (result1 & 0xFF00FF00);
137 template <
typename Pixel>
141 template <
unsigned x>
142 inline static Pixel blend(
unsigned a,
unsigned b);
144 template <
unsigned x,
unsigned y>
145 inline static Pixel blend(
unsigned a,
unsigned b,
unsigned c,
unsigned d);
149 template <
unsigned X,
unsigned OLD,
unsigned NEW>
152 (X >> (OLD - NEW)) + ((X >> (OLD - NEW - 1)) & 1);
155 template <
typename Pixel>
156 template <
unsigned x>
159 if (a == b)
return a;
161 const unsigned bits = (
sizeof(
Pixel) == 2) ? 5 : 8;
163 const unsigned areaA = (1 << bits) - areaB;
165 if (
sizeof(
Pixel) == 2) {
166 a = (a & redblueMask) | ((a & greenMask) << 16);
167 b = (b & redblueMask) | ((b & greenMask) << 16);
168 const unsigned result = ((areaA * a) + (areaB * b)) >> bits;
169 return (result & redblueMask) | ((result >> 16) & greenMask);
171 const unsigned result0 =
172 ((a & 0x00FF00FF) * areaA +
173 (b & 0x00FF00FF) * areaB) >> bits;
174 const unsigned result1 =
175 ((a & 0xFF00FF00) >> bits) * areaA +
176 ((b & 0xFF00FF00) >> bits) * areaB;
177 return (result0 & 0x00FF00FF) | (result1 & 0xFF00FF00);
181 template <
typename Pixel>
182 template <
unsigned wx,
unsigned wy>
184 unsigned a,
unsigned b,
unsigned c,
unsigned d)
186 const unsigned bits = (
sizeof(
Pixel) == 2) ? 5 : 8;
187 const unsigned xy = (wx * wy) >> 16;
188 const unsigned areaB =
Round<wx - xy, 16, bits>::result;
189 const unsigned areaC =
Round<wy - xy, 16, bits>::result;
191 const unsigned areaA = (1 << bits) - areaB - areaC - areaD;
193 if (
sizeof(
Pixel) == 2) {
194 a = (a & redblueMask) | ((a & greenMask) << 16);
195 b = (b & redblueMask) | ((b & greenMask) << 16);
196 c = (c & redblueMask) | ((c & greenMask) << 16);
197 d = (d & redblueMask) | ((d & greenMask) << 16);
199 (areaA * a) + (areaB * b) + (areaC * c) + (areaD * d)
201 return (result & redblueMask) | ((result >> 16) & greenMask);
203 const unsigned result0 =
204 ((a & 0x00FF00FF) * areaA +
205 (b & 0x00FF00FF) * areaB +
206 (c & 0x00FF00FF) * areaC +
207 (d & 0x00FF00FF) * areaD) >> bits;
208 const unsigned result1 =
209 ((a & 0xFF00FF00) >> bits) * areaA +
210 ((b & 0xFF00FF00) >> bits) * areaB +
211 ((c & 0xFF00FF00) >> bits) * areaC +
212 ((d & 0xFF00FF00) >> bits) * areaD;
213 return (result0 & 0x00FF00FF) | (result1 & 0xFF00FF00);
217 template <
unsigned i>
221 template <
typename Pixel>
227 template <
unsigned NX,
unsigned y,
typename Pixel>
230 unsigned sa,
unsigned sb,
unsigned sc,
unsigned sd,
231 unsigned se,
unsigned sg,
unsigned sj,
unsigned sl)
234 const unsigned x1 = ((NX - i) << 16) / NX;
235 const unsigned y1 = y;
236 const unsigned f1 = (x1 >> 1) + (0x10000 >> 2);
237 const unsigned f2 = (y1 >> 1) + (0x10000 >> 2);
238 if (y1 <= f1 && sa == sj && sa != se) {
240 }
else if (y1 >= f1 && sa == sg && sa != sl) {
242 }
else if (x1 >= f2 && sa == se && sa != sj) {
244 }
else if (x1 <= f2 && sa == sl && sa != sg) {
246 }
else if (y1 >= x1) {
248 }
else if (y1 <= x1) {
252 dp, sa, sb, sc, sd, se, sg, sj, sl );
255 template <
unsigned NX,
unsigned y,
typename Pixel>
258 unsigned sa,
unsigned sb,
unsigned sc,
unsigned sd,
259 unsigned sf,
unsigned sh,
unsigned si,
unsigned sk)
262 const unsigned x1 = ((NX - i) << 16) / NX;
263 const unsigned x2 = 0x10000 - x1;
264 const unsigned y1 = y;
265 const unsigned y2 = 0x10000 - y1;
266 const unsigned f1 = (x1 >> 1) + (0x10000 >> 2);
267 const unsigned f2 = (y1 >> 1) + (0x10000 >> 2);
268 if (y2 >= f1 && sb == sh && sb != sf) {
270 }
else if (y2 <= f1 && sb == si && sb != sk) {
272 }
else if (x2 >= f2 && sb == sf && sb != sh) {
274 }
else if (x2 <= f2 && sb == sk && sb != si) {
276 }
else if (y2 >= x1) {
278 }
else if (y2 <= x1) {
282 dp, sa, sb, sc, sd, sf, sh, si, sk );
285 template <
unsigned NX,
unsigned y,
typename Pixel>
287 Pixel*& dp,
unsigned sa,
unsigned sb,
unsigned sc,
unsigned sd)
289 const unsigned x = ((NX - i) << 16) / NX;
298 template <
typename Pixel>
301 template <
unsigned NX,
unsigned y,
typename Pixel>
303 Pixel*& ,
unsigned ,
unsigned ,
304 unsigned ,
unsigned ,
unsigned ,
305 unsigned ,
unsigned ,
unsigned ) { }
307 template <
unsigned NX,
unsigned y,
typename Pixel>
309 Pixel*& ,
unsigned ,
unsigned ,
310 unsigned ,
unsigned ,
unsigned ,
311 unsigned ,
unsigned ,
unsigned ) { }
313 template <
unsigned NX,
unsigned y,
typename Pixel>
315 unsigned ,
unsigned ,
unsigned ) { }
318 template <
unsigned i>
322 template <
unsigned NX,
unsigned NY,
typename Pixel>
324 const Pixel* __restrict src0,
const Pixel* __restrict src1,
325 const Pixel* __restrict src2,
const Pixel* __restrict src3,
330 const unsigned y1 = ((NY - i) << 16) / NY;
337 for (
unsigned srcX = 0; srcX < srcWidth; srcX++) {
338 const unsigned pos0 = pos1;
341 pos3 = std::min(pos1 + 3, srcWidth) - 1;
349 if (sa == sb && sc == sd && sa == sc) {
352 }
else if (sa == sd && sb != sc) {
355 dp, sa, sb, sc, sd, src0[pos1], src1[pos0], src2[pos3], src3[pos2]
357 }
else if (sb == sc && sa != sd) {
360 dp, sa, sb, sc, sd, src0[pos2], src2[pos0], src1[pos3], src3[pos1]
372 LineRepeater<i - 1>::template scaleFixedLine<NX, NY, Pixel>(
373 src0, src1, src2, src3, srcWidth, dst, dstY);
380 template <
unsigned NX,
unsigned NY,
typename Pixel>
383 const Pixel* ,
unsigned ,
388 template <
typename Pixel>
389 template <
unsigned NX,
unsigned NY>
390 void SaI3xScaler<Pixel>::scaleFixed(FrameSource& src,
391 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
392 ScalerOutput<Pixel>& dst,
unsigned dstStartY,
unsigned dstEndY)
394 assert(dst.getWidth() == srcWidth * NX);
395 assert(dst.getHeight() == src.getHeight() * NY);
397 int srcY = srcStartY;
398 const Pixel* src0 = src.getLinePtr<
Pixel>(srcY - 1, srcWidth);
399 const Pixel* src1 = src.getLinePtr<
Pixel>(srcY + 0, srcWidth);
400 const Pixel* src2 = src.getLinePtr<
Pixel>(srcY + 1, srcWidth);
401 for (
unsigned dstY = dstStartY; dstY < dstEndY; srcY++) {
402 const Pixel* src3 = src.getLinePtr<
Pixel>(srcY + 2, srcWidth);
403 LineRepeater<NY>::template scaleFixedLine<NX, NY, Pixel>(
404 src0, src1, src2, src3, srcWidth, dst, dstY);
411 template <
typename Pixel>
412 void SaI3xScaler<Pixel>::scaleAny(FrameSource& src,
413 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
414 ScalerOutput<Pixel>& dst,
unsigned dstStartY,
unsigned dstEndY) __restrict
417 const unsigned wfinish = (srcWidth - 1) << 16;
418 const unsigned dw = wfinish / (dst.getWidth() - 1);
419 const unsigned hfinish = (src.getHeight() - 1) << 16;
420 const unsigned dh = hfinish / (dst.getHeight() - 1);
423 for (
unsigned dstY = dstStartY; dstY < dstEndY; dstY++) {
425 int line = srcStartY + (h >> 16);
427 const Pixel* __restrict src0 = src.getLinePtr<
Pixel>(line - 1, srcWidth);
428 const Pixel* __restrict src1 = src.getLinePtr<
Pixel>(line + 0, srcWidth);
429 const Pixel* __restrict src2 = src.getLinePtr<
Pixel>(line + 1, srcWidth);
430 const Pixel* __restrict src3 = src.getLinePtr<
Pixel>(line + 2, srcWidth);
433 Pixel* dstLine = dst.acquireLine(dstY);
434 Pixel* __restrict dp = dstLine;
437 const unsigned y1 = h & 0xffff;
438 const unsigned y2 = 0x10000 - y1;
447 for (
unsigned w = 0; w < wfinish; ) {
448 const unsigned pos0 = pos1;
451 pos3 = std::min(pos1 + 3, srcWidth) - 1;
459 if (A == B && C == D && A == C) {
463 }
while ((w >> 16) == pos1);
464 }
else if (A == D && B != C) {
467 const unsigned x1 = w & 0xffff;
468 const unsigned f1 = (x1 >> 1) + (0x10000 >> 2);
469 const unsigned f2 = (y1 >> 1) + (0x10000 >> 2);
471 if (y1 <= f1 && A == src2[pos3] && A != src0[pos1]) {
472 product1 = bilinear<Pixel>(A, B, f1 - y1);
473 }
else if (y1 >= f1 && A == src1[pos0] && A != src3[pos2]) {
474 product1 = bilinear<Pixel>(A, C, y1 - f1);
475 }
else if (x1 >= f2 && A == src0[pos1] && A != src2[pos3]) {
476 product1 = bilinear<Pixel>(A, B, x1 - f2);
477 }
else if (x1 <= f2 && A == src3[pos2] && A != src1[pos0]) {
478 product1 = bilinear<Pixel>(A, C, f2 - x1);
479 }
else if (y1 >= x1) {
480 product1 = bilinear<Pixel>(A, C, y1 - x1);
483 product1 = bilinear<Pixel>(A, B, x1 - y1);
487 }
while ((w >> 16) == pos1);
488 }
else if (B == C && A != D) {
491 const unsigned x1 = w & 0xffff;
492 const unsigned x2 = 0x10000 - x1;
493 const unsigned f1 = (x1 >> 1) + (0x10000 >> 2);
494 const unsigned f2 = (y1 >> 1) + (0x10000 >> 2);
496 if (y2 >= f1 && B == src2[pos0] && B != src0[pos2]) {
497 product1 = bilinear<Pixel>(B, A, y2 - f1);
498 }
else if (y2 <= f1 && B == src1[pos3] && B != src3[pos1]) {
499 product1 = bilinear<Pixel>(B, D, f1 - y2);
500 }
else if (x2 >= f2 && B == src0[pos2] && B != src2[pos0]) {
501 product1 = bilinear<Pixel>(B, A, x2 - f2);
502 }
else if (x2 <= f2 && B == src3[pos1] && B != src1[pos3]) {
503 product1 = bilinear<Pixel>(B, D, f2 - x2);
504 }
else if (y2 >= x1) {
505 product1 = bilinear<Pixel>(B, A, y2 - x1);
508 product1 = bilinear<Pixel>(B, D, x1 - y2);
512 }
while ((w >> 16) == pos1);
516 const unsigned x1 = w & 0xffff;
517 *dp++ = bilinear4<Pixel>(A, B, C, D, x1, y1);
519 }
while ((w >> 16) == pos1);
522 dst.releaseLine(dstY, dstLine);
526 template <
typename Pixel>
528 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
531 scaleFixed<3, 3>(src, srcStartY, srcEndY, srcWidth, dst, dstStartY, dstEndY);