46 #if defined(__GNUC__) && !defined(__clang__) && !defined(__WIN32__) // We only want this for gcc, not clang or tdm-gcc
47 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8 )
48 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" //Suppress uninitialized variables warnings on GCC <= 4.8.x
54 template <u
int32_t N>
inline
55 unsigned char getByte(
uint32_t val) {
return static_cast<unsigned char>((val >> (8 * N)) & 0xff); }
57 inline unsigned char getRed (
uint32_t val) {
return getByte<2>(
val); }
58 inline unsigned char getGreen(
uint32_t val) {
return getByte<1>(
val); }
59 inline unsigned char getBlue (
uint32_t val) {
return getByte<0>(
val); }
61 template <
class T>
inline
65 return value < 0 ? -value :
value;
71 const uint32_t alphaMask = 0xff000000;
73 template <
unsigned int N,
unsigned int M>
inline
84 if (!col_alpha)
return;
100 dst = (redMask & ((col & redMask ) * N + (dst & redMask ) * (M - N)) / M) |
101 (greenMask & ((col & greenMask ) * N + (dst & greenMask ) * (M - N)) / M) |
102 (blueMask & ((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M) |
103 (alphaMask & (((col_alpha * N + dst_alpha * (M - N)) / M) << 24));
160 return (redMask & static_cast<uint32_t>((pix1 & redMask ) * alpha + (pix2 & redMask ) * (1 - alpha))) |
161 (greenMask &
static_cast<uint32_t>((pix1 & greenMask) * alpha + (pix2 & greenMask) * (1 -
alpha))) |
162 (blueMask & static_cast<uint32_t>((pix1 & blueMask ) * alpha + (pix2 & blueMask ) * (1 - alpha)));
166 uint32_t* byteAdvance(
uint32_t* ptr,
int bytes) {
return reinterpret_cast< uint32_t*
>(
reinterpret_cast< char*
>(ptr) + bytes); }
167 const uint32_t* byteAdvance(
const uint32_t* ptr,
int bytes) {
return reinterpret_cast<const uint32_t*
>(
reinterpret_cast<const char*
>(ptr) + bytes); }
172 void fillBlock(
uint32_t* trg,
int pitch,
uint32_t col,
int blockWidth,
int blockHeight)
177 for (
int y = 0;
y < blockHeight; ++
y, trg = byteAdvance(trg, pitch))
178 for (
int x = 0;
x < blockWidth; ++
x)
183 void fillBlock(
uint32_t* trg,
int pitch,
uint32_t col,
int n) { fillBlock(trg, pitch, col, n, n); }
187 #define FORCE_INLINE __forceinline
188 #elif defined __GNUC__
189 #define FORCE_INLINE __attribute__((always_inline)) inline
191 #define FORCE_INLINE inline
204 template <RotationDegree rotDeg,
size_t I,
size_t J,
size_t N>
205 struct MatrixRotation;
207 template <
size_t I,
size_t J,
size_t N>
208 struct MatrixRotation<ROT_0, I, J, N>
210 static const size_t I_old = I;
211 static const size_t J_old = J;
214 template <RotationDegree rotDeg,
size_t I,
size_t J,
size_t N>
215 struct MatrixRotation
217 static const size_t I_old = N - 1 - MatrixRotation<static_cast<RotationDegree>(rotDeg - 1), I, J, N>::J_old;
218 static const size_t J_old = MatrixRotation<static_cast<RotationDegree>(rotDeg - 1), I, J, N>::I_old;
222 template <
size_t N, RotationDegree rotDeg>
226 OutputMatrix(
uint32_t* out,
int outWidth) :
228 outWidth_(outWidth) {}
230 template <
size_t I,
size_t J>
233 static const size_t I_old = MatrixRotation<rotDeg, I, J, N>::I_old;
234 static const size_t J_old = MatrixRotation<rotDeg, I, J, N>::J_old;
235 return *(out_ + J_old + I_old * outWidth_);
244 template <
class T>
inline
300 void rgbtoLab(
uint32_t c,
unsigned char& L,
signed char& A,
signed char& B)
305 double r = getRed (c) / 255.0;
306 double g = getGreen(c) / 255.0;
307 double b = getBlue (c) / 255.0;
309 r = r > 0.04045 ? std::pow(( r + 0.055 ) / 1.055, 2.4) : r / 12.92;
310 r = g > 0.04045 ? std::pow(( g + 0.055 ) / 1.055, 2.4) : g / 12.92;
311 r = b > 0.04045 ? std::pow(( b + 0.055 ) / 1.055, 2.4) : b / 12.92;
317 double x = 0.4124564 * r + 0.3575761 * g + 0.1804375 *
b;
318 double y = 0.2126729 * r + 0.7151522 * g + 0.0721750 *
b;
319 double z = 0.0193339 * r + 0.1191920 * g + 0.9503041 *
b;
321 const double refX = 95.047;
322 const double refY = 100.000;
323 const double refZ = 108.883;
324 double var_X = x / refX;
325 double var_Y = y / refY;
326 double var_Z = z / refZ;
328 var_X = var_X > 0.008856 ? std::pow(var_X, 1.0 / 3) : 7.787 * var_X + 4.0 / 29;
329 var_Y = var_Y > 0.008856 ? std::pow(var_Y, 1.0 / 3) : 7.787 * var_Y + 4.0 / 29;
330 var_Z = var_Z > 0.008856 ? std::pow(var_Z, 1.0 / 3) : 7.787 * var_Z + 4.0 / 29;
332 L =
static_cast<unsigned char>(116 * var_Y - 16);
333 A =
static_cast< signed char>(500 * (var_X - var_Y));
334 B =
static_cast< signed char>(200 * (var_Y - var_Z));
342 unsigned char L1 = 0;
345 rgbtoLab(pix1, L1, a1, b1);
347 unsigned char L2 = 0;
350 rgbtoLab(pix2, L2, a2, b2);
356 return std::sqrt(square(1.0 * L1 - L2) +
357 square(1.0 * a1 - a2) +
358 square(1.0 * b1 - b2));
447 const double r_diff =
static_cast<int>(getRed (pix1)) - getRed (pix2);
448 const double g_diff =
static_cast<int>(getGreen(pix1)) - getGreen(pix2);
449 const double b_diff =
static_cast<int>(getBlue (pix1)) - getBlue (pix2);
452 return std::sqrt(square(r_diff) + square(g_diff) + square(b_diff));
461 const double r_diff =
static_cast<int>(getRed (pix1)) - getRed (pix2);
462 const double g_diff =
static_cast<int>(getGreen(pix1)) - getGreen(pix2);
463 const double b_diff =
static_cast<int>(getBlue (pix1)) - getBlue (pix2);
465 const double r_avg = (
static_cast<double>(getRed(pix1)) + getRed(pix2)) / 2;
466 return std::sqrt((2 + r_avg / 255) * square(r_diff) + 4 * square(g_diff) + (2 + (255 - r_avg) / 255) * square(b_diff));
475 const int r_diff =
static_cast<int>(getRed (pix1)) - getRed (pix2);
476 const int g_diff =
static_cast<int>(getGreen(pix1)) - getGreen(pix2);
477 const int b_diff =
static_cast<int>(getBlue (pix1)) - getBlue (pix2);
479 const double k_b = 0.0722;
480 const double k_r = 0.2126;
481 const double k_g = 1 - k_b - k_r;
483 const double scale_b = 0.5 / (1 - k_b);
484 const double scale_r = 0.5 / (1 - k_r);
486 const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff;
487 const double c_b = scale_b * (b_diff -
y);
488 const double c_r = scale_r * (r_diff -
y);
491 return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r));
500 const double r_diff =
static_cast<int>(getRed (pix1)) - getRed (pix2);
501 const double g_diff =
static_cast<int>(getGreen(pix1)) - getGreen(pix2);
502 const double b_diff =
static_cast<int>(getBlue (pix1)) - getBlue (pix2);
505 const double w_b = 0.114;
506 const double w_r = 0.299;
507 const double w_g = 1 - w_r - w_b;
509 const double u_max = 0.436;
510 const double v_max = 0.615;
512 const double scale_u = u_max / (1 - w_b);
513 const double scale_v = v_max / (1 - w_r);
515 double y = w_r * r_diff + w_g * g_diff + w_b * b_diff;
516 double u = scale_u * (b_diff -
y);
517 double v = scale_v * (r_diff -
y);
520 const double eps = 0.5;
522 assert(std::abs(y) <= 255 + eps);
523 assert(std::abs(u) <= 255 * 2 * u_max + eps);
524 assert(std::abs(v) <= 255 * 2 * v_max + eps);
526 return std::sqrt(square(luminanceWeight * y) + square(u) + square(v));
542 return distYCbCr(pix1, pix2, luminanceWeight);
588 BlendResult preProcessCorners(
const Kernel_4x4& ker,
const xbrz::ScalerCfg& cfg)
592 if ((ker.f == ker.g &&
600 const int weight = 4;
601 double jg = dist(ker.i, ker.f) + dist(ker.f, ker.c) + dist(ker.n, ker.k) + dist(ker.k, ker.h) + weight * dist(ker.j, ker.g);
602 double fk = dist(ker.e, ker.j) + dist(ker.j, ker.o) + dist(ker.b, ker.g) + dist(ker.g, ker.l) + weight * dist(ker.f, ker.k);
607 if (ker.f != ker.g && ker.f != ker.j)
608 result.blend_f = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;
610 if (ker.k != ker.j && ker.k != ker.g)
611 result.blend_k = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;
616 if (ker.j != ker.f && ker.j != ker.k)
617 result.blend_j = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;
619 if (ker.g != ker.f && ker.g != ker.k)
620 result.blend_g = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL;
635 #define DEF_GETTER(x) template <RotationDegree rotDeg> uint32_t inline get_##x(const Kernel_3x3& ker) { return ker.x; }
642 #define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_90>(const Kernel_3x3& ker) { return ker.y; }
648 #define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_180>(const Kernel_3x3& ker) { return ker.y; }
654 #define DEF_GETTER(x, y) template <> inline uint32_t get_##x<ROT_270>(const Kernel_3x3& ker) { return ker.y; }
662 inline BlendType getTopR (
unsigned char b) {
return static_cast<BlendType>(0x3 & (b >> 2)); }
663 inline BlendType getBottomR(
unsigned char b) {
return static_cast<BlendType>(0x3 & (b >> 4)); }
664 inline BlendType getBottomL(
unsigned char b) {
return static_cast<BlendType>(0x3 & (b >> 6)); }
666 inline void setTopL (
unsigned char& b,
BlendType bt) { b |= bt; }
667 inline void setTopR (
unsigned char& b,
BlendType bt) { b |= (bt << 2); }
668 inline void setBottomR(
unsigned char& b,
BlendType bt) { b |= (bt << 4); }
669 inline void setBottomL(
unsigned char& b,
BlendType bt) { b |= (bt << 6); }
671 inline bool blendingNeeded(
unsigned char b) {
return b != 0; }
673 template <RotationDegree rotDeg>
inline
674 unsigned char rotateBlendInfo(
unsigned char b) {
return b; }
675 template <>
inline unsigned char rotateBlendInfo<ROT_90 >(
unsigned char b) {
return ((b << 2) | (b >> 6)) & 0xff; }
676 template <>
inline unsigned char rotateBlendInfo<ROT_180>(
unsigned char b) {
return ((b << 4) | (b >> 4)) & 0xff; }
677 template <>
inline unsigned char rotateBlendInfo<ROT_270>(
unsigned char b) {
return ((b << 6) | (b >> 2)) & 0xff; }
681 int debugPixelX = -1;
682 int debugPixelY = 84;
683 bool breakIntoDebugger =
false;
696 template <
class Scaler, RotationDegree rotDeg>
698 void scalePixel(
const Kernel_3x3& ker,
700 unsigned char blendInfo,
703 #define a get_a<rotDeg>(ker)
704 #define b get_b<rotDeg>(ker)
705 #define c get_c<rotDeg>(ker)
706 #define d get_d<rotDeg>(ker)
707 #define e get_e<rotDeg>(ker)
708 #define f get_f<rotDeg>(ker)
709 #define g get_g<rotDeg>(ker)
710 #define h get_h<rotDeg>(ker)
711 #define i get_i<rotDeg>(ker)
714 (
void) breakIntoDebugger;
719 const unsigned char blend = rotateBlendInfo<rotDeg>(blendInfo);
721 if (getBottomR(blend) >= BLEND_NORMAL)
727 const uint32_t px = dist(e, f) <= dist(e, h) ? f :
h;
729 OutputMatrix<Scaler::scale, rotDeg> out(target, trgWidth);
731 bool doLineBlend =
true;
733 if (getBottomR(blend) >= BLEND_DOMINANT)
737 else if (getTopR(blend) != BLEND_NONE && !eq(e, g))
739 else if (getBottomL(blend) != BLEND_NONE && !eq(e, c))
743 else if (eq(g, h) && eq(h , i) && eq(i, f) && eq(f, c) && !eq(e, i))
746 else doLineBlend =
true;
751 const double fg = dist(f, g);
752 const double hc = dist(h, c);
760 Scaler::blendLineSteepAndShallow(px, out);
762 Scaler::blendLineShallow(px, out);
767 Scaler::blendLineSteep(px, out);
769 Scaler::blendLineDiagonal(px,out);
773 Scaler::blendCorner(px, out);
788 template <
class Scaler>
791 yFirst = std::max(yFirst, 0);
792 yLast = std::min(yLast, srcHeight);
793 if (yFirst >= yLast || srcWidth <= 0)
800 const int bufferSize = srcWidth;
801 unsigned char* preProcBuffer =
reinterpret_cast<unsigned char*
>(trg + yLast * Scaler::scale * trgWidth) - bufferSize;
802 std::fill(preProcBuffer, preProcBuffer + bufferSize, 0);
809 const int y = yFirst - 1;
811 const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);
812 const uint32_t* s_0 = src + srcWidth *
y;
813 const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);
814 const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);
816 for (
int x = 0; x < srcWidth; ++
x)
818 const int x_m1 = std::max(x - 1, 0);
819 const int x_p1 = std::min(x + 1, srcWidth - 1);
820 const int x_p2 = std::min(x + 2, srcWidth - 1);
843 const BlendResult
res = preProcessCorners(ker, cfg);
852 setTopR(preProcBuffer[x], res.blend_j);
854 if (x + 1 < srcWidth)
855 setTopL(preProcBuffer[x + 1], res.blend_k);
860 for (
int y = yFirst; y < yLast; ++
y)
862 uint32_t* out = trg + Scaler::scale * y * trgWidth;
864 const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);
865 const uint32_t* s_0 = src + srcWidth *
y;
866 const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);
867 const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);
869 unsigned char blend_xy1 = 0;
874 breakIntoDebugger = debugPixelX == x && debugPixelY ==
y;
877 const int x_m1 = std::max(x - 1, 0);
878 const int x_p1 = std::min(x + 1, srcWidth - 1);
879 const int x_p2 = std::min(x + 2, srcWidth - 1);
882 unsigned char blend_xy = 0;
905 const BlendResult
res = preProcessCorners(ker, cfg);
914 blend_xy = preProcBuffer[
x];
915 setBottomR(blend_xy, res.blend_f);
917 setTopR(blend_xy1, res.blend_j);
918 preProcBuffer[
x] = blend_xy1;
921 setTopL(blend_xy1, res.blend_k);
923 if (x + 1 < srcWidth)
924 setBottomL(preProcBuffer[x + 1], res.blend_g);
928 fillBlock(out, trgWidth *
sizeof(
uint32_t), s_0[x], Scaler::scale);
931 if (blendingNeeded(blend_xy))
947 scalePixel<Scaler, ROT_0 >(ker, out, trgWidth, blend_xy, cfg);
948 scalePixel<Scaler, ROT_90 >(ker, out, trgWidth, blend_xy, cfg);
949 scalePixel<Scaler, ROT_180>(ker, out, trgWidth, blend_xy, cfg);
950 scalePixel<Scaler, ROT_270>(ker, out, trgWidth, blend_xy, cfg);
959 static const int scale = 2;
961 template <
class OutputMatrix>
962 static void blendLineShallow(
uint32_t col, OutputMatrix& out)
964 alphaBlend<1, 4>(out.template
ref<scale - 1, 0>(), col);
965 alphaBlend<3, 4>(out.template
ref<scale - 1, 1>(), col);
968 template <
class OutputMatrix>
969 static void blendLineSteep(
uint32_t col, OutputMatrix& out)
971 alphaBlend<1, 4>(out.template
ref<0,
scale - 1>(), col);
972 alphaBlend<3, 4>(out.template
ref<1,
scale - 1>(), col);
975 template <
class OutputMatrix>
976 static void blendLineSteepAndShallow(
uint32_t col, OutputMatrix& out)
978 alphaBlend<1, 4>(out.template
ref<1, 0>(), col);
979 alphaBlend<1, 4>(out.template
ref<0, 1>(), col);
980 alphaBlend<5, 6>(out.template
ref<1, 1>(), col);
983 template <
class OutputMatrix>
984 static void blendLineDiagonal(
uint32_t col, OutputMatrix& out)
986 alphaBlend<1, 2>(out.template
ref<1, 1>(), col);
989 template <
class OutputMatrix>
990 static void blendCorner(
uint32_t col, OutputMatrix& out)
993 alphaBlend<21, 100>(out.template
ref<1, 1>(), col);
1000 static const int scale = 3;
1002 template <
class OutputMatrix>
1003 static void blendLineShallow(
uint32_t col, OutputMatrix& out)
1005 alphaBlend<1, 4>(out.template
ref<scale - 1, 0>(), col);
1006 alphaBlend<1, 4>(out.template
ref<scale - 2, 2>(), col);
1008 alphaBlend<3, 4>(out.template
ref<
scale - 1, 1>(), col);
1009 out.template
ref<
scale - 1, 2>() = col;
1012 template <
class OutputMatrix>
1013 static void blendLineSteep(
uint32_t col, OutputMatrix& out)
1015 alphaBlend<1, 4>(out.template
ref<0,
scale - 1>(), col);
1016 alphaBlend<1, 4>(out.template
ref<2,
scale - 2>(), col);
1018 alphaBlend<3, 4>(out.template
ref<1,
scale - 1>(), col);
1019 out.template
ref<2,
scale - 1>() = col;
1022 template <
class OutputMatrix>
1023 static void blendLineSteepAndShallow(
uint32_t col, OutputMatrix& out)
1025 alphaBlend<1, 4>(out.template
ref<2, 0>(), col);
1026 alphaBlend<1, 4>(out.template
ref<0, 2>(), col);
1027 alphaBlend<3, 4>(out.template
ref<2, 1>(), col);
1028 alphaBlend<3, 4>(out.template
ref<1, 2>(), col);
1032 template <
class OutputMatrix>
1033 static void blendLineDiagonal(
uint32_t col, OutputMatrix& out)
1035 alphaBlend<1, 8>(out.template
ref<1, 2>(), col);
1036 alphaBlend<1, 8>(out.template
ref<2, 1>(), col);
1037 alphaBlend<7, 8>(out.template
ref<2, 2>(), col);
1040 template <
class OutputMatrix>
1041 static void blendCorner(
uint32_t col, OutputMatrix& out)
1044 alphaBlend<45, 100>(out.template
ref<2, 2>(), col);
1053 static const int scale = 4;
1055 template <
class OutputMatrix>
1056 static void blendLineShallow(
uint32_t col, OutputMatrix& out)
1058 alphaBlend<1, 4>(out.template
ref<scale - 1, 0>(), col);
1059 alphaBlend<1, 4>(out.template
ref<scale - 2, 2>(), col);
1061 alphaBlend<3, 4>(out.template
ref<
scale - 1, 1>(), col);
1062 alphaBlend<3, 4>(out.template
ref<
scale - 2, 3>(), col);
1064 out.template
ref<
scale - 1, 2>() = col;
1065 out.template
ref<scale - 1, 3>() = col;
1068 template <
class OutputMatrix>
1069 static void blendLineSteep(
uint32_t col, OutputMatrix& out)
1071 alphaBlend<1, 4>(out.template
ref<0,
scale - 1>(), col);
1072 alphaBlend<1, 4>(out.template
ref<2,
scale - 2>(), col);
1074 alphaBlend<3, 4>(out.template
ref<1,
scale - 1>(), col);
1075 alphaBlend<3, 4>(out.template
ref<3,
scale - 2>(), col);
1077 out.template
ref<2,
scale - 1>() = col;
1078 out.template
ref<3,
scale - 1>() = col;
1081 template <
class OutputMatrix>
1082 static void blendLineSteepAndShallow(
uint32_t col, OutputMatrix& out)
1084 alphaBlend<3, 4>(out.template
ref<3, 1>(), col);
1085 alphaBlend<3, 4>(out.template
ref<1, 3>(), col);
1086 alphaBlend<1, 4>(out.template
ref<3, 0>(), col);
1087 alphaBlend<1, 4>(out.template
ref<0, 3>(), col);
1088 alphaBlend<1, 3>(out.template
ref<2, 2>(), col);
1092 template <
class OutputMatrix>
1093 static void blendLineDiagonal(
uint32_t col, OutputMatrix& out)
1095 alphaBlend<1, 2>(out.template
ref<
scale - 1, scale / 2 >(), col);
1096 alphaBlend<1, 2>(out.template
ref<
scale - 2, scale / 2 + 1>(), col);
1097 out.template
ref<
scale - 1, scale - 1>() = col;
1100 template <
class OutputMatrix>
1101 static void blendCorner(
uint32_t col, OutputMatrix& out)
1104 alphaBlend<68, 100>(out.template
ref<3, 3>(), col);
1105 alphaBlend< 9, 100>(out.template
ref<3, 2>(), col);
1106 alphaBlend< 9, 100>(out.template
ref<2, 3>(), col);
1113 static const int scale = 5;
1115 template <
class OutputMatrix>
1116 static void blendLineShallow(
uint32_t col, OutputMatrix& out)
1118 alphaBlend<1, 4>(out.template
ref<scale - 1, 0>(), col);
1119 alphaBlend<1, 4>(out.template
ref<scale - 2, 2>(), col);
1120 alphaBlend<1, 4>(out.template
ref<
scale - 3, 4>(), col);
1122 alphaBlend<3, 4>(out.template
ref<
scale - 1, 1>(), col);
1123 alphaBlend<3, 4>(out.template
ref<
scale - 2, 3>(), col);
1125 out.template
ref<
scale - 1, 2>() = col;
1126 out.template
ref<scale - 1, 3>() = col;
1127 out.template
ref<scale - 1, 4>() = col;
1128 out.template
ref<scale - 2, 4>() = col;
1131 template <
class OutputMatrix>
1132 static void blendLineSteep(
uint32_t col, OutputMatrix& out)
1134 alphaBlend<1, 4>(out.template
ref<0,
scale - 1>(), col);
1135 alphaBlend<1, 4>(out.template
ref<2,
scale - 2>(), col);
1136 alphaBlend<1, 4>(out.template
ref<4,
scale - 3>(), col);
1138 alphaBlend<3, 4>(out.template
ref<1,
scale - 1>(), col);
1139 alphaBlend<3, 4>(out.template
ref<3,
scale - 2>(), col);
1141 out.template
ref<2,
scale - 1>() = col;
1142 out.template
ref<3,
scale - 1>() = col;
1143 out.template
ref<4,
scale - 1>() = col;
1144 out.template
ref<4,
scale - 2>() = col;
1147 template <
class OutputMatrix>
1148 static void blendLineSteepAndShallow(
uint32_t col, OutputMatrix& out)
1150 alphaBlend<1, 4>(out.template
ref<0,
scale - 1>(), col);
1151 alphaBlend<1, 4>(out.template
ref<2,
scale - 2>(), col);
1152 alphaBlend<3, 4>(out.template
ref<1,
scale - 1>(), col);
1154 alphaBlend<1, 4>(out.template
ref<
scale - 1, 0>(), col);
1155 alphaBlend<1, 4>(out.template
ref<
scale - 2, 2>(), col);
1156 alphaBlend<3, 4>(out.template
ref<
scale - 1, 1>(), col);
1158 out.template
ref<2,
scale - 1>() = col;
1159 out.template
ref<3,
scale - 1>() = col;
1161 out.template
ref<
scale - 1, 2>() = col;
1162 out.template
ref<scale - 1, 3>() = col;
1164 out.template
ref<4, scale - 1>() = col;
1166 alphaBlend<2, 3>(out.template
ref<3, 3>(), col);
1169 template <
class OutputMatrix>
1170 static void blendLineDiagonal(
uint32_t col, OutputMatrix& out)
1172 alphaBlend<1, 8>(out.template
ref<
scale - 1, scale / 2 >(), col);
1173 alphaBlend<1, 8>(out.template
ref<
scale - 2, scale / 2 + 1>(), col);
1174 alphaBlend<1, 8>(out.template
ref<
scale - 3, scale / 2 + 2>(), col);
1176 alphaBlend<7, 8>(out.template
ref<4, 3>(), col);
1177 alphaBlend<7, 8>(out.template
ref<3, 4>(), col);
1182 template <
class OutputMatrix>
1183 static void blendCorner(
uint32_t col, OutputMatrix& out)
1186 alphaBlend<86, 100>(out.template
ref<4, 4>(), col);
1187 alphaBlend<23, 100>(out.template
ref<4, 3>(), col);
1188 alphaBlend<23, 100>(out.template
ref<3, 4>(), col);
1201 return scaleImage<Scaler2x>(
src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
1203 return scaleImage<Scaler3x>(
src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
1205 return scaleImage<Scaler4x>(
src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
1207 return scaleImage<Scaler5x>(
src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
1215 return colorDist(col1, col2, luminanceWeight) < equalColorTolerance;
1220 uint32_t* trg,
int trgWidth,
int trgHeight,
int trgPitch,
1223 if (srcPitch < srcWidth * static_cast<int>(
sizeof(
uint32_t)) ||
1224 trgPitch < trgWidth * static_cast<int>(
sizeof(
uint32_t)))
1234 yFirst = std::max(yFirst, 0);
1235 yLast = std::min(yLast, srcHeight);
1236 if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0)
return;
1238 for (
int y = yFirst; y < yLast; ++
y)
1244 const int yTrg_first = ( y * trgHeight + srcHeight - 1) / srcHeight;
1245 const int yTrg_last = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight;
1246 const int blockHeight = yTrg_last - yTrg_first;
1248 if (blockHeight > 0)
1250 const uint32_t* srcLine = byteAdvance(src, y * srcPitch);
1251 uint32_t* trgLine = byteAdvance(trg, yTrg_first * trgPitch);
1254 for (
int x = 0; x < srcWidth; ++
x)
1256 int xTrg_last = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth;
1257 const int blockWidth = xTrg_last - xTrg_first;
1260 xTrg_first = xTrg_last;
1261 fillBlock(trgLine, trgPitch, srcLine[x], blockWidth, blockHeight);
1262 trgLine += blockWidth;
1271 yFirst = std::max(yFirst, 0);
1272 yLast = std::min(yLast, trgHeight);
1273 if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0)
return;
1275 for (
int y = yFirst; y < yLast; ++
y)
1277 uint32_t* trgLine = byteAdvance(trg, y * trgPitch);
1278 const int ySrc = srcHeight * y / trgHeight;
1279 const uint32_t* srcLine = byteAdvance(src, ySrc * srcPitch);
1280 for (
int x = 0; x < trgWidth; ++
x)
1282 const int xSrc = srcWidth * x / trgWidth;
1283 trgLine[
x] = srcLine[
xSrc];
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
GLenum GLenum GLenum GLenum GLenum scale
double dominantDirectionThreshold
GLuint const GLfloat * val
GLint GLint GLint GLint GLint GLint y
GLdouble GLdouble GLdouble b
void scale(size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, const ScalerCfg &cfg=ScalerCfg(), int yFirst=0, int yLast=std::numeric_limits< int >::max())
GLsizei const GLfloat * value
GLboolean GLboolean GLboolean GLboolean a
GLclampf GLclampf GLclampf alpha
bool equalColor(uint32_t col1, uint32_t col2, double luminanceWeight, double equalColorTolerance)
double steepDirectionThreshold
GLfloat GLfloat GLfloat GLfloat h
GLint GLint GLint GLint GLint x
GLdouble GLdouble GLdouble r
int int int int int int ySrc
void nearestNeighborScale(const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight)
double equalColorTolerance_