在MacOS和Linux上使用ImageMagick,Vapor 3和Swift对照片加水印
回顾过去(您还记得Web 2.0吗?😉),我过去经常围绕照片进行编程。 在格式之间调整大小,缩放,旋转和转换。 最近,我不得不创建一个Web服务,该服务使用Vapor生成带水印的图像。 事实证明,还没有太多用于图像处理的库,因此这个简单的任务成为研究中一个有趣的问题。
有两个主要的图像处理库:GD和ImageMagick。 ImageMagick有点像高级库,所以我决定首先使用它。 ImageMagick有一个有趣的Swift包装器,称为MagickWand。 不幸的是,它根本不支持文本操作,因此我不得不更深入地研究。 我找不到任何有用的东西,所以我想:“为什么不在Swift中只使用一些ImageMagick C函数呢?”事实证明,这很容易做到!
安装ImageMagick
在ImageMagick网站的开发部分中,您可以找到MagickWand和MagickCore的文档。 这些是用C编写的用于与ImageMagick处理库进行交互的接口。 将其包装到Swift包中非常容易,但是首先让我们安装ImageMagick。
让我们从macOS开始。 您可以自己编译ImageMagick,但对于macOS,仅使用Homebrew会更容易。
➜brew安装imagemagick @ 6
如果未指定@6
,则默认情况下将安装最新版本。 我在Linux上的版本7遇到问题,因此我决定将macOS和Linux都使用旧版本。
安装后,您会注意到自制软件未创建符号链接(有关以下信息:仅桶依赖项)。 为了获得有关ImageMagick所需的信息,此部分很重要:
为了使pkg-config查找[受电子邮件保护],您可能需要设置:
导出PKG_CONFIG_PATH =“ / usr / local / opt / imagemagick @ 6 / lib / pkgconfig”
您可以只在终端中在每个pkg-config
命令之前添加PKG_CONFIG_PATH
,但是如果使用zsh只需运行,则永久添加它更容易:
➜echo'export PKG_CONFIG_PATH =“ / usr / local / opt / imagemagick @ 6 / lib / pkgconfig:$ PKG_CONFIG_PATH”'>>〜/ .zshrc
对于Linux,我使用的是带有Swift 4.2
Ubuntu 18.04
。 如果您已预先安装ImageMagick,最好在编译之前将其删除:
➜apt-get remove imagemagick && apt-get autoremove
您可以在此处获取ImageMagick软件包。
➜wget https://www.imagemagick.org/download/ImageMagick-6.9.10-12.tar.gz
➜tar xzvf ImageMagick-6.9.10-12.tar.gz
➜cd ImageMagick-6.9.10-12
在ImageMagick的源目录中运行:
➜./配置
配置完成后,请找到“ Delegate Library Configuration
”部分,并检查是否存在JPEG
和PNG support
。 如果在第三列上看不到no
,则可能没有必需的依赖项,例如libpng12-dev
和libjpeg-dev
。 您可以使用apt-get轻松安装它们。
如果配置正确,只需编译源代码:
➜使
并安装:
➜进行安装
要确认安装正确完成,请运行:
➜convert --version
如果看到此错误:
转换:加载共享库时出错:libMagickCore-6.Q16.so.6:无法打开共享库文件:没有这样的文件或目录
赶紧跑:
➜ldconfig / usr / local / lib /
已安装ImageMagick。 现在我们可以从有趣的部分开始
将ImageMagick包装为Swift包
要在Swift代码中使用ImageMagick
您需要将其包装到Swift系统模块包中。 通过公开头文件,您的Swift代码将能够使用所有ImageMagick
函数。
让我们开始创建一个名为SwiftImageMagick
的新目录,并使用Swift包管理器初始化新的Swift系统模块:
➜mkdir SwiftImageMagick
➜cd SwiftImageMagick
➜swift package init --type系统模块
打开module.modulemap
文件。 您应该看到SPM生成的代码:
模块SwiftImageMagick [system] {
标题“ /usr/include/SwiftImageMagick.h”
链接“ SwiftImageMagick”
出口 *
}
让我们先从macOS开始。 将模块的名称更改为SwiftImageMagick
> SwiftImageMagickMac
。
现在,为了告诉您如何编译和链接所有软件包,您需要使用pkg-config
工具。 您应该已经拥有它,如果不仅仅使用brew安装它:
➜brew安装pkg-config
如前所述,您需要设置PKG_CONFIG_PATH
以便pkg-config
可以找到ImageMagick
。
➜pkg-config --list-all | grep -i魔术师
您应该看到几个软件包:
➜〜pkg-config --list-all | grep -i魔术师
Magick ++ Magick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
Wand-6.Q16 MagickWand-MagickCore-ImageMagick的C API(ABI Q16)
ImageMagick ++ ImageMagick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
MagickWand MagickWand-MagickWand-用于ImageMagick的C API(ABI Q16)
ImageMagick ImageMagick-ImageMagick-转换,编辑和合成图像(ABI Q16)
MagickCore-6.Q16 MagickCore-MagickCore-ImageMagick的C API(ABI Q16)
Magick ++-6.Q16 Magick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
魔杖MagickWand-MagickCore-ImageMagick的C API(ABI Q16)
MagickWand-6.Q16 MagickWand-MagickWand-用于ImageMagick的C API(ABI Q16)
ImageMagick ++-6.Q16 ImageMagick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
ImageMagick-6.Q16 ImageMagick-ImageMagick-转换,编辑和合成图像(ABI Q16)
MagickCore MagickCore-MagickCore-ImageMagick的C API(ABI Q16)
查找ImageMagick
的头文件路径:
➜〜pkg-config --cflags-only-I MagickWand
-I/usr/local/Cellar/imagemagick@6/6.9.10-12/include/ImageMagick-6
在此目录/usr/local/Cellar/[email protected]/6.9.10-12/include/ImageMagick-6
您会找到/usr/local/Cellar/[email protected]/6.9.10-12/include/ImageMagick-6
标题: wand/MagickWand.h
和链接器标志:
➜〜pkg-config --libs MagickWand
-L/usr/local/Cellar/imagemagick@6/6.9.10-12/lib -lMagickWand-6.Q16 -lMagickCore-6.Q16
再次打开module.modulemap
,添加标题和链接:
模块SwiftImageMagickMac [系统] {
标题“ /usr/local/Cellar/imagemagick@6/6.9.10-12/include/ImageMagick-6/wand/MagickWand.h”
链接“ MagickWand-6.Q16”
链接“ MagickCore-6.Q16”
出口 *
}
让我们为Linux做同样的事情。 您还应该在Linux机器上安装pkg-config
,如果不仅仅使用:
➜apt-get install pkg-config
让我们检查一下pkg-config
看到的内容:
pkg-config --list-all | grep -i魔术师
root @ 8cc05b6015fc:〜#pkg-config --list-all | grep -i魔术师
Wand-6.Q16 MagickWand-MagickCore-ImageMagick的C API(ABI Q16)
ImageMagick ++-6.Q16 ImageMagick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
MagickWand-6.Q16 MagickWand-MagickWand-用于ImageMagick的C API(ABI Q16)
ImageMagick ImageMagick-ImageMagick-转换,编辑和合成图像(ABI Q16)
魔杖MagickWand-MagickCore-ImageMagick的C API(ABI Q16)
ImageMagick-6.Q16 ImageMagick-ImageMagick-转换,编辑和合成图像(ABI Q16)
MagickCore MagickCore-MagickCore-ImageMagick的C API(ABI Q16)
Magick ++-6.Q16 Magick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
MagickWand MagickWand-MagickWand-用于ImageMagick的C API(ABI Q16)
ImageMagick ++ ImageMagick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
Magick ++ Magick ++-Magick ++-用于ImageMagick的C ++ API(ABI Q16)
MagickCore-6.Q16 MagickCore-MagickCore-ImageMagick的C API(ABI Q16)
从标题开始:
root @ 8cc05b6015fc:〜#pkg-config --cflags-only-I MagickWand
-I / usr / local / include / ImageMagick-6
和链接器标志:
root @ 8cc05b6015fc:〜#pkg-config --libs MagickWand
-L / usr / local / lib -lMagickWand-6.Q16 -lMagickCore-6.Q16
在macOS部分下面的module.modulemap
中添加linux模块:
模块SwiftImageMagickMac [系统] {
标题“ /usr/local/Cellar/imagemagick@6/6.9.10-12/include/ImageMagick-6/wand/MagickWand.h”
链接“ MagickWand-6.Q16”
链接“ MagickCore-6.Q16”
出口 *
}
模块SwiftImageMagickLinux [系统] {
标题“ /usr/local/include/ImageMagick-6/wand/MagickWand.h”
链接“ MagickWand-6.Q16”
链接“ MagickCore-6.Q16”
出口 *
}
请记住从Package.swift
删除依赖项部分:
// swift-tools-version:4.2
// swift-tools-version声明构建此软件包所需的最低Swift版本。
导入PackageDescription
让包=包(
名称:“ SwiftImageMagick”
)
现在,一切就绪后,不要忘记创建git存储库并提交更改。
➜git init
➜git add。
➜git commit -m“初始提交”。
现在我们的包已经准备好了。 我们来用吧😄
如何在Swift中使用ImageMagick
现在,让我们创建一个简单的测试应用程序,该应用程序将导入ImageMagick库并创建一个用红色背景填充的100x100px图像,以确保我们的程序包可以正常工作。
➜mkdir MagicTest
➜cd MagicTest
➜swift软件包init --type可执行文件
创建可执行包:MagicTest
创建Package.swift
创建README.md
创建.gitignore
创建源/
创建Sources / MagicTest / main.swift
创建测试/
创建测试/LinuxMain.swift
创建测试/ MagicTestTests /
创建测试/MagicTestTests/MagicTestTests.swift
创建测试/MagicTestTests/XCTestManifests.swift
SPM将为您创建基本结构; --type executable
将告诉SPM创建命令行工具。
首先,您需要将SwiftImageMagick
添加为Package.swift
的依赖项。 您可以将其添加为本地git存储库的路径:
// swift-tools-version:4.2
// swift-tools-version声明构建此软件包所需的最低Swift版本。
导入PackageDescription
让包=包(
名称:“ MagicTest”,
依赖项:[
.package(URL:“ ../SwiftImageMagick”,.branch(“ master”)),
],
目标:[
。目标(
名称:“ MagicTest”,
依赖项:[]),
.testTarget(
名称:“ MagicTestTests”,
依赖项:[“ MagicTest”]),
]
)
编译它以确保您的依赖项可以访问:
Test MagicTest快速构建
抓取/用户/麦克/文档/项目/游乐场/ SwiftImageMagick
在0.35秒内完成分辨率
克隆/用户/麦克/文档/项目/游乐场/ SwiftImageMagick
解决主用户的/ Users / mike / Documents / projects / playground / SwiftImageMagick
'SwiftImageMagick'/Users/mike/Documents/projects/playground/MagicTest/.build/checkouts/SwiftImageMagick-2878331876767139303:警告:系统软件包已弃用; 改用系统库目标
编译Swift模块'MagicTest'(1源码)
链接./.build/x86_64-apple-macosx10.10/debug/MagicTest
如果您使用的是Swift 4.2
您还将看到以下内容: warning: system packages are deprecated; use system library targets instead
warning: system packages are deprecated; use system library targets instead
–这与系统库目标有关。
然后,在应用程序的主文件( ./Sources/MagicTest/main.swift
)中,删除所有内容并导入ImageMagick
库。
#if os(Linux)
导入SwiftImageMagickLinux
#其他
导入SwiftImageMagickMac
#万一
您可以使用Swift构建配置导入测试来判断您的程序是在Linux上还是在macOS上运行。
现在要编译该应用程序,还需要提供标题和链接器的路径,这与您上一次使用pkg-config
获得的路径相同。 检查是否还需要提供其他标志也是一个好主意:
Test MagicTest pkg-config --cflags-only-other ImageMagick
-DMAGICKCORE_HDRI_ENABLE = 0 -DMAGICKCORE_QUANTUM_DEPTH = 16
让我们把它们全部加起来:
➜swift build -Xswiftc -I/usr/local/Cellar/imagemagick@6/6.9.10-12/include/ImageMagick-6 -Xlinker -L/usr/local/Cellar/imagemagick@6/6.9.10-12/ lib -Xlinker -lMagickWand-6.Q16 -Xlinker -lMagickCore-6.Q16 -Xcc -DMAGICKCORE_HDRI_ENABLE = 0 -Xcc -DMAGICKCORE_QUANTUM_DEPTH = 16
抓取/用户/麦克/文档/项目/游乐场/ SwiftImageMagick
在0.35秒内完成分辨率
克隆/用户/麦克/文档/项目/游乐场/ SwiftImageMagick
解决主用户的/ Users / mike / Documents / projects / playground / SwiftImageMagick
'SwiftImageMagick'/Users/mike/Documents/projects/playground/MagicTest/.build/checkouts/SwiftImageMagick--9014361064470696861:警告:系统软件包已弃用; 改用系统库目标
编译Swift模块'MagicTest'(1源码)
链接./.build/x86_64-apple-macosx10.10/debug/MagicTest
成功! 😄库正在运行,现在让我们创建一个Xcode项目文件并添加一些代码。
➜swift包generate-xcodeproj
使用Xcode 10运行./MagicTest.xcodeproj
当您尝试使用Xcode进行编译时,您将看到与终端相同的错误:
实际上很容易修复。 只需打开构建设置并找到Header search path
并添加路径:
对Library search path
执行相同的操作:
不要忘记添加Other Swift Flags
:
按Cmd + R
,一切都应该编译并运行,没有任何警告。
当然,当您以后希望重新生成xcodeproj
时,所有这些更改都将消失。 您可以使用xcconfig
来存储它们,但请注意Xcode 10
存在一些奇怪的问题(雷达报告的错误)。
创建一个新文件: Package.xcconfig
LIBRARY_SEARCH_PATHS = / usr / local /地窖/imagemagick@6/6.9.10-12/lib
HEADER_SEARCH_PATHS = /usr/local/Cellar/imagemagick@6/6.9.10-12/include/ImageMagick-6
OTHER_SWIFT_FLAGS = -Xcc -DMAGICKCORE_HDRI_ENABLE = 0 -Xcc -DMAGICKCORE_QUANTUM_DEPTH = 16
然后生成xcode项目文件:
➜swift软件包generate-xcodeproj --xcconfig-覆盖Package.xcconfig
现在,该项目应编译而没有任何错误或警告。
当您的xcode项目正常工作时,请再次打开: Sources/MagicTest/main.swift
在ImageMagick import
下面,添加以下内容:
MagickWandGenesis()
让魔杖= NewMagickWand()
让像素= NewPixelWand()
MagickWandGenesis
初始化MagickWand环境。 完成工作后,还需要终止环境。 NewMagickWand
创建新的魔杖资源,该资源表示包含图像的结构。 NewPixelWand
创建负责颜色操纵的新像素棒。
PixelSetColor(像素,“红色”)
MagickSetBackgroundColor(wand,pixel)
PixelSetColor
将设置像素棒的颜色。 使用名称- "red"
,十六进制值#FF0000
或rbg- rgb(255,0,0)
。 如果将其另存为png,则甚至可以使用“透明”来制作透明背景。
现在,将颜色应用于魔杖后,只需创建一个新图像并将其保存:
MagickNewImage(wand,100,100,pixel)
MagickWriteImage(wand,“ test.jpg”)
您也可以提供图像的绝对路径,但是如果不这样做,请记住该文件将在Xcode DerivedData
目录中创建。
差不多完成了:只释放棒,像素的内存并终止环境:
摧毁魔杖(魔杖)
DestroyPixelWand(像素)
MagickWandTerminus()
现在运行该应用程序。 我已将整个示例应用程序上传到GitHub。
如果未提供文件的绝对路径,则可以打开“ Products
,选择程序名称,然后单击Show in Finder
。 您将在此处找到test.jpg
:
test.jpg
应该看起来像这样:
因此,ImageMagick正常工作。 让我们创建新的Vapor应用并添加水印文本😄
在这篇文章的开头,我以为我会创建一个用于图像处理的帮助程序库,但是这篇文章已经太长了,因此让我们保持简单并在Vapor中使用ImageMagick命令。 图像处理库将是下一篇文章的好话题
在蒸气中提供带水印的照片
这将非常简单,只需创建一个新的Vapor项目:
➜蒸气新的WatermarkPhotos
默认情况下, vapor new
将基于api模板创建一个项目。 现在,您需要添加ImageMagick
包装器依赖项。 如果Package.swift
文件中的Swift版本仍为3.0.0
,最好将Swift版本更新为4.2
并将Vapor更新为3.1.0
:
// swift-tools-version:4.2
导入PackageDescription
让包=包(
名称:“ WatermarkPhotos”,
依赖项:[
//💧服务器端Swift Web框架。
.package(URL:“ https://github.com/vapor/vapor.git”,来自:“ 3.1.0”),
//🔵基于SQLite 3构建的Swift ORM(查询,模型,关系等)
.package(网址:“ https://github.com/vapor/fluent-sqlite.git”,来自“ 3.0.0”),
//🎨ImageMagick包装器
.package(URL:“ https://github.com/mikina/SwiftImageMagick”,.branch(“ master”))
],
目标:[
.target(name:“ App”,依赖项:[“ FluentSQLite”,“ Vapor”]),
.target(name:“ Run”,依赖项:[“ App”]),
.testTarget(name:“ AppTests”,依赖项:[“ App”])
]
)
生成Xcode项目文件并打开它:
➜cd水印照片/
➜蒸气xcode -y
可能需要一段时间才能获取所有依赖项。
至此,您已经具备了入门所需的一切。 让我们编写一个非常简单的测试。 很难将图像与图像进行比较,因为这会使您的测试不稳定,所以我们只检查水印端点响应是否为:
- 返回状态码
200 .ok
- 内容类型设置为
image/jpeg
- 内容长度大于零
创建一个新的测试文件: /Tests/AppTests/PhotoTests.swift
导入XCTest
@testable进口蒸气
@testable导入应用
最终课程PhotoTests:XCTestCase {
}
不幸的是, Vapor 3.1
还没有用于测试的任何帮助程序,但是您可以使用一些用于测试Vapor本身的扩展。 你可以在这里找到。
创建一个新的测试助手: /Tests/AppTests/TestsHelper.swift
并复制此私有应用程序扩展。 不要忘记将其公开,以便其他测试可以看到它。 它应该看起来像这样。
现在回到PhotoTests.swift
并添加以下简单测试:
导入XCTest
@testable进口蒸气
@testable导入应用
最终课程PhotoTests:XCTestCase {
func testGetWatermakedPhoto()抛出{
让app =尝试Application.makeTest(路线:路线)
尝试app.test(.GET,“ / photos / show / barcelona”){在
XCTAssertEqual(response.http.status,.ok)
XCTAssertEqual(response.http.contentType,MediaType.jpeg)
让length = response.http.headers [“ content-length”]。first!
XCTAssertGreaterThan(Int(length)!, 0)
}
}
静态让allTests = [
(“ testGetWatermakedPhoto”,testGetWatermakedPhoto)
]
}
当然,此测试将立即失败,因为还没有光控器,因此让我们创建一个。
创建文件: /Sources/App/Controllers/PhotoController.swift
进口蒸气
进口基金会
最终课程PhotoController {
func show(_ req:Request)抛出->响应{
返回响应(使用:req)
}
}
另外,在/Sources/App/routes.swift
添加路由。
进口蒸气
///在这里注册您的应用程序的路由。
公共功能路由(_路由器:路由器)抛出{
//照片控制器
让photoController = PhotoController()
router.get(“ photos”,“ show”,String.parameter,使用:photoController.show)
}
如果您不熟悉路由,则String.parameter
意味着您可以在路由内部传递一个字符串值,它将在控制器内部用作请求参数。
您的照片网址如下所示:
http:// localhost:8080 / photos / show / barcelona
此时,它只是以一个空白页进行响应。 让我们回到/Sources/App/Controllers/PhotoController.swift
并添加一些代码。
在现实生活中的应用程序中,您需要将数据库中的照片列表和实际文件保存在外部存储(例如AWS
S3
中。 但是对于此演示,我们让它保持简单,只需在主项目目录中创建一个名为photos
新目录,然后在其中添加一些照片即可。
在PhotoController.swift
内部添加照片列表:
私人let photosList = [“ barcelona.jpg”,“ oslo.jpg”,“ porto.jpg”,“ rome.jpg”]
private let photosDirectory =“照片”
您可以从请求parameters
获取照片名称:
让名称=尝试req.parameters.next(String.self)
让filename = name.lowercased()。appending(“。jpg”)
只需检查文件是否在列表中:
保护photosList.contains(filename)else {
抛出Abort(.notFound,原因:“未找到照片”)
}
在将水印添加到照片之前,让我们从磁盘中加载水印并作为响应发送。
在Vapor 3.1中,存在DirectoryConfig结构,该结构可以帮助您获取工作目录的路径。
让目录= DirectoryConfig.detect()
让workingDirectory = URL(fileURLWithPath:directory.workDir)
警告:
当您将通过Xcode运行应用程序时,您需要做的一件事。 如果检查了DirectoryConfig,则可能会看到有一个用于目录检测的函数: detect()
。 有一个条件编译标志: #if Xcode
您需要在Active Compilation Conditions
定义它:
或者只是将其添加到Package.xcconfig
:
SWIFT_ACTIVE_COMPILATION_CONDITIONS [config = Debug] = Xcode
并生成xcodeproject
文件:
➜swift包generate-xcodeproj --xcconfig-overrides = Package.xcconfig
当然,它不会影响linux构建。
你快到了 现在,使用文件内容创建Data
并将其作为jpeg响应返回:
让数据=尝试数据(contentsOf:workingDirectory.appendingPathComponent(photosDirectory,isDirectory:true).appendingPathComponent(filename))
返回req.response(数据,如.jpeg)
PhotoController
将如下所示:
func show(_ req:Request)抛出->响应{
让名称=尝试req.parameters.next(String.self)
让filename = name.lowercased()。appending(“。jpg”)
保护photosList.contains(filename)else {
抛出Abort(.notFound,原因:“未找到照片”)
}
让目录= DirectoryConfig.detect()
让workingDirectory = URL(fileURLWithPath:directory.workDir)
让数据=尝试数据(contentsOf:workingDirectory.appendingPathComponent(photosDirectory,isDirectory:true).appendingPathComponent(filename))
返回req.response(数据,如.jpeg)
}
在Xcode中运行应用程序并打开url:
http:// localhost:8080 / photos / show / barcelona
现在是最后一步的时候了:添加水印。
创建模型文件: /Sources/App/Models/Photo.swift
像在示例项目中一样,导入Vapor,Foundation和ImageMagick标头:
#if os(Linux)
导入SwiftImageMagickLinux
#其他
导入SwiftImageMagickMac
#万一
进口蒸气
进口基金会
您可能会看到类似以下的错误:
找不到'magick / magick-config.h'文件
这与示例应用程序中的错误相同。 只需添加Package.xcconfig并重新生成xcode项目文件:
快速软件包generate-xcodeproj --xcconfig-overrides = Package.xcconfig
使用文件属性创建类Photo:
最终课程照片{
私人租赁文件:URL
init(文件:URL)引发{
保护FileManager.default.fileExists(atPath:file.path)else {
引发Abort(.internalServerError,原因:“找不到照片文件”)
}
self.file =文件
}
检查文件是否存在是个好主意,因为ImageMagick的错误报告并不总是最好的。
现在创建一个将返回带水印的照片的函数:
带水印的公共功能(字体:URL,文本:String)引发->数据{
保护FileManager.default.fileExists(atPath:font.path)else {
抛出Abort(.internalServerError,原因:“找不到字体文件”)
}
它使用将使用的字体文件的URL和输入的水印文本。
准备魔术堆栈:
MagickWandGenesis()
让魔杖= NewMagickWand()
让像素= NewPixelWand()
让draw = NewDrawingWand()
我已经描述了那些方法。 这里的新功能是绘图棒:它将用于在图像上绘图,或者在这种情况下将水印文本附加到图像上。
将图像加载到Magick Wand中:
MagickReadImage(wand,file.path)
并准备绘图棒:
PixelSetColor(像素,“白色”)
DrawSetFillColor(绘制像素)
DrawSetFont(draw,font.path)
DrawSetFontSize(draw,70)
DrawSetGravity(draw,CenterGravity)
DrawAnnotation(draw,0,0,text)
这很简单。 像素棒被设置为白色并附着在绘图棒上。 字体,重力参数和大小也应用于绘图棒。 DrawAnnotation
将水印文本附加到绘图棒。
这里值得一提的是您可以设置不同的重力。 重力告诉ImageMagick它应该在哪里放置图形,因此您不必计算它。 使用CenterGravity
将在图像的中心绘制水印文本。 将其设置为SouthWestGravity
将在左下角绘制水印。 无需手动计算边界框和在屏幕上的位置。
画水印文字:
MagickDrawImage(想要绘制)
您还需要在获取数据之前设置图像格式和压缩质量:
MagickSetImageCompressionQuality(wand,85)
MagickSetImageFormat(wand,“ jpg”)
要从ImageMagick获取数据,只需调用MagickGetImageBlob
:
var length = 0
保护卫队形象= MagickGetImageBlob(wand,&length)else {
引发Abort(.internalServerError,原因:“无法从ImageMagick获取图像。”)
}
MagickGetImageBlob
将返回UnsafeMutablePointer
,您要做的就是使用bytes
创建Data
:
让数据=数据(字节:图像,计数:长度)
不要忘记清理并返回数据:
摧毁魔杖(魔杖)
DestroyPixelWand(像素)
DestroyDrawingWand(绘制)
MagickRelinquishMemory(图像)
MagickWandTerminus()
返回数据
您的模型现在一切都很好。 让我们回到控制器并使用它。
在使用模型之前,您需要下载将用于创建水印的字体。 您可以从GoogleFont
库中获得许多不同的字体。 我正在使用Open Sans。 只需下载ttf文件,然后将其放在项目内的fonts目录中即可。
在PhotoController.swift
,添加字体目录的属性和水印文本的属性:
最终课程PhotoController {
私人let photosList = [“ barcelona.jpg”,“ oslo.jpg”,“ porto.jpg”,“ rome.jpg”]
private let photosDirectory =“照片”
private let fontsDirectory =“字体”
私人let watermarkText =“ ImageMagick \ nVapor”
在show(_ req: Request)
函数中,用您的Photo模型替换当前加载的照片:
让文件= workingDirectory.appendingPathComponent(photosDirectory,isDirectory:true).appendingPathComponent(filename)
让字体= workingDirectory.appendingPathComponent(fontsDirectory,isDirectory:true).appendingPathComponent(“ OpenSans-Regular.ttf”)
让照片=尝试照片(文件:文件)
let watermarkedPhoto =试试photo.watermarked(with:font,and:watermarkText)
整个PhotoController
应该看起来像这样。
现在,在Xcode中运行该应用程序,然后再次打开该URL:
http:// localhost:8080 / photos / show / barcelona
当我最近尝试在Vapor
项目中使用ImageMagick
时,我花了几个小时试图弄清楚如何将ImageMagick
设置并包装到Swift包中。 文件丢失和链接器错误有很多问题。 解决了所有这些问题之后,使用ImageMagick
变得非常简单明了
我们从这里去哪里?
我强烈建议您与ImageMagick
一起玩。 您可以创建一个非常方便且量身定制的库,可以在Vapor
项目中重复使用。
如果您还没有尝试过,也应该尝试在Linux上运行它。 我正在使用Docker
进行开发,我将在下一篇博客文章中介绍如何在Vapor
上使用它。
你觉得这个怎样? 您是否已经尝试将ImageMagick与Vapor结合使用? 您遇到任何问题了吗? 在Twitter @mikemikina 上让我知道您的问题,评论或反馈
快乐编码😊
最初发布于 mikemikina.com 。