Android уменьшить размер изображения с камеры - PullRequest
6 голосов
/ 06 января 2012

ОБНОВЛЕНИЕ, возможно, изменение размера растрового изображения в новом занятии может решить проблему

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), что, я думаю, означает, что изображение слишком большое.

Я проверил, поместив меньшее изображение в код вместо изображения с камеры, которое было снято, и это работает, что также возвращает меня к проблеме, заключающейся в размере изображения с камеры.

Итак, я пытаюсь реализовать This From 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 ]

13 голосов
/ 06 января 2012

Пока у меня есть приложение, которое делает снимок, а затем использует намерение для переноса изображения и отображения в новом действии.

В большинстве случаев передача данных между действиями с использованием дополнений Intent является хорошим решением. Однако большие растровые изображения вызывают проблемы из-за потребления памяти. Это один из случаев, когда я осторожно использовал бы элемент статических данных.

В моем logcat я получаю java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины (размер кучи = 7431 КБ, выделено = 2956 КБ, размер растрового изображения = 19764 КБ), что, как мне кажется, означает, что изображение слишком велико.

Это означает, что у вас недостаточно памяти для того, что вы пытаетесь сделать.

Просматривая код, я думаю, что он ищет наименьшее разрешение / размер, а затем снимает камеру с этими настройками. Я прав, думая, что

Да.

если так, как я могу внедрить это в мой код?

Копирование и вставка обычно работает. : -)

Чтобы указать камере, какой размер снимка сделать, используйте setPictureSize() на Camera.Parameters. Однако вы должны выбрать размер, который он поддерживает, и не все устройства будут поддерживать произвольные размеры. Позвонив по номеру getSupportedPictureSizes(), вы узнаете, какие размеры поддерживаются. Вам решать, какой из этих размеров использовать. В примере, с которым я связал из вашего другого вопроса, я перебираю эти размеры и нахожу наименьший с точки зрения площади.

При этом, если проблема only с размером изображения передает его от действия к действию, я бы сначала пошел по маршруту статического члена данных. Просто убедитесь, что null этот статический элемент данных, когда вам больше не нужен образ.

Нечто подобное может быть?

Опять же, это зависит от вашей цели. Вы, кажется, колеблетесь вокруг в поисках решений, когда вы сформулировали только одну проблему (и даже там вы не сказали нам , где вы получаете ошибку нехватки памяти).

Если ваша цель состоит в том, чтобы сделать снимок в полном разрешении, сохранить его в файл и затем сохранить в памяти миниатюру, createScaledBitmap() является хорошим решением.

Если ваша цель состоит в том, чтобы сначала сделать миниатюрное изображение (то есть вам не нужно или не нужно изображение в полном разрешении), используйте setPictureSize().

Если ваша цель - использовать изображение с полным разрешением повсюду, осторожно используйте статический элемент данных, чтобы исключить ненужные копии Bitmap и посмотрите, достаточно ли этого. Это может быть не так, в зависимости от того, что вы пытаетесь сделать с изображением.

2 голосов
/ 06 января 2012

Попробуйте захват изображения с камеры.

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();
                            }

Теперь вы можете добавить на клик по этому.

...