2012-06-07 2 views
3

У меня есть приложение, в котором клиент использует камеру для съемки. Предварительный просмотр изображения отображается на планшете с помощью SurfaceView, прежде чем пользователь нажмет кнопку «кликнуть». Когда человек нажимает кнопку клика, вызывается метод onPictureTaken, и в этом методе я сохраняю изображение, а также вызываю метод camera.stopPreview() (чтобы пользователь мог видеть снимок, который был сделан).Android (Camera) - Как синхронизировать stopPreview() с onPictureTaken()?

Существует проблема, однако ... Если пользователь перемещается по планшету в тот момент, когда снимок сделан, неподвижное изображение, фактически показанное после вызова метода stopPreview, НЕ соответствует тому, что я войдите в массив байтов метода onPictureTaken. Существует задержка в несколько милисекунд, в которой это различие выделяется, когда пользователь перемещается по планшету непосредственно перед съемкой (я знаю, что 99% людей не будут перемещать планшет во время съемки, но мой клиент действительно заметил эту проблему и исправил ее ...). Я попытался переместить операцию сохранения в поток separete, как показано ниже, поэтому метод onPictureTaken может выполняться как можно быстрее. Тем не менее, это не имело никакого эффекта на всех ...

private PictureCallback pictureCallback = new PictureCallback() { 

    public void onPictureTaken(byte[] data, Camera camera) { 

     camera.stopPreview(); 
     reference = data; 

     new PictureCallbackHeavy().execute(); 
    } 
}; 

Я также trield называть camera.stopPreview(), прежде чем я вызвать метод takePicture (а не внутри метода onPictureTaken()). Но результат тот же.

Что я могу сделать, чтобы синхронизировать метод stopPreview, чтобы я мог ТОЛЬКО показать изображение, которое было выполнено, и что находится в массиве байтов обратного вызова onPictureTaken()?

Благодарим вас заранее! =)

+0

какие операции вы делаете в 'новом PictureCallbackHeavy() выполнить()'? –

ответ

1

К сожалению, вы не можете получить разумное изображение для предварительного просмотра, просто позвонив stopPreview(), потому что между моментом, когда картинка берется и момент вызова onPictureTaken() может пройти довольно долго, потому что он работает так :

  • камера на самом деле занимает изображение (то, что вы хотите просмотреть)
  • onShutter() называется
  • onPictureTaken() для данных исходного изображения называется (на некоторых устройствах)
  • onPictureTaken() для масштабированного Ситуация в сфере изображение называется (на некоторых устройствах)
  • onPictureTaken() для данных конечного сжатого изображения называется (тот, который мы говорим здесь)

Таким образом, вы должны преобразовать byte[] data в вашем onPictureTaken() обратный вызов в битмап и сопоставление этого растрового изображения с ImageView, которое вы должны позиционировать над SurfaceView, чтобы показать изображение предварительного просмотра. код будет, вероятно, выглядеть следующим образом:.

public void onPictureTaken(byte[] data, Camera camera) { 
    camera.stopPreview(); 
    final Bitmap image = BitmapFactory.decodeByteArray(data, 0, data.length); 
    surfaceView.setVisibility(SurfaceView.GONE); 
    imageView.setVisibility(ImageView.VISIBLE); 
    imageView.setImageBitmap(image); 
    reference = data; 
    new PictureCallbackHeavy().execute(); 
} 
+0

Благодарим вас за ответ Daniel. Фактически, я делал ТОЧНО то, что вы описали (помещая байт [] в ImageView, а затем отображая его поверх Surface). Однако мне пришлось перестать это делать, поскольку изображение, отображаемое в ImageView, было «зернистым» (например, на нем был шум). Я постарался установить качество на 100% и все, но оно все еще выглядит немного зернистым. Вы знаете, что я могу делать неправильно? И да, я уверен, что отображаемое изображение находится в той же пропорции, что и планшет. Еще раз спасибо. – Tiago

+0

Спасибо, что приняли Тьяго! К сожалению, я не знаю, почему ваш образ выглядит зернистым.Имеет ли выходной JPEG также зернистый вид, когда вы исследуете его в полном размере? Может быть, сама камера делает плохие снимки - в конце концов, это мобильный телефон. Или, может быть, это потому, что метод масштабирования, который использует ImageView для сжатия Bitmap, является быстрым, но, тем не менее, алгоритмом плохого качества? Возможно, вам нужно использовать лучший алгоритм, такой как выборка Lanczos, чтобы уменьшить изображение до нужного размера, прежде чем назначать его ImageView. Но это просто догадки. – Daniel

+0

Привет, Даниэль. Понимаю. Я считаю, что проблема заключается в алгоритме, используемом API Android. И изображение выглядит немного в JPEG. Разница действительно короткая, но достаточно для человеческого глаза (и моего клиента), чтобы обнаружить это ... В любом случае, если кто-нибудь когда-нибудь найдет решение этого, пожалуйста, поделитесь им с нами! =) – Tiago

Смежные вопросы