/* * input kernel area naming convention: * ------------- | A | B | C | | ----|---|---| | D | E | F | //input pixel is at position E | ----|---|---| | G | H | I | | ------------- */ private static void _ScalePixel( IScaler scaler, RotationDegree rotDeg, Kernel_3X3 ker, sPixel[] trg, int trgi, int trgWidth, byte blendInfo, //result of preprocessing all four corners of pixel "e" IColorEq scalePixelColorEq, IColorDist scalePixelColorDist, OutputMatrix outputMatrix ) { //int a = kernel._[Rot._[(0 << 2) + rotDeg]]; var b = ker._[Rot._[(1 << 2) + (int)rotDeg]]; var c = ker._[Rot._[(2 << 2) + (int)rotDeg]]; var d = ker._[Rot._[(3 << 2) + (int)rotDeg]]; var e = ker._[Rot._[(4 << 2) + (int)rotDeg]]; var f = ker._[Rot._[(5 << 2) + (int)rotDeg]]; var g = ker._[Rot._[(6 << 2) + (int)rotDeg]]; var h = ker._[Rot._[(7 << 2) + (int)rotDeg]]; var i = ker._[Rot._[(8 << 2) + (int)rotDeg]]; var blend = BlendInfo.Rotate(blendInfo, rotDeg); if (BlendInfo.GetBottomR(blend) == BlendType.BlendNone) { return; } var eq = scalePixelColorEq; var dist = scalePixelColorDist; bool doLineBlend; if (BlendInfo.GetBottomR(blend) >= BlendType.BlendDominant) { doLineBlend = true; } //make sure there is no second blending in an adjacent //rotation for this pixel: handles insular pixels, mario eyes //but support double-blending for 90? corners else if (BlendInfo.GetTopR(blend) != BlendType.BlendNone && !eq._(e, g)) { doLineBlend = false; } else if (BlendInfo.GetBottomL(blend) != BlendType.BlendNone && !eq._(e, c)) { doLineBlend = false; } //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes") else if (eq._(g, h) && eq._(h, i) && eq._(i, f) && eq._(f, c) && !eq._(e, i)) { doLineBlend = false; } else { doLineBlend = true; } //choose most similar color var px = dist._(e, f) <= dist._(e, h) ? f : h; var output = outputMatrix; output.Move(rotDeg, trgi); if (!doLineBlend) { scaler.BlendCorner(px, output); return; } //test sample: 70% of values max(fg, hc) / min(fg, hc) //are between 1.1 and 3.7 with median being 1.9 var fg = dist._(f, g); var hc = dist._(h, c); var haveShallowLine = _CONFIGURATION.steepDirectionThreshold * fg <= hc && e != g && d != g; var haveSteepLine = _CONFIGURATION.steepDirectionThreshold * hc <= fg && e != c && b != c; if (haveShallowLine) { if (haveSteepLine) { scaler.BlendLineSteepAndShallow(px, output); } else { scaler.BlendLineShallow(px, output); } } else { if (haveSteepLine) { scaler.BlendLineSteep(px, output); } else { scaler.BlendLineDiagonal(px, output); } } }
/* input kernel area naming convention: ------------- | A | B | C | ----|---|---| | D | E | F | //input pixel is at position E ----|---|---| | G | H | I | ------------- */ private static void _ScalePixel( IScaler scaler, RotationDegree rotDeg, Kernel_3X3 ker, sPixel[] trg, int trgi, int trgWidth, byte blendInfo,//result of preprocessing all four corners of pixel "e" IColorEq scalePixelColorEq, IColorDist scalePixelColorDist, OutputMatrix outputMatrix ) { //int a = kernel._[Rot._[(0 << 2) + rotDeg]]; var b = ker._[Rot._[(1 << 2) + (int)rotDeg]]; var c = ker._[Rot._[(2 << 2) + (int)rotDeg]]; var d = ker._[Rot._[(3 << 2) + (int)rotDeg]]; var e = ker._[Rot._[(4 << 2) + (int)rotDeg]]; var f = ker._[Rot._[(5 << 2) + (int)rotDeg]]; var g = ker._[Rot._[(6 << 2) + (int)rotDeg]]; var h = ker._[Rot._[(7 << 2) + (int)rotDeg]]; var i = ker._[Rot._[(8 << 2) + (int)rotDeg]]; var blend = BlendInfo.Rotate(blendInfo, rotDeg); if (BlendInfo.GetBottomR(blend) == BlendType.BlendNone) return; var eq = scalePixelColorEq; var dist = scalePixelColorDist; bool doLineBlend; if (BlendInfo.GetBottomR(blend) >= BlendType.BlendDominant) doLineBlend = true; //make sure there is no second blending in an adjacent //rotation for this pixel: handles insular pixels, mario eyes //but support double-blending for 90? corners else if (BlendInfo.GetTopR(blend) != BlendType.BlendNone && !eq._(e, g)) doLineBlend = false; else if (BlendInfo.GetBottomL(blend) != BlendType.BlendNone && !eq._(e, c)) doLineBlend = false; //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes") else if (eq._(g, h) && eq._(h, i) && eq._(i, f) && eq._(f, c) && !eq._(e, i)) doLineBlend = false; else doLineBlend = true; //choose most similar color var px = dist._(e, f) <= dist._(e, h) ? f : h; var output = outputMatrix; output.Move(rotDeg, trgi); if (!doLineBlend) { scaler.BlendCorner(px, output); return; } //test sample: 70% of values max(fg, hc) / min(fg, hc) //are between 1.1 and 3.7 with median being 1.9 var fg = dist._(f, g); var hc = dist._(h, c); var haveShallowLine = _CONFIGURATION.steepDirectionThreshold * fg <= hc && e != g && d != g; var haveSteepLine = _CONFIGURATION.steepDirectionThreshold * hc <= fg && e != c && b != c; if (haveShallowLine) { if (haveSteepLine) scaler.BlendLineSteepAndShallow(px, output); else scaler.BlendLineShallow(px, output); } else { if (haveSteepLine) scaler.BlendLineSteep(px, output); else scaler.BlendLineDiagonal(px, output); } }
/* * input kernel area naming convention: * ----------------- | A | B | C | D | | ----|---|---|---| | E | F | G | H | //evalute the four corners between F, G, J, K | ----|---|---|---| //input pixel is at position F | I | J | K | L | | ----|---|---|---| | M | N | O | P | | ----------------- */ //detect blend direction private static void _PreProcessCorners(Kernel_4X4 kernel, BlendResult blendResult, IColorDist preProcessCornersColorDist) { blendResult.Reset(); if ((kernel.f == kernel.g && kernel.j == kernel.k) || (kernel.f == kernel.j && kernel.g == kernel.k)) { return; } var dist = preProcessCornersColorDist; var weight = 4; var jg = dist._(kernel.i, kernel.f) + dist._(kernel.f, kernel.c) + dist._(kernel.n, kernel.k) + dist._(kernel.k, kernel.h) + weight * dist._(kernel.j, kernel.g); var fk = dist._(kernel.e, kernel.j) + dist._(kernel.j, kernel.o) + dist._(kernel.b, kernel.g) + dist._(kernel.g, kernel.l) + weight * dist._(kernel.f, kernel.k); if (jg < fk) { var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * jg < fk; if (kernel.f != kernel.g && kernel.f != kernel.j) { blendResult.f = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } if (kernel.k != kernel.j && kernel.k != kernel.g) { blendResult.k = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } } else if (fk < jg) { var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * fk < jg; if (kernel.j != kernel.f && kernel.j != kernel.k) { blendResult.j = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } if (kernel.g != kernel.f && kernel.g != kernel.k) { blendResult.g = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } } }
/* input kernel area naming convention: ----------------- | A | B | C | D | ----|---|---|---| | E | F | G | H | //evalute the four corners between F, G, J, K ----|---|---|---| //input pixel is at position F | I | J | K | L | ----|---|---|---| | M | N | O | P | ----------------- */ //detect blend direction private static void _PreProcessCorners(Kernel_4X4 kernel, BlendResult blendResult, IColorDist preProcessCornersColorDist) { blendResult.Reset(); if ((kernel.f == kernel.g && kernel.j == kernel.k) || (kernel.f == kernel.j && kernel.g == kernel.k)) return; var dist = preProcessCornersColorDist; var weight = 4; var jg = dist._(kernel.i, kernel.f) + dist._(kernel.f, kernel.c) + dist._(kernel.n, kernel.k) + dist._(kernel.k, kernel.h) + weight * dist._(kernel.j, kernel.g); var fk = dist._(kernel.e, kernel.j) + dist._(kernel.j, kernel.o) + dist._(kernel.b, kernel.g) + dist._(kernel.g, kernel.l) + weight * dist._(kernel.f, kernel.k); if (jg < fk) { var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * jg < fk; if (kernel.f != kernel.g && kernel.f != kernel.j) blendResult.f = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; if (kernel.k != kernel.j && kernel.k != kernel.g) blendResult.k = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } else if (fk < jg) { var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * fk < jg; if (kernel.j != kernel.f && kernel.j != kernel.k) blendResult.j = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; if (kernel.g != kernel.f && kernel.g != kernel.k) blendResult.g = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal; } }