Android Bitmap Fatal signal 11 (SIGSEGV)

2019-07-05 22:41发布

问题:

I'm developing and android app that take a picture and OCRed it.
I'm getting this error sometime and sometime not without changing my code,

THE ERROR : 01-08 20:41:59.940: A/libc(10967): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

I have a method that crop the image to let the user highlight the text :

private void performCrop(){

    File file = new File(_path);
    Uri outputFileUri = Uri.fromFile(file);

    try{

        //call the standard crop action intent (the user device may not support it)
        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        //indicate image type and Uri
        cropIntent.setDataAndType(picUri, "image/*");
        //set crop properties
        cropIntent.putExtra("crop", "true");
        //indicate aspect of desired crop
        cropIntent.putExtra("aspectX", 5);
        cropIntent.putExtra("aspectY", 1);
        //indicate output X and Y
        cropIntent.putExtra("outputX", 500);
        cropIntent.putExtra("outputY", 100);
        //retrieve data on return
        cropIntent.putExtra("return-data", true);
        //start the activity - we handle returning in onActivityResult
        startActivityForResult(cropIntent, 2);

    }catch(ActivityNotFoundException anfe){
         //display an error message
         String errorMessage = "Whoops - your device doesn't support the crop action!";
         Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
         toast.show();
    } catch (Exception ex) {
        Log.v(TAG, ex.toString());
    }
}

and here is the method that do the OCR :

protected void onPhotoTaken() {
    _taken = true;

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;

    Bitmap bitmap = BitmapFactory.decodeFile(_path, options);

    try {
        ExifInterface exif = new ExifInterface(_path);
        int exifOrientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        Log.v(TAG, "Orient: " + exifOrientation);

        int rotate = 0;

        switch (exifOrientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            rotate = 90;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            rotate = 180;
            break;
        case ExifInterface.ORIENTATION_ROTATE_270:
            rotate = 270;
            break;
        }

        Log.v(TAG, "Rotation: " + rotate);

        if (rotate != 0) {

            // Getting width & height of the given image.
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();

            // Setting pre rotate
            Matrix mtx = new Matrix();
            mtx.preRotate(rotate);

            // Rotating Bitmap
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
        }

        // Convert to ARGB_8888, required by tess
        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

    } catch (IOException e) {
        Log.e(TAG, "Couldn't correct orientation: " + e.toString());
    }

    // _image.setImageBitmap( bitmap );

    Log.v(TAG, "Before baseApi");

    TessBaseAPI baseApi = new TessBaseAPI();
    baseApi.setDebug(true);
    baseApi.init(DATA_PATH, lang);
    baseApi.setImage(bitmap);

    String recognizedText = baseApi.getUTF8Text();

    baseApi.end();

    // You now have the text in recognizedText var, you can do anything with it.
    // We will display a stripped out trimmed alpha-numeric version of it (if lang is eng)
    // so that garbage doesn't make it to the display.

    Log.v(TAG, "OCRED TEXT: " + recognizedText);

    if ( lang.equalsIgnoreCase("eng") ) {
        recognizedText = recognizedText.replaceAll("[^a-zA-Z0-9]+", " ");
    }

    recognizedText = recognizedText.trim();

    if ( recognizedText.length() != 0 ) {
        _field.setText(_field.getText().toString().length() == 0 ? recognizedText : _field.getText() + " " + recognizedText);
        _field.setSelection(_field.getText().toString().length());
    }

    // Cycle done.
}

回答1:

One suggestion is a ExifInterface initialization problem.

ExifInterface's constructor has a serious bug. It won't check whether the argument filename string is null or not, and no exception will be thrown, so crashing on JNI results to SIGSEGV.

The following post will help you(sorry, this post is in japanese...) http://alpha.mixi.co.jp/2013/11572/ http://alpha.mixi.co.jp/images/android-compat-jni-crash-exif.png

So you should check the _path value before initializing ExifInterface object.