{"id":18031748,"url":"https://github.com/dagronf/bitmap","last_synced_at":"2025-09-03T03:32:31.220Z","repository":{"id":199604213,"uuid":"702777308","full_name":"dagronf/Bitmap","owner":"dagronf","description":"A Swift-y convenience for loading, saving and manipulating bitmap images.","archived":false,"fork":false,"pushed_at":"2025-04-14T22:56:50.000Z","size":874,"stargazers_count":22,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-30T00:13:10.255Z","etag":null,"topics":["bitmap","cgimage","drawing","image","load-save","nsimage","swift","uiimage"],"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/dagronf.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-10-10T02:02:05.000Z","updated_at":"2025-05-30T03:10:30.000Z","dependencies_parsed_at":"2023-11-13T07:23:36.740Z","dependency_job_id":"f46e3b0b-14f3-453e-b4be-0cd23e5003e3","html_url":"https://github.com/dagronf/Bitmap","commit_stats":null,"previous_names":["dagronf/bitmap"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/dagronf/Bitmap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FBitmap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FBitmap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FBitmap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FBitmap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dagronf","download_url":"https://codeload.github.com/dagronf/Bitmap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FBitmap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273385073,"owners_count":25096028,"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","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"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":["bitmap","cgimage","drawing","image","load-save","nsimage","swift","uiimage"],"created_at":"2024-10-30T10:10:39.465Z","updated_at":"2025-09-03T03:32:31.179Z","avatar_url":"https://github.com/dagronf.png","language":"Swift","readme":"# Bitmap\n\n![tag](https://img.shields.io/github/v/tag/dagronf/Bitmap)\n![Swift](https://img.shields.io/badge/Swift-5.5-orange.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-magenta.svg)](https://github.com/dagronf/Bitmap/blob/master/LICENSE) \n![SPM](https://img.shields.io/badge/spm-compatible-maroon.svg)\n\n![macOS](https://img.shields.io/badge/macOS-10.13+-darkblue)\n![iOS](https://img.shields.io/badge/iOS-13+-crimson)\n![tvOS](https://img.shields.io/badge/tvOS-13+-forestgreen)\n![watchOS](https://img.shields.io/badge/watchOS-6+-indigo)\n![macCatalyst](https://img.shields.io/badge/macCatalyst-2+-orangered)\n\nA Swift-y convenience for loading/saving and manipulating bitmap images.\n\n## Why?\n\nI wanted a simple Swift interface for wrapping some of the common image manipulations\nthat I come across in my day-to-day image needs, the primary being easily being able to draw directly into a\nbitmap image.\n\n* Supports all Apple platforms (with some limitations on watchOS)\n* supports loading non-RGBA format images (eg. CMYK) by converting the image to RGBA during load.\n* objects are easily saved via its `representation` property.\n* supports both mutable and immutable methods (functional-style) for manipulating bitmaps.\n* bitmap manipulation functions\n* `Sendable` support to push bitmap information between tasks.\n\n## Definitions\n\nThe `Bitmap` object represents an RGBA image. The image data is stored internally in a simple 1-D array of bytes\nrepresenting the R,G,B,A sequence of pixels. \n\nThe bitmap object holds and manages a `CGContext` representation of the bitmap to allow CG- operations directly \non the bitmap itself. \n\n* `Bitmap`s coordinate system starts at (0, 0) in the bottom left. \n* All operations/manipulations/coordinates occur from the bottom left.\n\n## Creating a new image\n\nNice and simple :-)\n\n```swift\nvar bitmap = try Bitmap(width: 640, height: 480)\n```\n\n## Loading an image into a Bitmap\n\nSupports any file formats that `NSImage`, `UIImage` and `CGImageSource` support when loading.\n\n```swift\n// From a file...\nvar bitmap = try Bitmap(fileURL: ...)\n\n// From image data\nvar bitmap = try Bitmap(imageData: ...)\n```\n\n## Saving a bitmap\n\nSupports any file formats that `NSImage`, `UIImage` and `CGImageSource` support when saving.\n\n`Bitmap` provides methods for writing to some different formats, such as `png`.\nThe `representation` property on the bitmap contains the methods for generating\nimage data in different formats\n\n```swift\nvar bitmap = try Bitmap(fileURL: ...)\n...\nlet pngData = bitmap.representation?.png()\n```\n\n## Drawing into a bitmap\n\n### Drawing into the bitmap's context using CG methods\n\n```swift\nvar bitmap = try Bitmap(width: 640, height: 480)\nbitmap.draw { ctx in\n   ctx.setFillColor(.black)\n   ctx.fill([CGRect(x: 5, y: 5, width: 20, height: 20)])\n}\n```\n\n### Drawing an image into the bitmap\n\n```swift\nvar bitmap = try Bitmap(width: 640, height: 480)\n// Draw an image into a defined rectangle (with optional scaling types aspectFit, aspectFill, axes independent)\nbitmap.drawImage(image, in: CGRect(x: 50, y: 50, width: 100, height: 100))\n// Draw a bitmap at a point\nbitmap.drawBitmap(bitmap, at: CGPoint(x: 300, y: 300))\n```\n\n## Getting/setting individual pixels\n\nYou can directly access pixel information in the bitmap using subscripts or the get/setPixel methods on `Bitmap`\n\n```swift\nvar bitmap = Bitmap(...)\n\n// Retrieve the color of the pixel at x = 4, y = 3.\nlet rgbaPixel = bitmap[4, 3]   // or bitmap.getPixel(x: 4, y: 3)\n\n// Set the color of the pixel at x = 4, y = 3. Only available when `bitmap` is mutable\nbitmap[4, 3] = Bitmap.RGBA(r: 255, g: 0, b: 0, a: 255)   // or bitmap.setPixel(x: 4, y: 3, ...)\n```\n\n## Bitmap operations\n\n`Bitmap` provides a number of built-in operations (such as rotate, tint) that operate on a `Bitmap` instance. \n\n### Mutable\n\nMutable functions operate on a Bitmap variable. Each method modifies the original bitmap instance.\n\n```swift\n// Load an image, rotate it and convert it to grayscale\nvar bitmap = try Bitmap(fileURL: ...)\ntry bitmap.rotate(by: 1.4)\ntry bitmap.grayscale()\n```\n\n### Immutable\n\nImmutable functions work on a copy of the bitmap and return the copy. The original bitmap (which can be a `let` variable\nremains untouched.\n\nImmutable function variations are named with 'ing' in the title, such as `tinting()` or `scaling()`.\n\n```swift\n// Load an image, rotate it and convert it to grayscale\nlet bitmap = try Bitmap(fileURL: ...)\nlet rotated = try bitmap.rotating(by: 1.4)\nlet grayscale = try rotated.grayscaling()\n```\n\nThis allows functional-style chaining on a bitmap.\n\n```swift\n// Functional style\nlet bitmap = try Bitmap(fileURL: ...)\n\t.rotating(by: 1.4)\n\t.grayscaling()\n```\n\n### Available bitmap manipulation functions\n\n* Resizing/scaling\n* Padding/inset\n* Clipping/masking\n* Rotation\n* Scrolling\n* Blurring\n* Transparency removal\n* Punching holes\n* Color manipulation (eg. grayscale, tinting, gamma adjustment, saturation etc)\n* Flipping\n* Drawing (eg. lines, shapes, paths, fill/stroke)\n* Drawing text\n* Drawing borders\n\n… and more!\n\n## Sendable support\n\nYou will not be able to directly send a `Bitmap` object between Tasks.\nThis is due to `Bitmap` internally caching a `CGContext` instance in order to increase performance and \nreduce the memory footprint.\n\nInternally, `Bitmap` keeps pixel information inside a `Bitmap.RGBAData` object which conforms to `Sendable`. \nThis object can be passed safely between tasks and are easily reconstituted into a new `Bitmap` object.\n\n```swift\nvar myBitmap = try Bitmap(...)\nlet bitmapData = myBitmap.bitmapData\n\n// Pass `bitmapData` to another Task\n\nvar myBitmap = try Bitmap(bitmapData)\n```\n\n--------\n\n# License\n\n```\nMIT License\n\nCopyright (c) 2025 Darren Ford\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fbitmap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdagronf%2Fbitmap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fbitmap/lists"}