Rotating video taken in portrait mode - java

My app lets the user capture video:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_VIDEO_REQUEST);
or pics:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
In the case of the pics, I can tell whether they were taken in any mode other than landscape and then rotate them before I upload them to the web:
ExifInterface exif = new ExifInterface(fileName);
int exifOrientation = Integer.parseInt(exif.getAttribute(ExifInterface.TAG_ORIENTATION));
float 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){
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
OutputStream outStream = context.getContentResolver().openOutputStream(Uri.fromFile(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
}
How do I accomplish the same with video?

I do not seem to fully understand your question. Here are some questions that I thought would at least steer you in the right direction. Hope it helps
Do you want to rotate the video for playback with the MediaPlayer?
Do you want to change the hard code in the video file to make it play rotated everywhere?
Rotate buffered video orientation?
==================================================================================
This answer to question # 1:
//rotating a SurfaceView that contains the MediaPlayer
/*
Create a new MediaPlayer SurfaceView, then use the SurfaceHolder interface
*/
video = new SurfaceView();
video.getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
video.getHolder().lockCanvas().rotate(90);
This answer to question # 2:
As for changing the hard code of a video. I would advise to use a nice GUI video codec to rotate the video and it should save its settings. Otherwise you will have to access the source code from the decoder then your SOL with my advice.
This answer to question # 3:
The post below explains how you can rotate a buffered video and/or change its orientation settings for different modes.
Post here: Android VideoView orientation change with buffered video
==================================================================================
If this doesn't help you then I am sure it will help someone else, and good luck.

Related

Android canvas doesn't draw the text on my bitmap

I'm trying to get the text input from the user and draw it on the image using Canvas but the image is saved without what was supposed to be drawn. Right now, I'm just trying to get the text on the Image before I worry about the font, colour, styles, etc.
This is my code:
public void createBitmapAndSave(ImageView img){
BitmapDrawable bitmapDrawable = ((BitmapDrawable) img.getDrawable());
Bitmap bitmap = bitmapDrawable.getBitmap();
Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(200);
paint.setStyle(Paint.Style.FILL);
paint.setShadowLayer(10f, 10f, 10f, Color.BLACK);
String topText = topTextView.getText().toString();
String bottomText = bottomTextView.getText().toString();
canvas.drawText(topText, 0, 0, paint);
canvas.drawText(bottomText, 50, 50, paint);
File file;
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
file = new File(path + "/SimpliMeme/" + timeStamp + "-" + counter + ".jpg");
file.getParentFile().mkdir();
try{
OutputStream stream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);
stream.flush();
stream.close();
Toast.makeText(getContext(), "Meme Saved", Toast.LENGTH_SHORT).show();
}
catch (IOException e){ e.printStackTrace();}
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
Objects.requireNonNull(getContext()).sendBroadcast(mediaScanIntent);
counter++;
}
At the moment, I only have the 2 .drawText() implementations based on the examples that I've seen in other SO posts. My assumption is that the text isn't visible and no changes are made to the image because I haven't provided the paint object with any attributes.
The main issue why you see no changes is that you make changes to mutableBitmap but save the original bitmap to disk.
This can be avoided by joining the first two (or even three) statements together:
final Bitmap bitmap = bitmapDrawable.getBitmap()
.copy(Bitmap.Config.ARGB_8888, true);
You didn't need the orginal bitmap anywhere else, this effectively prevents you from making the mistake. Don't do what you don't need to do.
Some tips:
Always be explicit when drawing. Specify the color, specify the font. You can't trust default values. (At least I'm never sure about the values. Is the default color black or transparent?)
If you want to be asolutely sure about the font, bundle it with your app or use downloadable fonts. Some platforms allow the user to change the default font to something crazy.
If you ever want to draw multiline text look into StaticLayout.
Make sure your app works on Android 7 and above. Sending intents with file Uri outside your app is prohibited.

Camera Intent Image Preview Orientation

