├── .github └── workflows │ ├── android.yml │ ├── gradle-publish.yml │ └── gradle.yml ├── .gitignore ├── ImageCompressor ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── android │ │ └── imagecompressor │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── android │ │ └── imagecompressor │ │ └── compressImageUtils.kt │ └── test │ └── java │ └── com │ └── android │ └── imagecompressor │ └── ExampleUnitTest.kt ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── kl │ │ └── compress_image │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── kl │ │ │ └── compress_image │ │ │ └── MainActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── kl │ └── compress_image │ └── ExampleUnitTest.kt ├── build.gradle ├── google6401b219a8c25f30.html ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image (2)_google-pixel4xl-clearlywhite-portrait.jpg └── settings.gradle /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: set up JDK 11 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: '11' 20 | distribution: 'temurin' 21 | cache: gradle 22 | 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Build with Gradle 26 | run: ./gradlew build 27 | -------------------------------------------------------------------------------- /.github/workflows/gradle-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created 6 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle 7 | 8 | name: Gradle Package 9 | 10 | on: 11 | release: 12 | types: [created] 13 | 14 | jobs: 15 | build: 16 | 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: read 20 | packages: write 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Set up JDK 11 25 | uses: actions/setup-java@v3 26 | with: 27 | java-version: '11' 28 | distribution: 'temurin' 29 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 30 | settings-path: ${{ github.workspace }} # location for the settings.xml file 31 | 32 | - name: Build with Gradle 33 | uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 34 | with: 35 | arguments: build 36 | 37 | # The USERNAME and TOKEN need to correspond to the credentials environment variables used in 38 | # the publishing section of your build.gradle 39 | - name: Publish to GitHub Packages 40 | uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 41 | with: 42 | arguments: publish 43 | env: 44 | USERNAME: ${{ github.actor }} 45 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time 6 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 7 | 8 | name: Java CI with Gradle 9 | 10 | on: 11 | push: 12 | branches: [ "master" ] 13 | pull_request: 14 | branches: [ "master" ] 15 | 16 | permissions: 17 | contents: read 18 | 19 | jobs: 20 | build: 21 | 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | - name: Set up JDK 11 27 | uses: actions/setup-java@v3 28 | with: 29 | java-version: '11' 30 | distribution: 'temurin' 31 | - name: Build with Gradle 32 | uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 33 | with: 34 | arguments: build 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /ImageCompressor/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /ImageCompressor/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | compileSdk 33 8 | 9 | defaultConfig { 10 | minSdk 21 11 | targetSdk 33 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | kotlinOptions { 28 | jvmTarget = '1.8' 29 | } 30 | } 31 | 32 | dependencies { 33 | 34 | implementation 'androidx.core:core-ktx:1.10.0' 35 | implementation 'androidx.appcompat:appcompat:1.6.1' 36 | implementation 'com.google.android.material:material:1.8.0' 37 | testImplementation 'junit:junit:4.13.2' 38 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 39 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 40 | } -------------------------------------------------------------------------------- /ImageCompressor/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/ImageCompressor/consumer-rules.pro -------------------------------------------------------------------------------- /ImageCompressor/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /ImageCompressor/src/androidTest/java/com/android/imagecompressor/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.android.imagecompressor 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.android.imagecompressor.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /ImageCompressor/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /ImageCompressor/src/main/java/com/android/imagecompressor/compressImageUtils.kt: -------------------------------------------------------------------------------- 1 | /*Copyright [2022] [Vinod Baste] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License.*/ 14 | 15 | @file:Suppress("DEPRECATION") 16 | 17 | package com.android.imagecompressor 18 | 19 | import android.content.Context 20 | import android.graphics.* 21 | import android.media.ExifInterface 22 | import android.os.Build 23 | import android.os.Environment 24 | import android.util.Log 25 | import java.io.File 26 | import java.io.FileNotFoundException 27 | import java.io.FileOutputStream 28 | import java.io.IOException 29 | import java.nio.file.Files 30 | import kotlin.math.roundToInt 31 | 32 | object ImageCompressUtils { 33 | 34 | //compress the image 35 | @JvmOverloads 36 | fun compressImage( 37 | context: Context, 38 | imagePath: String?, 39 | imageName: String?, 40 | imageQuality: Int = 50 41 | ): String { 42 | 43 | var filePath = "" 44 | try { 45 | var scaledBitmap: Bitmap? = null 46 | val options = BitmapFactory.Options() 47 | // by setting this field as true, the actual bitmap pixels are not loaded in the memory. 48 | // Just the bounds are loaded. If you try the use the bitmap here, you will get null. 49 | options.inJustDecodeBounds = true 50 | var actualHeight = options.outHeight 51 | var actualWidth = options.outWidth 52 | 53 | val imageFile = File(imagePath!!) 54 | val fileContent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 55 | Files.readAllBytes(imageFile.toPath()) 56 | } else { 57 | File(imagePath).readBytes() 58 | } 59 | var bmp = BitmapFactory.decodeByteArray(fileContent, 0, fileContent.size, options) 60 | 61 | //max Height and width values of the compressed image is taken as 1024x912 62 | val maxHeight = 1024.0f 63 | val maxWidth = 912.0f 64 | var imgRatio = actualWidth / actualHeight.toFloat() 65 | val maxRatio = maxWidth / maxHeight 66 | 67 | //width and height values are set maintaining the aspect ratio of the image 68 | if (actualHeight > maxHeight || actualWidth > maxWidth) { 69 | when { 70 | imgRatio < maxRatio -> { 71 | imgRatio = maxHeight / actualHeight 72 | actualWidth = (imgRatio * actualWidth).toInt() 73 | actualHeight = maxHeight.toInt() 74 | } 75 | imgRatio > maxRatio -> { 76 | imgRatio = maxWidth / actualWidth 77 | actualHeight = (imgRatio * actualHeight).toInt() 78 | actualWidth = maxWidth.toInt() 79 | } 80 | else -> { 81 | actualHeight = maxHeight.toInt() 82 | actualWidth = maxWidth.toInt() 83 | } 84 | } 85 | } 86 | 87 | //setting inSampleSize value allows to load a scaled down version of the original image 88 | options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight) 89 | //inJustDecodeBounds set to false to load the actual bitmap 90 | options.inJustDecodeBounds = false 91 | //this removes the redundant quality of the image 92 | options.inPurgeable = true 93 | //this options allow android to claim the bitmap memory if it runs low on memory 94 | options.inInputShareable = true 95 | 96 | options.inTempStorage = ByteArray(16 * 1024) 97 | try { 98 | //load the bitmap from its path 99 | bmp = BitmapFactory.decodeFile(imagePath, options) 100 | } catch (exception: OutOfMemoryError) { 101 | exception.printStackTrace() 102 | } 103 | try { 104 | scaledBitmap = 105 | Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888) 106 | } catch (exception: OutOfMemoryError) { 107 | exception.printStackTrace() 108 | } 109 | val ratioX = actualWidth / options.outWidth.toFloat() 110 | val ratioY = actualHeight / options.outHeight.toFloat() 111 | val middleX = actualWidth / 2.0f 112 | val middleY = actualHeight / 2.0f 113 | val scaleMatrix = Matrix() 114 | scaleMatrix.setScale(ratioX, ratioY, middleX, middleY) 115 | val canvas = Canvas(scaledBitmap!!) 116 | canvas.setMatrix(scaleMatrix) 117 | canvas.drawBitmap( 118 | bmp, 119 | middleX - bmp.width / 2, 120 | middleY - bmp.height / 2, 121 | Paint(Paint.FILTER_BITMAP_FLAG) 122 | ) 123 | 124 | //check the rotation of the image and display it properly 125 | val exif: ExifInterface 126 | try { 127 | exif = ExifInterface(imagePath.toString()) 128 | val orientation = exif.getAttributeInt( 129 | ExifInterface.TAG_ORIENTATION, 0 130 | ) 131 | Log.d("EXIF", "Exif: $orientation") 132 | val matrix = Matrix() 133 | when (orientation) { 134 | 6 -> { 135 | matrix.postRotate(90f) 136 | Log.d("EXIF", "Exif: $orientation") 137 | } 138 | 3 -> { 139 | matrix.postRotate(180f) 140 | Log.d("EXIF", "Exif: $orientation") 141 | } 142 | 8 -> { 143 | matrix.postRotate(270f) 144 | Log.d("EXIF", "Exif: $orientation") 145 | } 146 | } 147 | scaledBitmap = Bitmap.createBitmap( 148 | scaledBitmap, 0, 0, 149 | scaledBitmap.width, scaledBitmap.height, matrix, 150 | true 151 | ) 152 | } catch (e: IOException) { 153 | e.printStackTrace() 154 | } catch (e: java.lang.Exception) { 155 | e.printStackTrace() 156 | } 157 | val out: FileOutputStream? 158 | filePath = imageName?.let { getOutputMediaFile(it, context) }!!.absolutePath 159 | try { 160 | out = FileOutputStream(filePath) 161 | 162 | //write the compressed bitmap at the destination specified by filename. 163 | scaledBitmap!!.compress(Bitmap.CompressFormat.JPEG, imageQuality, out) 164 | } catch (e: FileNotFoundException) { 165 | e.printStackTrace() 166 | } 167 | } catch (e: java.lang.Exception) { 168 | e.printStackTrace() 169 | } 170 | 171 | return filePath 172 | } 173 | 174 | } 175 | 176 | private fun getOutputMediaFile(imageName: String, context: Context): File? { 177 | var imageFile1: File? = null 178 | try { 179 | imageFile1 = createImageFile(context, imageName) 180 | } catch (e: IOException) { 181 | e.printStackTrace() 182 | } 183 | if (imageFile1!!.exists()) imageFile1.delete() 184 | var imageNew: File? = null 185 | try { 186 | imageNew = createImageFile(context, imageName) 187 | } catch (e: IOException) { 188 | e.printStackTrace() 189 | } 190 | return imageNew 191 | } 192 | 193 | private fun calculateInSampleSize( 194 | options: BitmapFactory.Options, 195 | reqWidth: Int, 196 | reqHeight: Int 197 | ): Int { 198 | val height = options.outHeight 199 | val width = options.outWidth 200 | var inSampleSize = 1 201 | try { 202 | if (height > reqHeight || width > reqWidth) { 203 | val heightRatio = 204 | (height.toFloat() / reqHeight.toFloat()).roundToInt() 205 | val widthRatio = 206 | (width.toFloat() / reqWidth.toFloat()).roundToInt() 207 | inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio 208 | } 209 | val totalPixels = width * height.toFloat() 210 | val totalReqPixelsCap = reqWidth * reqHeight * 2.toFloat() 211 | while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { 212 | inSampleSize++ 213 | } 214 | } catch (e: java.lang.Exception) { 215 | e.printStackTrace() 216 | } 217 | return inSampleSize 218 | } 219 | 220 | @Throws(IOException::class) 221 | private fun createImageFile(context: Context, FileName: String): File { 222 | return File( 223 | context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) 224 | .toString() + File.separator + FileName + ".png" 225 | ) 226 | } -------------------------------------------------------------------------------- /ImageCompressor/src/test/java/com/android/imagecompressor/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.android.imagecompressor 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Vinod Baste 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image Compressor 2 | 3 | An Android image compress library, **image compressor**, is small and effective. With very little or no image quality degradation, a compressor enables you to reduce the size of large photos into smaller size photos. 4 | 5 | [![Google DevLibrary - VinodBaste](https://img.shields.io/badge/Google_DevLibrary-VinodBaste-ea9f2d?logo=Android<%2Ftitle><path+d%3D"M17.523+15.3414c-.5511+0-.9993-.4486-.9993-.9997s.4483-.9993.9993-.9993c.5511+0+.9993.4483.9993.9993.0001.5511-.4482.9997-.9993.9997m-11.046+0c-.5511+0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511+0+.9993.4483.9993.9993+0+.5511-.4483.9997-.9993.9997m11.4045-6.02l1.9973-3.4592a.416.416+0+00-.1521-.5676.416.416+0+00-.5676.1521l-2.0223+3.503C15.5902+8.2439+13.8533+7.8508+12+7.8508s-3.5902.3931-5.1367+1.0989L4.841+5.4467a.4161.4161+0+00-.5677-.1521.4157.4157+0+00-.1521.5676l1.9973+3.4592C2.6889+11.1867.3432+14.6589+0+18.761h24c-.3435-4.1021-2.6892-7.5743-6.1185-9.4396"%2F><%2Fsvg>&logoColor=30DC80)](https://devlibrary.withgoogle.com/products/android/repos/vinodbaste-Image-compressor) 6 | 7 | [![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21) 8 | [![GitHub tag](https://img.shields.io/github/tag/vinodbaste/image-compressor?include_prereleases=&sort=semver&color=blue)](https://github.com/vinodbaste/image-compressor/releases/) 9 | [![License](https://img.shields.io/badge/License-Apache_2.0-blue)](#license) 10 | [![News - Android Weekly](https://img.shields.io/badge/News-Android_Weekly-d36f21)](https://androidweekly.net/issues/issue-326) 11 | [![Story - Medium](https://img.shields.io/badge/Story-Medium-2ea44f)](https://medium.com/codex/image-compressor-13dbfd0445a3) 12 | [![GitHub - VinodBaste](https://img.shields.io/badge/GitHub-VinodBaste-4664c6)](https://github.com/vinodbaste/Image-compressor) 13 | [![](https://jitpack.io/v/vinodbaste/Image-compressor.svg)](https://jitpack.io/#vinodbaste/Image-compressor) 14 | 15 | <img src = "https://raw.githubusercontent.com/vinodbaste/ImageCompressor/main/image%20(2)_google-pixel4xl-clearlywhite-portrait.jpg" width = 250 height = 500 /> 16 | 17 | # How to implement 18 | To get a Git project into your build: 19 | ## Gradle 20 | ` Step 1:` Add it in your **root build.gradle** at the end of repositories: 21 | ```kotlin 22 | allprojects { 23 | repositories { 24 | ... 25 | maven { url 'https://jitpack.io' } 26 | } 27 | } 28 | ``` 29 | 30 | `Step 2:` Add the dependency in your **project build.gradle** 31 | ```kotlin 32 | dependencies { 33 | implementation 'com.github.vinodbaste:ImageCompressor:1.1.0' 34 | } 35 | ``` 36 | # Let's compress the image size! 37 | #### Compress Image File at the specified `imagePath` 38 | When **compressing** a picture, add the following block of code to the **activity or fragment**. Either after taking a **picture with a camera** or selecting one **from a gallery**. 39 | ```kotlin 40 | ImageCompressUtils.compressImage( 41 | context = this, 42 | imagePath = "actualImagePath", 43 | imageName = "imageName", 44 | imageQuality = 50 45 | ) 46 | ``` 47 | **compressImage** takes 4 parameters where the **last one is optional** 48 | * **context**, the current/active state of the application. 49 | * **imagePath** parameter takes the absolute image path. 50 | * **imageName** is completely up to the user. 51 | * **imageQuality** is set to 50 by default. The max can be set to 100. 52 | 53 | #### Compress Image File at the specified `imagePath` and return the `compressed ImagePath` 54 | ```kotlin 55 | val compressedImagePath = ImageCompressUtils.compressImage( 56 | context = this, 57 | imagePath = "actualImagePath", 58 | imageName = "imageName", 59 | imageQuality = 50 60 | ) 61 | ``` 62 | With the image name supplied, the code block above returns the path to the compressed picture. 63 | **compressedImagePath** has the imagePath with the imageName specified. 64 | 65 | # Example 66 | An illustration of how the code block can be utilized. 67 | ```kotlin 68 | //absolute path of the image 69 | val imagePath= "actualImagePath" 70 | 71 | val imageFileBc = File(imagePath) 72 | val imageSizeBc = imageFileBc.length() / 1024 // In BYTES 73 | Log.d("image_before_compress", imageSizeBc.toString()) 74 | 75 | ImageCompressUtils.compressImage( 76 | context = this, 77 | imagePath = imagePath, 78 | imageName = "imageName", 79 | imageQuality = 50 80 | ) 81 | 82 | val imageFileAc = File(imagePath) 83 | val imageSizeAC = imageFileAc.length() / 1024 // In BYTES 84 | Log.d("image_after_compress", imageSizeAC.toString()) 85 | 86 | //your function to play with compressed image 87 | loadCompressedImage(imagePath) 88 | ``` 89 | # proguard-rules 90 | ``` 91 | -keepclassmembers class com.android.imagecompressor.compressImageUtils 92 | 93 | -keep class * extends com.android.imagecompressor.compressImageUtils { 94 | <init>(...); 95 | } 96 | 97 | -dontwarn javax.annotation.Nullable 98 | -dontwarn javax.annotation.ParametersAreNonnullByDefault 99 | ``` 100 | 101 | **If you find this library useful, please consider starring this repository from the top of this page.** 102 | [![](https://i.imgur.com/oSLuE0e.png)](#) 103 | 104 | # Support my work 105 | <a href="https://www.buymeacoffee.com/bastevinod" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a> 106 | 107 | # Note 108 | ``` 109 | > In the event that an image is selected from a gallery, make a copy of it and follow the path. 110 | > The original picture path is used to compress and rewrite the image. 111 | ``` 112 | # License 113 | ``` 114 | Copyright [2022] [Vinod Baste] 115 | 116 | Licensed under the Apache License, Version 2.0 (the "License"); 117 | you may not use this file except in compliance with the License. 118 | You may obtain a copy of the License at 119 | 120 | http://www.apache.org/licenses/LICENSE-2.0 121 | 122 | Unless required by applicable law or agreed to in writing, software 123 | distributed under the License is distributed on an "AS IS" BASIS, 124 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 125 | See the License for the specific language governing permissions and 126 | limitations under the License. 127 | ``` 128 | 129 | 130 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | /*Copyright [2022] [Vinod Baste] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License.*/ 14 | 15 | plugins { 16 | id 'com.android.application' 17 | id 'org.jetbrains.kotlin.android' 18 | } 19 | 20 | android { 21 | compileSdk 31 22 | 23 | defaultConfig { 24 | applicationId "com.kl.compress_image" 25 | minSdk 21 26 | targetSdk 31 27 | versionCode 1 28 | versionName "1.0" 29 | 30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 31 | } 32 | 33 | buildTypes { 34 | release { 35 | minifyEnabled false 36 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 37 | } 38 | } 39 | compileOptions { 40 | sourceCompatibility JavaVersion.VERSION_1_8 41 | targetCompatibility JavaVersion.VERSION_1_8 42 | } 43 | kotlinOptions { 44 | jvmTarget = '1.8' 45 | } 46 | } 47 | 48 | dependencies { 49 | 50 | implementation 'androidx.core:core-ktx:1.7.0' 51 | implementation 'androidx.appcompat:appcompat:1.4.2' 52 | implementation 'com.google.android.material:material:1.6.1' 53 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 54 | implementation 'androidx.exifinterface:exifinterface:1.3.3' 55 | testImplementation 'junit:junit:4.13.2' 56 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 57 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 58 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/kl/compress_image/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.kl.compress_image 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.kl.compress_image", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 | package="com.kl.compress_image"> 4 | 5 | <application 6 | android:allowBackup="true" 7 | android:icon="@mipmap/ic_launcher" 8 | android:label="@string/app_name" 9 | android:roundIcon="@mipmap/ic_launcher_round" 10 | android:supportsRtl="true" 11 | android:theme="@style/Theme.Compress_Image"> 12 | <activity 13 | android:name=".MainActivity" 14 | android:exported="true"> 15 | <intent-filter> 16 | <action android:name="android.intent.action.MAIN" /> 17 | 18 | <category android:name="android.intent.category.LAUNCHER" /> 19 | </intent-filter> 20 | </activity> 21 | </application> 22 | 23 | </manifest> -------------------------------------------------------------------------------- /app/src/main/java/com/kl/compress_image/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /*Copyright [2022] [Vinod Baste] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License.*/ 14 | 15 | package com.kl.compress_image 16 | 17 | import androidx.appcompat.app.AppCompatActivity 18 | import android.os.Bundle 19 | 20 | class MainActivity : AppCompatActivity() { 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | setContentView(R.layout.activity_main) 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" 2 | xmlns:aapt="http://schemas.android.com/aapt" 3 | android:width="108dp" 4 | android:height="108dp" 5 | android:viewportWidth="108" 6 | android:viewportHeight="108"> 7 | <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z"> 8 | <aapt:attr name="android:fillColor"> 9 | <gradient 10 | android:endX="85.84757" 11 | android:endY="92.4963" 12 | android:startX="42.9492" 13 | android:startY="49.59793" 14 | android:type="linear"> 15 | <item 16 | android:color="#44000000" 17 | android:offset="0.0" /> 18 | <item 19 | android:color="#00000000" 20 | android:offset="1.0" /> 21 | </gradient> 22 | </aapt:attr> 23 | </path> 24 | <path 25 | android:fillColor="#FFFFFF" 26 | android:fillType="nonZero" 27 | android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z" 28 | android:strokeWidth="1" 29 | android:strokeColor="#00000000" /> 30 | </vector> -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <vector xmlns:android="http://schemas.android.com/apk/res/android" 3 | android:width="108dp" 4 | android:height="108dp" 5 | android:viewportWidth="108" 6 | android:viewportHeight="108"> 7 | <path 8 | android:fillColor="#3DDC84" 9 | android:pathData="M0,0h108v108h-108z" /> 10 | <path 11 | android:fillColor="#00000000" 12 | android:pathData="M9,0L9,108" 13 | android:strokeWidth="0.8" 14 | android:strokeColor="#33FFFFFF" /> 15 | <path 16 | android:fillColor="#00000000" 17 | android:pathData="M19,0L19,108" 18 | android:strokeWidth="0.8" 19 | android:strokeColor="#33FFFFFF" /> 20 | <path 21 | android:fillColor="#00000000" 22 | android:pathData="M29,0L29,108" 23 | android:strokeWidth="0.8" 24 | android:strokeColor="#33FFFFFF" /> 25 | <path 26 | android:fillColor="#00000000" 27 | android:pathData="M39,0L39,108" 28 | android:strokeWidth="0.8" 29 | android:strokeColor="#33FFFFFF" /> 30 | <path 31 | android:fillColor="#00000000" 32 | android:pathData="M49,0L49,108" 33 | android:strokeWidth="0.8" 34 | android:strokeColor="#33FFFFFF" /> 35 | <path 36 | android:fillColor="#00000000" 37 | android:pathData="M59,0L59,108" 38 | android:strokeWidth="0.8" 39 | android:strokeColor="#33FFFFFF" /> 40 | <path 41 | android:fillColor="#00000000" 42 | android:pathData="M69,0L69,108" 43 | android:strokeWidth="0.8" 44 | android:strokeColor="#33FFFFFF" /> 45 | <path 46 | android:fillColor="#00000000" 47 | android:pathData="M79,0L79,108" 48 | android:strokeWidth="0.8" 49 | android:strokeColor="#33FFFFFF" /> 50 | <path 51 | android:fillColor="#00000000" 52 | android:pathData="M89,0L89,108" 53 | android:strokeWidth="0.8" 54 | android:strokeColor="#33FFFFFF" /> 55 | <path 56 | android:fillColor="#00000000" 57 | android:pathData="M99,0L99,108" 58 | android:strokeWidth="0.8" 59 | android:strokeColor="#33FFFFFF" /> 60 | <path 61 | android:fillColor="#00000000" 62 | android:pathData="M0,9L108,9" 63 | android:strokeWidth="0.8" 64 | android:strokeColor="#33FFFFFF" /> 65 | <path 66 | android:fillColor="#00000000" 67 | android:pathData="M0,19L108,19" 68 | android:strokeWidth="0.8" 69 | android:strokeColor="#33FFFFFF" /> 70 | <path 71 | android:fillColor="#00000000" 72 | android:pathData="M0,29L108,29" 73 | android:strokeWidth="0.8" 74 | android:strokeColor="#33FFFFFF" /> 75 | <path 76 | android:fillColor="#00000000" 77 | android:pathData="M0,39L108,39" 78 | android:strokeWidth="0.8" 79 | android:strokeColor="#33FFFFFF" /> 80 | <path 81 | android:fillColor="#00000000" 82 | android:pathData="M0,49L108,49" 83 | android:strokeWidth="0.8" 84 | android:strokeColor="#33FFFFFF" /> 85 | <path 86 | android:fillColor="#00000000" 87 | android:pathData="M0,59L108,59" 88 | android:strokeWidth="0.8" 89 | android:strokeColor="#33FFFFFF" /> 90 | <path 91 | android:fillColor="#00000000" 92 | android:pathData="M0,69L108,69" 93 | android:strokeWidth="0.8" 94 | android:strokeColor="#33FFFFFF" /> 95 | <path 96 | android:fillColor="#00000000" 97 | android:pathData="M0,79L108,79" 98 | android:strokeWidth="0.8" 99 | android:strokeColor="#33FFFFFF" /> 100 | <path 101 | android:fillColor="#00000000" 102 | android:pathData="M0,89L108,89" 103 | android:strokeWidth="0.8" 104 | android:strokeColor="#33FFFFFF" /> 105 | <path 106 | android:fillColor="#00000000" 107 | android:pathData="M0,99L108,99" 108 | android:strokeWidth="0.8" 109 | android:strokeColor="#33FFFFFF" /> 110 | <path 111 | android:fillColor="#00000000" 112 | android:pathData="M19,29L89,29" 113 | android:strokeWidth="0.8" 114 | android:strokeColor="#33FFFFFF" /> 115 | <path 116 | android:fillColor="#00000000" 117 | android:pathData="M19,39L89,39" 118 | android:strokeWidth="0.8" 119 | android:strokeColor="#33FFFFFF" /> 120 | <path 121 | android:fillColor="#00000000" 122 | android:pathData="M19,49L89,49" 123 | android:strokeWidth="0.8" 124 | android:strokeColor="#33FFFFFF" /> 125 | <path 126 | android:fillColor="#00000000" 127 | android:pathData="M19,59L89,59" 128 | android:strokeWidth="0.8" 129 | android:strokeColor="#33FFFFFF" /> 130 | <path 131 | android:fillColor="#00000000" 132 | android:pathData="M19,69L89,69" 133 | android:strokeWidth="0.8" 134 | android:strokeColor="#33FFFFFF" /> 135 | <path 136 | android:fillColor="#00000000" 137 | android:pathData="M19,79L89,79" 138 | android:strokeWidth="0.8" 139 | android:strokeColor="#33FFFFFF" /> 140 | <path 141 | android:fillColor="#00000000" 142 | android:pathData="M29,19L29,89" 143 | android:strokeWidth="0.8" 144 | android:strokeColor="#33FFFFFF" /> 145 | <path 146 | android:fillColor="#00000000" 147 | android:pathData="M39,19L39,89" 148 | android:strokeWidth="0.8" 149 | android:strokeColor="#33FFFFFF" /> 150 | <path 151 | android:fillColor="#00000000" 152 | android:pathData="M49,19L49,89" 153 | android:strokeWidth="0.8" 154 | android:strokeColor="#33FFFFFF" /> 155 | <path 156 | android:fillColor="#00000000" 157 | android:pathData="M59,19L59,89" 158 | android:strokeWidth="0.8" 159 | android:strokeColor="#33FFFFFF" /> 160 | <path 161 | android:fillColor="#00000000" 162 | android:pathData="M69,19L69,89" 163 | android:strokeWidth="0.8" 164 | android:strokeColor="#33FFFFFF" /> 165 | <path 166 | android:fillColor="#00000000" 167 | android:pathData="M79,19L79,89" 168 | android:strokeWidth="0.8" 169 | android:strokeColor="#33FFFFFF" /> 170 | </vector> 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 | xmlns:app="http://schemas.android.com/apk/res-auto" 4 | xmlns:tools="http://schemas.android.com/tools" 5 | android:layout_width="match_parent" 6 | android:layout_height="match_parent" 7 | tools:context=".MainActivity"> 8 | 9 | <TextView 10 | android:layout_width="wrap_content" 11 | android:layout_height="wrap_content" 12 | android:text="Hello World!" 13 | app:layout_constraintBottom_toBottomOf="parent" 14 | app:layout_constraintLeft_toLeftOf="parent" 15 | app:layout_constraintRight_toRightOf="parent" 16 | app:layout_constraintTop_toTopOf="parent" /> 17 | 18 | </androidx.constraintlayout.widget.ConstraintLayout> -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> 3 | <background android:drawable="@drawable/ic_launcher_background" /> 4 | <foreground android:drawable="@drawable/ic_launcher_foreground" /> 5 | </adaptive-icon> -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> 3 | <background android:drawable="@drawable/ic_launcher_background" /> 4 | <foreground android:drawable="@drawable/ic_launcher_foreground" /> 5 | </adaptive-icon> -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | <resources xmlns:tools="http://schemas.android.com/tools"> 2 | <!-- Base application theme. --> 3 | <style name="Theme.Compress_Image" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> 4 | <!-- Primary brand color. --> 5 | <item name="colorPrimary">@color/purple_200</item> 6 | <item name="colorPrimaryVariant">@color/purple_700</item> 7 | <item name="colorOnPrimary">@color/black</item> 8 | <!-- Secondary brand color. --> 9 | <item name="colorSecondary">@color/teal_200</item> 10 | <item name="colorSecondaryVariant">@color/teal_200</item> 11 | <item name="colorOnSecondary">@color/black</item> 12 | <!-- Status bar color. --> 13 | <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> 14 | <!-- Customize your theme here. --> 15 | </style> 16 | </resources> -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <resources> 3 | <color name="purple_200">#FFBB86FC</color> 4 | <color name="purple_500">#FF6200EE</color> 5 | <color name="purple_700">#FF3700B3</color> 6 | <color name="teal_200">#FF03DAC5</color> 7 | <color name="teal_700">#FF018786</color> 8 | <color name="black">#FF000000</color> 9 | <color name="white">#FFFFFFFF</color> 10 | </resources> -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | <resources> 2 | <string name="app_name">Compress_Image</string> 3 | </resources> -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | <resources xmlns:tools="http://schemas.android.com/tools"> 2 | <!-- Base application theme. --> 3 | <style name="Theme.Compress_Image" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> 4 | <!-- Primary brand color. --> 5 | <item name="colorPrimary">@color/purple_500</item> 6 | <item name="colorPrimaryVariant">@color/purple_700</item> 7 | <item name="colorOnPrimary">@color/white</item> 8 | <!-- Secondary brand color. --> 9 | <item name="colorSecondary">@color/teal_200</item> 10 | <item name="colorSecondaryVariant">@color/teal_700</item> 11 | <item name="colorOnSecondary">@color/black</item> 12 | <!-- Status bar color. --> 13 | <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> 14 | <!-- Customize your theme here. --> 15 | </style> 16 | </resources> -------------------------------------------------------------------------------- /app/src/test/java/com/kl/compress_image/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.kl.compress_image 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /*Copyright [2022] [Vinod Baste] 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License.*/ 14 | 15 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 16 | plugins { 17 | id 'com.android.application' version '7.1.0' apply false 18 | id 'com.android.library' version '7.1.0' apply false 19 | id 'org.jetbrains.kotlin.android' version '1.6.21' apply false 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } -------------------------------------------------------------------------------- /google6401b219a8c25f30.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google6401b219a8c25f30.html -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jul 23 11:08:12 IST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /image (2)_google-pixel4xl-clearlywhite-portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinodbaste/Image-compressor/b7cfaa6bb17ed3bbaab3728cb1b0517b4edc615d/image (2)_google-pixel4xl-clearlywhite-portrait.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "Compress_Image" 16 | include ':app' 17 | include ':ImageCompressor' 18 | --------------------------------------------------------------------------------