How to draw on Camera Preview - java

for some time I've been working on this app, that allows user to take photos. The interesting thing about it, is that there should be some lines drawn over camera preview. The problem is that I'm not quite sure how to do this. I do have codes to initiate camera and to draw line, but I do not know how to merge them.
I use this code to initiate camera on button click:
initCamera.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//Starting a new Intent
/*Intent nextScreen = new Intent(getActivity().getApplicationContext(), CameraActivity.class);
startActivity(nextScreen);*/
count++;
String file = dir+count+".jpg";
File newfile = new File(file);
try {
newfile.createNewFile();
} catch (IOException e) {}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
}
});
And here's how I usually draw lines:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
imageView1 = (ImageView) findViewById(R.id.imageView1);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
bmp = Bitmap.createBitmap(width, height, conf);
canvas = new Canvas(bmp);
p = new Paint();
p.setColor(Color.RED);
imageView1.setImageBitmap(bmp);
p.setStrokeWidth(5);
canvas.drawLine(0, height/2, width, height/2, p);

You will need an overlay to draw on top of the live camera preview. The overlay is a child class of the surface the preview is drawn on. The preview class looks something like this:
class Preview extends ViewGroup implements SurfaceHolder.Callback, Camera.PreviewCallback
{
Preview(Context context)
{
super(context);
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
mSurfaceView = new SurfaceView(PreviewContext);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
PreviewCameraOverlay = new CameraOverlay(context);
addView(PreviewCameraOverlay);
}
// Additional functions like:
// surfaceChanged(SurfaceHolder holder, int format, int width, int height)
// onPreviewFrame(byte[] data, Camera pCamera)
// etc.
}
protected class CameraOverlay extends View
{
public CameraOverlay(Context context)
{
super(context);
setWillNotDraw(false);
setBackgroundColor(Color.TRANSPARENT);
setAlpha(1f);
OverlayPaint = new Paint[PaintColors];
}
// Additional functions:
// onDraw(Canvas canvas)
// onMeasure(int widthMeasureSpec, int heightMeasureSpec)
}
From your main activity you would call: Preview CameraPreview = new Preview(this); and draw whatever it is you want to draw from CameraOverlay's onDraw().

Related

Android App crashes with Simple draw to canvas, disp Bitmap

#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(this);
int height = this.getWindow().getDecorView().getHeight();
int width = this.getWindow().getDecorView().getWidth();
bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888 );
canvas = new Canvas(bitmap);
imageView = findViewById(R.id.imageView);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.button){
canvas.drawColor(Color.RED);
}
imageView.setImageBitmap(bitmap);
}
}
Does anyone have any idea why the above code snippet for Android Studio would cause the app to crash constantly? I'm new to Android Studio and I want to get used to building rectangles and shapes before anything more, but it seems I'm having difficulty with even that.
Displays error of drawing Bitmap with values not > 0, but the issue is that after using a print function in onClick, grabbing height or width from either window or the imageView, I am returned a value > 0, so I don't understand.
You are getting height and width in onCreate method before view has been drawn and thus resulting in returning height 0, width 0 since android system don't know exact width and height of view.You can use some method like post(Runnable) to know if view has drawn.Modify you code like below.
View view = this.getWindow().getDecorView();
view.post( new Runnable() {
#Override
public void run() {
width = view.getMeasuredWidth();
height = view.getMeasuredHeight();
bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888 );
canvas = new Canvas(bitmap);
}
});

How to add Custom color Effect on My Custom camera in android