I take an image in Android using the following Code:
File image = new File(this.images_object_dir, loadedObjekt.getFilename());
Uri uri = FileProvider.getUriForFile(this, FILE_PROVIDER, image);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, CAMERA_ACTIVITY_CODE);
In the camera intent, the image preview is always in portrait mode on my Huawei P20 Pro. On another test-device the preview image (the one where you can decide if you wanna retake the image) is stuck in the "inital" rotation as well which looks ugly. For instance, if you want to take an image in landscape mode, the preview gets flipped to portrait mode.
Is there a solution for this?
There are ~2 billion Android devices, spread across ~20,000 device models. There are dozens, if not hundreds, of pre-installed camera apps across those device models. There are plenty of other camera apps that the user can download and install.
Your code might start any of them.
In the camera intent, the image preview is always in portrait mode on my Huawei P20 Pro
That is the behavior of that one camera app out of hundreds.
On another test-device the preview image (the one where you can decide if you wanna retake the image) is stuck in the "inital" rotation as well which looks ugly.
That is the behavior of that one camera app out of hundreds.
There is no requirement for a camera app to behave that way. Of course, there is no requirement for a camera app to have preview images at all.
Is there a solution for this?
If you wish to use ACTION_IMAGE_CAPTURE, no. The behavior of those hundreds of camera apps is up to the developers of those camera apps, not you.
There are other options for taking pictures, such as using the camera APIs directly or using third-party libraries like Fotoapparat or CameraKit-Android.
Use ExifInterface to check the orientation of the image while decoding it. Then you rotate the image to get required image in proper orientation.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
Bitmap decoded = BitmapFactory.decodeFile(filePath, options);
if (decoded == null) return null;
try {
ExifInterface exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotation = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
rotation = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
rotation = 270;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
rotation = 180;
}
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
Bitmap newBitmap = Bitmap.createBitmap(decoded, 0, 0, decoded.getWidth(),
decoded.getHeight(), matrix, true);
decoded.recycle();
Runtime.getRuntime().gc();
decoded = newBitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
If you want to use support library in order to support devices with lower API levels, use the following dependency:
implementation 'com.android.support:exifinterface:27.1.1'
and import android.support.media.ExifInterface

Image from ACTION_IMAGE_CAPTURE Rotated

