{"id":18859877,"url":"https://github.com/kashif-e/camerak","last_synced_at":"2026-01-28T01:07:17.188Z","repository":{"id":257650212,"uuid":"857451193","full_name":"Kashif-E/CameraK","owner":"Kashif-E","description":"A camera library for Compose Multiplatform","archived":false,"fork":false,"pushed_at":"2025-05-13T11:40:22.000Z","size":11077,"stargazers_count":303,"open_issues_count":12,"forks_count":20,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-16T18:06:45.104Z","etag":null,"topics":["android-library","camerax","compose-multiplatform","compose-ui","hacktoberfest","kotlin-android","kotlin-multiplatform"],"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/Kashif-E.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2024-09-14T17:36:19.000Z","updated_at":"2025-05-16T13:25:43.000Z","dependencies_parsed_at":"2024-12-06T08:25:25.805Z","dependency_job_id":"417ff199-823b-4150-9801-1ff41b66cfb2","html_url":"https://github.com/Kashif-E/CameraK","commit_stats":null,"previous_names":["kashif-e/camerak"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kashif-E%2FCameraK","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kashif-E%2FCameraK/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kashif-E%2FCameraK/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kashif-E%2FCameraK/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kashif-E","download_url":"https://codeload.github.com/Kashif-E/CameraK/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254582905,"owners_count":22095518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-library","camerax","compose-multiplatform","compose-ui","hacktoberfest","kotlin-android","kotlin-multiplatform"],"created_at":"2024-11-08T04:19:35.263Z","updated_at":"2026-01-28T01:07:17.182Z","avatar_url":"https://github.com/Kashif-E.png","language":"Kotlin","funding_links":["https://www.buymeacoffee.com/kashifmehmood","https://img.buymeacoffee.com/button-api/?text=Buy"],"categories":[],"sub_categories":[],"readme":"# CameraK\n\nA modern camera library for Compose Multiplatform supporting Android, iOS, and Desktop with a unified API.\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.kashif-mehmood-km/camerak?label=Maven%20Central\u0026color=blue)](https://search.maven.org/search?q=g:io.github.kashif-mehmood-km)\n[![GitHub Release](https://img.shields.io/github/v/release/kashif-e/camerak)](https://github.com/Kashif-E/CameraK/releases)\n[![Kotlin Weekly](https://img.shields.io/badge/Kotlin_Weekly-425-7F52FF)](https://mailchi.mp/kotlinweekly/kotlin-weekly-425)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\n## Features\n\n- 📱 **Cross-Platform**: Android, iOS, and JVM Desktop\n- 📸 **Compose-First**: Native Compose Multiplatform API  \n- 🎯 **Flexible Configuration**: Aspect ratios, zoom, flash control\n- 🔌 **Plugin System**: Modular QR/barcode scanning, OCR, image saving\n- ⚡ **Optimized Capture**: Direct file saving with `takePictureToFile()`\n- 📷 **Advanced Control**: Camera selection (ultra-wide, telephoto on iOS)\n\n## Installation\n\nAdd dependencies to your `build.gradle.kts`:\n\n```kotlin\ndependencies {\n    // Core library\n    implementation(\"io.github.kashif-mehmood-km:camerak:0.1.0\")\n    \n    // Optional plugins\n    implementation(\"io.github.kashif-mehmood-km:image_saver_plugin:0.1.0\")\n    implementation(\"io.github.kashif-mehmood-km:qr_scanner_plugin:0.1.0\")\n    implementation(\"io.github.kashif-mehmood-km:ocr_plugin:0.1.0\")\n}\n```\n\n### Using Version Catalog\n\nAdd to your `libs.versions.toml`:\n\n```toml\n[versions]\ncamerak = \"0.1.0\"\n\n[libraries]\ncamerak = { module = \"io.github.kashif-mehmood-km:camerak\", version.ref = \"camerak\" }\ncamerak-image-saver = { module = \"io.github.kashif-mehmood-km:image_saver_plugin\", version.ref = \"camerak\" }\ncamerak-qr-scanner = { module = \"io.github.kashif-mehmood-km:qr_scanner_plugin\", version.ref = \"camerak\" }\ncamerak-ocr = { module = \"io.github.kashif-mehmood-km:ocr_plugin\", version.ref = \"camerak\" }\n```\n\nThen in your `build.gradle.kts`:\n\n```kotlin\ndependencies {\n    implementation(libs.camerak)\n    implementation(libs.camerak.image.saver)\n    implementation(libs.camerak.qr.scanner)\n    implementation(libs.camerak.ocr)\n}\n```\n\n### Platform Setup\n\n**Android** - Add to `AndroidManifest.xml`:\n```xml\n\u003cuses-permission android:name=\"android.permission.CAMERA\" /\u003e\n\u003cuses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" /\u003e\n```\n\n**iOS** - Add to `Info.plist`:\n```xml\n\u003ckey\u003eNSCameraUsageDescription\u003c/key\u003e\n\u003cstring\u003eCamera access required for taking photos\u003c/string\u003e\n\u003ckey\u003eNSPhotoLibraryAddUsageDescription\u003c/key\u003e\n\u003cstring\u003ePhoto library access required for saving images\u003c/string\u003e\n```\n\n## Quick Start\n\n```kotlin\n@Composable\nfun CameraScreen() {\n    val permissions = providePermissions()\n    val cameraController = remember { mutableStateOf\u003cCameraController?\u003e(null) }\n    val scope = rememberCoroutineScope()\n    \n    // Request permissions\n    LaunchedEffect(Unit) {\n        if (!permissions.hasCameraPermission()) {\n            permissions.RequestCameraPermission(\n                onGranted = { /* Granted */ },\n                onDenied = { /* Denied */ }\n            )\n        }\n    }\n    \n    // Camera preview\n    CameraPreview(\n        modifier = Modifier.fillMaxSize(),\n        cameraConfiguration = {\n            setCameraLens(CameraLens.BACK)\n            setFlashMode(FlashMode.OFF)\n            setAspectRatio(AspectRatio.RATIO_16_9)\n        },\n        onCameraControllerReady = { controller -\u003e\n            cameraController.value = controller\n        }\n    )\n    \n    // Capture button\n    cameraController.value?.let { controller -\u003e\n        Button(\n            onClick = {\n                scope.launch {\n                    when (val result = controller.takePictureToFile()) {\n                        is ImageCaptureResult.SuccessWithFile -\u003e {\n                            println(\"Saved: ${result.filePath}\")\n                        }\n                        is ImageCaptureResult.Error -\u003e {\n                            println(\"Error: ${result.exception.message}\")\n                        }\n                    }\n                }\n            }\n        ) {\n            Text(\"Capture Photo\")\n        }\n    }\n}\n```\n\n## Platform Support\n\n| Platform | Min Version | Backend |\n|----------|-------------|---------|\n| Android | API 21+ | CameraX |\n| iOS | iOS 13.0+ | AVFoundation |\n| Desktop | JDK 11+ | JavaCV |\n\n## Configuration\n\n### Camera Configuration DSL\n\n```kotlin\nCameraPreview(\n    cameraConfiguration = {\n        // Camera selection\n        setCameraLens(CameraLens.BACK)  // FRONT or BACK\n        \n        // Visual settings\n        setAspectRatio(AspectRatio.RATIO_16_9)  // 4:3, 16:9, 9:16, 1:1\n        setResolution(1920 to 1080)  // Optional specific resolution\n        \n        // Flash control\n        setFlashMode(FlashMode.AUTO)  // ON, OFF, AUTO\n        \n        // Image output\n        setImageFormat(ImageFormat.JPEG)  // JPEG or PNG\n        setDirectory(Directory.PICTURES)  // DCIM, DOCUMENTS, etc.\n        \n        // iOS only: Camera device type\n        setCameraDeviceType(CameraDeviceType.ULTRA_WIDE)\n        // Options: DEFAULT, ULTRA_WIDE, TELEPHOTO, DUAL_CAMERA, TRIPLE_CAMERA\n        \n        // Add plugins\n        addPlugin(imageSaverPlugin)\n        addPlugin(qrScannerPlugin)\n    }\n)\n```\n\n### Zoom Control\n\n```kotlin\n// Get maximum zoom capability\nval maxZoom = controller.getMaxZoom()\n\n// Set zoom level (1.0 = no zoom)\ncontroller.setZoom(2.5f)\n\n// Get current zoom\nval currentZoom = controller.getZoom()\n```\n\n### Flash and Torch\n\n```kotlin\n// Toggle flash modes (cycles: OFF → ON → AUTO)\ncontroller.toggleFlashMode()\n\n// Set specific flash mode\ncontroller.setFlashMode(FlashMode.ON)\n\n// Get current flash mode\nval mode = controller.getFlashMode()\n\n// Torch mode (continuous light)\ncontroller.toggleTorchMode()\n```\n\n### Camera Lens\n\n```kotlin\n// Switch between front/back cameras\ncontroller.toggleCameraLens()\n\n// Set specific lens\ncontroller.setCameraLens(CameraLens.FRONT)\n```\n\n### Aspect Ratios\n\n```kotlin\nAspectRatio.RATIO_4_3   // Standard 4:3\nAspectRatio.RATIO_16_9  // Widescreen 16:9\nAspectRatio.RATIO_9_16  // Vertical 9:16 (stories)\nAspectRatio.RATIO_1_1   // Square 1:1\n```\n\n## Plugins\n\n### Image Saver Plugin\n\n```kotlin\nval imageSaverPlugin = rememberImageSaverPlugin(\n    config = ImageSaverConfig(\n        isAutoSave = false,\n        prefix = \"MyApp\",\n        directory = Directory.PICTURES,\n        customFolderName = \"MyAppPhotos\"  // Android only\n    )\n)\n\n// Add to camera configuration\naddPlugin(imageSaverPlugin)\n\n// Manual save\nscope.launch {\n    when (val result = controller.takePicture()) {\n        is ImageCaptureResult.Success -\u003e {\n            imageSaverPlugin.saveImage(\n                byteArray = result.byteArray,\n                imageName = \"Photo_${System.currentTimeMillis()}\"\n            )\n        }\n        is ImageCaptureResult.Error -\u003e {\n            // Handle error\n        }\n    }\n}\n```\n\n### QR Scanner Plugin\n\n```kotlin\nval qrScannerPlugin = rememberQRScannerPlugin(\n    coroutineScope = rememberCoroutineScope()\n)\n\n// Start scanning\nLaunchedEffect(Unit) {\n    qrScannerPlugin.startScanning()\n    \n    qrScannerPlugin.getQrCodeFlow()\n        .distinctUntilChanged()\n        .collectLatest { qrCode -\u003e\n            println(\"QR Code: $qrCode\")\n            qrScannerPlugin.pauseScanning()\n            \n            // Show result, then resume\n            delay(2000)\n            qrScannerPlugin.resumeScanning()\n        }\n}\n\n// Add to camera configuration\naddPlugin(qrScannerPlugin)\n```\n\n### OCR Plugin\n\n```kotlin\nval ocrPlugin = rememberOcrPlugin()\n\n// Add to camera configuration\naddPlugin(ocrPlugin)\n\n// Use OCR\nscope.launch {\n    when (val result = controller.takePicture()) {\n        is ImageCaptureResult.Success -\u003e {\n            val text = ocrPlugin.recognizeText(result.byteArray)\n            println(\"Detected text: $text\")\n        }\n        is ImageCaptureResult.Error -\u003e {\n            // Handle error\n        }\n    }\n}\n```\n\n\n### Debug Tips\n\n```kotlin\n@Composable\nfun CameraScreen() {\n    val controller = remember { mutableStateOf\u003cCameraController?\u003e(null) }\n    \n    DisposableEffect(Unit) {\n        onDispose {\n            // Always release camera resources\n            controller.value?.stopSession()\n            controller.value = null\n        }\n    }\n}\n```\n\n## API Reference\n\n### CameraController\n\n```kotlin\n// Capture to file (recommended - faster)\nsuspend fun takePictureToFile(): ImageCaptureResult\n\n// Capture to ByteArray (slower - deprecated)\n@Deprecated(\"Use takePictureToFile() instead\")\nsuspend fun takePicture(): ImageCaptureResult\n\n// Zoom control\nfun setZoom(zoom: Float)\nfun getZoom(): Float\nfun getMaxZoom(): Float\n\n// Flash control\nfun setFlashMode(mode: FlashMode)\nfun getFlashMode(): FlashMode?\nfun toggleFlashMode()\n\n// Torch control\nfun toggleTorchMode()\n\n// Camera selection\nfun setCameraLens(lens: CameraLens)\nfun toggleCameraLens()\n\n// Session management\nfun startSession()\nfun stopSession()\n```\n\n### CameraPreview\n\n```kotlin\n@Composable\nfun CameraPreview(\n    modifier: Modifier = Modifier,\n    cameraConfiguration: CameraConfiguration.() -\u003e Unit,\n    onCameraControllerReady: (CameraController) -\u003e Unit\n)\n```\n\n## Deprecation Notices\n\n### v1.0 Migration\n\n#### `takePicture()` → `takePictureToFile()`\n\n```kotlin\n// ❌ Deprecated (slower, will be removed in v2.0)\nwhen (val result = controller.takePicture()) {\n    is ImageCaptureResult.Success -\u003e {\n        val byteArray = result.byteArray\n        // Manual file save required\n    }\n}\n\n// ✅ Recommended (2-3x faster)\nwhen (val result = controller.takePictureToFile()) {\n    is ImageCaptureResult.SuccessWithFile -\u003e {\n        val filePath = result.filePath\n        // File already saved\n    }\n}\n```\n\n#### iOS: `rememberIOSPermissions()` → `providePermissions()`\n\n```kotlin\n// ❌ Deprecated (iOS-only)\nval permissions = rememberIOSPermissions()\n\n// ✅ Recommended (cross-platform)\nval permissions = providePermissions()\n```\n\n\n## Contributing\n\nContributions welcome! Please:\n\n1. Open an issue to discuss changes\n2. Fork the repository\n3. Create a feature branch\n4. Submit a pull request\n\n## Support\n\nIf you find this library useful:\n\n\u003ca href=\"https://www.buymeacoffee.com/kashifmehmood\"\u003e\u003cimg src=\"https://img.buymeacoffee.com/button-api/?text=Buy me a coffee\u0026emoji=\u0026slug=kashifmehmood\u0026button_colour=FFDD00\u0026font_colour=000000\u0026font_family=Cookie\u0026outline_colour=000000\u0026coffee_colour=ffffff\" /\u003e\u003c/a\u003e\n\n## License\n\n```\nApache License 2.0\n\nCopyright 2025 Kashif Mehmood\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkashif-e%2Fcamerak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkashif-e%2Fcamerak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkashif-e%2Fcamerak/lists"}