Android уменьшить размер изображения с камеры
ОБНОВЛЕНИЕ, возможно, изменение размера растрового изображения в новом действии может решить проблему
String myRef = this.getIntent().getStringExtra("filepath");
File imgFile = new File(myRef);
Log.e("BeatEmUp", myRef);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imagepunch);
myImage.setImageBitmap(myBitmap);
}
Может быть как то так?
Bitmap scaled = Bitmap.createScaledBitmap(bit, 200, 200, true);
Или, может быть, это лучший способ ниже
Пока у меня есть мое приложение, которое делает снимок, а затем с помощью Intent
перенести картинку и отобразить в новом Activity
, Как только я это сделал, у меня есть код, который отображает изображения поверх onClick
, Проблема в том, что когда изображение снято, оно берется в максимальном размере, поэтому мое приложение принудительно закрывается.
В моем logcat я получаю java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=7431KB, Allocated=2956KB, Bitmap Size=19764KB)
что я думаю означает, что изображение слишком велико.
Я проверил, поместив в код меньшее изображение вместо изображения с камеры, которое было снято, и это работает, что также возвращает меня к проблеме, заключающейся в размере изображения с камеры.
Поэтому я пытаюсь реализовать это из CommonsWare, но пока безуспешно. Просматривая код, я думаю, что он ищет наименьшее разрешение / размер и затем снимает камеру с этими настройками. Правильно ли я думаю, и если да, то как я могу внедрить это в мой код?
public class AndroidCamera extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
final int RESULT_SAVEIMAGE = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl
= new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
Button buttonTakePicture = (Button)findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(myShutterCallback,
myPictureCallback_RAW, myPictureCallback_JPG);
}});
}
ShutterCallback myShutterCallback = new ShutterCallback(){
public void onShutter() {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_RAW = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
/*Bitmap bitmapPicture
= BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */
int imageNum = 0;
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Punch");
imagesFolder.mkdirs(); // <----
String fileName = "image_" + String.valueOf(imageNum) + ".jpg";
File output = new File(imagesFolder, fileName);
while (output.exists()){
imageNum++;
fileName = "image_" + String.valueOf(imageNum) + ".jpg";
output = new File(imagesFolder, fileName);
}
Uri uriSavedImage = Uri.fromFile(output);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
Toast.makeText(AndroidCamera.this,
"Image saved",
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent intent = new Intent(getBaseContext(), Punch.class);
intent.putExtra("filepath",Uri.parse(output.getAbsolutePath()).toString());
//just using a request code of zero
int request=0;
startActivityForResult(intent,request);
}};
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if(previewing){
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
camera.release();
e.printStackTrace();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
try {
Camera.Parameters parameters = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
// This is an undocumented although widely known feature
parameters.set("orientation", "portrait");
// For Android 2.2 and above
camera.setDisplayOrientation(90);
// Uncomment for Android 2.0 and above
parameters.setRotation(90);
} else {
// This is an undocumented although widely known feature
parameters.set("orientation", "landscape");
// For Android 2.2 and above
camera.setDisplayOrientation(0);
// Uncomment for Android 2.0 and above
parameters.setRotation(0);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if(previewing && camera != null) {
if(camera!=null) {
camera.stopPreview();
camera.release();
camera = null;
}
previewing = false;
}
}
}
2 ответа
До сих пор у меня есть приложение, которое делает снимок, а затем использует намерение для переноса изображения и отображения в новом действии.
В большинстве случаев передача данных между действиями с использованием Intent
Дополнительно это прекрасное решение. Однако большие растровые изображения вызывают проблемы из-за потребления памяти. Это один из случаев, когда я бы осторожно использовал статический член данных.
В моем logcat я получаю java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины (размер кучи =7431 КБ, выделенный =2956 КБ, размер растрового изображения =19764 КБ), что, как мне кажется, означает, что изображение слишком велико.
Это означает, что у вас недостаточно памяти для того, что вы пытаетесь сделать.
Просматривая код, я думаю, что он ищет наименьшее разрешение / размер, а затем берет камеру с этими настройками, я прав, думая, что
Да.
если так, как я могу реализовать это в моем коде?
Копирование и вставка обычно работает.:-)
Чтобы указать камере, какой размер снимка сделать, используйте setPictureSize()
на Camera.Parameters
, Однако вы должны выбрать размер, который он поддерживает, и не все устройства будут поддерживать произвольные размеры. призвание getSupportedPictureSizes()
скажет вам, какие размеры поддерживаются. Вам решать, какой из этих размеров использовать. В примере, на который я ссылался из вашего другого вопроса, я перебираю эти размеры и нахожу наименьший по площади.
Тем не менее, если единственная проблема с размером изображения - это передача его от действия к действию, я бы сначала пошел по маршруту статического члена данных. Просто обязательно null
этот статический член данных, когда вам больше не нужно изображение.
Может быть как то так?
Опять же, это зависит от вашей цели. Вы, кажется, колеблетесь вокруг в поисках решений, когда вы сформулировали только одну проблему (и даже там вы не сказали нам, где вы получаете ошибку нехватки памяти).
Если ваша цель состоит в том, чтобы сделать снимок в полном разрешении, сохраните его в файл, а затем сохраните в памяти миниатюру, createScaledBitmap()
это хорошее решение.
Если ваша цель состоит в том, чтобы в первую очередь сделать миниатюру (то есть вам не нужно или не нужно изображение в полном разрешении), используйте setPictureSize()
,
Если ваша цель - использовать изображение с полным разрешением, аккуратно используйте статический элемент данных, чтобы исключить ненужные копии Bitmap
и посмотрим, достаточно ли этого Это может быть не так, в зависимости от того, что вы пытаетесь сделать с изображением.
Попробуйте захват изображения с камеры.
Intent cameraActivity=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraActivity.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(left));
startActivityForResult(cameraActivity,CAMERA_PIC_REQUEST_LEFTIMAGE);
Это вернет вам изображение большого размера, теперь для его уменьшения вы можете использовать что-то вроде этого
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 6;
FileInputStream fileInputStream;
try {
fileInputStream=new FileInputStream(left);
leftPhoto=BitmapFactory.decodeStream(fileInputStream,null,options);
leftImage.setImageBitmap(leftPhoto);
fileInputStream.close();
} catch (FileNotFoundException e) {
Toast.makeText(getCurrentContext(), e.getMessage(),Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getCurrentContext(), e.getMessage(),Toast.LENGTH_LONG).show();
}
Теперь вы можете добавить на клик по этому.