Сохранить растровое изображение в местоположение


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

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

другой вариант у меня есть, чтобы использовать MediaStore:

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

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

16 405

16 ответов:

try (FileOutputStream out = new FileOutputStream(filename)) {
    bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
    // PNG is a lossless format, the compression factor (100) is ignored
} catch (IOException e) {
    e.printStackTrace();
}

вы должны использовать Bitmap.compress() метод сохранения растрового изображения в виде файла. Он будет сжимать (если используемый формат позволяет это) ваше изображение и толкать его в выходной поток.

вот пример растрового экземпляра, полученного через getImageBitmap(myurl) который может быть сжат в формате JPEG со степенью сжатия 85%:

// Assume block needs to be inside a Try/Catch block.
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
Integer counter = 0;
File file = new File(path, "FitnessGirl"+counter+".jpg"); // the File to save , append increasing numeric counter to prevent files from getting overwritten.
fOut = new FileOutputStream(file);

Bitmap pictureBitmap = getImageBitmap(myurl); // obtaining the Bitmap
pictureBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // saving the Bitmap to a file compressed as a JPEG with 85% compression rate
fOut.flush(); // Not really required
fOut.close(); // do not forget to close the stream

MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
outStream = new FileOutputStream(file);

будет бросать исключение без разрешения в AndroidManifest.xml (по крайней мере, в os2.2):

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

внутри onActivityResult:

String filename = "pippo.png";
File sd = Environment.getExternalStorageDirectory();
File dest = new File(sd, filename);

Bitmap bitmap = (Bitmap)data.getExtras().get("data");
try {
     FileOutputStream out = new FileOutputStream(dest);
     bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
     out.flush();
     out.close();
} catch (Exception e) {
     e.printStackTrace();
}

некоторые форматы, такие как PNG без потерь, будут игнорировать настройку качества.

почему бы не назвать Bitmap.compress метод с 100 (который звучит так, как будто он без потерь)?

Bitmap bbicon;

bbicon=BitmapFactory.decodeResource(getResources(),R.drawable.bannerd10);
//ByteArrayOutputStream baosicon = new ByteArrayOutputStream();
//bbicon.compress(Bitmap.CompressFormat.PNG,0, baosicon);
//bicon=baosicon.toByteArray();

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
OutputStream outStream = null;
File file = new File(extStorageDirectory, "er.PNG");
try {
    outStream = new FileOutputStream(file);
    bbicon.compress(Bitmap.CompressFormat.PNG, 100, outStream);
    outStream.flush();
    outStream.close();
} catch(Exception e) {

}

вот пример кода для сохранения растрового изображения в файл :

public static File savebitmap(Bitmap bmp) throws IOException {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 60, bytes);
    File f = new File(Environment.getExternalStorageDirectory()
            + File.separator + "testimage.jpg");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();
    return f;
}

теперь вызовите эту функцию, чтобы сохранить растровое изображение во внутренней памяти.

File newfile = savebitmap(bitmap);

Я надеюсь, что это поможет вам. Счастливая жизнь кодирования.

Я также хотел бы сохранить изображение. Но моя проблема(?) это то, что я хочу сохранить его из растрового изображения, которое я нарисовал.

Я сделал так:

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.save_sign:      

                myView.save();
                break;

            }
            return false;    

    }

public void save() {
            String filename;
            Date date = new Date(0);
            SimpleDateFormat sdf = new SimpleDateFormat ("yyyyMMddHHmmss");
            filename =  sdf.format(date);

            try{
                 String path = Environment.getExternalStorageDirectory().toString();
                 OutputStream fOut = null;
                 File file = new File(path, "/DCIM/Signatures/"+filename+".jpg");
                 fOut = new FileOutputStream(file);

                 mBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
                 fOut.flush();
                 fOut.close();

                 MediaStore.Images.Media.insertImage(getContentResolver()
                 ,file.getAbsolutePath(),file.getName(),file.getName());

            }catch (Exception e) {
                e.printStackTrace();
            }

 }

Как я нашел, чтобы отправить PNG и прозрачность.

String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() +
                    "/CustomDir";
File dir = new File(file_path);
if(!dir.exists())
  dir.mkdirs();

String format = new SimpleDateFormat("yyyyMMddHHmmss",
       java.util.Locale.getDefault()).format(new Date());

File file = new File(dir, format + ".png");
FileOutputStream fOut;
try {
        fOut = new FileOutputStream(file);
        yourbitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut);
        fOut.flush();
        fOut.close();
     } catch (Exception e) {
        e.printStackTrace();
 }

Uri uri = Uri.fromFile(file);     
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
intent.putExtra(Intent.EXTRA_STREAM, uri);

startActivity(Intent.createChooser(intent,"Sharing something")));

Эй, просто дайте имя .БМП

этого:

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**")

это будет звучать, что я просто дурачусь, но попробуйте, как только он будет сохранен в bmp foramt..Ура

создать эскиз видео для видео. Он может возвращать значение null, если видео повреждено или формат не поддерживается.

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;
} 

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

new File(FileName.substring(0,FileName.lastIndexOf("/"))).mkdirs();

на самом деле не ответ, а комментарий. Я нахожусь на 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.разрешение.WRITE_EXTERNAL_STORAGE в файл манифеста (как отмечено другими).

/ / / = = / создайте 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);
}

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

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

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

@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 классы.