I want to create my custom camera with supports different color
effects for taking images ... I want to custom color effect on my
camera . i put some effect that is Built_In in device but i have no
idea that how i apply other effect like AFTER SNOW FALLING EFFECT
from here and so many other Color Effects.
Please Give me some hints or any link that is helpful for me
My code for effect is
((ImageView)findViewById(R.id.e1)).setOnClickListener(onButtonClick);
private View.OnClickListener onButtonClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.e1: MonoEffect();
break;}
}
};
private void MonoEffect()
{
Camera.Parameters parameters =mCamera.getParameters();
parameters.setColorEffect(android.hardware.Camera.Parameters.EFFECT_MONO);
mCamera.setParameters(parameters);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cameraPreviewLayout = (FrameLayout) findViewById(R.id.camera_preview);
//this code is holding an realtime overlay
RelativeLayout layout = (RelativeLayout) findViewById(R.id.preview);
FrameLayout fr = new FrameLayout(this);
fr.setBackgroundResource(R.drawable.snow);
ImageView b1 = new ImageView(this);
b1.setBackgroundResource(R.drawable.snow);
fr.addView(b1);
layout.addView(fr);
/*one solution could be,you if you want a real-time effect on your camera layout,you can add an overlay on the preview as given up.snow is a png format picture with transparent background */ after that... add both the camera output and ta transparent snoweffect as..
Bitmap cameraBitmap =BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap overlayBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.snow);
Bitmap cameraScaledBitmap = Bitmap.createScaledBitmap(cameraBitmap, 1200, 1600, true);
int wid = cameraScaledBitmap.getWidth();
int hgt = cameraScaledBitmap.getHeight();
Bitmap newImage = Bitmap.createBitmap(wid,hgt, Bitmap.Config.ARGB_8888);
Bitmap overlayScaledBitmap = Bitmap.createScaledBitmap(overlayBitmap, wid, hgt, true);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(cameraBitmap , 0, 0, null);
canvas.drawBitmap(overlayScaledBitmap , 0, 0, null);
now you have got your final bitmap as named overlayScaledBitmap.now save it.dont tension about 1200,1600.i just scaled both the camera output bitmap and the snow transparent png as same size.i am currently working on the same project as you qustioned.i would like to take any suggetion from you. https://www.facebook.com/mohammad.mukul.37

Android: Create a mirror image of a view

I wrote a code that reflects the view of an ImageView in the splash activity. In order to implement this, I took three steps.
Create an ImageView in the layout_splash.xml file and also in the SplashActivity.java.
Call the setImageBitmap method with the reflected ImageView variable
Declare a method that reflects the view of the image.
And here is the code.
public class SplashActivity extends Activity {
private ImageView ivLogo;
private SharedPreferences appPreferences;
private Typeface typeface;
private TextView tvAppName;
private boolean isAppInstalled = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
String appName = getResources().getString(R.string.app_name);
appPreferences = PreferenceManager.getDefaultSharedPreferences(this);
isAppInstalled = appPreferences.getBoolean("isAppInstalled", false);
if(isAppInstalled == false) {
Intent shortcutIntent = new Intent(getApplicationContext(), SplashActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, appName);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.mipmap.ic_launcher));
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(intent);
SharedPreferences.Editor editor = appPreferences.edit();
editor.putBoolean("isAppInstalled", true);
editor.commit();
}
// Set the app name's font
typeface = Typeface.createFromAsset(getAssets(), "fonts/Catull.ttf");
tvAppName = (TextView) findViewById(R.id.tvAppName);
tvAppName.setTypeface(typeface);
Bitmap originalImage = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_gruppo);
ivLogo = new ImageView(this);
ivLogo.setImageBitmap(getReflection(originalImage));
Handler hd = new Handler();
hd.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getApplicationContext(), InitialActivity.class);
startActivity(intent);
// Implement the animation on activity change
overridePendingTransition(R.anim.push_down_in, R.anim.push_down_out);
finish();
}
}, 1200);
}
public Bitmap getReflection(Bitmap image) {
// The gap we want between the reflection and the original image
final int reflectionGap = 4;
// Get the bitmap from the mipmap folder
Bitmap originalImage = image;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matrix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Bitmap.Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw the reflection Image
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
}
But when running the application, I don't see the reflected image but just the plain one. Something wrong with the code?
Problems always occur from the very small things. In here the problem is that the ivLogo variable was not added into the content view. So the ivLogo must be added in the onCreate method like this,
ivLogo = (ImageView) findViewById(R.id.ivLogo);
instead of
ivLogo = new ImageView();

Android Camera not returning photo to main activity when I rotate the screen in the camera application and my main activity fails

