Сохранить растровое изображение в местоположении - PullRequest
439 голосов
/ 16 марта 2009

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

Моя проблема в том, что я могу загрузить изображение и отобразить его на экране в виде растрового изображения. Единственный способ найти изображение для сохранения изображения в определенной папке - это использовать FileOutputStream, но для этого требуется байтовый массив. Я не уверен, как преобразовать (если это даже правильный путь) из растрового изображения в байтовый массив, поэтому я могу использовать FileOutputStream для записи данных.

Другой вариант - использовать MediaStore:

MediaStore.Images.Media.insertImage(getContentResolver(), bm,
    barcodeNumber + ".jpg Card Image", barcodeNumber + ".jpg Card Image");

Хорошо работает для сохранения на SD-карту, но не позволяет настроить папку.

Ответы [ 18 ]

2 голосов
/ 28 июня 2018

Создание миниатюры видео для видео. Может вернуть ноль, если видео повреждено или формат не поддерживается.

private void makeVideoPreview() {
    Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoAbsolutePath, MediaStore.Images.Thumbnails.MINI_KIND);
    saveImage(thumbnail);
}

Чтобы сохранить ваше растровое изображение в SDCard, используйте следующий код

Изображение магазина

private void storeImage(Bitmap image) {
    File pictureFile = getOutputMediaFile();
    if (pictureFile == null) {
        Log.d(TAG,
                "Error creating media file, check storage permissions: ");// e.getMessage());
        return;
    } 
    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }  
}

Чтобы получить путь для хранения изображений

/** Create a File for saving an image or video */
private  File getOutputMediaFile(){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this. 
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
            + "/Android/data/"
            + getApplicationContext().getPackageName()
            + "/Files"); 

    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            return null;
        }
    } 
    // Create a media file name
    String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
    File mediaFile;
        String mImageName="MI_"+ timeStamp +".jpg";
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);  
    return mediaFile;
} 
1 голос
/ 14 января 2019

Некоторые новые устройства не сохраняют растровое изображение. Поэтому я объяснил немного подробнее ..

убедитесь, что вы добавили ниже разрешения

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

и создайте XML-файл в xml имя папки provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
</paths>

и в AndroidManifest под

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>

, затем просто вызовите saveBitmapFile (passYourBitmapHere)

public static void saveBitmapFile(Bitmap bitmap) throws IOException {
        File mediaFile = getOutputMediaFile();
        FileOutputStream fileOutputStream = new FileOutputStream(mediaFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, getQualityNumber(bitmap), fileOutputStream);
        fileOutputStream.flush();
        fileOutputStream.close();
    }

, где

File getOutputMediaFile() {
        File mediaStorageDir = new File(
                Environment.getExternalStorageDirectory(),
                "easyTouchPro");
        if (mediaStorageDir.isDirectory()) {

            // Create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                    .format(Calendar.getInstance().getTime());
            String mCurrentPath = mediaStorageDir.getPath() + File.separator
                            + "IMG_" + timeStamp + ".jpg";
            File mediaFile = new File(mCurrentPath);
            return mediaFile;
        } else { /// error handling for PIE devices..
            mediaStorageDir.delete();
            mediaStorageDir.mkdirs();
            galleryAddPic(mediaStorageDir);

            return (getOutputMediaFile());
        }
    }

и другие методы

public static int getQualityNumber(Bitmap bitmap) {
        int size = bitmap.getByteCount();
        int percentage = 0;

        if (size > 500000 && size <= 800000) {
            percentage = 15;
        } else if (size > 800000 && size <= 1000000) {
            percentage = 20;
        } else if (size > 1000000 && size <= 1500000) {
            percentage = 25;
        } else if (size > 1500000 && size <= 2500000) {
            percentage = 27;
        } else if (size > 2500000 && size <= 3500000) {
            percentage = 30;
        } else if (size > 3500000 && size <= 4000000) {
            percentage = 40;
        } else if (size > 4000000 && size <= 5000000) {
            percentage = 50;
        } else if (size > 5000000) {
            percentage = 75;
        }

        return percentage;
    }

и

void galleryAddPic(File f) {
        Intent mediaScanIntent = new Intent(
                "android.intent.action.MEDIA_SCANNER_SCAN_FILE");
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);

        this.sendBroadcast(mediaScanIntent);
    }
1 голос
/ 09 декабря 2018

Вы хотите сохранить растровое изображение в каталог по вашему выбору. Я создал библиотеку ImageWorker, которая позволяет пользователю загружать, сохранять и конвертировать растровые изображения / рисунки / изображения base64.

Мин SDK - 14

Предварительные условия

  • Для сохранения файлов потребуется разрешение WRITE_EXTERNAL_STORAGE.
  • Для извлечения файлов потребуется разрешение READ_EXTERNAL_STORAGE.

Сохранение растрового изображения / Drawable / Base64

ImageWorker.to(context).
    directory("ImageWorker").
    subDirectory("SubDirectory").
    setFileName("Image").
    withExtension(Extension.PNG).
    save(sourceBitmap,85)

Загрузка растрового изображения

