I ve created my custom camera on my app.When I press capture button it saves the taken photo where I set it before.
Everything is fine for now. But the problem is the phone saves the photo as phones pixels I mean I want to 600x600 pixel but everyphone saves the picture as its camera defaults.
How can I solve this?
I use this example for my custom camera : link
You must have to re size the bitmap of of your taken picture Like...
Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
then after delete the previous image which one was taken by camera
Whats happen in your case:
1.) always custom camera returns it default preview size you can get your preview and picture size using the code and chooses as depending on your requirement.
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<Camera.Size> sizes = params.getSupportedPictureSizes()
Related
I'm trying build a camera app in android using camera API.
I follow the instructions: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/ and I have built one camera app
Now i need to display preview camera inside a frame and take picture include the frame
Please see the two pictures below:
Frame in resource folder : https://i.stack.imgur.com/AaNIQ.png
The photo I want to achieve: https://i.stack.imgur.com/UWXcq.jpg
Anyone can give me suggestions or if possible give me a simple example?
I searched about this but didn't get proper example.
Thank you so much.
Half of the answer can be found here: https://stackoverflow.com/a/47240902/192373.
As for keeping the same layout for full-res picture capture, first of all make sure that you keep preview- and picture- sizes in sync. This does not mean that they must be the same, but the aspect ratios should. Some devices have weird effects when the aspect ratio changes to capture a photo.
Next, you capture the jpeg as usual, unpack it to bitmap, overlay with the frame bitmap (you may need a hi-res version of your frame here) and combine the two (based on https://stackoverflow.com/a/4863551/192373):
public Bitmap combineImages(Bitmap picture, Bitmap frame) {
Bitmap bmp = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(bmp);
comboImage.drawBitmap(picture, 0f, 0f, null);
comboImage.drawBitmap(frame, 0f, 0f, null);
return bmp;
}
I am working on a camera app.The camera preview show is with 4:3 ratio,When i take a photo i get the complete image or full screen image.
Since i am showing the user a Camera Preview with 4:3 ratio, i want the user to also get the image with 4:3 ratio only.
I have seen many libraries which gives the user an option to crop, but here as i give path of the image and then it should crop the image and display it to user.
How can i achieve this ?
I don't think android has an out of the box cropper - but you can crop your own with Bitmap.createBitmap(originalBitmap, x1, y1, x2, y2)
Each Camera on each Android device has List of Preview Sizes and Picture Sizes.
Camera.Parameters parameters = camera.getParameters();
List<Size> preview_sizes = parameters.getSupportedPreviewSizes();
List<Size> pictures_sizes = parameters.getSupportedPictureSizes();
Try to loop all this Sizes and pick 4:3. So your result will be 4:3 without cropping.
Read more here.
I'm working on Camera 2 API recently and my device has a 16:9 screen ratio but my camera sensor is 4:3. So all the preview size I got is 4:3. I' wondering is there any way I get a crop the size and only display the 16:9 part? I tried a long time and didn't find any help for camera 2.
My current camera code is similar to the camera 2 basic sample.
So how should I crop the preview and only display the 16:9 part on the texture view?
Thanks!!
You could create a SurfaceTexture with your ratio 4:3 instead of 16:9.
You could use the custom view from that sample project or create your own with the new ConstraintLayout and setting the ratio of height from 16:9 of your width (or inverse).
Then when you set the size of your texture:
texture.setDefaultBufferSize(width, height)
You will get not problems streching, because your texture is the same ratio as your camera output.
Hope this helps
I answered a similar question after having this same problem, and not being able to change the aspect ratio of the actual view to match the camera output (as Sulfkain's answer suggests).
Tl;dr: the answer lies in the configureTransform in Camera2BasicFragment. Although their function is mostly implemented for orientation, the scaling matrix can resolve scaling/aspect ratio issues with views that are the wrong shape for the camera output.
You have to do some debug on
setUpCameraOutputs(int width, int height)
and check the part that you are selecting the size of the output
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
// garbage capture data.
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedPreviewWidth,
rotatedPreviewHeight, maxPreviewWidth, maxPreviewHeight, largest);
maybe you have to hard select something there.
My application needs to capture some pictures of a given size (lets say WxH) in a portrait orientation mode.
In a general case the size WxH I want is not supported by the camera therefore I will need to crop the captured picture in order to match my specifications.
This apparently simple program is driving me crazy for the problem of "good" corrispondence among preview and picture sizes and format.
Let me explain:
I need a format (let's give some numbers: 800x600) for the output image, and I have to take pictures in a portrait screen orientation. My camera by default is in Landscape mode therefore it takes pictures with a Width much larger than the height. But since I want a portrait preview I need to rotate the image and as a consequence I get images with an height much larger than the width (the transpose of the original image I guess).
In this scenario I need to cut a horizontally extended rectangle from a bigger vertically extended rectangle and I would like to do that by having an accettable large preview.
the problem of cropping the out image from the picture does not scare me (for the moment), the mean problem is the matching among what the user sees into the preview and what the camera actually captures.
for each possible phone I need to:
- chose a suitable camera picture size with respect the desired image format
- chose a suitable camera preview size with respect to the picture size and format.
- hide the preview parts that will be cropped.
And with the constraints of no distortion and large preview.
How to do it in general?
What I thought and tried:
the main algorithm steps are:
- get the optimal picture size once known the desired format
- get the optimal preview size once known the picture size
- hide the parts not capturable of the preview
- crop the image
tried method 1)
A) I get the optimal picture size by minimizing the area difference (I could also check the aspect ratio affinity is not very important). (Size is a custom type different from Camera.Size)
public Size getOptimalPictureSize(List<Camera.Size> sizes) {
Size opt = new Size();
float objf = Float.MAX_VALUE;
float v;
for(Camera.Size s : sizes){
if(s.height<target_size.width || s.width<target_size.height)
continue;
v = (s.height-target_size.width)*s.width + (s.width-target_size.height)*target_size.width;
if(v<objf){
opt.width=s.width;
opt.height=s.height;
objf=v;
}
}
return opt;
}
B) I get the optimal preview size by finding the best compromise among different aspect ratio (with respect to the picture size) :
#Override
public Size getOptimalPreviewSize(Size picSize,List<android.hardware.Camera.Size> sizes) {
Size opt = new Size();
double objf = Double.MAX_VALUE;
double aspratio = picSize.getAspectRatio();
double v;
for(Camera.Size s : sizes){
v = Math.abs( ((double)s.width)/((double)s.height) - aspratio )/(Math.max(((double)s.width)/((double)s.height), aspratio));
if(v<objf){
objf=v;
opt.width=s.width;
opt.height=s.height;
}
}
return opt;
}
C) hiding methods for displaying only capturable parts....(discussed later)
** Trial 2) **
A) I get the picture and preview sizes by minimizing an optimality functions that weights at the same time the misfit among camera image aspect ratio and desired one and the misfit among the preview and picture aspect ratio.
public void setOptimalCameraSizes(List<Camera.Size> preview_sizes,List<Camera.Size> picture_sizes,Size preview_out, Size picture_out) {
double objf=Double.MAX_VALUE;
double tmp;
for(Camera.Size pts : picture_sizes){
for(Camera.Size pws : preview_sizes){
tmp = percv(((double)pws.height)/((double)pws.width),target_size.getAspectRatio())
+ percv(((double)pws.width)/((double)pws.height),((double)pts.width)/((double)pts.height));
if(tmp<objf){
preview_out.set(pws.width, pws.height);
picture_out.set(pts.width, pts.height);
objf=tmp;
}
}
}
}
where
percv(a,b) = |a-b|/max(|a|,|b|) measures the relative deviation (and thus is dimensionless).
C) some hiding methods...
Ok this two sizes selection methods are the best I found and chose good sizes, but they have a physiological problem that comes from the camera landscape orientation... they can only produce vertical rectangular images and this implies that when I draw the preview I can get two cases:
1. I set the surface dimensions so as not distort the preview image -> due to the huge height this reflects in a very small valid area in which the image is visible (so the user experience is hurted)
2. I set the maximum possible width -> I can obtain (it depends on the preview aspect ratio) distorted previews but much bigger than in case 1.
How to avoid these problems??
What I though is work on phase C) of the algorithm (hiding phase) and I tried to:
trial 1: make the camera preview go beyond the screen sizes. This will allow me to make an arbitrary zoom in the area of interest and make the screen crop the preview. I tried using a scrollview but it didn't work and I don't know why. The topology was simple a root scrollview and inside a FrameLayout with the attached surfaceview but the surface always filled the screen leading to horrible distortions.
trial 2: capture the camera frame and manipulate them directly by overriding the onPreviewFrame(.) method: I got a misteryous error in locking the canvas (IllegalArgumentException)
How can I solve this?
I created a layout where my surface view has been resized from the "original size", I did the following:
ViewGroup.LayoutParams params = mSurfaceView.getLayoutParams();
int mPixels=getResources().getDimensionPixelSize(R.dimen.profile_pic_dimension); //200
params.width=mPixels;
params.height=mPixels;
mSurfaceView.setLayoutParams(params);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
and I obtain a view like this:
http://img412.imageshack.us/img412/9379/layoutp.png
but then.. whenever I take the picture.. it doesn't saves as how I can see it on the view... but instead it saves it normal size like if the view was taking the whole screen (like if the surfaceview was never resized).
I tried using this:
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
#Override
public void onShutter() {
Camera.Parameters p = mCamera.getParameters();
p.setPictureSize(mSurfaceView.getWidth(), mSurfaceView.getHeight());
mCamera.setParameters(p);
}
};
but still didn't get the image size i wanted to.
You cannot just supply any width and height value when setting the picture (or preview) size. In stead, you'll have to use one of the items from the list of supported sizes, which you can retrieve by calling getSupportedPictureSizes() (there's an equivalent for the preview).
So far I haven't come across any devices that support taking square pictures, so after a 4:3, 16:9, 16:10, or whatever ratio, picture has been taken, you will have to 'cut' out the relevant part yourself, and optionally scale it down to a specific dimension. Probably the most straightforward way to do this, is by creating a new Bitmap as a subset from a source Bitmap (and then optionally scale it down). In order to get the source bitmap, you'll likely need to hook up a PictureCallback to the camera with takePicture(...).