Получение черного экрана после сохранения фотографии — Камера Android

#android #camera #screen #photo

#Android #камера #экран #фото

Вопрос:

Я разрабатываю приложение для Android, которое фиксирует максимальное количество кадров в секунду и сохраняет на SD-карту.

Проблема в том, что сохраненная фотография имеет черный экран, и я не могу понять, почему.

Кто-нибудь может сказать мне, в чем проблема?

Код, в котором я это делаю:

 public class PhotoFragment extends Fragment {
private Camera cam;
private CameraPreview camPreview;
private boolean recording = false;
private ArrayList<byte[]> fotos;
private ArrayList<String> tempos;
private Thread thread;

public PhotoFragment() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_photofinish, container, false);
    cam = getCameraInstance();
    if(cam != null) {
        cam.setDisplayOrientation(90);

        // set Camera parameters
        Camera.Parameters cameraParameters = cam.getParameters();

        //set color efects to none
        cameraParameters.setColorEffect(Camera.Parameters.EFFECT_NONE);

        //set antibanding to none
        if (cameraParameters.getAntibanding() != null) {
            cameraParameters.setAntibanding(Camera.Parameters.ANTIBANDING_OFF);
        }

        // set white ballance
        if (cameraParameters.getWhiteBalance() != null) {
            cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
        }

        //set flash
        if (cameraParameters.getFlashMode() != null) {
            cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        }

        //set zoom
        if (cameraParameters.isZoomSupported()) {
            cameraParameters.setZoom(0);
        }

        //set focus mode
        cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);

        List<Size> sizes = cameraParameters.getSupportedPictureSizes();
        Camera.Size size = sizes.get(0);
        cameraParameters.setPictureSize(size.width, size.height);
        cam.setParameters(cameraParameters);
        fotos = new ArrayList<byte[]>();
        tempos = new ArrayList<String>();
        camPreview = new CameraPreview(this.getActivity(), cam);
        FrameLayout preview = (FrameLayout) rootView.findViewById(R.id.camera_preview);
        preview.addView(camPreview);
        TextView startRecording = (TextView) rootView.findViewById(R.id.start_record_button);
        startRecording.setOnClickListener( new View.OnClickListener() {
            public void onClick(View v) {
                if(!recording)
                {
                    recording = true;   
                    Size previewSize = cam.getParameters().getPreviewSize();
                    int dataBufferSize=(int)(previewSize.height*previewSize.width*(ImageFormat.getBitsPerPixel(cam.getParameters().getPreviewFormat())/8.0));
                    thread.start();
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.setPreviewCallbackWithBuffer(new PreviewCallback() {
                        public void onPreviewFrame(byte[] imageData, Camera arg1) {
                            try {                                   
                                fotos.add(imageData);
                                tempos.add(new SimpleDateFormat("HH_mm_ss_SSS", Locale.getDefault()).format(new Date()));
                            } catch(Exception e) {
                                System.out.println("ERRO: "   e);
                            }

                        }
                    });
                }
                else
                {
                    recording = false;
                    try {
                        thread.join();
                    } catch (Exception e) {

                    }
                }
            }               
        });
        thread = new Thread(new Runnable() {
              public void run() {
                  while(recording) {
                      if(fotos.size()>0 amp;amp; tempos.size()>0)
                      {
                          File pictureFile = getOutputMediaFile(1, tempos.get(0));
                            if (pictureFile == null){
                                System.out.println("Error creating media file, check storage permissions: ");
                                return;
                            }

                            try {               
                                FileOutputStream fos = new FileOutputStream(pictureFile);
                                fos.write(fotos.get(0));
                                fos.close();
                                pictureFile = null;
                                cam.addCallbackBuffer(fotos.get(0));
                                fotos.remove(0);
                                tempos.remove(0);           
                            } catch (FileNotFoundException e) {
                                System.out.println("ERRO FILE NOT FOUND! : "   e);
                            } catch (IOException e) {
                                System.out.println("ERRO IOException!");
                            }
                      }
                  }

              }
        });
    }
    else
    {
        Toast.makeText(getActivity(), "Camera not available", Toast.LENGTH_LONG).show();
    }

    return rootView;
}

public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open();
    }
    catch (Exception e){

    }
    return c;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    cam.release();
}

private static File getOutputMediaFile(int type, String timeStamp){
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "L_P");
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            System.out.println("L_P failed to create directory");
            return null;
        }
    }

    String timeStampDay = new SimpleDateFormat("ddMMyyyy", Locale.getDefault()).format(new Date());

    new File(mediaStorageDir.getPath()   File.separator   timeStampDay).mkdirs();

    File mediaFile;
    if (type == 1){
        mediaFile = new File(mediaStorageDir.getPath()   File.separator   timeStampDay   File.separator   "IMG_"  timeStamp   ".jpg");
    } else if(type == 2) {
        mediaFile = new File(mediaStorageDir.getPath()   File.separator   "VID_"  timeStamp   ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}
  

}

Ответ №1:

Вы утверждаете, что файл является JPEG. Однако вы ничего не сделали, чтобы преобразовать изображение в формат JPEG. Кадры предварительного просмотра по умолчанию не в формате JPEG, а в формате NV21. Используйте getSupportedPreviewFormats() , чтобы узнать, возможны ли предварительные просмотры в формате JPEG, затем используйте setPreviewFormat() для запроса предварительных просмотров в формате JPEG.

И, как я отметил в вашем предыдущем вопросе, у вас нет двух потоков, работающих с ArrayList . Кроме того, не загружайте фоновый поток — подождите, постоянно ожидая появления изображения на ArrayList экране. Используйте a LinkedBlockingQueue или что-то еще, что является потокобезопасным и позволяет фоновому потоку блокироваться во время ожидания изображения.

Комментарии:

1. спасибо за вашу помощь! Теперь я конвертирую NV21 в JPEG, и фотографии работают нормально. Сегодня я изменю arraylist на LinkedBlockingQueue. Теперь у меня еще один вопрос: я пытаюсь получить предварительные просмотры и отбросить их (просто чтобы посмотреть, сколько кадров в секунду я могу получить), и я не могу получить больше 16/17 кадров в секунду. Я загрузил приложение, которое может получать 27/28 кадров в секунду с моего смартфона. Знаете почему? Еще раз спасибо! 🙂

2. @user2989493: возможно, вам потребуется добавить еще пару буферов через addCallbackBuffer() . Если появляется рамка предварительного просмотра и используются все ваши существующие буферы, этот кадр удаляется. Вы не можете сойти с ума и добавить 100 буферов, так как у вас закончится память. Но вы могли бы поэкспериментировать, добавив четвертый, затем пятый и т.д., пока не дойдете до точки, когда добавление дополнительных буферов не поможет.

3. Я добавил еще два и три буфера, и количество кадров в секунду осталось прежним. Но я пробовал только с одним буфером, и количество кадров в секунду такое же, как и с тремя и более буферами. Это нормально?

4. @user2989493: извините, я не могу ответить на этот вопрос. Это звучит неправильно.