{"id":19472950,"url":"https://github.com/eskils/kaleidoscopeengine","last_synced_at":"2026-06-17T11:31:10.615Z","repository":{"id":242729085,"uuid":"810416648","full_name":"Eskils/KaleidoscopeEngine","owner":"Eskils","description":"Kaleidoscope effects to images and videos on iOS and macOS","archived":false,"fork":false,"pushed_at":"2024-06-04T16:56:09.000Z","size":1862,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-25T15:32:37.529Z","etag":null,"topics":["image-processing","kaleidoscope","metal","swift","triangle-kaleidoscope"],"latest_commit_sha":null,"homepage":"","language":"Swift","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/Eskils.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}},"created_at":"2024-06-04T16:50:38.000Z","updated_at":"2025-01-13T06:29:29.000Z","dependencies_parsed_at":"2024-06-04T18:25:39.250Z","dependency_job_id":null,"html_url":"https://github.com/Eskils/KaleidoscopeEngine","commit_stats":null,"previous_names":["eskils/kaleidoscopeengine"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Eskils/KaleidoscopeEngine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eskils%2FKaleidoscopeEngine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eskils%2FKaleidoscopeEngine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eskils%2FKaleidoscopeEngine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eskils%2FKaleidoscopeEngine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Eskils","download_url":"https://codeload.github.com/Eskils/KaleidoscopeEngine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eskils%2FKaleidoscopeEngine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34447264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"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":["image-processing","kaleidoscope","metal","swift","triangle-kaleidoscope"],"created_at":"2024-11-10T19:16:18.587Z","updated_at":"2026-06-17T11:31:10.592Z","avatar_url":"https://github.com/Eskils.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Kaleidoscope Engine Logo](DocsResources/KEIcon-small.png)\n\n# Kaleidoscope Engine\n\nLibrary for iOS and macOS providing kaleidoscope effects to images and videos.\n\nA kaleidoscope shows a symetric pattern as a result of repeated reflections between two or more mirrors. Kaleidoscope Engine provides methods for a kaleidoscope with a varying number of mirrors (“Kaleidoscope”) and three mirrors arranged in a triangle (“Triangle Kaleidoscope”).\n\n![A chamomile flower with a kaleidoscope effect](DocsResources/ke-flowers-1.jpg)\n\nPlease try the [demo application](Demo) for iOS and macOS.\n\n## Table of contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Applying kaleidoscope effects to images](#applying-kaleidoscope-effects-to-images)\n    - [Applying kaleidoscope effects to videos](#applying-kaleidoscope-effects-to-videos)\n- [Kaleidoscope kinds](#kaleidoscope-kinds)\n    - [Kaleidoscope](#kaleidoscope)\n    - [Triangle kaleidoscope](#triangle-kaleidoscope)\n- [Video Kaleidoscope Engine](#video-kaleidoscope-engine)\n    - [Video framerate](#video-framerate)\n    - [Concurrent frame processing](#concurrent-frame-processing)\n- [Testing](#testing)\n    - [Writing new tests](#writing-new-tests)\n- [Contributing](#contributing)\n\n## Installation\n\nTo use this package in a SwiftPM project, you need to set it up as a package dependency:\n\n```swift\n// swift-tools-version:5.9\nimport PackageDescription\n\nlet package = Package(\n  name: \"MyPackage\",\n  dependencies: [\n    .package(\n      url: \"https://github.com/Eskils/KaleidoscopeEngine\", \n      .upToNextMinor(from: \"1.0.0\") // or `.upToNextMajor\n    )\n  ],\n  targets: [\n    .target(\n      name: \"MyTarget\",\n      dependencies: [\n        .product(name: \"KaleidoscopeEngine\", package: \"KaleidoscopeEngine\")\n        // For video-support:  .product(name: \"VideoKaleidoscopeEngine\", package: \"KaleidoscopeEngine\") \n      ]\n    )\n  ]\n)\n```\n\n## Usage\n\nKaleidoscope Engine works by applying a kaleidoscope effect on an image or video. The effects are written as compute shaders in Metal.\n\nThere are separate libraries for image and video support.\n\n- **KaleidoscopeEngine** is for images, and\n- **VideoKaleidoscopeEngine** is for videos/movies.\n\nVideoKaleidoscopeEngine depends on KaleidoscopeEngine internally.\n\nThe available kaleidoscope effects are:\n\n- [Kaleidoscope](#kaleidoscope)\n- [TriangleKaleidoscope](#triangle-kaleidoscope)\n\n### Applying kaleidoscope effects to images\n\nKaleidoscope Engine works on **CGImage**.\n\nExample usage:\n\n```swift\nimport KaleidoscopeEngine\n\n// ...\n\nlet kaleidoscopeEngine = KaleidoscopeEngine()\n\nkaleidoscopeEngine.kaleidoscope(\n    image:      inputCGImage,\n    count:      count,\n    angle:      angle,\n    position:   position,\n    fillMode:   fillMode\n)\n```\n\nSee [Kaleidoscope kinds](#kaleidoscope-kinds) for an overview of the various kaleidoscope effects available.\n\n### Applying kaleidoscope effects to videos\n\nVideo Kaleidoscope Engine works on **URL**. The url provided is fed to an AVAsset internally.\n\nAll methods in the Video Kaleidoscope Engine has the same parameters as its corresponding method in Kaleidoscope Engine, and additionally:\n    - outputURL: The resulting video is written to disk, and so an output url is required.\n    - progressHandler: Block to handle progress and whether to continue.\n    - completionHandler: Block to handle completion and errors.\n\nExample usage:\n\n```swift\nimport VideoKaleidoscopeEngine\n\n// ...\n\nlet videoKaleidoscopeEngine = VideoKaleidoscopeEngine(frameRate: 30)\n\nvideoKaleidoscopeEngine.kaleidoscope(\n    video:              videoURL,\n    outputURL:          outputURL,\n    count:              count,\n    angle:              angle,\n    position:           position,\n    fillMode:           fillMode,\n    progressHandler:    progressHandler,\n    completionHandler:  completionHandler\n)\n```\n\n## Kaleidoscope Kinds\n\nHere is an overview of the available kaleidoscope effects.\n\n### Kaleidoscope\n\nKaleidoscope is the familiar look of a physical kaleidoscope with two or more mirrors. The number of mirrors can be varied, as well as the rotation of the kaleidoscope, center of reflection, and how to fill where the kaleidoscope effect would be blank.\n\n![A rapeseed flower with a kaleidoscope effect.](DocsResources/ke-flowers-3.jpg)\n\nCode name: `.kaleidoscope`\n\n**Configurable properties**\n\n#### Count\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Count | Float | 3 | The number of mirrors | \n\nExample values: \n| 3 | 4 | 5 |\n|---|---|---|\n![Count is 3](DocsResources/ke-kal-count-3.png) | ![Count is 4](DocsResources/ke-kal-count-4.png) | ![Count is 5](DocsResources/ke-kal-count-5.png) |\n\n#### Angle \n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Angle | Float | 0 | The rotation of the kaleidoscope | \n\n\u003e **NOTE:** Angle is expected in radians. \n\nExample values: \n| 0° | 15° | 90° | 120° |\n|---|---|---|---|\n![Angle is 0](DocsResources/ke-kal-count-3.png) | ![Angle is 15 degrees](DocsResources/ke-kal-angle-15.png) | ![Angle is 90 degrees](DocsResources/ke-kal-angle-90.png) | ![Angle is 120 degrees](DocsResources/ke-kal-angle-120.png) |\n\n#### Position\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Position | CGPoint | (0.5, 0.5) | The center of reflection | \n\n\u003e **NOTE:** The position is in normalized coordinates. I.e. (1, 1) = (width, height)\n\nExample values: \n| (0.5, 0.5) | (0.2, 0.2) | (0.8, 0.8) |\n|---|---|---|\n![Position is (0.5, 0.5)](DocsResources/ke-kal-count-3.png) | ![Position is (0.2, 0.2)](DocsResources/ke-kal-pos-0.png) | ![Position is (0.8, 0.8)](DocsResources/ke-kal-pos-1.png) |\n\n#### Tile Mode\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Tile Mode | TileMode | `.tile` | How to fill where the kaleidoscope effect would be blank | \n\nPossible values: \n| `.tile` | `.blank` |\n|---|---|\n![Tile mode is tile](DocsResources/ke-kal-count-3.png) | ![Tile mode is blank](DocsResources/ke-kal-tile-mode-blank.png) |\n\n### Triangle Kaleidoscope\n\nTriangle Kaleidoscope is the look of a kaleidoscope with three mirrors arranged in a triangle. This kaleidoscope effect gives a symetric reflection of equilateral triangles.\n\n![A chamomile flower with a triangle kaleidoscope effect.](DocsResources/ke-flowers-tri-1.jpg)\n\nCode name: `.triangleKaleidoscope`\n\n**Configurable properties**\n\n#### Size\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Size | Float | 200 | The length of each mirror / size of the triangle to reflct | \n\nExample values: \n| 200 | 100 | 300 |\n|---|---|---|\n![Size is 200](DocsResources/ke-tri-size-200.png) | ![Size is 100](DocsResources/ke-tri-size-100.png) | ![Size is 300](DocsResources/ke-tri-size-300.png) |\n\n#### Decay\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Decay | Float | 0 | How much each reflection decreases in brightness | \n\n\u003e **NOTE:** Decay is expected to be between 0 to 1, where 0 is no decay and 1 is full decay — i.e. only the center triangle shows.\n\nExample values: \n| 0 | 0.1 | 0.75 |\n|---|---|---|\n![Decay is 0](DocsResources/ke-tri-size-200.png) | ![Decay is 10%](DocsResources/ke-tri-decay-10.png) | ![Decay is 75%](DocsResources/ke-tri-decay-75.png) |\n\n#### Position\n\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| Position | CGPoint | (0.5, 0.5) | The center of reflection | \n\n\u003e **NOTE:** The position is in normalized coordinates. I.e. (1, 1) = (width, height)\n\nExample values: \n| (0.5, 0.5) | (0.2, 0.2) | (0.8, 0.8) |\n|---|---|---|\n![Position is (0.5, 0.5)](DocsResources/ke-tri-pos-origo.png) | ![Position is (0.2, 0.2)](DocsResources/ke-tri-pos-0.png) | ![Position is (0.8, 0.8)](DocsResources/ke-tri-pos-1.png) |\n\n\u003e The example values are shown with decay = 0.2 to indicate the differences more clearly.\n\n## Video Kaleidoscope Engine\n\nVideo Kaleidoscope Engine is a separate library included in the KaleidoscopeEngine package for adding kaleidoscope effects to videos/movies. Video Kaleidoscope Engine works by applying a kaleidoscope effect to each frame in the video.\n\nExample usage:\n\n```swift\nimport VideoKaleidoscopeEngine\n\n// ...\n\nlet videoKaleidoscopeEngine = VideoKaleidoscopeEngine(frameRate: 30)\n\nvideoKaleidoscopeEngine.kaleidoscope(\n    video:              videoURL,\n    outputURL:          outputURL,\n    count:              count,\n    angle:              angle,\n    position:           position,\n    fillMode:           fillMode,\n    progressHandler:    progressHandler,\n    completionHandler:  completionHandler\n)\n```\n\n### Video framerate\n\nBy default, the final video has a framerate of 30. You may adjust the final framerate by providing a frame rate when initializing Video Kaleidoscope Engine. The final frame rate is less than or equal to the specified value.:\n```swift\nVideoKaleidoscopeEngine(frameRate: Int)\n```\n\n### Concurrent frame processing\n\nBy default, video frames are rendered concurrently. You can disable this behaviour, or change the number of frames processed simultaneously using the `numberOfConcurrentFrames` property. \n\nSetting this to 1 will effectively disable concurrent frame processing. A higher number will be faster if the CPU has enough cores to handle the load, but will also use more memory.\n\n## Testing\n\nThe tests work by checking if the image produced by the code look the same to expected output images. To save space, the expected output images are not bundled with the package. \n\nThe expected images can be generated by running the `MakeExpectedImagesForTests` scheme. \n\n### Writing new tests\n\nWhen writing new tests, you start by adding configuration to produce the expected image for your test, then writing the test. \n\nThe tests are mainly written using `isEqual(expectedImageName: String, afterPerformingImageOperations block: (CGImage) throws -\u003e CGImage) throws -\u003e Bool`\n\nEach expected image is described in the *ke-tests-configuration.json* file. This configuration provides details such as which image to use as input, where to output, and which transforms to apply to the input image. Each transform consists of a kind and a configuration that suits its kind.\n\nExtract of *ke-tests-configuration.json*:\n```json\n{\n\t\"input\": \"./Inputs/lines.png\",\n\t\"output\": \"./ExpectedOutputs\",\n    \"clearOutputDirectory\": true,\n\t\"transforms\": [\n\t\t{\n\t\t\t\"kind\": \"kaleidoscope\",\n\t\t\t\"configuration\": {\n\t\t\t\t\"count\": 1,\n                \"angle\": 0,\n\t\t\t\t\"fillMode\": \"tile\"\n\t\t\t}\n\t\t},\n        ...\n    ]\n}\n```\n\nKaleidoscope transform:\n```json\n{\n    \"kind\": \"kaleidoscope\",\n    \"configuration\": {\n        \"count\": 3,\n        \"angle\": 0,\n        \"fillMode\": \"tile\"\n    }\n}\n```\n\nTriangle kaleidoscope transform:\n```json\n{\n    \"kind\": \"triangleKaleidoscope\",\n    \"configuration\": {\n        \"size\": 200,\n        \"decay\": 0.2\n    }\n}\n```\n\n## Contributing\n\nContributions are welcome and encouraged. Feel free to check out the project, submit issues and code patches.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feskils%2Fkaleidoscopeengine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feskils%2Fkaleidoscopeengine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feskils%2Fkaleidoscopeengine/lists"}