Android / Java: сохранение байтового массива в файл (.jpeg) - PullRequest
27 голосов
/ 02 ноября 2011

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

Все, что мне нужно сделать, это сохранить массив байтов в файл изображения .jpeg. Я попытался сделать это с помощью BitmapFactory.decodeByteArray (чтобы получить растровое изображение), а затем bImage.compress (в OutputStream), простой OutputStream и BufferedOutputStream. Кажется, все эти три метода дают мне одну и ту же странную ошибку. Мой телефон Android (8-мегапиксельная камера и приличный процессор), кажется, сохраняет фотографию (размер выглядит правильно), но искаженным образом (изображение нарезается и каждый срез сдвигается, или я просто получаю почти горизонтальные линии разных цветов) ; Странно то, что планшет Android с 5-мегапиксельной камерой и быстрым процессором, похоже, правильно сохраняет изображение.

Так что я подумал, что процессор может не поспевать за сохранением больших изображений, потому что я получил исключения OutOfMemory после примерно 3 снимков (даже при качестве сжатия 40). Но как же это делает встроенное приложение «Камера», причем намного быстрее? Я почти уверен (из отладки), что OutputStream записывает все данные (байты), и все должно быть в порядке, но все равно повреждено.

*** Короче говоря, какой самый лучший / самый быстрый способ (который работает), чтобы сохранить массив байтов в файл JPEG?

Заранее спасибо, Mark

код, который я пробовал (и некоторые другие небольшие изменения):

    try {
        Bitmap image = BitmapFactory.decodeByteArray(args, 0, args.length);
        OutputStream fOut = new FileOutputStream(externalStorageFile);
        long time = System.currentTimeMillis();
        image.compress(Bitmap.CompressFormat.JPEG,
                jpegQuality, fOut);
        System.out.println(System.currentTimeMillis() - time);
        fOut.flush();
        fOut.close();
    } catch (Exception e) {
    }

и

    try {
        externalStorageFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(externalStorageFile);
        fos.write(args);
        fos.flush();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

Ответы [ 2 ]

54 голосов
/ 02 ноября 2011

Все, что мне нужно сделать, это сохранить массив байтов в файл изображения .jpeg.

Просто запишите это в файл. Это уже в формате JPEG. Вот пример приложения, демонстрирующего это . Вот ключевой фрагмент кода:

class SavePhotoTask extends AsyncTask<byte[], String, String> {
    @Override
    protected String doInBackground(byte[]... jpeg) {
      File photo=new File(Environment.getExternalStorageDirectory(), "photo.jpg");

      if (photo.exists()) {
            photo.delete();
      }

      try {
        FileOutputStream fos=new FileOutputStream(photo.getPath());

        fos.write(jpeg[0]);
        fos.close();
      }
      catch (java.io.IOException e) {
        Log.e("PictureDemo", "Exception in photoCallback", e);
      }

      return(null);
    }
}
0 голосов
/ 19 сентября 2018

Этот код идеально подходит для сохранения изображения в памяти, начиная с byte [] ... обратите внимание, что здесь "image" - это byte [] .... взятый как "byte [] image" в качестве параметра в функцию.

    File photo=new File(Environment.getExternalStorageDirectory(), "photo.jpg");

    if (photo.exists()) {
        photo.delete();
    }

    try {
        FileOutputStream fos=new FileOutputStream(photo.getPath());
        Toast.makeText(this, photo.getPath(), Toast.LENGTH_SHORT).show();
        fos.write(image);
        fos.close();
    }
    catch (java.io.IOException e) {
        Log.e("PictureDemo", "Exception in photoCallback", e);
    }
}
...