Question

Je travaille sur une fonction pour télécharger une image à partir d'un serveur Web, l'afficher à l'écran et, si l'utilisateur souhaite conserver l'image, enregistrez-la sur la carte SD dans un certain dossier. Existe-t-il un moyen simple de prendre une bitmap et de la sauvegarder sur la carte SD dans le dossier de mon choix?

Mon problème est que je peux télécharger l'image, l'afficher à l'écran sous forme de bitmap. Le seul moyen que j'ai pu trouver pour enregistrer une image dans un dossier particulier est d'utiliser FileOutputStream, mais cela nécessite un tableau d'octets. Je ne suis pas sûr de savoir comment convertir (si c'est même le bon moyen) de Bitmap en tableau d'octets, afin de pouvoir utiliser un FileOutputStream pour écrire les données.

L’autre option que j’ai est d’utiliser MediaStore:

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

Ce qui fonctionne bien pour enregistrer sur une carte SD, mais ne vous permet pas de personnaliser le dossier.

Était-ce utile?

La solution

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

Autres conseils

Vous devez utiliser la méthode Bitmap.compress () pour enregistrer un bitmap en tant que fichier. Il compressera (si le format utilisé le permet) votre image et la poussera dans un flux de sortie.

Voici un exemple d'instance Bitmap obtenue via getImageBitmap (myurl) pouvant être compressée au format JPEG avec un taux de compression de 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);

lève une exception sans autorisation dans AndroidManifest.xml (au moins dans os2.2):

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

Dans 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();
}

Certains formats, comme le format PNG sans perte, ignorent le paramètre de qualité.

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) {

}

Voici l'exemple de code permettant d'enregistrer une image bitmap dans un fichier:

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

Appelez maintenant cette fonction pour enregistrer le bitmap dans la mémoire interne.

Fichier newfile = savebitmap (bitmap) ;

J'espère que cela vous aidera. Bonne codage de la vie.

Pourquoi ne pas appeler la méthode Bitmap.compress avec 100 (ce qui semble être sans perte)?

Je voudrais aussi sauvegarder une photo. Mais mon problème (?) Est que je veux l'enregistrer d'un bitmap que j'ai dessiné.

Je l'ai fait comme ça:

 @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();
            }

 }

La façon dont j'ai trouvé l'envoi du fichier PNG et de la transparence.

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

Créez une miniature de vidéo pour une vidéo. Il peut retourner la valeur null si la vidéo est corrompue ou si le format n'est pas pris en charge.

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

Pour enregistrer votre bitmap dans sdcard, utilisez le code suivant

Stocker l'image

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

Pour obtenir le chemin d'accès au stockage d'images

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

Hé, donnez simplement le nom à .bmp

Faites ceci:

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

ça sonnera comme si je jaillais à peine mais essayez-le une fois que ça sera sauvegardé dans bmp foramt..Cheers

Assurez-vous que le répertoire est créé avant d'appeler bitmap.compress :

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

Après Android 4.4 Kitkat, et à partir de 2017, la part d'Android 4.4 et inférieur est d'environ 20% et moins, il n'est pas possible de sauvegarder sur une carte SD en utilisant Fichier et getExternalStorageDirectory (). méthode. Cette méthode rend la mémoire interne de votre appareil et les images sauvegardées visibles pour chaque application. Vous pouvez également enregistrer des images uniquement privées dans votre application et les supprimer lorsque l'utilisateur supprime votre application avec la méthode openFileOutput () .

À partir d'Android 6.0, vous pouvez formater votre carte SD en tant que mémoire interne, mais uniquement privée pour votre appareil. (Si vous formatez la voiture SD en tant que mémoire interne, seul votre appareil peut accéder à son contenu ou en voir le contenu.) La carte SD utilise d’autres réponses, mais si vous souhaitez utiliser une carte SD amovible, lisez ma réponse ci-dessous.

