TinySwiftJPEG

TinyJPEG 库的简单 Swift 封装。

它使接口非常 Swifty,示例可见

// this is all just generating simple, raw image data
let imageDimensions = (x: 1275, y: 800)
let imageRowStride = 1280 * 4

func offset(for point: Point, channelCount: Int) -> Int {
	(point.y * imageRowStride) + point.x * channelCount
}

let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: imageRowStride * imageDimensions.y, alignment: 32)
for y in 0..<imageDimensions.y {
	for x in 0..<imageDimensions.x {
		let redIndex = offset(for: (x, y), channelCount: 4)

		let red = (Double(x) / Double(imageDimensions.x)) * 255
		let green = (Double(y) / Double(imageDimensions.y)) * 255
		let blue = 255 - red

		buffer[redIndex] = UInt8(red)
		buffer[redIndex + 1] = UInt8(green)
		buffer[redIndex + 2] = UInt8(blue)
		buffer[redIndex + 3] = 255
	}
}

let pixelData = Data(bytesNoCopy: buffer.baseAddress!, count: buffer.count, deallocator: .free)

// now that that's done (you'll probably get this from CoreGraphics or any other library
providing raw, 8 bits/channel RGB or RGBA interleaved data), here's the actual magic:

let jpeg = try TinySwiftJPEG.encodeJPEG( // this is the actual magic
	from: pixelData,
	rowStride: imageRowStride,
	width: imageDimensions.x,
	height: imageDimensions.y,
	channels: .rgba)

try jpeg.write(to: URL(filePath: "/path/to/output.jpg")

我对 TinyJPEG 库做了一个小的修改,以便支持与简单的 width * channelCount 不同的每行字节数(通道计数取决于 alpha 通道,可以是 3 或 4),因为这在 CoreGraphics 中(以及可能在其他地方)是很常见的情况。这样应该能为我们节省一次不必要的字节复制!