Android: Jpeg, сохраненный с камеры, выглядит поврежденным

Я пишу приложение для Android, которое сохраняет снимок в формате JPEG с камеры, когда пользователь нажимает кнопку. К сожалению, когда я смотрю на файл JPEG, мой код выглядит поврежденным. Похоже, это вызвано моим вызовом parameters.setPreviewSize (см. фрагмент кода ниже) - если я удалю это, изображение сохранится нормально; однако без него я не могу установить размер предварительного просмотра, и setDisplayOrientation также не имеет никакого эффекта без него.

Мое приложение нацелено на уровень API 8 (Android 2.2), и я занимаюсь отладкой на HTC Desire HD. Не совсем уверен, что я делаю неправильно здесь... любая помощь будет очень признательна!

Привет, Скотти

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();        
    Camera.Size size = getBestPreviewSize(w,h);

    // This next call is required in order for preview size to be set and
    // setDisplayOrientation to take effect...
    // Unfortunately it's also causing JPEG to be created wrong
    parameters.setPreviewSize(size.width, size.height);

    parameters.setPictureFormat(ImageFormat.JPEG);
    mCamera.setParameters(parameters);
    mCamera.setDisplayOrientation(90);

    mCamera.startPreview();

}

// This is the snapshot button event handler
public void onSnapshotButtonClick(View target) {
    //void android.hardware.Camera.takePicture(ShutterCallback shutter, 
    //                              PictureCallback raw, PictureCallback jpeg)
    mPreview.mCamera.takePicture(null, null, mPictureCallback);
}


// This saves the camera snapshot as a JPEG file on the SD card
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] imageData, Camera c) {

        if (imageData != null) {
            FileOutputStream outStream = null;
            try {
                String myJpgPath = String.format(
                        "/sdcard/%d.jpg", System.currentTimeMillis());

                outStream = new FileOutputStream(myJpgPath);
                outStream.write(imageData);
                outStream.close();
                Log.d("TestApp", "onPictureTaken - wrote bytes: "
                        + imageData.length);

                c.startPreview();
                Toast.makeText(getApplicationContext(), String.format("%s written", myJpgPath), Toast.LENGTH_SHORT).show();

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
};

person Scottie    schedule 02.05.2011    source источник
comment
У меня тоже бывает, но только у HTC Desire HD. JPEG отлично сохраняется на Samsung Galaxy S и эмуляторе.   -  person jA_cOp    schedule 15.05.2011
comment
@jA_cOp - Спасибо за это, по крайней мере, я знаю, что это не я ошибаюсь! Приложение камеры в исходном коде Android работает нормально, поэтому я собираюсь изучить его и найти разницу.   -  person Scottie    schedule 16.05.2011
comment
Вы решили проблему? я столкнулся с такой же проблемой, только с HTC Desire HD   -  person Ikky    schedule 07.06.2011
comment
@Ikky - у меня еще не было возможности вернуться к этому проекту, я обновлю здесь, когда сделаю это   -  person Scottie    schedule 08.06.2011
comment
Если setPreviewSize не нужен, попробуйте удалить параметры .setPreviewSize, у меня это сработало.   -  person Ikky    schedule 15.06.2011


Ответы (2)


Другим обходным решением является согласование соотношения сторон между размерами предварительного просмотра и изображения (например, setPreviewSize(w1,h1); setPictureSize(w2,h2) с w1/h1 ~ w2/h2 (небольшие различия, кажется, в порядке)). Например. для Desire HD S w1=800,h1=480, w2=2592,h2=1552 работает так же, как w1=960,h1=720,h2=2592,h2=1952 (если вас не смущают искажения изображения ;-)

person user995639    schedule 14.10.2011
comment
Я могу подтвердить это на своем устройстве HTC Desire S. Кстати, в родном приложении камеры на этом устройстве в настройках можно указать как соотношение сторон (4:3 или 5:3), так и разрешение. Список доступных разрешений зависит от соотношения сторон, поскольку кажется, что они должны совпадать. - person guillaume-tgl; 25.04.2014

Я предполагаю, что вы используете общую реализацию метода getBestPreviewSize(w,h), которая плавает, где вы циклически перебираете различные методы getSupportedPreviewSizes(), чтобы найти наилучшее соответствие. Хотя я не уверен, почему это приводит к искажению изображений, я обнаружил, что вызов метода parameters.setPreviewSize(size.width, size.height) с выводом метода getBestPreviewSize является причиной проблемы на ХТС Желание. Я также убедился, что, прокомментировав это, проблема с искаженным изображением исчезнет.

person BluJ IT    schedule 28.05.2011
comment
У меня есть аналогичная проблема с моим приложением, и я удалил setPreviewSize, но у некоторых пользователей (Desire S) все еще есть проблема. Так что это касается не только этой части кода. Я видел много сообщений об этом, и мне очень хотелось, чтобы кто-то мог объяснить в деталях, почему изображение выглядит так. - person plus-; 08.07.2011
comment
Отличный ответ! Я искал именно это в течение последних нескольких часов, борясь с искаженными изображениями, которые я получаю от onFramePreview при преобразовании в YUV. Большое спасибо ! - person Muzikant; 10.03.2012