Vous devez utiliser Storage Access Framework pour obtenir la méthode d'activité uri du dossier onActivityResult afin de sélectionner le dossier sélectionné par l'utilisateur, puis d'ajouter une autorisation persistante permettant d'accéder au dossier. après le redémarrage du périphérique par l'utilisateur.

@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);

            }
        }
    }
}

Enregistrez maintenant le dossier de sauvegarde dans les préférences partagées pour ne pas demander à l'utilisateur de sélectionner le dossier à chaque fois que vous souhaitez enregistrer une image.

Vous devez utiliser la classe DocumentFile pour enregistrer votre image et non pas Fichier ou ParcelFileDescriptor , pour plus d'informations, vous pouvez vérifier ce fil pour enregistrer l'image sur la carte SD avec compresser (CompressFormat.JPEG, 100, out); méthode et classes DocumentFile .

Vous souhaitez enregistrer Bitmap dans le répertoire de votre choix. J'ai créé une bibliothèque ImageWorker qui permet à l'utilisateur de charger, enregistrer et convertir des images bitmaps / drawables / base64.

SDK min. - 14

Pré-requis

  • L'enregistrement des fichiers nécessiterait l'autorisation WRITE_EXTERNAL_STORAGE.
  • La récupération de fichiers nécessiterait une autorisation READ_EXTERNAL_STORAGE.

Enregistrement de bitmap / dessinable / base64

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

Chargement du bitmap

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

Mise en oeuvre

Ajouter des dépendances

Au niveau du projet, diplôme

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

Dans Niveau d'application

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

Vous pouvez en savoir plus sur https://github.com/1AboveAll/ ImageWorker / blob / master / README.md

  

Certains nouveaux appareils n'enregistrent pas les images bitmap. J'ai donc expliqué un peu plus.

assurez-vous d'avoir ajouté sous l'autorisation

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

et créez un fichier xml sous le nom de dossier xml chemin fournisseur

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

et dans AndroidManifest sous

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

appelez simplement 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());
        }
    }

et autres méthodes

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

et

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

Pas vraiment une réponse, mais un commentaire. Je suis sur un Mac exécutant l'environnement de l'émulateur et j'obtiens une exception java.io.IOException: autorisation refusée - erreur liée à ce code:

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

J'ai également ajouté l'utilisations-permission android.permission.WRITE_EXTERNAL_STORAGE au fichier manifeste (comme indiqué par d'autres).

Enregistrer le bitmap dans votre galerie sans compression.

private File saveBitMap(Context context, Bitmap Final_bitmap) {
    File pictureFileDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Your Folder Name");
    if (!pictureFileDir.exists()) {
        boolean isDirectoryCreated = pictureFileDir.mkdirs();
        if (!isDirectoryCreated)
            Log.i("TAG", "Can't create directory to save the image");
        return null;
    }
    String filename = pictureFileDir.getPath() + File.separator + System.currentTimeMillis() + ".jpg";
    File pictureFile = new File(filename);
    try {
        pictureFile.createNewFile();
        FileOutputStream oStream = new FileOutputStream(pictureFile);
        Final_bitmap.compress(Bitmap.CompressFormat.PNG, 100, oStream);
        oStream.flush();
        oStream.close();
        Toast.makeText(Full_Screen_Activity.this, "Save Image Successfully..", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
        Log.i("TAG", "There was an issue saving the image.");
    }
    scanGallery(context, pictureFile.getAbsolutePath());
    return pictureFile;
}
private void scanGallery(Context cntx, String path) {
    try {
        MediaScannerConnection.scanFile(cntx, new String[]{path}, null, new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Toast.makeText(Full_Screen_Activity.this, "Save Image Successfully..", Toast.LENGTH_SHORT).show();
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
        Log.i("TAG", "There was an issue scanning gallery.");
    }
}

// | == | Créez un fichier PNG à partir de Bitmap:

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

// | == | Obtenir la bimap à partir du fichier:

Bitmap getBmjFrmFylFnc(String pthAndFylTtlVar)
{
    return BitmapFactory.decodeFile(pthAndFylTtlVar);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top