{"id":1991,"url":"https://github.com/twostraws/swiftgd","last_synced_at":"2025-04-07T14:11:01.362Z","repository":{"id":39880280,"uuid":"74604687","full_name":"twostraws/SwiftGD","owner":"twostraws","description":"A simple Swift wrapper for libgd","archived":false,"fork":false,"pushed_at":"2024-09-19T10:45:19.000Z","size":123,"stargazers_count":460,"open_issues_count":14,"forks_count":75,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-03-31T13:15:23.148Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/twostraws.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":"2016-11-23T18:44:59.000Z","updated_at":"2025-03-24T14:02:21.000Z","dependencies_parsed_at":"2024-01-07T22:23:42.532Z","dependency_job_id":"561c75f3-37c8-41fa-a025-7453d63c76cd","html_url":"https://github.com/twostraws/SwiftGD","commit_stats":{"total_commits":72,"total_committers":16,"mean_commits":4.5,"dds":0.7638888888888888,"last_synced_commit":"07650dcb343d5b045598459fd3aad0936e0259bf"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twostraws%2FSwiftGD","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twostraws%2FSwiftGD/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twostraws%2FSwiftGD/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twostraws%2FSwiftGD/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twostraws","download_url":"https://codeload.github.com/twostraws/SwiftGD/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247666008,"owners_count":20975787,"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":[],"created_at":"2024-01-05T20:16:00.680Z","updated_at":"2025-04-07T14:11:01.339Z","avatar_url":"https://github.com/twostraws.png","language":"Swift","funding_links":[],"categories":["Server"],"sub_categories":["Keychain","Other free courses"],"readme":"# SwiftGD\n\nThis is a simple Swift wrapper for libgd, allowing for basic graphic rendering on server-side Swift where Core Graphics is not available. Although this package was originally written to accompany my book [Server-Side Swift](https://www.hackingwithswift.com/store/server-side-swift), it's likely to be of general use to anyone wishing to perform image manipulation on their server.\n\nSwiftGD wraps GD inside classes to make it easier to use, and provides the following functionality:\n\n- Loading PNGs and JPEGs from disk.\n- Writing images back to disk as PNG or JPEG.\n- Creating new images at a specific width and height.\n- Resizing to a specific width or height.\n- Cropping at a location and size.\n- Flood filling a color from a coordinate.\n- Drawing lines\n- Drawing images\n- Reading and writing individual pixels.\n- Stroking and filling ellipses and rectangles.\n- Flipping images horizontally and vertically.\n- Basic effects: pixelate, blur, colorize, and desaturate.\n\nSwiftGD manages GD resources for you, so the underlying memory is released when your images are destroyed.\n\n\n## Installation\n\nInstall the GD library on your computer. If you're using macOS, install [Homebrew](http://brew.sh/) then run the command `brew install gd`. If you're using Linux, run `apt-get libgd-dev` as root.\n\nModify your Package.swift file to include the following dependency:\n\n    .package(url: \"https://github.com/twostraws/SwiftGD.git\", from: \"2.0.0\")\n\nYou should also include “SwiftGD” in your list of target dependencies.\n\nSwiftGD itself has a single Swift dependency, which is [Cgd](https://github.com/twostraws/Cgd.git).\n\n\n## Classes\n\nSwiftGD provides four classes for basic image operations:\n\n- `Image` is responsible for loading, saving, and manipulating image data.\n- `Point` stores `x` and `y` coordinates as integers.\n- `Size` stores `width` and `height` integers.\n- `Rectangle` combines `Point` and `Size` into one value.\n- `Color` provides red, green, blue, and alpha components stored in a `Double` from 0 to 1, as well as some built-in colors to get you started.\n\nThese are implemented as classes rather than structs because only classes have deinitializers. These are required so that GD's memory can be cleaned up when an image is destroyed.\n\n\n## Reading and writing images\n\nYou can load an image from disk like this:\n\n```swift\nlet location = URL(fileURLWithPath: \"/path/to/image.png\")\nlet image = Image(url: location)\n```\n\nThat will return an optional `Image` object, which will be `nil` if the load failed for some reason. SwiftGD uses the file extension to load the correct file format, so it's important you name your files with \"jpg\", \"jpeg\", or \"png\".\n\nYou can also create new images from scratch by providing a width and height, like this:\n\n```swift\nlet image = Image(width: 500, height: 500)\n```\n\nAgain, that will return an optional `Image` if the memory was allocated correctly.\n\nYou can even create an image from `Data` instances:\n\n```swift  \nlet data: Data = ... // e.g. from networking request\nlet image = try Image(data: data, as: .png)\n```\n\nThis will throw an `Error` if `data` is not actual an image data representation or does not match given raster format (`.png` in this case). If you omit the raster format, all supported raster formats will be evaluated and an `Image` will be returned if any matches (caution, this may take significantly longer).\n\nWhen you want to save an image back to disk, use the `write(to:)` method on `Image`, like this:\n\n```swift\nlet url = URL(fileURLWithPath: \"/path/to/save.jpg\")\nimage.write(to: url)\n```\n\nAgain, the format is determined by your choice of file extension. `write(to:)` will return false and refuse to continue if the file exists already; it will return true if the file was saved successfully.\n\nYou can also export images as `Data` representations with certain image raster format, like so:\n\n```swift  \nlet image = Image(width: 500, height: 500)\nimage?.fill(from: .zero, color: .red)\nlet data = try image?.export(as: .png)\n```\n\nThis will return the data representation of a red PNG image with 500x500px in size.\n\nImages are also created when performing a resize or crop operation, which means your original image is untouched. You have three options for resizing:\n\n- `resizedTo(width:height:)` lets you stretch an image to any dimensions.\n- `resizedTo(width:)` resizes an image to a specific width, and calculates the correct height to maintain the original aspect ratio.\n- `resizedTo(height:)` resizes an image to a specific height, and calculates the correct width to maintain the original aspect ratio.\n\nAll three have an optional extra parameter, `applySmoothing`. When set to true (the default) the resize is performed using bilinear filter. When false, the resize is performed using nearest neighbor, and the result is likely to look jagged.\n\nTo crop an image, call its `cropped(to:)` method, passing in the `Rectangle` that specifies the crop origin and size.\n\n\n\n## Drawing shapes, colors and images\n\nThere are nine methods you can use to draw into your images:\n\n- `fill(from:color:)` performs a flood fill from a `Point` on your image using the `Color` you specify.\n- `drawLine(from:to:color:)` draws a line between the `to` and `from` parameters (both instances of `Point`) in the `Color` you specify.\n- `drawImage(_:at:)` draws an `Image` at the specified `Point` (or just top left if `at` is omitted).\n- `set(pixel:to:)` sets a pixel at a specific `Point` to the `Color` you specify.\n- `get(pixel:)` returns the `Color` value of a pixel at a specific `Point`.\n- `strokeEllipse(center:size:color:)` draws an empty ellipse at the center `Point`, with the `Size` and `Color` you specify.\n- `func fillEllipse(center:size:color:)` fills an ellipse at the center `Point`, with the `Size` and `Color` you specify.\n- `strokeRectangle(topLeft:bottomRight:color:)` draws an empty rectangle from `topLeft` to `bottomRight` (both instances of `Point`) using the `Color` you specify.\n- `fillRectangle(topLeft:bottomRight:color:)` fills a rectangle from `topLeft` to `bottomRight` (both instances of `Point`) using the `Color` you specify.\n\n\n## Manipulating images\n\nThere are several methods that apply filters to image objects:\n\n- `pixelate(blockSize:)` simplifies your image to large pixels, with the pixel size dictated by the integer you provide as `blockSize`.\n- `blur(radius:)` applies a Gaussian blur effect. Using a larger value for radius causes stronger blurs.\n- `colorize(using:)` applies a tint using a `Color` you specify.\n- `desaturate()` renders your image grayscale.\n- `flip(_:)` flips your image horizontally, vertically, or both. Pass `.horizontal`, ``vertical`, or `.both` as its parameter.\n\n\n\n## Example code\n\nThis first example creates a new 500x500 image, fills it red, draw a blue ellipse in the center, draws a green rectangle on top, runs the desaturate and colorize filters, and saves the resulting image to \"output-1.png\":\n\n```swift\nimport Foundation\nimport SwiftGD\n\n// figure out where to save our file\nlet currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)\nlet destination = currentDirectory.appendingPathComponent(\"output-1.png\")\n\n// attempt to create a new 500x500 image\nif let image = Image(width: 500, height: 500) {\n    // flood from from X:250 Y:250 using red\n    image.fill(from: Point(x: 250, y: 250), color: Color.red)\n\n    // draw a filled blue ellipse in the center\n    image.fillEllipse(center: Point(x: 250, y: 250), size: Size(width: 150, height: 150), color: Color.blue)\n        \n    // draw a filled green rectangle also in the center\n    image.fillRectangle(topLeft: Point(x: 200, y: 200), bottomRight: Point(x: 300, y: 300), color: Color.green)\n\n    // remove all the colors from the image\n    image.desaturate()\n        \n    // now apply a dark red tint\n    image.colorize(using: Color(red: 0.3, green: 0, blue: 0, alpha: 1))\n        \n    // save the final image to disk\n    image.write(to: destination)\n}\n```\n\nThis second examples draws concentric rectangles in alternating blue and white colors, then applies a Gaussian blur to the result:\n\n```swift\nimport Foundation\nimport SwiftGD\n\nlet currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)\nlet destination = currentDirectory.appendingPathComponent(\"output-2.png\")\n\nif let image = Image(width: 500, height: 500) {\n    var counter = 0\n        \n    for i in stride(from: 0, to: 250, by: 10) {\n        let drawColor: Color\n        \n        if counter % 2 == 0 {\n            drawColor = .blue\n        } else {\n            drawColor = .white\n        }\n        \n        image.fillRectangle(topLeft: Point(x: i, y: i), bottomRight: Point(x: 500 - i, y: 500 - i), color: drawColor)\n        counter += 1\n    }\n\n    image.blur(radius: 10)\n    image.write(to: destination)\n}\n```\n\nThis third example creates a black, red, green, and yellow gradient by setting individual pixels in a nested loop:\n\n```swift\nimport Foundation\nimport SwiftGD\n\nlet currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)\nlet destination = currentDirectory.appendingPathComponent(\"output-3.png\")\n\nlet size = 500\n\nif let image = Image(width: size, height: size) {\n    for x in 0 ... size {\n        for y in 0 ... size {\n            image.set(pixel: Point(x: x, y: y), to: Color(red: Double(x) / Double(size), green: Double(y) / Double(size), blue: 0, alpha: 1))\n        }\n    }\n        \n    image.write(to: destination)\n}\n```\n\n\n## License\n\nThis package is released under the MIT License, which is copied below.\n\nCopyright (c) 2017 Paul Hudson\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwostraws%2Fswiftgd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwostraws%2Fswiftgd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwostraws%2Fswiftgd/lists"}