Getting image data continuously from camera, SurfaceView or SurfaceHolder - java

So I have this camera preview set up with Camera, SurfaceView and SurfaceHolder.
I have also an ImageView where I will be putting a modified version of the camera image and I want this to update lets say once every second.
All code is ready and already working when I load images from "res" but I have a really hard time reading the image data from the camera.
I've tried following already:
Creating an intent for MediaStore.ACTION_IMAGE_CAPTURE and starting an onActivityResult getting a small thumbnail (enough for me actually) from (Bitmap)data.getExtras().get("data")
The problem is that this opens the camera App and you need to "manually" take a picture.
Creating a Camera.PreviewCallback, taking the YuvImage, and converting it to an image using YuvImage.compressToJpeg(...).
The problem here is that I can't get it to start no matter when or where i put the Camera.setPreviewCallbackWithBuffer(PreviewCallback).
Try to take the data directly from PreviewHolder by locking in to the canvas using lockCanvas() and trying to convert it to a bitmap
Obviously Doesn't work.
Edit:
What is the best way to make this work? I mean QR-Code readers must read the image data out of the camera continuously, how do they work?

I went for option number 2 and finally made it work.
used this callback, forgot the #Override before
private Camera.PreviewCallback previewCallback= new Camera.PreviewCallback()
{
#Override
public void onPreviewFrame(byte[] data,Camera cam)
{
Camera.Size previewSize = cam.getParameters().getPreviewSize();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21,previewSize.width,previewSize.height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0,0,previewSize.width,previewSize.height),80,baos);
byte[] jdata = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jdata,0,jdata.length);
}
};
And initiating it using setPreviewCallback rather than setPreviewCallbackWithBuffer
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder) {
camera.setPreviewCallback(previewCallback);
}
}

Related

Bitmap not updating/ showing old values

I have a linear layout that has multiple fields that are to be filled by the user. The fields are to be filled with text or decimal numbers and they are all TextInputLayouts with one date picker. After the user has filled those fields I have a review button which once clicked shows a preview of all the values entered in an image view. I am showing the image by using bitmap and canvas and sending the bitmap as an argument to my material bottom sheet with the following code.
private Bitmap getDailySheetBitmap() {
Bitmap bitmap = Bitmap.createBitmap(completeSheetLinearLayout.getWidth(), completeSheetLinearLayout.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Log.d("Bitmap", "bitmap size: "+bitmap.getByteCount());
completeSheetLinearLayout.draw(canvas);
return bitmap;
}
And the code for sending arg is
private void buildBottomSheet(Bitmap bitmap) {
Bundle args = new Bundle();
args.putParcelable("Bitmap", bitmap);
ViewDailySheet viewDailySheet = new ViewDailySheet();
viewDailySheet.setArguments(args);
viewDailySheet.show(getChildFragmentManager(), "DailySheet");
}
The problem is that after the user reviews the fields and changes are made to those fields and when the user again clicks on the review button, the bitmap with the same old values is shown. I have tried recycling bitmap, invalidating the view, requestLayout() and forceLayout() method. But none of it is helping.
This is the code that puts bitmap into image view.This is in bottom sheet dialog fragment.
if (getArguments() != null) {
bitmap = getArguments().getParcelable("Bitmap");
binding.dailySheetImage.invalidate();
binding.dailySheetImage.setImageBitmap(bitmap);
getArguments().clear();
}
What am I doing wrong or missing?
The bitmap only captures what it thinks has changed. If the text field(not the data, just UI) is not changed it will show the same text field value as before. So I refreshed the whole layout as it would re-draw the entire layout by the following code.
private void refreshView() {
completeSheetLinearLayout.setVisibility(View.GONE);
completeSheetLinearLayout.setVisibility(View.VISIBLE);
}
I put this code just before creating the bitmap.

ImageView won't hide or clear image on Android

I've been working with android this days (iOS Developer), and I am unable to clear a ImageView. I've tried everything! Literally! I take a photo with my Camera instance, I am able to place the image in the image view and then when I want to remove it. It just freezes. However, the other UIView elements altered in the code below, work normally. (So I guess the UI Thread is working just fine).
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("DEFAULTS", "Back to Defaults");
processedTranslations = 0;
totalTranslations = 0;
nextIsProcessFaces = false;
nextIsFinish = false;
currentImage = null;
imagePreview.setVisibility(View.GONE);
imagePreview.setImageDrawable(null);
imagePreview.setImageBitmap(null);
imagePreview.setImageURI(null);
imagePreview.setImageResource(android.R.color.transparent);
imagePreview.setImageResource(0);
imagePreview.destroyDrawingCache();
imagePreview.invalidate();
loadingView.setVisibility(View.GONE);
captureButton.setEnabled(true);
}
});
And here is where I assign the resource to the ImageView (This block gets executed before the previous block) (Maybe the error is that it is nested in another thread? It is not released when the other thread tries to edit that imageView?)
runOnUiThread(new Runnable() {
#Override
public void run() {
Bitmap bitMapImage = BitmapFactory.decodeByteArray(blockData, 0, blockData.length);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitMapImage , 0, 0, bitMapImage .getWidth(), bitMapImage .getHeight(), matrix, true);
imagePreview.setImageBitmap(rotatedBitmap);
imagePreview.setScaleType(ImageView.ScaleType.CENTER_CROP);
imagePreview.setVisibility(View.VISIBLE);
}
});
I know this appears to be a really novice question (And a very repeated question) but I've tried all of the answers in similar questions (As you can see in my code.) Thanks so much for your help!

