diff --git a/vendor/kik/scanner/src/androidTest/kotlin/com/kik/scan/KikCodeScanTest.kt b/vendor/kik/scanner/src/androidTest/kotlin/com/kik/scan/KikCodeScanTest.kt index 66e0e96a6a..c2d613cb5f 100644 --- a/vendor/kik/scanner/src/androidTest/kotlin/com/kik/scan/KikCodeScanTest.kt +++ b/vendor/kik/scanner/src/androidTest/kotlin/com/kik/scan/KikCodeScanTest.kt @@ -3,11 +3,11 @@ package com.kik.scan import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color -import android.graphics.drawable.ShapeDrawable -import android.graphics.drawable.shapes.OvalShape import android.os.Debug import android.util.Log +import androidx.core.content.ContextCompat import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import com.getcode.codes.kikcode.LuminancePlane import com.kik.kikx.kikcodes.ScanQuality import com.kik.kikx.kikcodes.implementation.KikCodeScannerImpl @@ -36,9 +36,18 @@ class KikCodeScanTest { /** * The detector locates a code by its centre ellipse, so the badge well must be filled — in the * app that is the round logo drawable. An empty well is simply not scannable. + * + * Use the *real* artwork, not a plain white oval. The logo knocks its glyph out of the disc + * with the even-odd rule, and the glyph's round dot is itself an ellipse the detector can + * latch onto; a substituted oval has no dot and quietly hides that whole class of bug. */ private val renderer = KikCodeContentRendererImpl().apply { - badge = ShapeDrawable(OvalShape()).apply { paint.color = Color.WHITE } + badge = requireNotNull( + ContextCompat.getDrawable( + InstrumentationRegistry.getInstrumentation().context, + com.kik.kikx.test.R.drawable.ic_logo_round_white, + ) + ) } private val scanner = KikCodeScannerImpl() diff --git a/vendor/kik/scanner/src/androidTest/res/drawable/ic_logo_round_white.xml b/vendor/kik/scanner/src/androidTest/res/drawable/ic_logo_round_white.xml new file mode 100644 index 0000000000..28c3d72128 --- /dev/null +++ b/vendor/kik/scanner/src/androidTest/res/drawable/ic_logo_round_white.xml @@ -0,0 +1,10 @@ + + + diff --git a/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp b/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp index 368c55d74f..937def5211 100644 --- a/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp +++ b/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp @@ -417,23 +417,6 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u Mat whitish; Mat blackish; - // --- START OF EDIT --- - // we switch to an inverted scheme (dark is high, light is low) if the - // center ellipse is dark, but we don't want to compute the extra threshold everytime - // so we only do this when needed. - // - // Using adaptive thresholding is more robust to lighting changes than a global threshold. - // It calculates a threshold for smaller regions, making it less susceptible to shadows or glare. - // A block size of 11 or higher is a good starting point and must be an odd number. - // The constant 'C' (here, 5) is subtracted from the mean, which helps in finding features. - - // For finding dark features on a light background. - adaptiveThreshold(greyscale, blackish, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 5); - - // For finding light features on a dark background. - adaptiveThreshold(greyscale, whitish, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 21, 5); - // --- END OF EDIT --- - // we switch to an inverted scheme (dark is high, light is low) if the // center ellipse is dark, but we don't want to compute the extra threshold everytime // so we only do this when necessary @@ -728,7 +711,15 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u float dist = sqrt(pow(center1.x - center2.x, 2) + pow(center1.y - center2.y, 2)); - if (dist < 50 && 2 * potential_ellipses[i].size.area() > potential_ellipses[j].size.area()) { + float area1 = potential_ellipses[i].size.area(); + float area2 = potential_ellipses[j].size.area(); + + // Only prune true near-duplicates -- the same physical circle fitted twice from the + // inner and outer edge of its stroke, which are comparable in area. A nearby ellipse + // that is much smaller is a *different* feature nested inside this one (e.g. the dot + // knocked out of the centre badge's glyph), and dropping the enclosing candidate in + // its favour loses the only ellipse that can yield finder points. + if (dist < 50 && 2 * area1 > area2 && 2 * area2 > area1) { allowed = false; break; }