Сохранить растровое изображение в местоположении
Вопрос
Я работаю над функцией загрузки изображения с веб-сервера, отображения его на экране, и если пользователь желает сохранить изображение, сохраните его на SD-карте в определенной папке.Есть ли простой способ взять растровое изображение и просто сохранить его на SD-карту в папке по моему выбору?
Моя проблема в том, что я могу загрузить изображение и отобразить его на экране в виде растрового изображения.Единственный способ, который я смог найти для сохранения изображения в определенную папку, - это использовать FileOutputStream, но для этого требуется массив байтов.Я не уверен, как преобразовать (если это вообще правильный способ) из Bitmap в byte array, поэтому я могу использовать FileOutputStream для записи данных.
Другой вариант, который у меня есть, - это использовать MediaStore :
MediaStore.Images.Media.insertImage(getContentResolver(), bm,
barcodeNumber + ".jpg Card Image", barcodeNumber + ".jpg Card Image");
Который отлично работает для сохранения на SD-карту, но не позволяет настроить папку.
Решение
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()
, чтобы сохранить растровое изображение в виде файла. Он сжимает (если позволяет используемый формат) ваше изображение и помещает его в OutputStream.
Вот пример экземпляра растрового изображения, полученного через 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 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)
;
Я надеюсь, что это поможет вам.Счастливой кодирующей жизни.
Почему бы не вызвать метод Bitmap.compress
со значением 100 (что звучит так, будто оно без потерь)?
Я также хотел бы сохранить изображение. Но моя проблема (?) В том, что я хочу сохранить его из растрового изображения, которое я нарисовал. Р>
Я сделал это так:
@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")));
Создайте миниатюру видео для видео. Может вернуть ноль, если видео повреждено или формат не поддерживается.
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;
}
Эй, просто дайте имя .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
Убедитесь, что каталог создан, прежде чем позвонить bitmap.compress
:
new File(FileName.substring(0,FileName.lastIndexOf("/"))).mkdirs();
После 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
для сохранения своего изображения, а не ParcelFileDescriptor
или compress(CompressFormat.JPEG, 100, out);
, для получения дополнительной информации вы можете проверить этот поток для сохранения изображения на SD-карту с помощью метода <=> и <=> классов.
Вы хотите сохранить растровое изображение в каталог по вашему выбору.Я создал библиотеку ImageWorker, которая позволяет пользователю загружать, сохранять и конвертировать растровые изображения / drawables / base64.
Минимальный SDK - 14
Предварительное условие
- Для сохранения файлов потребуется разрешение WRITE_EXTERNAL_STORAGE.
- Для извлечения файлов потребуется разрешение READ_EXTERNAL_STORAGE.
Сохранение растрового изображения / Для рисования / 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
Некоторые новые устройства не сохраняют растровое изображение, поэтому я объяснил немного подробнее..
убедитесь, что вы добавили приведенное ниже Разрешение
<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);
}
На самом деле не ответ, а комментарий. Я на Mac, на котором запущена среда эмулятора, и получаю java.io.IOException: Отказано в доступе - ошибка с этим кодом:
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 в файл манифеста (как отмечалось другими). Р>
Сохранить растровое изображение в своей галерее без сжатия.
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.");
}
}
// | == | Создать файл 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);
}