简体   繁体   English

Android-使用确定的ProgressDialog将位图保存到SD卡

[英]Android - Save bitmap to SD Card with determinated ProgressDialog

I'm using this AsyncTask for saving my image resource to SD Card: 我正在使用此AsyncTask将我的图像资源保存到SD卡:

public class SaveImageAsync extends AsyncTask<String, String, String> {

    private Context mContext;

    int imageResourceID;

    private ProgressDialog mProgressDialog;

    public SaveImageAsync(Context context, int image) 
    {
        mContext = context;
        imageResourceID = image;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = new ProgressDialog(mContext);
        mProgressDialog.setMessage("Saving Image to SD Card");
        mProgressDialog.setMax(100);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setCancelable(false);
        mProgressDialog.show();
    }

    @SuppressLint("NewApi")
    @Override
    protected String doInBackground(String... filePath) {
        try {


            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), imageResourceID);

            ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
            bitmap.compress(CompressFormat.JPEG, 100, bos); 
            byte[] bitmapdata = bos.toByteArray();
            ByteArrayInputStream bis = new ByteArrayInputStream(bitmapdata);

            int lenghtOfFile = bitmap.getByteCount();
            Log.d("LOG", "File Lenght = " + lenghtOfFile);

            byte[] buffer = new byte[64];
            int len1 = 0;
            long total = 0;

            while ((len1 = bis.read(buffer)) > 0) {
                total += len1;
                publishProgress("" + (int) ((total * 100) / lenghtOfFile));
                bos.write(buffer, 0, len1);
            }
            bos.flush();
            bos.close();
            bitmap.recycle();
            bis.close();

            return getTempUri().getPath();
        } catch (Exception e) {
            return null;
        }


    }

    protected void onProgressUpdate(String... progress) {
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected void onPostExecute(String filename) {
        // dismiss the dialog after the file was saved
        try {
            mProgressDialog.dismiss();
            mProgressDialog = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Uri getTempUri() {
        return Uri.fromFile(getTempFile());
    }

    private File getTempFile() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

            File directory = new File(mContext.getExternalCacheDir().getPath());
            directory.mkdirs();
            File file = new File(directory , "temp.jpg");
            try  {
                file.createNewFile();
            }  catch (IOException e) {}
            return file;
        } else  {
            return null;
        }
    }   
}

And I call it from my Activity with this: 我从我的Activity中这样称呼它:

new SaveImageAsync(this, R.drawable.my_image_resource).execute();

It works fine, the problem is that the bitmap size returned by bitmap.getByteCount(); 它工作正常,问题是由bitmap.getByteCount();返回的位图大小bitmap.getByteCount(); is completely different from the final size of the saved file. 与保存文件的最终大小完全不同。 The result when the process is completed that the indicated progress is only 20% more or less. 该过程完成时,指示进度仅或多或少20%的结果。

Is there any way to know the final size of the file before save it? 在保存文件之前,有什么方法可以知道文件的最终大小? Thanks. 谢谢。

You use PNG compressession and how good this compression works depends on the actual content of the image, ie a blank image only containing white space will be of small size, a colorful image where all pixels are different will be of huge size. 您使用PNG压缩,这种压缩的效果取决于图像的实际内容,即仅包含空白的空白图像的尺寸较小,而所有像素均不同的彩色图像的尺寸较大。 So long story...the bitmap.getByteCount() gives you the information how much bytes will be used to store the actual image in the memory (uncompressed), not on the SD card (compressed). 这么长的故事... bitmap.getByteCount()为您提供了将多少字节用于将实际图像存储在内存中(未压缩),而不是SD卡上(压缩)的信息。 The difference between your expectation and what you realy get explains the ~20% break point. 您的期望与实际获得的收益之间的差异解释了〜20%的突破点。

If I should guess a solution might be to use the length of the bitmapdata array. 如果我猜想一个解决方案可能是使用bitmapdata数组的长度。 I modified your code: 我修改了您的代码:

Bitmap bitmap = null;

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
bitmap.compress(CompressFormat.JPEG, 100, bos); 
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bitmapdata);

int lenghtOfFile = bitmapdata.length;
byte[] buffer = new byte[64];
int currentProcess = 0;
int totalReadedYet = 0;

try {
while ((currentProcess = bis.read(buffer)) > 0) {
    totalReadedYet += currentProcess;
    publishProgress(Integer.toString((int) ((totalReadedYet) / lenghtOfFile)));
    bos.write(buffer, 0, currentProcess);
}

bos.flush();
bos.close();
bitmap.recycle();
bis.close();
} catch (IOException e) {
    e.printStackTrace();
}

Thanks to Baschi answer, bitmapdata.length; 感谢Baschi的回答, bitmapdata.length; is just what I need, this is my AsyncTask for save a bitmap to the SD Card with Determinated ProgressBar , I hope someone will find it useful: 就是我所需要的,这是我的AsyncTask用于使用Determinated ProgressBarbitmap保存到SD卡中,希望有人会发现它有用:

public class SaveImageAsync extends AsyncTask<Void, String, Void> {

    private Context mContext;
    private int imageResourceID;

    private ProgressDialog mProgressDialog;

    public SaveImageAsync(Context context, int image) {
        mContext = context;
        imageResourceID = image;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = new ProgressDialog(mContext);
        mProgressDialog.setMessage("Saving Image to SD Card");
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setCancelable(false);
        mProgressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... filePath) {
        try {
            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), imageResourceID);

            ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); 
            bitmap.compress(CompressFormat.JPEG, 100, byteOutputStream); 
            byte[] mbitmapdata = byteOutputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(mbitmapdata);

            String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
            String fileName = "mySavedImage.jpg";

            OutputStream outputStream = new FileOutputStream(baseDir + File.separator + fileName);
            byteOutputStream.writeTo(outputStream);

            byte[] buffer = new byte[128]; //Use 1024 for better performance
            int lenghtOfFile = mbitmapdata.length;
            int totalWritten = 0;
            int bufferedBytes = 0;

            while ((bufferedBytes = inputStream.read(buffer)) > 0) {
                totalWritten += bufferedBytes;
                publishProgress(Integer.toString((int) ((totalWritten * 100) / lenghtOfFile)));
                outputStream.write(buffer, 0, bufferedBytes);
            }

        } catch (IOException e) { e.printStackTrace(); }
        return null;

    }

    protected void onProgressUpdate(String... progress) {
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected void onPostExecute(Void filename) {
        mProgressDialog.dismiss();
        mProgressDialog = null;
    }
}

Use this line in your Activity to save an image: 在您的Activity使用以下行来保存图片:

new SaveImageAsync(this, R.drawable.your_image_resource).execute();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM