这是一个用于 libgd 的简单 Swift 封装,允许在服务器端 Swift 上进行基本的图形渲染,而服务器端 Swift 通常无法使用 Core Graphics。 虽然这个包最初是为了配合我的书《Server-Side Swift》而编写的,但对于任何希望在其服务器上执行图像操作的人来说,它也可能具有普遍用途。
SwiftGD 将 GD 封装在类中,使其更易于使用,并提供以下功能:
SwiftGD 为您管理 GD 资源,因此当您的图像被销毁时,底层内存会被释放。
在您的计算机上安装 GD 库。如果您使用的是 macOS,请安装 Homebrew,然后运行命令 brew install gd
。如果您使用的是 Linux,请以 root 身份运行 apt-get libgd-dev
。
修改您的 Package.swift 文件以包含以下依赖项
.package(url: "https://github.com/twostraws/SwiftGD.git", from: "2.0.0")
您还应该在您的目标依赖项列表中包含 “SwiftGD”。
SwiftGD 本身只有一个 Swift 依赖项,即 Cgd。
SwiftGD 提供了四个类用于基本图像操作
Image
负责加载、保存和操作图像数据。Point
将 x
和 y
坐标存储为整数。Size
存储 width
和 height
整数。Rectangle
将 Point
和 Size
组合成一个值。Color
提供红色、绿色、蓝色和 alpha 分量,存储为 0 到 1 的 Double
值,以及一些内置颜色供您入门。这些被实现为类而不是结构体,因为只有类具有析构器。这些是必需的,以便在图像被销毁时可以清理 GD 的内存。
您可以像这样从磁盘加载图像
let location = URL(fileURLWithPath: "/path/to/image.png")
let image = Image(url: location)
这将返回一个可选的 Image
对象,如果加载因某种原因失败,则该对象将为 nil
。SwiftGD 使用文件扩展名来加载正确的文件格式,因此请务必使用 “jpg”、“jpeg” 或 “png” 命名您的文件。
您还可以通过提供宽度和高度从头开始创建新图像,如下所示
let image = Image(width: 500, height: 500)
同样,如果内存分配正确,这将返回一个可选的 Image
。
您甚至可以从 Data
实例创建图像
let data: Data = ... // e.g. from networking request
let image = try Image(data: data, as: .png)
如果 data
实际上不是图像数据表示形式或与给定的栅格格式(在本例中为 .png
)不匹配,这将抛出一个 Error
。如果您省略栅格格式,将评估所有支持的栅格格式,如果任何格式匹配,将返回一个 Image
(注意,这可能需要更长的时间)。
当您想将图像保存回磁盘时,请使用 Image
上的 write(to:)
方法,如下所示
let url = URL(fileURLWithPath: "/path/to/save.jpg")
image.write(to: url)
同样,格式由您选择的文件扩展名决定。如果文件已存在,write(to:)
将返回 false 并拒绝继续;如果文件保存成功,它将返回 true。
您还可以将图像导出为具有特定图像栅格格式的 Data
表示形式,如下所示
let image = Image(width: 500, height: 500)
image?.fill(from: .zero, color: .red)
let data = try image?.export(as: .png)
这将返回一个 500x500px 大小的红色 PNG 图像的数据表示形式。
当执行调整大小或裁剪操作时也会创建图像,这意味着您的原始图像不会被触及。 您有三种调整大小的选项:
resizedTo(width:height:)
允许您将图像拉伸到任何尺寸。resizedTo(width:)
将图像调整为特定宽度,并计算正确的height以保持原始宽高比。resizedTo(height:)
将图像调整为特定高度,并计算正确的宽度以保持原始宽高比。所有这三个方法都有一个可选的额外参数 applySmoothing
。当设置为 true(默认值)时,调整大小使用双线性滤波器执行。当为 false 时,调整大小使用最近邻插值执行,结果可能看起来有锯齿。
要裁剪图像,请调用其 cropped(to:)
方法,传入指定裁剪原点和大小的 Rectangle
。
您可以使用九种方法在图像中进行绘制
fill(from:color:)
使用您指定的 Color
从图像上的 Point
执行颜色填充。drawLine(from:to:color:)
在 to
和 from
参数(均为 Point
的实例)之间用您指定的 Color
绘制一条线。drawImage(_:at:)
在指定的 Point
处(如果省略 at
,则默认为左上角)绘制 Image
。set(pixel:to:)
将特定 Point
处的像素设置为您指定的 Color
。get(pixel:)
返回特定 Point
处像素的 Color
值。strokeEllipse(center:size:color:)
在中心 Point
处绘制一个空心椭圆,使用您指定的 Size
和 Color
。func fillEllipse(center:size:color:)
在中心 Point
处填充一个实心椭圆,使用您指定的 Size
和 Color
。strokeRectangle(topLeft:bottomRight:color:)
使用您指定的 Color
从 topLeft
到 bottomRight
(均为 Point
的实例)绘制一个空心矩形。fillRectangle(topLeft:bottomRight:color:)
使用您指定的 Color
从 topLeft
到 bottomRight
(均为 Point
的实例)填充一个实心矩形。有几种方法可以将滤镜应用于图像对象
pixelate(blockSize:)
将您的图像简化为大像素,像素大小由您作为 blockSize
提供的整数决定。blur(radius:)
应用高斯模糊效果。半径值越大,模糊效果越强。colorize(using:)
使用您指定的 Color
应用色调。desaturate()
将您的图像渲染为灰度。flip(_:)
水平、垂直或同时翻转您的图像。传递 .horizontal
、.vertical
或 .both
作为其参数。第一个示例创建一个新的 500x500 图像,填充红色,在中心绘制一个蓝色椭圆,在顶部绘制一个绿色矩形,运行去饱和和着色滤镜,并将结果图像保存为 “output-1.png”
import Foundation
import SwiftGD
// figure out where to save our file
let currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)
let destination = currentDirectory.appendingPathComponent("output-1.png")
// attempt to create a new 500x500 image
if let image = Image(width: 500, height: 500) {
// flood from from X:250 Y:250 using red
image.fill(from: Point(x: 250, y: 250), color: Color.red)
// draw a filled blue ellipse in the center
image.fillEllipse(center: Point(x: 250, y: 250), size: Size(width: 150, height: 150), color: Color.blue)
// draw a filled green rectangle also in the center
image.fillRectangle(topLeft: Point(x: 200, y: 200), bottomRight: Point(x: 300, y: 300), color: Color.green)
// remove all the colors from the image
image.desaturate()
// now apply a dark red tint
image.colorize(using: Color(red: 0.3, green: 0, blue: 0, alpha: 1))
// save the final image to disk
image.write(to: destination)
}
第二个示例绘制交替蓝白色的同心矩形,然后对结果应用高斯模糊
import Foundation
import SwiftGD
let currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)
let destination = currentDirectory.appendingPathComponent("output-2.png")
if let image = Image(width: 500, height: 500) {
var counter = 0
for i in stride(from: 0, to: 250, by: 10) {
let drawColor: Color
if counter % 2 == 0 {
drawColor = .blue
} else {
drawColor = .white
}
image.fillRectangle(topLeft: Point(x: i, y: i), bottomRight: Point(x: 500 - i, y: 500 - i), color: drawColor)
counter += 1
}
image.blur(radius: 10)
image.write(to: destination)
}
第三个示例通过在嵌套循环中设置单个像素来创建黑色、红色、绿色和黄色渐变
import Foundation
import SwiftGD
let currentDirectory = URL(fileURLWithPath: FileManager().currentDirectoryPath)
let destination = currentDirectory.appendingPathComponent("output-3.png")
let size = 500
if let image = Image(width: size, height: size) {
for x in 0 ... size {
for y in 0 ... size {
image.set(pixel: Point(x: x, y: y), to: Color(red: Double(x) / Double(size), green: Double(y) / Double(size), blue: 0, alpha: 1))
}
}
image.write(to: destination)
}
本软件包根据 MIT 许可证发布,许可证内容如下。
版权所有 (c) 2017 Paul Hudson
特此授予任何人免费获得本软件及相关文档文件(“软件”)副本的许可,以便在不受限制的情况下处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售本软件副本的权利,并允许向接受本软件的人员提供本软件,但须符合以下条件
上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
本软件按“原样”提供,不提供任何形式的明示或暗示保证,包括但不限于适销性、特定用途适用性和非侵权保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中,因本软件或本软件的使用或其他交易而产生、产生或与之相关的任何索赔、损害或其他责任。