2016-01-16 3 views
4

ОБНОВЛЕНО с большим количеством кодаAndroid набор изображений из URI на ImageView

Я пытаюсь захватить изображение, которое было только что отснятый и установить его в ImageView программно.

Кнопка фотография нажата,

picture_button.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     takePhoto(mTextureView); 
    } 
}); 

он запускает метод takePhoto:

public void takePhoto(View view) { 
    try { 
     mImageFile = createImageFile(); 
     final ImageView latest_picture = (ImageView) findViewById(R.id.latest_picture); 
     final RelativeLayout latest_picture_container = (RelativeLayout) findViewById(R.id.latest_picture_container); 
     final String mImageFileLocationNew = mImageFileLocation.replaceFirst("^/", ""); 
     Toast.makeText(getApplicationContext(), "" + mImageFile, Toast.LENGTH_SHORT).show(); 
     Uri uri = Uri.fromFile(mImageFile); 
     Toast.makeText(getApplicationContext(), ""+uri, Toast.LENGTH_LONG).show(); 
     latest_picture.setImageURI(uri); 
     latest_picture_container.setVisibility(View.VISIBLE); 
    } catch (IOException e){ 
     e.printStackTrace(); 
    } 
    lockFocus(); 
    captureStillImage(); 
} 

, который работает createImageFile() и captureStillImage()

private void captureStillImage() { 
    try { 
     CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
     captureStillBuilder.addTarget(mImageReader.getSurface()); 
     int rotation = getWindowManager().getDefaultDisplay().getRotation(); 
     captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); 
     CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() { 
      @Override 
      public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
       super.onCaptureCompleted(session, request, result); 
       //Toast.makeText(getApplicationContext(), "Image Taken", Toast.LENGTH_SHORT).show(); 
       unLockFocus(); 
      } 
     }; 
     mCameraCaptureSession.capture(captureStillBuilder.build(), captureCallback, null); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

File createImageFile() throws IOException { 
    String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date()); 
    String subFolder = ""; 
    if(pref_session_unique_gallery.equals("yes")){ 
     if(event_name != null){ 
      subFolder = event_name; 
     } else { 
      subFolder = timestamp; 
     } 
    } else { 
     subFolder = "_GEN"; 
    } 
    if(event_name == null){ 
     event_name = ""; 
    } else { 
     event_name = event_name + "_"; 
    } 
    String imageFileName = "CPB_"+event_name+timestamp+"_"; 
    File storageDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder); 
    storageDirectory.mkdir(); 
    File image = File.createTempFile(imageFileName, ".jpg", storageDirectory); 
    mImageFileLocation = image.getAbsolutePath(); 
    return image; 
} 

и изображение сохраняется здесь:

private static class ImageSaver implements Runnable { 
    private final Image mImage; 
    private ImageSaver(Image image) { 
     mImage = image; 
    } 
    @Override 
    public void run() { 
     ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer(); 
     byte[] bytes = new byte[byteBuffer.remaining()]; 
     byteBuffer.get(bytes); 

     FileOutputStream fileOutputStream = null; 

     try { 
      fileOutputStream = new FileOutputStream(mImageFile); 
      fileOutputStream.write(bytes); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      mImage.close(); 
      if(fileOutputStream != null){ 
       try { 
        fileOutputStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

      } 
     } 

Я получаю правильный путь к изображению после createImageFile() и поджариваю его, чтобы показать, что это каждый раз. Но даже не setVisibility на latest_picture_container работает ... Если я прокомментирую InputStream, Bitmap и setImageBitmap, тогда latest_picture_container появится как обычно. Не уверен, почему это неправильно.

По какой-то причине, URI возвращается с тремя косыми чертами после файла,

file:///storage/0/... 
+0

Вы уверены, что вы получаете правильный путь к изображению? Вы пробовали распечатать путь? –

+0

@ 4k3R Я только что узнал, что путь помещается в дополнительный файл '/' after': // ', поэтому я пытаюсь выяснить, откуда это происходит и как избавиться от него. – ntgCleaner

+0

@ 4k3R, я добавлен метод создания изображения, если это поможет. – ntgCleaner

ответ

3

Метод AssetManager#open() работает только для активов вашего приложения; то есть файлы в папке /assets вашего проекта. Поскольку вы пытаетесь открыть внешний файл, вместо этого вы должны использовать FileInputStream на объекте File, созданном на пути. Кроме того, метод takePhoto() устанавливает изображение на ImageView, прежде чем что-либо будет записано в файл, что приведет к пустым ImageView.

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

Сначала мы создадим интерфейс, через который ImageSaver может передать изображение обратно на Activity для отображения в ImageView.

public interface OnImageDecodedListener { 
    public void onImageDecoded(Bitmap b); 
} 

Тогда мы должны изменять ImageSaver класс немного принять Activity параметр в конструкторе. Я также добавил параметр File, поэтому поле Activity не должно быть static.

private static class ImageSaver implements Runnable { 
    private final Activity mActivity; 
    private final Image mImage; 
    private final File mImageFile; 

    public ImageSaver(Activity activity, Image image, File imageFile) { 
     mActivity = activity; 
     mImage = image; 
     mImageFile = imageFile; 
    } 

    @Override 
    public void run() { 
     ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer(); 
     byte[] bytes = new byte[byteBuffer.remaining()]; 
     byteBuffer.get(bytes); 

     final Bitmap b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
     mActivity.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        ((OnImageDecodedListener) mActivity).onImageDecoded(b); 
       } 
      } 
     ); 

     FileOutputStream fileOutputStream = null; 
     ... 
    } 
} 