val bitmap: Bitmap? = ImageWorker.from(context).
    directory("ImageWorker").
    subDirectory("SubDirectory").
    setFileName("Image").
    withExtension(Extension.PNG).
    load()

Осуществление

Добавить зависимости

На уровне проекта Gradle

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

На уровне приложения Gradle

dependencies {
            implementation 'com.github.1AboveAll:ImageWorker:0.51'
    }

Вы можете прочитать больше на https://github.com/1AboveAll/ImageWorker/blob/master/README.md

1 голос
/ 15 сентября 2017

После Android 4.4 Kitkat, а с 2017 года доля Android 4.4 и ниже составляет около 20% и уменьшается, сохранение на SD-карту невозможно, используя класс File и метод getExternalStorageDirectory(). Этот метод возвращает внутреннюю память устройства и сохраненные изображения, видимые для каждого приложения. Вы также можете сохранять изображения только для вашего приложения и удалять, когда пользователь удаляет ваше приложение методом openFileOutput().

Начиная с Android 6.0, вы можете отформатировать свою SD-карту как внутреннюю память, но только для своего устройства. (Если вы отформатируете SD-автомобиль как внутреннюю память, только ваше устройство может получить доступ к его содержимому или просмотреть его). SD-карта использует другие ответы, но если вы хотите использовать съемную SD-карту, прочитайте мой ответ ниже.

Вы должны использовать Storage Access Framework , чтобы получить uri к папке onActivityResult метод действия, чтобы получить папку, выбранную пользователем, и добавить извлекаемое постоянное разрешение, чтобы иметь возможность доступа к папке после того, как пользователь перезапустит устройство.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_OK) {

        // selectDirectory() invoked
        if (requestCode == REQUEST_FOLDER_ACCESS) {

            if (data.getData() != null) {
                Uri treeUri = data.getData();
                tvSAF.setText("Dir: " + data.getData().toString());
                currentFolder = treeUri.toString();
                saveCurrentFolderToPrefs();

                // grantUriPermission(getPackageName(), treeUri,
                // Intent.FLAG_GRANT_READ_URI_PERMISSION |
                // Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

                final int takeFlags = data.getFlags()
                        & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                // Check for the freshest data.
                getContentResolver().takePersistableUriPermission(treeUri, takeFlags);

            }
        }
    }
}

Теперь сохраните папку сохранения в общих настройках, чтобы не просить пользователя выбирать папку каждый раз, когда вы хотите сохранить изображение.

Вы должны использовать DocumentFile класс для сохранения вашего изображения, а не File или ParcelFileDescriptor, для получения дополнительной информации вы можете проверить этот поток для сохранения изображения на SD-карту с помощью метода compress(CompressFormat.JPEG, 100, out); и DocumentFile классы.

1 голос
/ 22 января 2013

Эй, просто дайте имя .bmp

Сделайте это:

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
_bitmapScaled.compress(Bitmap.CompressFormat.PNG, 40, bytes);

//you can create a new file name "test.BMP" in sdcard folder.
File f = new File(Environment.getExternalStorageDirectory()
                        + File.separator + "**test.bmp**")

будет звучать, что IM ПРОСТО ОСТАЕТСЯ ВОПРОС, но попробуйте, как только он будет сохранен в bmp foramt..Cheers

1 голос
/ 18 февраля 2016

Убедитесь, что каталог создан, прежде чем звонить bitmap.compress:

new File(FileName.substring(0,FileName.lastIndexOf("/"))).mkdirs();
0 голосов
/ 29 июня 2017

// | == | Создать файл PNG из растрового изображения:

void devImjFylFnc(String pthAndFylTtlVar, Bitmap iptBmjVar)
{
    try
    {
        FileOutputStream fylBytWrtrVar = new FileOutputStream(pthAndFylTtlVar);
        iptBmjVar.compress(Bitmap.CompressFormat.PNG, 100, fylBytWrtrVar);
        fylBytWrtrVar.close();
    }
    catch (Exception errVar) { errVar.printStackTrace(); }
}

// | == | Получить Bimap из файла:

Bitmap getBmjFrmFylFnc(String pthAndFylTtlVar)
{
    return BitmapFactory.decodeFile(pthAndFylTtlVar);
}
0 голосов
/ 11 марта 2017

На самом деле не ответ, а комментарий. Я на Mac с запущенной средой эмулятора и получаю исключение java.io.IOException: Permission denied - ошибка с этим кодом:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    Log.d("DEBUG", "onActivityResult called");
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    if(requestCode == 0 && resultCode == RESULT_OK) {
        Log.d("DEBUG", "result is ok");
        try{
            Bitmap map = (Bitmap) imageReturnedIntent.getExtras().get("data");
            File sd = new File(Environment.getExternalStorageDirectory(), "test.png");
            sd.mkdirs();
            sd.createNewFile();
            FileOutputStream out = new FileOutputStream(sd);
            map.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
        } catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Я также добавил использование-разрешения android.permission.WRITE_EXTERNAL_STORAGE в файл манифеста (как отмечено другими).

...