The first problem mentioned in the comment below the question is that you must load the native library that implements the image loading. This can be done with the following code:
static {
// TODO: use OpenCVLoader.initAsync for a real application
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Failed to initialize OpenCV.");
}
}
In a real application you would use the initAsync
function such that the loading of the libraries does not block the main thread. In a simple example this does not matter.
Another problem is, that file IO on Android requires a permission if you want to access files in arbitrary directories. The permission must be declared in your manifest file. This can be done by adding the following two lines above the application
tag in the manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
These permissions must be requested at runtime. To check if the permission was granted already the following code can be used:
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// do something with the permission
}
If the permission is not available, it can be requested as follows:
ActivityCompat.requestPermissions(this, new String[]{
android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, RW_PERMISSION_REQUEST_CODE);
Note: we only request the write permission because they are grouped and if the user grants the write permission we automatically also obtain the read permission.
To handle the result the onRequestPermissionsResult
callback in the activity class should be overwritten as seen in the full code example below. Because the permission system is quite complex take a look at the official documentation. For info on requesting permissions look here.
Finally to make the loading work the file path must be correct. The user-accessible memory locations depend on the phone manufacturer, therefore it is good to use the system methods provided by Android to find the correct path, for example getExternalStorageDirectory()
. More information on the various storage locations can be found here.
Here the full code:
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.os.Environment.getExternalStorageDirectory;
public class MainActivity extends AppCompatActivity {
private static String TAG = "MainActivity";
private static final int RW_PERMISSION_REQUEST_CODE = 123;
static {
// TODO: use OpenCVLoader.initAsync for a real application
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Failed to initialize OpenCV.");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(
this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissionDenied();
} else {
permissionGranted();
}
}
private void permissionDenied() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Read/Write permission required to read an image file.")
.setCancelable(false)
.setPositiveButton("Grant", (dialog, which) ->
ActivityCompat.requestPermissions(this, new String[]{
WRITE_EXTERNAL_STORAGE}, RW_PERMISSION_REQUEST_CODE))
.setNegativeButton("Deny", (dialog, which) -> {
Toast.makeText(this,
"App cannot work without permission.", Toast.LENGTH_LONG).show();
this.finish();
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(
this, new String[]{WRITE_EXTERNAL_STORAGE}, RW_PERMISSION_REQUEST_CODE);
}
}
private void permissionGranted() {
String path = getExternalStorageDirectory().getAbsolutePath() + "/a.png";
Mat image = Imgcodecs.imread(path, Imgcodecs.IMREAD_GRAYSCALE);
if (image.empty()) {
Toast.makeText(this, "Failed image", Toast.LENGTH_LONG).show();
} else {
Size size = image.size();
Toast.makeText(this, "Loaded image " + size.height, Toast.LENGTH_LONG).show();
// the following code is only necessary to display the image in an ImageView
ImageView iv = findViewById(R.id.imageView);
Mat tmp = new Mat((int) size.height, (int) size.width, CvType.CV_8U, new Scalar(4));
try {
Imgproc.cvtColor(image, tmp, Imgproc.COLOR_GRAY2RGBA, 4);
Bitmap bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, bmp);
iv.setImageBitmap(bmp);
} catch (CvException e) {
Log.d(TAG, e.getMessage());
Toast.makeText(this, "Couldn't convert image.", Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == RW_PERMISSION_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionGranted();
} else {
permissionDenied();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
To make this code work add an ImageView
with id imageView
to your activity_main.xml
layout file.