{"id":37029185,"url":"https://github.com/guhungry/android-photo-manipulator","last_synced_at":"2026-01-14T03:30:02.528Z","repository":{"id":46957839,"uuid":"175389166","full_name":"guhungry/android-photo-manipulator","owner":"guhungry","description":"Android React Native Image Processing API to edit photo programmatically. It features print text, overlay on another image (add watermark), resize, crop, flip, rotate and optimize image size then convert file format to jpeg or png","archived":false,"fork":false,"pushed_at":"2026-01-13T00:22:49.000Z","size":665,"stargazers_count":8,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-13T00:40:17.560Z","etag":null,"topics":["android","image-manipulation","image-processing","kotlin"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guhungry.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"guhungry","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":"guhungry","custom":null}},"created_at":"2019-03-13T09:33:18.000Z","updated_at":"2026-01-12T16:58:28.000Z","dependencies_parsed_at":"2024-04-01T15:57:38.080Z","dependency_job_id":"5af4e77d-a2c8-4d42-83d4-b2a7d8d5f55c","html_url":"https://github.com/guhungry/android-photo-manipulator","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/guhungry/android-photo-manipulator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guhungry%2Fandroid-photo-manipulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guhungry%2Fandroid-photo-manipulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guhungry%2Fandroid-photo-manipulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guhungry%2Fandroid-photo-manipulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guhungry","download_url":"https://codeload.github.com/guhungry/android-photo-manipulator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guhungry%2Fandroid-photo-manipulator/sbom","scorecard":{"id":448361,"data":{"date":"2025-08-11","repo":{"name":"github.com/guhungry/android-photo-manipulator","commit":"48496059f28a902465b381b33b37923b37c2262b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build-and-test.yml:1","Warn: no topLevel permission defined: .github/workflows/debug.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-and-test.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/build-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-and-test.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/build-and-test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build-and-test.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/build-and-test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build-and-test.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/build-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/debug.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/debug.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/debug.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/debug.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/guhungry/android-photo-manipulator/publish.yml/master?enable=pin","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:9"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'master'","Warn: could not determine whether codeowners review is allowed","Warn: no status checks found to merge onto branch 'master'","Warn: PRs are not required to make changes on branch 'master'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: all commits (19) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T07:30:03.087Z","repository_id":46957839,"created_at":"2025-08-19T07:30:03.087Z","updated_at":"2025-08-19T07:30:03.087Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408843,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","image-manipulation","image-processing","kotlin"],"created_at":"2026-01-14T03:30:01.958Z","updated_at":"2026-01-14T03:30:02.514Z","avatar_url":"https://github.com/guhungry.png","language":"Kotlin","funding_links":["https://github.com/sponsors/guhungry","https://buymeacoffee.com/guhungry"],"categories":[],"sub_categories":[],"readme":"# Android Photo Manipulator\n[![Build and Test](https://github.com/guhungry/android-photo-manipulator/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/guhungry/android-photo-manipulator/actions/workflows/build-and-test.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=guhungry_android-photo-manipulator\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=guhungry_android-photo-manipulator)\n[![codecov](https://codecov.io/gh/guhungry/android-photo-manipulator/branch/master/graph/badge.svg)](https://codecov.io/gh/guhungry/android-photo-manipulator)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.guhungry.android/photo-manipulator/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.guhungry.android/photo-manipulator)\n\nAndroid Image Processing API to edit photo programmatically.\nThis library is used by [react-native-photo-manipulator](https://github.com/guhungry/react-native-photo-manipulator/).\n\n## Installation\nAdd dependency in module `build.gradle`\n\n```gradle\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation 'com.guhungry.android:photo-manipulator:1.0.2'\n}\n```\n\n## Usage BitmapUtils\n\nImport using\n`import com.guhungry.photomanipulator.BitmapUtils`\n\n### BitmapUtils.readImageDimensions()\nGet width and height of image in `CGSize`\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                  |\n|------------|-----------------------|----------|------------------------------|\n| image      | Bitmap                | Yes      | Source image                 |\n\n### BitmapUtils.crop()\nCrop image from specified `cropRegion`\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                               |\n|------------|-----------------------|----------|-----------------------------------------------------------|\n| image      | Bitmap                | Yes      | Source image to be crop and resize                        |\n| cropRegion | CGRect                | Yes      | Region to be crop in CGRect(`x`, `y`, `size`, `width`)    |\n| outOptions | BitmapFactory.Options | Yes      | Configuration for decode and encode result bitmap         |\n\n### BitmapUtils.cropAndResize()\nCrop and resize image from specified `cropRegion` into `targetSize` using resize mode `cover`\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                                                                |\n|------------|-----------------------|----------|------------------------------------------------------------------------------------------------------------|\n| image      | Bitmap                | Yes      | Source image to be crop and resize                                                                         |\n| cropRegion | CGRect                | Yes      | Region to be crop in CGRect(`x`, `y`, `size`, `width`)                                                     |\n| targetSize | CGSize                | Yes      | Size of result image                                                                                       |\n| outOptions | BitmapFactory.Options | Yes      | Configuration for decode and encode result bitmap                                                          |\n| matrix     | Matrix                | No       | Orientation transform matrix from [getCorrectOrientationMatrix()](#bitmaputilsgetcorrectorientationmatrix) |\n\n### BitmapUtils.printText()\nPrint text into image\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                            |\n|------------|-----------------------|----------|------------------------------------------------------------------------|\n| image      | Bitmap                | Yes      | Source image to be crop and resize                                     |\n| text       | String                | Yes      | Text to print in image                                                 |\n| position   | PointF                | Yes      | Position to in in `x`, `y`                                             |\n| color      | Int                   | Yes      | Text color                                                             |\n| textSize   | Float                 | Yes      | Text size                                                              |\n| font       | Typeface              | No       | Font use to print. Default = App's Default Font                        |\n| alignment  | Paint.Align           | No       | Text alignment (`left`, `right` and `center`). Default = `left`        |\n| thickness  | Float                 | No       | Outline of text. Default = 0                                           |\n| rotation   | Float                 | No       | Rotation angle in degrees. Default = 0                                 |\n\n### BitmapUtils.overlayImage()\nOverlay image on top of background image\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                            |\n|------------|-----------------------|----------|------------------------------------------------------------------------|\n| background | Bitmap                | Yes      | Background image                                                       |\n| overlay    | Bitmap                | Yes      | Overlay image                                                          |\n| position   | PointF                | Yes      | Position of overlay image in background image                          |\n\n### BitmapUtils.flip()\nFlip the image horizontally, vertically or both\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                            |\n|------------|-----------------------|----------|------------------------------------------------------------------------|\n| image      | Bitmap                | Yes      | The image to be flipped                                                |\n| mode       | FlipMode              | Yes      | Flip mode .Horizontal, .Vertical or .Both                              |\n\n### BitmapUtils.rotate()\nRotate the image 90°, 180° or 270°\n\n| NAME  | TYPE         | REQUIRED | DESCRIPTION                                                                                                        |\n|-------|--------------|----------|--------------------------------------------------------------------------------------------------------------------|\n| image | Bitmap       | Yes      | The image to be rotated                                                                                            |\n| mode  | RotationMode | Yes      | Rotation mode .R90 (90° Clockwise), .R180 (180° Half Rotation) or .R270 (270° Clockwise, aka 90° Counterclockwise) |\n\n### BitmapUtils.getCorrectOrientationMatrix()\nGet corrected transform matrix for orientation data in EXIF\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                            |\n|------------|-----------------------|----------|------------------------------------------------------------------------|\n| image      | InputStream           | Yes      | Image input stream                                                     |\n\n## Usage FileUtils\n\nImport using\n`import com.guhungry.photomanipulator.FileUtils`\n\n### FileUtils.createTempFile()\nCreate temp file into cache directory with a prefix\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                     |\n|------------|-----------------------|----------|-------------------------------------------------|\n| context    | Context               | Yes      | Android context                                 |\n| prefix     | String                | Yes      | Temp file name prefix                           |\n| mimeType   | String                | Yes      | Mime type of image. Default = image/jpeg        |\n\n### FileUtils.cachePath()\nGet cache path of app\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                     |\n|------------|-----------------------|----------|-------------------------------------------------|\n| context    | Context               | Yes      | Android context                                 |\n\n### FileUtils.cleanDirectory()\nDelete all files in directory with prefix\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                     |\n|------------|-----------------------|----------|-------------------------------------------------|\n| directory  | File                  | Yes      | Path to clean                                   |\n| prefix     | String                | Yes      | File name prefix to match                       |\n\n### FileUtils.openBitmapInputStream()\nOpen file from uri as input stream\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                                                              |\n|------------|-----------------------|----------|------------------------------------------------------------------------------------------|\n| context    | File                  | Yes      | Path to clean                                                                            |\n| uri        | String                | Yes      | Uri of image can be remote (https?://) or local (file://, android.res:// and content://) |\n\n## Usage MimeUtils\n\nImport using\n`import com.guhungry.photomanipulator.MimeUtils`\n\n### MimeUtils.toExtension()\nGet image file extension from mimeType (Support .jpg, .png and .webp)\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                     |\n|------------|-----------------------|----------|-------------------------------------------------|\n| mimeType   | String                | Yes      | Image mime type                                 |\n\n### MimeUtils.toCompressFormat()\nGet image `Bitmap.CompressFormat` from mimeType (Support .jpg, .png and .webp)\n\n| NAME       | TYPE                  | REQUIRED | DESCRIPTION                                     |\n|------------|-----------------------|----------|-------------------------------------------------|\n| mimeType   | String                | Yes      | Image mime type                                 |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguhungry%2Fandroid-photo-manipulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguhungry%2Fandroid-photo-manipulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguhungry%2Fandroid-photo-manipulator/lists"}