How to save a bitmap after applying effects

I have some buttons and one image view. I load a photo from gallery,the photo is displayed on image view. For every button,there is on click method to apply that applies one of the effects for the image. There is another button,that is for saving the photo on internal storage. I want to save the photo after one of the effects is applied. I searched,but I just find how to save the photo without effect . Does somebody know how with the on click method to save the image AFTER the effect is applied .
you can simply get the bitmap from ImageView by calling this function:
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap()
and then save your bitmap where you want with in/out streams:
private void saveBitmapFromImageView(File destFile, ImageView imageView){
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap()
OutputStream os;
try {
os = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
} catch(Exception e) {
Log.e(TAG, "saveBitmapFromImageView", e);
} finally {
IOUtils.closeQuietly(os);
}
}
Edit #1:
IOUtils is Apache commons lib, add to your gradle:
compile 'org.apache.commons:commons-io:1.3.2'

ANDROID STUDIO: Take picture with Camera API -> Send this picture to another activity

After I take a picture with the Camera API, this picture displays on the screen/this activity. I want to send this picture that covers the whole screen to another activity called PictureEditor. There I will add functionality that can edit the picture.
// Code in MainActivity
mCamera.takePicture(null, null, mPicture);
Intent i = new Intent(getApplicationContext(), PictureEditor.class);
Bitmap b = getBitmapFromView(mPreview);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startActivity(i);
In PictureEditor I have this code in OnCreate.
// Code in PictureEditor
if(getIntent().hasExtra("byteArray")) {
ImageView previewThumbnail = new ImageView(this);
Bitmap b = BitmapFactory.decodeByteArray(
getIntent().getByteArrayExtra("byteArray"),0,getIntent().getByteArrayExtra("byteArray").length);
previewThumbnail.setImageBitmap(b);
}
What can I do to retrive this picture in PictureEditor, and that this picture is the only thing that is visible on the screen in this activity? (Decode the bitmap and display it as an image on the screen)
Thanks for all kind of help!
Instead of startActivity call startActivityForResult and get the image from the bundle in onActivityResult call back method in the same activity and pass the image to the new Activity.
// Code in PictureEditor
if(getIntent().hasExtra("byteArray")) {
ImageView previewThumbnail = new ImageView(this);
Bitmap b =(Bitmap) getIntent().getParcelableExtra("byteArray");
previewThumbnail.setImageBitmap(b);
}
But if you send information between activitys. The size of this information cant exceed 1 MB. You have to compress your bitmap.

How to show a captured image in an ImageView?

I'm trying to display a captured image from a camera intent, but when I call a showPhoto method the image isn't shown in the ImageView. There is no error output to the stack trace so I'm not sure how the issue can be debugged.
Does anyone know what is wrong with the method that its not showing the captured image?
The showPhoto method is as follows:
private void showPhoto(Uri photoUri) {
String filePath = photoUri.getEncodedPath();
File imageFile = new File(filePath);
//File imageFile = new File(photoUri.getPath());
if (imageFile.exists()){
Drawable oldDrawable = photoImage.getDrawable();
if (oldDrawable != null) {
((BitmapDrawable)oldDrawable).getBitmap().recycle();
}
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
BitmapDrawable drawable = new BitmapDrawable(this.getResources(), bitmap);
photoImage.setScaleType(ImageView.ScaleType.FIT_CENTER);
photoImage.setImageDrawable(drawable);
}
}
This is the tutorial that I've followed: http://www.linux.com/learn/tutorials/722038-android-calling-the-camera
The device I'm testing on is JellyBean 4.1 and this is the link to the complete class:
http://hastebin.com/oqokupulol.java
Use BitmapOptions.inJustDecodeBounds to find out the dimension of the image first
Typically, Android won't load images larger than 4000px wide/tall
If you find out the image is too large, you can use BitmapOptions.inSampleSize to downscale the image so that Android would load it
And in fact, you can directly use ImageView.setImageBitmap(Bitmap) instead of setImageDrawable

Categories