I want to add image at runtime in ARCore database. So, in my MainActivity.java, I have a button Registered Image, which on Click , added the image in ARCore database.
MainActivity.java :
public class MainActivity extends AppCompatActivity {
private CustomArFragment arFragment;
private TextView textView;
private AugmentedImageDatabase aid;
private Frame frame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);
textView = findViewById(R.id.textView);
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdate);
findViewById(R.id.registeredBtn).setOnClickListener(v -> {
if(ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
return;
}
registeredImage();
});
}
private static byte[] NV21toJPEG(byte[] nv21, int width, int height) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuv = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
yuv.compressToJpeg(new Rect(0, 0, width, height), 100, out);
return out.toByteArray();
}
private static byte[] YUV_420_888toNV21(Image image) {
byte[] nv21;
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
return nv21;
}
// This function triggered when Registered image button clicked
private void registeredImage() {
File file = new File(getExternalFilesDir(null) + "/db.imgdb");
Frame CurrFrame = frame;
Image currentImage;
int idx = -1;
try {
currentImage = CurrFrame.acquireCameraImage();
byte[] data = null;
data = NV21toJPEG(YUV_420_888toNV21(currentImage),
currentImage.getWidth(), currentImage.getHeight());
FileOutputStream outputStream = new FileOutputStream(file);
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
idx = aid.addImage("earth",bitmap);
aid.serialize(outputStream);
outputStream.close();
Toast.makeText(this, "image Registered", Toast.LENGTH_SHORT).show();
} catch (NotYetAvailableException | IOException e) {
e.printStackTrace();
}
}
private void onUpdate(FrameTime frameTime) {
frame = arFragment.getArSceneView().getArFrame();
Collection<AugmentedImage> images = frame.getUpdatedTrackables(AugmentedImage.class);
for(AugmentedImage image : images){
if(image.getTrackingMethod() == AugmentedImage.TrackingMethod.FULL_TRACKING){
if(image.getName().equals("test")){
textView.setText("Test is visible");
}
else if(image.getName().equals("earth")){
textView.setText("earth is visible");
}
}
}
}
}
When I clicked on button, the app crashes and image didnot add in database. Following are the errors when idx = aid.addImage("earth",bitmap); line called in registeredImage() function.
2020-10-05 14:11:39.738 31013-31013/com.example.artag E/native: error_policy_util.cc:261
################ ARCore Native Error ##################
BUILD_CHANGELIST:331869482
BUILD_BASELINE_CHANGELIST:331085015
################### Stack Trace Begin ################
ARCoreError: third_party/arcore/ar/planar_targets/augmented_image_database_utils.cc:58 https://cs.corp.google.com/piper///depot/google3/third_party/arcore/ar/planar_targets/augmented_image_database_utils.cc?g=0&l=58
ARCoreError: third_party/arcore/ar/core/c_api/augmented_image_database_c_api.cc:133 https://cs.corp.google.com/piper///depot/google3/third_party/arcore/ar/core/c_api/augmented_image_database_c_api.cc?g=0&l=133
################### Stack Trace End #################
2020-10-05 14:11:39.739 31013-31013/com.example.artag D/AndroidRuntime: Shutting down VM
2020-10-05 14:11:39.742 31013-31013/com.example.artag E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.artag, PID: 31013
com.google.ar.core.exceptions.ImageInsufficientQualityException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at com.google.ar.core.Session.throwExceptionFromArStatus(Session.java:101)
at com.google.ar.core.AugmentedImageDatabase.nativeAddImage(Native Method)
at com.google.ar.core.AugmentedImageDatabase.addImage(AugmentedImageDatabase.java:5)
at com.example.artag.MainActivity.registeredImage(MainActivity.java:130)
at com.example.artag.MainActivity.lambda$onCreate$0$MainActivity(MainActivity.java:72)
at com.example.artag.-$$Lambda$MainActivity$5zEkixen6UibjSKLs5AkDUICWdM.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7333)
at android.widget.TextView.performClick(TextView.java:14160)
at android.view.View.performClickInternal(View.java:7299)
at android.view.View.access$3200(View.java:846)
at android.view.View$PerformClick.run(View.java:27773)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6990)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Please help to find out the problem,
Thanks :)
The image that you attempted to add to the database does not have enough features.
Check https://developers.google.com/ar/reference/java/com/google/ar/core/exceptions/ImageInsufficientQualityException#ImageInsufficientQualityException()
for the complete specification of the errors.
If you want users to upload images, I recommend using a try-catch-block and letting the user know about the error instead of having the app crash.
Related
I have an error whit FaceDetector
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
at com.tec.nonfacies.adapters.UsuariosAdapter$1.onSuccess(UsuariosAdapter.java:126)
at com.tec.nonfacies.adapters.UsuariosAdapter$1.onSuccess(UsuariosAdapter.java:108)
at com.google.android.gms.tasks.zzm.run(com.google.android.gms:play-services-tasks##18.0.1:1)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
This is the code in JAVA
mUsersProvider.getUser(userId).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()){
if (documentSnapshot.contains("image_profile")){
mImageProfile = documentSnapshot.getString("image_profile");
if (mImageProfile != null){
if (!mImageProfile.isEmpty()){
if (user.getImage_profile() != null) {
if (!user.getImage_profile().isEmpty()) {
Picasso.with(context).load(mImageProfile).into(holder.mCircleImageViewProfile);
String ruta = mImageProfile;
holder.mCircleImageViewProfile.setImageBitmap(BitmapFactory.decodeFile(ruta));
//Bitmap bitmapcam = (Bitmap) data.getExtras().get("data");
holder.mCircleImageViewProfile.setImageBitmap(BitmapFactory.decodeFile(ruta));
final Bitmap tempBitmap = Bitmap.createBitmap(BitmapFactory.decodeFile(ruta).getWidth(),BitmapFactory.decodeFile(ruta).getHeight(), Bitmap.Config.RGB_565);
canvas = new Canvas(tempBitmap);
canvas.drawBitmap(BitmapFactory.decodeFile(ruta),0,0,null);
FaceDetector faceDetector = new FaceDetector.Builder(context)
.setTrackingEnabled(false)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.FAST_MODE)
.build();
if(!faceDetector.isOperational())
{
Toast.makeText(context, "Face Detector could not be set up on your device", Toast.LENGTH_SHORT).show();
return;
}
Frame frame = new Frame.Builder().setBitmap(BitmapFactory.decodeFile(ruta)).build();
SparseArray<Face> sparseArray = faceDetector.detect(frame);
for(int i=0;i<sparseArray.size();i++)
{
Face face = sparseArray.valueAt(i);
float x1=face.getPosition().x;
float y1 =face.getPosition().y;
float x2 = x1+face.getWidth();
float y2=y1+face.getHeight();
RectF rectF = new RectF(x1,y1,x2,y2);
//canvas.drawRoundRect(rectF,2,2,rectPaint);
int scaledWidth = (int) face.getWidth();
int scaledHeight = (int) face.getHeight();
eyePatchBitmap = Bitmap.createScaledBitmap(eyePatchBitmap,scaledWidth+50, scaledHeight+50, true);
holder.mCircleImageViewProfile.setImageBitmap(eyePatchBitmap);
detectLandmarks(face);
ViewGroup.LayoutParams params=imageViewFire.getLayoutParams();
//int ancho = eyePatchBitmap.getScaledHeight();
params.height= eyePatchBitmap.getHeight()*7;
params.width= eyePatchBitmap.getWidth()*7;
imageViewFire.setLayoutParams(params);
}
Toast.makeText(context, "Message", Toast.LENGTH_SHORT).show();
}
}
}
}
}
}
}
});
I dont undertand, this same code working perfectly in others activitys.
Sometimes this code not working 100% but I have the error only here.
I know that FaceDetector is deprecated but I need that working.
I dont speak English, sorry.
Can you help me?
I'm using ARCore in my android project. It has one activity, MainActivity.java and one CustomArFragment.java.
The problem is that the camera quality is very low. how can I increase the camera preview resolution. In future , I need the recognize the text using camera and having such low quality, its difficult to recognize. I am not able to find the solution on google. Tried many things but got no success. Anyone please tell how to increase camera quality. I'm totally new in AR and android field.
Thanks :)
MainActivity.java :
public class MainActivity extends AppCompatActivity {
private CustomArFragment arFragment;
private TextView textView;
private AugmentedImageDatabase aid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);
textView = findViewById(R.id.textView);
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdate);
findViewById(R.id.registeredBtn).setOnClickListener(v -> {
if(ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
return;
}
registeredImage();
});
}
private void registeredImage() {
File file = new File(getExternalFilesDir(null) + "/db.imgdb");
try {
FileOutputStream outputStream = new FileOutputStream(file);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.earth);
aid.addImage("earth",bitmap);
aid.serialize(outputStream);
outputStream.close();
Toast.makeText(this, "image Registered", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
private void onUpdate(FrameTime frameTime) {
frame = arFragment.getArSceneView().getArFrame();
Collection<AugmentedImage> images = frame.getUpdatedTrackables(AugmentedImage.class);
for(AugmentedImage image : images){
if(image.getTrackingMethod() == AugmentedImage.TrackingMethod.FULL_TRACKING){
if(image.getName().equals("lion")){
textView.setText("LION is visible");
}
else if(image.getName().equals("download")){
textView.setText("download is visible");
}
else{
textView.setText("Nothing is visible till now");
}
Log.d("Value of textView : "," " + textView.getText());
}
Log.d("Value of textView1 : "," " + textView.getText());
}
}
public void loadDB(Session session, Config config){
//InputStream dbStream = getResources().openRawResource(R.raw.imagedb);
try {
File file = new File(getExternalFilesDir(null) + "/db.imgdb");
FileInputStream dbStream = new FileInputStream(file);
aid = AugmentedImageDatabase.deserialize(session, dbStream);
config.setAugmentedImageDatabase(aid);
session.configure(config);
Log.d("TotalImages"," : " + aid.getNumImages());
}catch (IOException e){
e.printStackTrace();
}
}
CustomArFragment.java
public class CustomArFragment extends ArFragment {
#Override
protected Config getSessionConfiguration(Session session){
getPlaneDiscoveryController().setInstructionView(null);
Config config = new Config(session);
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
MainActivity activity = (MainActivity) getActivity();
activity.loadDB(session,config);
this.getArSceneView().setupSession(session);
return config;
}
}
I added some info regarding a similar topic in this other question. But answering yours, check what CameraConfig is used by default (use getCameraConfig() on the Session). Then you can get the one that is of your interest (high GPU texture size) through getSupportedCameraConfigs() and configure the Session with it through setCameraConfig.
Reading your question again, if you need in the future to recognize some text on the image, you might want to get a higher CPU image instead of GPU texture size. You can still use CameraConfig to check that and choose your favorite, but keep in mind that higher CPU images decreases the performance quite a bit. You might want to check my answer in the question I mentioned earlier.
EDIT: Use this code snippet to check the CameraConfig being used and adapt it to your needs:
Session session = new Session(requireActivity());
// ...
Size selectedSize = new Size(0, 0);
CameraConfig selectedCameraConfig = null;
CameraConfigFilter filter = new CameraConfigFilter(session);
List<CameraConfig> cameraConfigsList = session.getSupportedCameraConfigs(filter);
for (CameraConfig currentCameraConfig : cameraConfigsList) {
Size cpuImageSize = currentCameraConfig.getImageSize();
Size gpuTextureSize = currentCameraConfig.getTextureSize();
Log.d("TAG", "CurrentCameraConfig CPU image size:" + cpuImageSize + " GPU texture size:" + gpuTextureSize);
// Adapt this check to your needs
if (gpuTextureSize.getWidth() > selectedSize.getWidth()) {
selectedSize = gpuTextureSize;
selectedCameraConfig = currentCameraConfig;
}
}
Log.d("TAG", "Selected CameraConfig CPU image size:" + selectedCameraConfig.getImageSize() + " GPU texture size:" + selectedCameraConfig.getTextureSize());
session.setCameraConfig(selectedCameraConfig);
// ...
// Don't forget to configure the session afterwards
session.configure(config);
I'm using the firebase realtime database to get some users info and show a custom marker for each one.. to set the icon for the marker options I use the method below and it works for most cases.
But more often the app crashes when creating the bitmap of the custom view for the marker..! Is there a way to improve the method and prevent bitmap problems.!
Code
{ // other methods..
private void showMarker() {
BitmapDescriptor pin = BitmapDescriptorFactory
.fromBitmap(getMarkerBitmapFromView(data.getUserAvatar()));
userMarker = googleMap.addMarker(new MarkerOptions()
.position(latLng)
.title(data.getName() + "")
.snippet(data.getSectionName() + "")
.icon(pin));
}
// I take pic url from firebase and show it into the marker view
private Bitmap getMarkerBitmapFromView(String ImgUrl) {
if (getActivity() != null) {
View customMarkerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.map_marker, null);
CircleImageView markerImageView = customMarkerView.findViewById(R.id.pic_user);
FrameLayout pin = customMarkerView.findViewById(R.id.marker);
pin.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.map_marker_green));
Picasso.with(getActivity())
.load(ImgUrl)
.resize(80, 80)
.error(R.drawable.user_dummy)
.placeholder(R.drawable.user_dummy)
.into(markerImageView);
customMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
customMarkerView.buildDrawingCache(true);
Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
canvas.drawColor(Color.WHITE, Mode.SRC_IN);
Drawable drawable = customMarkerView.getBackground();
if (drawable != null) {
drawable.draw(canvas);
}
customMarkerView.draw(canvas);
return returnedBitmap;
} else {
// the crash didn't happen because of this! I've checked using breakpoints, it returns bitmap 99.9% of times.
return null;
}
}
}
The Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.arapeak.katateeb, PID: 30706
com.google.maps.api.android.lib6.common.apiexception.b: Failed to decode image. The provided image must be a Bitmap.
at com.google.maps.api.android.lib6.impl.k.a(:com.google.android.gms.dynamite_dynamitemodulesb#12529020#12.5.29 (040308-192802242):5)
at com.google.maps.api.android.lib6.impl.o.a(:com.google.android.gms.dynamite_dynamitemodulesb#12529020#12.5.29 (040308-192802242):7)
at com.google.maps.api.android.lib6.impl.db.<init>(:com.google.android.gms.dynamite_dynamitemodulesb#12529020#12.5.29 (040308-192802242):25)
at com.google.maps.api.android.lib6.impl.bc.a(:com.google.android.gms.dynamite_dynamitemodulesb#12529020#12.5.29 (040308-192802242):496)
at com.google.android.gms.maps.internal.l.onTransact(:com.google.android.gms.dynamite_dynamitemodulesb#12529020#12.5.29 (040308-192802242):94)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.internal.zzeu.zza(Unknown Source)
at com.google.android.gms.maps.internal.zzg.addMarker(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
Hi I have used like this and it's working fine for me
//generate bit map from view
private Bitmap createBitMap(View v) {
Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
if (b != null) {
Canvas c = new Canvas(b);
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.draw(c);
}
return b;
}
// created user marker with his image
private void addMyLocationMarker() {
View view = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.layout_marker, null, false);
view.setLayoutParams(new ViewGroup.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
view.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
if (userMarker != null)
userMarker = googleMap
.addMarker(new MarkerOptions()
.anchor(0.5F, 0.5F)
.position(latlng)
.icon(BitmapDescriptorFactory.fromBitmap(createBitMap(bindingUserMarker.getRoot()))));
userMarker.setZIndex(2f);
updateUserMarkerImage(view);
}
}
//update user image
private void updateUserMarkerImage(View view ) {
ImageView imageView=view.findViewById(R.id.image);
//load your image using any image loader and recreate marker with your view and set it marker
}
I try camera preview capture on android.
use Bitmap.
but occur NullpointerException
java.lang.NullPointerException
at kr.co.mytest.test.video.CameraTextureView.getImage(CameraTextureView.java:167)
at kr.co.mytest.test.video.CameraTextureView.onPreviewFrame(CameraTextureView.java:161)
at android.hardware.Camera$EventHandler.handleMessage(Camera.java:936)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
CameraTextureView.class
public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
private Camera mCamera;
private CaptureViewer captureView;
.
.
.
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Log.d(TAG,"CHECK");
YuvImage image = new YuvImage(data, 20, 640 ,480, null);
Rect rect = new Rect(0, 0, 640, 480);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
image.compressToJpeg(rect, 100, bao);
byte[] jpeg = bao.toByteArrary();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap convertedImage = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
Log.d(TAG, "convertedImage" + convertedImage); //android.graphics.Bitmap#21ac0b78
getImage(Bitmap.createScaleBitmap(convertedImage, 480, 360, true)); //nullPointerException
}
public void getImage(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
captureView.displayImage(bitmap);
}
CaptureView.class
public class CaptureView extends View {
private Bitmap mBitmap = null;
public void displayImage(Bitmap image) {
mBitmap = Bitmap.createBitmap(image);
postInvalidate();
}
}
displayImage is only showing capture image.
why occur nullpointerException?
onPreviewFrameis Called as preview frames are displayed.
how to process occur nullPointerException?
thanks.!
I have the Relative Layout which has a scroll view and has more than 20 textviews.
when i try to convert this layout into a bitmap it is not happening
when i view it in an external storage it says "this file is damaged"
in gallery the image shows a black view
this is the code which i have used to convert the view to bitmap
public static Bitmap loadBitmapFromView(Context context, View v) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
v.measure(View.MeasureSpec.makeMeasureSpec(dm.widthPixels, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(dm.heightPixels, View.MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
v.draw(c);
return bitmap;
}
I have passed the object of relative layout to loadBitmapFromView.
and
I have used this code for saving image to external storage
private void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 100000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG,1000,out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
this is my logcat
12-30 15:02:20.397 24825-24825/com.google.android.gms.samples.vision.barcodereader W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
12-30 15:02:20.397 24825-24825/com.google.android.gms.samples.vision.barcodereader W/System.err: at com.google.android.gms.samples.vision.barcodereader.ResultActivity.SaveImage(ResultActivity.java:3483)
12-30 15:02:20.397 24825-24825/com.google.android.gms.samples.vision.barcodereader W/System.err: at com.google.android.gms.samples.vision.barcodereader.ResultActivity.onCreate(ResultActivity.java:137)
Your createBitmap function would be returning null, You try to obtain the bitmap like below.
final View v = mView.findViewById(R.id.your_view_id);
Bitmap b = Bitmap.createBitmap( v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return b;
Try this
public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(
v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
and use it as
Bitmap b = loadBitmapFromView(your_layout_object);