I am trying to simply get an image from a phone's camera. Surprisingly, it returns rotated. I've scoured the internet for fixes and came across many solutions using ExifInterface, but it only works sometimes. It gets the orientation wrong seemingly randomly, as I merely recompile and see different results. I have found some people saying this is a fault of the class itself being bugged.
I found other solutions that require like two additional libraries and more java files to do the job, but that just seems ridiculous (and I am avoiding additional packages). How come images are rotated in the first place (in storage they are perfectly fine), and how hard can it possibly be to fix the issue? Also - rotating the Image View also works (and seems much easier than literally creating a rotated image), but I need to know by how much to rotate the view.
EDIT---- I realized that the image is consistently rotated 270 degrees clockwise from the orientation the image was taken in (inside the intent) if the back camera was used, and 90 degrees if the front camera was used. Thus I only really need a way to find out this orientation.
Intent called here:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = setUpPhotoFile();
mCurrentPhotoPath = photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
mCurrentPhotoPath = null;
}
// Continue only if the File was successfully created
if (photoFile != null) {
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
Toast noStorage = Toast.makeText(this, "Cannot access mounted storage.", Toast.LENGTH_SHORT);
noStorage.show();
}
}
}
Bitmap created here:
private void setPic() {
/* Get the size of the ImageView */
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/* Figure out which way needs to be reduced less */
int scale = 1;
if (photoH > targetH|| photoW > targetW) {
scale = Math.max(
(int)Math.pow(2, (int) Math.ceil(Math.log(targetW /
(double) photoW)) / Math.log(0.5)),
(int)Math.pow(2, (int) Math.ceil(Math.log(targetH /
(double) photoH)) / Math.log(0.5)));
;
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scale;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
/*-----------How should I rotate bitmap/mImageView to correct orientation?*/
/* Associate the Bitmap to the ImageView */
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(View.VISIBLE);
}
The best solution I have found is this one:
https://www.samieltamawy.com/how-to-fix-the-camera-intent-rotated-image-in-android/
I post the link because I don't want all the credit.
Sami Eltamawy has written a function that rotate the image if its need to be rotated.
I try the code and is working on my devices that the image got rotated.

Android: Check Number of Faces Before Crop Image in Android

currently I am developing android application. In my application I need to crop image from gallery. However, before I allow the user to crop the image, I want to check whether there is face detected in the image or not.
Here is how I allow user to crop an image from gallery:
Intent pickImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickImageIntent.setType("image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("noFaceDetection", true);
pickImageIntent.putExtra("aspectX", size);
pickImageIntent.putExtra("aspectY", size);
pickImageIntent.putExtra("outputX", size);
pickImageIntent.putExtra("outputY", size);
pickImageIntent.putExtra("scale", true);
pickImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri());
pickImageIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(pickImageIntent, RESULT_LOAD_IMAGE);
Before I run above code, I want to do something like this:
imageWidth = myBitmap.getWidth();
imageHeight = myBitmap.getHeight();
myFace = new FaceDetector.Face[numberOfFace];
myFaceDetect = new FaceDetector(imageWidth, imageHeight,
numberOfFace);
numberOfFaceDetected = myFaceDetect.findFaces(myBitmap, myFace);
But I am confuse about how to do it. Anyone can help me? Thanks.

Bitmap Memory Error Android

I am making an Android game, but when I load my Bitmaps, I get a memory error. I know that this is caused by a very large Bitmap (it's the game background), but I don't know how I could keep from getting a "Bitmap size extends VM Budget" error. I can't rescale the Bitmap to make it smaller because I can't make the background smaller. Any suggestions?
Oh yeah, and here's the code that causes the error:
space = BitmapFactory.decodeResource(context.getResources(),
R.drawable.background);
space = Bitmap.createScaledBitmap(space,
(int) (space.getWidth() * widthRatio),
(int) (space.getHeight() * heightRatio), false);
You're going to have to sample down the image. You can't "scale" it down smaller than the screen obviously, but for small screens etc it doesn't have to be as high resolution as it is for big screens.
Long story short you have to use the inSampleSize option to downsample. It should actually be pretty easy if the image fits the screen:
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
final int dimension = Math.max(display.getHeight(), display.getWidth());
final Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
InputStream bitmapStream = /* input stream for bitmap */;
BitmapFactory.decodeStream(bitmapStream, null, opt);
try
{
bitmapStream.close();
}
catch (final IOException e)
{
// ignore
}
final int imageHeight = opt.outHeight;
final int imageWidth = opt.outWidth;
int exactSampleSize = 1;
if (imageHeight > dimension || imageWidth > dimension)
{
if (imageWidth > imageHeight)
{
exactSampleSize = Math.round((float) imageHeight / (float) dimension);
}
else
{
exactSampleSize = Math.round((float) imageWidth / (float) dimension);
}
}
opt.inSampleSize = exactSampleSize; // if you find a nearest power of 2, the sampling will be more efficient... on the other hand math is hard.
opt.inJustDecodeBounds = false;
bitmapStream = /* new input stream for bitmap, make sure not to re-use the stream from above or this won't work */;
final Bitmap img = BitmapFactory.decodeStream(bitmapStream, null, opt);
/* Now go clean up your open streams... : ) */
Hope that helps.
This may help you: http://developer.android.com/training/displaying-bitmaps/index.html
From the Android Developer Website, a tutorial on how to efficiently display bitmaps + other stuff. =]
I don't understand why are you using ImageBitmap? for background. If its necessary , its okay. Otherwise please use Layout and set its background because you are using background image.
This is important. (Check Android docs. They have clearly indicated this issue.)
You can do this in following way
Drawable d = getResources().getDrawable(R.drawable.your_background);
backgroundRelativeLayout.setBackgroundDrawable(d);
In most android devices the Intent size equals 16MB. You MUST Follow these instructions Loading Large Bitmap Efficiently

Categories

Resources