|  | 
|  | 1 | +package com.github.mikephil.charting.utils | 
|  | 2 | + | 
|  | 3 | +import android.content.ContentValues | 
|  | 4 | +import android.content.Context | 
|  | 5 | +import android.graphics.Bitmap | 
|  | 6 | +import android.graphics.Bitmap.CompressFormat | 
|  | 7 | +import android.os.Environment | 
|  | 8 | +import android.provider.MediaStore | 
|  | 9 | +import java.io.File | 
|  | 10 | +import java.io.FileOutputStream | 
|  | 11 | +import java.io.IOException | 
|  | 12 | +import java.io.OutputStream | 
|  | 13 | + | 
|  | 14 | +object SaveUtils { | 
|  | 15 | + | 
|  | 16 | +    /** | 
|  | 17 | +     * Saves the current chart state with the given name to the given path on | 
|  | 18 | +     * the sdcard leaving the path empty "" will put the saved file directly on | 
|  | 19 | +     * the SD card chart is saved as a PNG image, example: | 
|  | 20 | +     * saveToPath("myfilename", "foldername1/foldername2"); | 
|  | 21 | +     * | 
|  | 22 | +     * @param pathOnSD e.g. "folder1/folder2/folder3" | 
|  | 23 | +     * @return returns true on success, false on error | 
|  | 24 | +     */ | 
|  | 25 | +    fun saveToPath(title: String?, pathOnSD: String?, chartBitmap: Bitmap): Boolean { | 
|  | 26 | +        val stream: OutputStream? | 
|  | 27 | +        try { | 
|  | 28 | +            stream = FileOutputStream(Environment.getExternalStorageDirectory().path + pathOnSD + "/" + title + ".png") | 
|  | 29 | + | 
|  | 30 | +            /* | 
|  | 31 | +			 * Write bitmap to file using JPEG or PNG and 40% quality hint for JPEG. | 
|  | 32 | +			 */ | 
|  | 33 | +            chartBitmap.compress(CompressFormat.PNG, 40, stream) | 
|  | 34 | + | 
|  | 35 | +            stream.close() | 
|  | 36 | +            return true | 
|  | 37 | +        } catch (e: Exception) { | 
|  | 38 | +            e.printStackTrace() | 
|  | 39 | +            return false | 
|  | 40 | +        } | 
|  | 41 | +    } | 
|  | 42 | + | 
|  | 43 | +    /** | 
|  | 44 | +     * Saves the current state of the chart to the gallery as an image type. The | 
|  | 45 | +     * compression must be set for JPEG only. 0 == maximum compression, 100 = low | 
|  | 46 | +     * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE | 
|  | 47 | +     * | 
|  | 48 | +     * @param fileName        e.g. "my_image" | 
|  | 49 | +     * @param subFolderPath   e.g. "ChartPics" | 
|  | 50 | +     * @param fileDescription e.g. "Chart details" | 
|  | 51 | +     * @param format          e.g. Bitmap.CompressFormat.PNG | 
|  | 52 | +     * @param quality         e.g. 50, min = 0, max = 100 | 
|  | 53 | +     * @return returns true if saving was successful, false if not | 
|  | 54 | +     */ | 
|  | 55 | +    fun saveToGallery(fileName: String, subFolderPath: String?, fileDescription: String?, format: CompressFormat, quality: Int, chartBitmap: Bitmap, context: Context): Boolean { | 
|  | 56 | +        // restrain quality | 
|  | 57 | +        var fileName = fileName | 
|  | 58 | +        var quality = quality | 
|  | 59 | +        if (quality < 0 || quality > 100) { | 
|  | 60 | +            quality = 50 | 
|  | 61 | +        } | 
|  | 62 | + | 
|  | 63 | +        val currentTime = System.currentTimeMillis() | 
|  | 64 | + | 
|  | 65 | +        val extBaseDir = Environment.getExternalStorageDirectory() | 
|  | 66 | +        val file = File(extBaseDir.absolutePath + "/DCIM/" + subFolderPath) | 
|  | 67 | +        if (!file.exists()) { | 
|  | 68 | +            if (!file.mkdirs()) { | 
|  | 69 | +                return false | 
|  | 70 | +            } | 
|  | 71 | +        } | 
|  | 72 | + | 
|  | 73 | +        val mimeType: String? | 
|  | 74 | +        when (format) { | 
|  | 75 | +            CompressFormat.PNG -> { | 
|  | 76 | +                mimeType = "image/png" | 
|  | 77 | +                if (!fileName.endsWith(".png")) { | 
|  | 78 | +                    fileName += ".png" | 
|  | 79 | +                } | 
|  | 80 | +            } | 
|  | 81 | + | 
|  | 82 | +            CompressFormat.WEBP -> { | 
|  | 83 | +                mimeType = "image/webp" | 
|  | 84 | +                if (!fileName.endsWith(".webp")) { | 
|  | 85 | +                    fileName += ".webp" | 
|  | 86 | +                } | 
|  | 87 | +            } | 
|  | 88 | + | 
|  | 89 | +            CompressFormat.JPEG -> { | 
|  | 90 | +                mimeType = "image/jpeg" | 
|  | 91 | +                if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) { | 
|  | 92 | +                    fileName += ".jpg" | 
|  | 93 | +                } | 
|  | 94 | +            } | 
|  | 95 | + | 
|  | 96 | +            else -> { | 
|  | 97 | +                mimeType = "image/jpeg" | 
|  | 98 | +                if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) { | 
|  | 99 | +                    fileName += ".jpg" | 
|  | 100 | +                } | 
|  | 101 | +            } | 
|  | 102 | +        } | 
|  | 103 | + | 
|  | 104 | +        val filePath = file.absolutePath + "/" + fileName | 
|  | 105 | +        val out: FileOutputStream? | 
|  | 106 | +        try { | 
|  | 107 | +            out = FileOutputStream(filePath) | 
|  | 108 | + | 
|  | 109 | +            chartBitmap.compress(format, quality, out) | 
|  | 110 | + | 
|  | 111 | +            out.flush() | 
|  | 112 | +            out.close() | 
|  | 113 | +        } catch (e: IOException) { | 
|  | 114 | +            e.printStackTrace() | 
|  | 115 | + | 
|  | 116 | +            return false | 
|  | 117 | +        } | 
|  | 118 | + | 
|  | 119 | +        val size = File(filePath).length() | 
|  | 120 | + | 
|  | 121 | +        val values = ContentValues(8) | 
|  | 122 | + | 
|  | 123 | +        // store the details | 
|  | 124 | +        values.put(MediaStore.Images.Media.TITLE, fileName) | 
|  | 125 | +        values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName) | 
|  | 126 | +        values.put(MediaStore.Images.Media.DATE_ADDED, currentTime) | 
|  | 127 | +        values.put(MediaStore.Images.Media.MIME_TYPE, mimeType) | 
|  | 128 | +        values.put(MediaStore.Images.Media.DESCRIPTION, fileDescription) | 
|  | 129 | +        values.put(MediaStore.Images.Media.ORIENTATION, 0) | 
|  | 130 | +        values.put(MediaStore.Images.Media.DATA, filePath) | 
|  | 131 | +        values.put(MediaStore.Images.Media.SIZE, size) | 
|  | 132 | + | 
|  | 133 | +        return context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) != null | 
|  | 134 | +    } | 
|  | 135 | + | 
|  | 136 | +} | 
0 commit comments