[Xposed Framework Development] esun:
So I've created module to hijack an app's onPictureTaken callback method to manipulate the image-data that is returned from the Camera (android.hardware.Camera.PictureCallback).

I have succeeded to manipulate the image to return a Grayscale of it which was my first goal.

Now I want to replace the entire image with an image loaded from the filesystem which I'm unsuccessful in doing. I've tried different methods, paths etc. but haven't managed to do it. I've never been able to find the file which I want to load.

The full path of the image file I want to load is according to Solid Explorer

/storage/emulated/0/input.png

What code should I use to load the filesystem image into a Bitmap?

Do I need to take any extra Camera parameters into account that says stuff about the image?

Do I need take file permissions into account?

I'm running an OPO on Lollipop 5.0.2 / Cyanogen OS 12.0 / Xposed 67

This is the code I've used to create the Grayscale example:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.os.Environment;

import java.io.ByteArrayOutputStream;
import java.io.File;

import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class CamHook implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
XposedBridge.log("Loaded app: " + lpparam.packageName);

if (!lpparam.packageName.equals("somepackage.somewhere.app"))
return;

XposedBridge.log("CamHook: We're here!");

findAndHookMethod("somepackage.somewhere.app.NewPhotoFragment$3$1", lpparam.classLoader, "onPictureTaken", "byte[]", "android.hardware.Camera", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("CamHook: before picture taken");
XposedBridge.log("CamHook: byteLength " + ((byte[]) (param.args)[0]).length);
byte[] bitmapdata = ((byte[]) (param.args)[0]);
Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapdata, 0, bitmapdata.length);
XposedBridge.log("CamHook: StorageState: " + Environment.getExternalStorageState());
XposedBridge.log("CamHook: StoragePath: " + Environment.getExternalStorageDirectory().getAbsolutePath());
XposedBridge.log("CamHook: StoragePathEnv: " + System.getenv("EXTERNAL_STORAGE"));
//Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/input.jpg");

XposedBridge.log("CamHook: Bitmap is null: " + (bitmap == null));

bitmap = toGrayscale(bitmap);

ByteArrayOutputStream blob = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, blob);
param.args[0] = blob.toByteArray();
}
/*@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// this will be called after the clock was updated by the original method
}*/
});
}

public Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();

Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
}