This is my first post and while I am new to Android, this community has been great so far.
Here is the trouble I am having with my relatively simple application.
I have a image view on my main activity. onClick, the image view will open up the Camera application. I can take a picture and the camera application will return that picture and set it as the picture in the image view.
The main activity will crash when I start in one orientation and take a picture in another. Example: I open the main activity initially in a vertical orientation, open the camera application and switch to a horizontal view, and take a picture. When the camera application tries to return the picture the main activity crashes. The application does not crash when all activities are used in the same orientation.
I'm lead to believe it's either the way that I am saving the picture or that on onResume, the main activity doesn't have enough time to switch to the new orientation and receive the picture before it crashes.... or maybe that it simply destroys the picture when the main activity is resumed.
public class mainActivity extends Activity {
static final int REQUEST_IMAGE_CAPTURE = 1;
//Declares variable of mImageView
ImageView mImageView;
String mCurrentPhotoPath;
//String activityOrientation;
File photoFile = null;
Uri uriFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Setting mImageView to the UI ID of
mImageView = (ImageView) findViewById(R.id.imageViewLicense); // making mImageView = the license image view right now just to make sure the code works, I can add to later when adding the medical card
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState.containsKey("cameraImageUri")) {
uriFile = Uri.parse(savedInstanceState.getString("cameraImageUri"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (uriFile != null) {
outState.putString("cameraImageUri", uriFile.toString());
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//Initialized the camera to take a picture then return the result of the picture
public void dispatchTakePictureIntent(View view)
{
//Create new intent
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
uriFile = Uri.fromFile(photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
uriFile);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
//Method for rotating the image of the bitmap to the corrected orientation
private Bitmap adjustImageOrientation(Bitmap image) {
ExifInterface exif;
try {
exif = new ExifInterface(mCurrentPhotoPath);
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
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;
}
if (rotate != 0) {
int w = image.getWidth();
int h = image.getHeight();
// Setting pre rotate
Matrix mtx = new Matrix();
mtx.preRotate(rotate);
// Rotating Bitmap & convert to ARGB_8888, required by tess
image = Bitmap.createBitmap(image, 0, 0, w, h, mtx, false);
}
} catch (IOException e) {
return null;
}
return image.copy(Bitmap.Config.ARGB_8888, true);
}
//The photo taken in the takePicture method is returned here
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
//Rotates the image to the proper orientation
Bitmap adjustedBitmap = adjustImageOrientation(bitmap);
//Sets the original imageview as picture taken.
mImageView.setImageBitmap(adjustedBitmap);
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
}
Android restarts the main activity when the orientation changes so you'll need to disable or handle that. You can find out more here: How do I disable orientation change on Android?
The accepted answer is bad practice, see Why not use always android:configChanges="keyboardHidden|orientation"?.
It would be a better idea to save your mCurrentPhotoPath variable.
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("filepath", mCurrentPhotoPath);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle state) {
mCurrentPhotoPath = state.getString("filepath");
super.onRestoreInstanceState(state);
}

android 4.2 how to adjust the screen brightness

I have an android device, it can only run a app (like ATM screen). Now I want to implement the following feature:
If the device is not in use for over 30 minutes, I will adjust the screen brightness to the lowest. At this time, if I touch the screen, I should adjust the screen brightness to the maximum. The user can not see any Android system menu, application, etc. They only can use this app (can't close it). This app will run in this device from the power on it and power off it.
I don't how to implement this feature.
Thanks.
You can use a class that extends service and can dim the screen brightness. Use AlarmManager to check the time that the user never touches the screen. I will give you an example of using the Service class:
public class DimScreen extends Service {
public static int ID_NOTIFICATION = 2018;
private WindowManager windowManager;
private LinearLayout saverScreen;
private PopupWindow pwindo;
boolean mHasDoubleClicked = false;
long lastPressTime;
private Boolean _enable = true;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
saverScreen = new LinearLayout(this);
saverScreen.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
Bitmap sample = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
saverScreen.setBackground(new BitmapDrawable(this.getResources(),
convertColorIntoBlackAndWhiteImage(sample)));
saverScreen.setClickable(false);
saverScreen.setFocusable(false);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
WindowManager.LayoutParams.FILL_PARENT,
PixelFormat.TRANSLUCENT);
params.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_DIM_BEHIND;
params.dimAmount = (float) 0.6;
params.screenBrightness = (float) 0.3;
params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE;
windowManager.addView(saverScreen, params);
}
#Override
public void onDestroy() {
super.onDestroy();
if (saverScreen != null) windowManager.removeView(saverScreen);
}
private Bitmap convertColorIntoBlackAndWhiteImage(Bitmap orginalBitmap) {
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(2);
ColorMatrixColorFilter colorMatrixFilter = new ColorMatrixColorFilter(
colorMatrix);
Bitmap blackAndWhiteBitmap = orginalBitmap.copy(
Bitmap.Config.ARGB_8888, true);
Paint paint = new Paint();
paint.setColorFilter(colorMatrixFilter);
Canvas canvas = new Canvas(blackAndWhiteBitmap);
canvas.drawBitmap(blackAndWhiteBitmap, 0, 0, paint);
return blackAndWhiteBitmap;
}
}
In your Activity class call
startService(new Intent(this,DimScreen.class));
You only have to implement the AlarmManager now. If the user never touches the screen, launch the Service class. If the user Interrupt with the app, then call stopService.
Try this
WindowManager.LayoutParams localLayoutParams = getWindow()
.getAttributes();
localLayoutParams.screenBrightness = 0.12F;
getWindow().setAttributes(localLayoutParams);

Categories