int llcv_gl_error_count() { EGLint error = eglGetError(); if (error != EGL_SUCCESS) { dmz_error_log("egl error: %i", error); dmz_set_gles_warp(0); return 1; } int err_count = 0; GLenum glerror; while ((glerror = glGetError())) { err_count++; dmz_error_log("gl error: 0x%X (%i)", glerror, glerror); } if (err_count) dmz_set_gles_warp(0); return err_count; }
void setDetectedCardImage(JNIEnv* env, jobject jCardResultBitmap, IplImage* cardY, IplImage* cb, IplImage* cr, dmz_corner_points corner_points, int orientation) { char* pixels = NULL; AndroidBitmapInfo bmInfo; int bmRes = AndroidBitmap_getInfo(env, jCardResultBitmap, &bmInfo); // Yes, it really is defined as _RESUT_ ... figures. <sigh> bool validCardInfo = (bmRes == ANDROID_BITMAP_RESUT_SUCCESS); if (!validCardInfo) { dmz_error_log("AndroidBitmap_getInfo() failed! error=%i", bmRes); } if (validCardInfo && bmInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { dmz_error_log("the dmz was given a bitmap that is not RGBA_8888"); validCardInfo = false; } bmRes = AndroidBitmap_lockPixels(env, jCardResultBitmap, (void**) &pixels ); if (bmRes != ANDROID_BITMAP_RESUT_SUCCESS) { dmz_error_log("couldn't lock bitmap:%i", bmRes); } else { IplImage* bigCb = NULL; dmz_transform_card(NULL, cb, corner_points, orientation, true, &bigCb); IplImage* bigCr = NULL; dmz_transform_card(NULL, cr, corner_points, orientation, true, &bigCr); IplImage* cardResult = cvCreateImageHeader(cvSize(bmInfo.width, bmInfo.height), IPL_DEPTH_8U, 4); cvSetData(cardResult, pixels, bmInfo.stride); dmz_YCbCr_to_RGB(cardY, bigCb, bigCr, &cardResult); AndroidBitmap_unlockPixels(env, jCardResultBitmap); cvReleaseImageHeader(&cardResult); cvReleaseImage(&bigCb); cvReleaseImage(&bigCr); } }
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv* env; jint status = vm->GetEnv( (void**) &env, JNI_VERSION_1_6); if (status != JNI_OK) return -1; /* find class ref and field IDs. * class refs must be explicitly stated as global. * field IDs could change with a new classloader, but this method will get called in that case. * see http://www.milk.com/kodebase/dalvik-docs-mirror/docs/jni-tips.html */ jclass myClass = env->FindClass("io/card/payment/CardScanner"); if (!myClass) { dmz_error_log("Couldn't find CardScanner from JNI"); return -1; } cardScannerId.classRef = (jclass)env->NewGlobalRef(myClass); cardScannerId.edgeUpdateCallback = env->GetMethodID(myClass, "onEdgeUpdate", "(Lio/card/payment/DetectionInfo;)V"); if (!cardScannerId.edgeUpdateCallback) { dmz_error_log("Couldn't find edge update callback"); return -1; } jclass rectClass = env->FindClass("android/graphics/Rect"); if (!rectClass) { dmz_error_log("Couldn't find Rect class"); return -1; } rectId.classRef = (jclass)env->NewGlobalRef(rectClass); rectId.top = env->GetFieldID(rectClass, "top", "I"); rectId.bottom = env->GetFieldID(rectClass, "bottom", "I"); rectId.left = env->GetFieldID(rectClass, "left", "I"); rectId.right = env->GetFieldID(rectClass, "right", "I"); if (!(rectId.top && rectId.bottom && rectId.left && rectId.right)) { dmz_error_log("Couldn't find square class"); return -1; } jclass creditCardClass = (jclass)env->FindClass("io/card/payment/CreditCard"); if (creditCardClass == NULL) { dmz_error_log("Couldn't find CreditCard class"); return -1; } creditCardId.classRef = (jclass)env->NewGlobalRef(creditCardClass); creditCardId.flipped = env->GetFieldID(creditCardClass, "flipped", "Z"); creditCardId.yoff = env->GetFieldID(creditCardClass, "yoff", "I"); creditCardId.xoff = env->GetFieldID(creditCardClass, "xoff", "[I"); if (!( creditCardId.flipped && creditCardId.yoff && creditCardId.xoff )) { dmz_error_log("at least one filed was not found for CreditCard"); return -1; } jclass dInfoClass = env->FindClass("io/card/payment/DetectionInfo"); if (dInfoClass == NULL) { dmz_error_log("Couldn't find DetectionInfo class"); return -1; } detectionInfoId.classRef = (jclass)env->NewGlobalRef(dInfoClass); detectionInfoId.complete = env->GetFieldID(dInfoClass, "complete", "Z"); detectionInfoId.topEdge = env->GetFieldID(dInfoClass, "topEdge", "Z"); detectionInfoId.bottomEdge = env->GetFieldID(dInfoClass, "bottomEdge", "Z"); detectionInfoId.leftEdge = env->GetFieldID(dInfoClass, "leftEdge", "Z"); detectionInfoId.rightEdge = env->GetFieldID(dInfoClass, "rightEdge", "Z"); detectionInfoId.focusScore = env->GetFieldID(dInfoClass, "focusScore", "F"); detectionInfoId.prediction = env->GetFieldID(dInfoClass, "prediction", "[I"); detectionInfoId.expiry_month = env->GetFieldID(dInfoClass, "expiry_month", "I"); detectionInfoId.expiry_year = env->GetFieldID(dInfoClass, "expiry_year", "I"); detectionInfoId.detectedCard = env->GetFieldID(dInfoClass, "detectedCard", "Lio/card/payment/CreditCard;"); if (!(detectionInfoId.complete && detectionInfoId.topEdge && detectionInfoId.bottomEdge && detectionInfoId.leftEdge && detectionInfoId.rightEdge && detectionInfoId.focusScore && detectionInfoId.prediction && detectionInfoId.expiry_month && detectionInfoId.expiry_year && detectionInfoId.detectedCard )) { dmz_error_log("at least one field was not found for DetectionInfo"); return -1; } return JNI_VERSION_1_6; }
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, jobject thiz, jbyteArray jb, jint width, jint height, jint orientation, jobject dinfo, jobject jCardResultBitmap, jboolean jScanExpiry) { dmz_trace_log("Java_io_card_payment_CardScanner_nScanFrame ... width:%i height:%i orientation:%i", width, height, orientation); if (orientation == 0) { dmz_error_log("orientation is 0. Nothing good can come from this."); return; } if (flipped) { orientation = dmz_opposite_orientation(orientation); } FrameScanResult result; IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1); jbyte *jBytes = env->GetByteArrayElements(jb, 0); image->imageData = (char *)jBytes; float focusScore = dmz_focus_score(image, false); env->SetFloatField(dinfo, detectionInfoId.focusScore, focusScore); dmz_trace_log("focus score: %f", focusScore); if (focusScore >= minFocusScore) { IplImage *cbcr = cvCreateImageHeader(cvSize(width / 2, height / 2), IPL_DEPTH_8U, 2); cbcr->imageData = ((char *)jBytes) + width * height; IplImage *cb, *cr; // Note: cr and cb are reversed here because Android uses android.graphics.ImageFormat.NV21. This is actually YCrCb rather than YCbCr! dmz_deinterleave_uint8_c2(cbcr, &cr, &cb); cvReleaseImageHeader(&cbcr); dmz_edges found_edges; dmz_corner_points corner_points; bool cardDetected = dmz_detect_edges(image, cb, cr, orientation, &found_edges, &corner_points ); updateEdgeDetectDisplay(env, thiz, dinfo, found_edges); if (cardDetected) { IplImage *cardY = NULL; dmz_transform_card(NULL, image, corner_points, orientation, false, &cardY); if (!detectOnly) { result.focus_score = focusScore; result.flipped = flipped; scanner_add_frame_with_expiry(&scannerState, cardY, jScanExpiry, &result); if (result.usable) { ScannerResult scanResult; scanner_result(&scannerState, &scanResult); if (scanResult.complete) { setScanCardNumberResult(env, dinfo, &scanResult); logDinfo(env, dinfo); } } else if (result.upside_down) { flipped = !flipped; } } setDetectedCardImage(env, jCardResultBitmap, cardY, cb, cr, corner_points, orientation); cvReleaseImage(&cardY); } cvReleaseImage(&cb); cvReleaseImage(&cr); } cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); }