From ad2691128ffe40941560c18eec0cadf4b43a200f Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Tue, 9 Sep 2025 11:07:58 +0200 Subject: [PATCH] Fix wrong thread issue for compress --- .../mikephil/charting/charts/Chart.java | 94 +----------- .../mikephil/charting/utils/SaveUtils.kt | 136 ++++++++++++++++++ 2 files changed, 139 insertions(+), 91 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/SaveUtils.kt diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 5ca21a988..45fce3333 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -44,6 +44,7 @@ import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; import com.github.mikephil.charting.utils.MPPointF; +import com.github.mikephil.charting.utils.SaveUtils; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -1413,27 +1414,7 @@ public Bitmap getChartBitmap() { * @return returns true on success, false on error */ public boolean saveToPath(String title, String pathOnSD) { - - - Bitmap b = getChartBitmap(); - - OutputStream stream; - try { - stream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + pathOnSD + "/" + title + ".png"); - - /* - * Write bitmap to file using JPEG or PNG and 40% quality hint for - * JPEG. - */ - b.compress(CompressFormat.PNG, 40, stream); - - stream.close(); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - - return true; + return SaveUtils.INSTANCE.saveToPath(title, pathOnSD, getChartBitmap()); } /** @@ -1449,76 +1430,7 @@ public boolean saveToPath(String title, String pathOnSD) { * @return returns true if saving was successful, false if not */ public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat format, int quality) { - // restrain quality - if (quality < 0 || quality > 100) { - quality = 50; - } - - long currentTime = System.currentTimeMillis(); - - File extBaseDir = Environment.getExternalStorageDirectory(); - File file = new File(extBaseDir.getAbsolutePath() + "/DCIM/" + subFolderPath); - if (!file.exists()) { - if (!file.mkdirs()) { - return false; - } - } - - String mimeType; - switch (format) { - case PNG: - mimeType = "image/png"; - if (!fileName.endsWith(".png")) { - fileName += ".png"; - } - break; - case WEBP: - mimeType = "image/webp"; - if (!fileName.endsWith(".webp")) { - fileName += ".webp"; - } - break; - case JPEG: - default: - mimeType = "image/jpeg"; - if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) { - fileName += ".jpg"; - } - break; - } - - String filePath = file.getAbsolutePath() + "/" + fileName; - FileOutputStream out; - try { - out = new FileOutputStream(filePath); - - Bitmap b = getChartBitmap(); - b.compress(format, quality, out); - - out.flush(); - out.close(); - - } catch (IOException e) { - e.printStackTrace(); - - return false; - } - - long size = new File(filePath).length(); - - ContentValues values = new ContentValues(8); - - // store the details - values.put(Images.Media.TITLE, fileName); - values.put(Images.Media.DISPLAY_NAME, fileName); - values.put(Images.Media.DATE_ADDED, currentTime); - values.put(Images.Media.MIME_TYPE, mimeType); - values.put(Images.Media.DESCRIPTION, fileDescription); - values.put(Images.Media.ORIENTATION, 0); - values.put(Images.Media.DATA, filePath); - values.put(Images.Media.SIZE, size); - - return getContext().getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values) != null; + return SaveUtils.INSTANCE.saveToGallery(fileName, subFolderPath, fileDescription, format, quality, getChartBitmap(), getContext()); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SaveUtils.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SaveUtils.kt new file mode 100644 index 000000000..607019e0a --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SaveUtils.kt @@ -0,0 +1,136 @@ +package com.github.mikephil.charting.utils + +import android.content.ContentValues +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Bitmap.CompressFormat +import android.os.Environment +import android.provider.MediaStore +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStream + +object SaveUtils { + + /** + * Saves the current chart state with the given name to the given path on + * the sdcard leaving the path empty "" will put the saved file directly on + * the SD card chart is saved as a PNG image, example: + * saveToPath("myfilename", "foldername1/foldername2"); + * + * @param pathOnSD e.g. "folder1/folder2/folder3" + * @return returns true on success, false on error + */ + fun saveToPath(title: String?, pathOnSD: String?, chartBitmap: Bitmap): Boolean { + val stream: OutputStream? + try { + stream = FileOutputStream(Environment.getExternalStorageDirectory().path + pathOnSD + "/" + title + ".png") + + /* + * Write bitmap to file using JPEG or PNG and 40% quality hint for JPEG. + */ + chartBitmap.compress(CompressFormat.PNG, 40, stream) + + stream.close() + return true + } catch (e: Exception) { + e.printStackTrace() + return false + } + } + + /** + * Saves the current state of the chart to the gallery as an image type. The + * compression must be set for JPEG only. 0 == maximum compression, 100 = low + * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE + * + * @param fileName e.g. "my_image" + * @param subFolderPath e.g. "ChartPics" + * @param fileDescription e.g. "Chart details" + * @param format e.g. Bitmap.CompressFormat.PNG + * @param quality e.g. 50, min = 0, max = 100 + * @return returns true if saving was successful, false if not + */ + fun saveToGallery(fileName: String, subFolderPath: String?, fileDescription: String?, format: CompressFormat, quality: Int, chartBitmap: Bitmap, context: Context): Boolean { + // restrain quality + var fileName = fileName + var quality = quality + if (quality < 0 || quality > 100) { + quality = 50 + } + + val currentTime = System.currentTimeMillis() + + val extBaseDir = Environment.getExternalStorageDirectory() + val file = File(extBaseDir.absolutePath + "/DCIM/" + subFolderPath) + if (!file.exists()) { + if (!file.mkdirs()) { + return false + } + } + + val mimeType: String? + when (format) { + CompressFormat.PNG -> { + mimeType = "image/png" + if (!fileName.endsWith(".png")) { + fileName += ".png" + } + } + + CompressFormat.WEBP -> { + mimeType = "image/webp" + if (!fileName.endsWith(".webp")) { + fileName += ".webp" + } + } + + CompressFormat.JPEG -> { + mimeType = "image/jpeg" + if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) { + fileName += ".jpg" + } + } + + else -> { + mimeType = "image/jpeg" + if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) { + fileName += ".jpg" + } + } + } + + val filePath = file.absolutePath + "/" + fileName + val out: FileOutputStream? + try { + out = FileOutputStream(filePath) + + chartBitmap.compress(format, quality, out) + + out.flush() + out.close() + } catch (e: IOException) { + e.printStackTrace() + + return false + } + + val size = File(filePath).length() + + val values = ContentValues(8) + + // store the details + values.put(MediaStore.Images.Media.TITLE, fileName) + values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName) + values.put(MediaStore.Images.Media.DATE_ADDED, currentTime) + values.put(MediaStore.Images.Media.MIME_TYPE, mimeType) + values.put(MediaStore.Images.Media.DESCRIPTION, fileDescription) + values.put(MediaStore.Images.Media.ORIENTATION, 0) + values.put(MediaStore.Images.Media.DATA, filePath) + values.put(MediaStore.Images.Media.SIZE, size) + + return context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) != null + } + +}