Как только мы получаем данные изображения в массив байтов, мы декодировать его и передать его обратно в Activity, так что не нужно ждать на записи файла, который может протекать спокойно в задний план. Нам нужно вызвать метод интерфейса в потоке пользовательского интерфейса, так как мы «трогаем» View.

Activity необходимо реализовать интерфейс, и мы можем переместить View материал из информации о связанных takePhoto() методы onImageDecoded().

public class MainActivity extends Activity 
    implements ImageSaver.OnImageDecodedListener { 
    ... 

    @Override 
    public void onImageDecoded(Bitmap b) { 
     final ImageView latest_picture = 
      (ImageView) findViewById(R.id.latest_picture); 
     final RelativeLayout latest_picture_container = 
      (RelativeLayout) findViewById(R.id.latest_picture_container); 

     latest_picture.setImageBitmap(b); 
     latest_picture_container.setVisibility(View.VISIBLE); 
    } 

    public void takePhoto(View view) { 
     try { 
      mImageFile = createImageFile(); 
      captureStillImage(); 
      lockFocus(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    ... 
} 

Наконец, мы должны фактически выполнить ImageSaver в onImageAvailable() методе ImageReader «s. Снова после примера, это будет что-то вроде этого.

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = 
    new ImageReader.OnImageAvailableListener() { 
    @Override 
    public void onImageAvailable(ImageReader reader) { 
     mBackgroundHandler.post(new ImageSaver(MainActivity.this, 
               reader.acquireNextImage(), 
               mImageFile) 
     ); 
    } 
}; 
+1

Абсолютно удивительный Майк, Спасибо вам за всю вашу тяжелую работу и помощь – ntgCleaner

0

То, что я обычно делаю использовать библиотеку Пикассо

Добавить зависимость в build.gradle

compile 'com.squareup.picasso:picasso:2.5.2' 

Поскольку вы получаете путь к файлу, установите путь к файлу объект, а затем позволить Picasso захватить изображение с телефона и установить его на требуемый ImageView

File fileLocation = new File(uri) //file path, which can be String, or Uri 

Picasso.with(this).load(fileLocation).into(imageView); 

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

0
public static String getEDirectory(String folderName,Activity activity) { 
    if(Environment.MEDIA_MOUNTED.equalsIgnoreCase(Environment.getExternalStorageState())){ 
     LogUtils.e(activity.getExternalFilesDir(folderName).getAbsolutePath()); 
     return activity.getExternalFilesDir(folderName).getAbsolutePath(); 
    }else{ 
     return activity.getFilesDir().getAbsolutePath() +File.separator+folderName; 
    } 
}  
public static Uri getImageUri(String shortname,Activity activity) { 

    if (shortname == null) { 
     shortname = "www.jpg"; 
    } 
    String path = DataStore.getEDirectory("pure",activity); 
    File files = new File(path); 
    files.mkdirs(); 

    File file = new File(path, shortname); 
    return Uri.fromFile(file); 

} 
    public static Uri attemptStartCamera(Activity ctx){ 
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
     String latestfilename = System.currentTimeMillis() + ".jpg"; 
     Uri imageUri = getImageUri(latestfilename,ctx); 
     intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); 
     ctx.startActivityForResult(intent, MsgCodes.PICK_CAMERA); 
     return imageUri; 
    } 

В деятельности:

mUri = attemptStartCamera(Activity.this); 

Таким образом, вы получаете Uri.

Вы можете загрузить изображение в onActivityResult:

public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if(requestCode==MsgCodes.PICK_CAMERA && resultCode == RESULT_OK){ 
     mImageView.setImageUri(mUri); 
    } 
}