Optimize images with ImageOptim

This commit is contained in:
Christoph Hagen 2022-11-30 15:29:51 +01:00
parent 58f7642ca5
commit 4c2c4b7dd3

View File

@ -18,6 +18,10 @@ private struct ImageJob {
final class ImageGenerator { final class ImageGenerator {
private let imageOptimSupportedFileExtensions: Set<String> = ["jpg", "png", "svg"]
private let imageOptimizationBatchSize = 50
/** /**
The path to the input folder. The path to the input folder.
*/ */
@ -66,6 +70,11 @@ final class ImageGenerator {
*/ */
private var generatedImages: Set<String> = [] private var generatedImages: Set<String> = []
/**
The images optimized by ImageOptim
*/
private var optimizedImages: Set<String> = []
/** /**
A cache to get the size of source images, so that files don't have to be loaded multiple times. A cache to get the size of source images, so that files don't have to be loaded multiple times.
@ -182,8 +191,9 @@ final class ImageGenerator {
create(images: jobs, from: source) create(images: jobs, from: source)
count += 1 count += 1
} }
print(String(format: " \r", count, imageJobs.count), terminator: "") print(" \r", terminator: "")
createMultiImages() createMultiImages()
optimizeImages()
printMissingImages() printMissingImages()
printImageWarnings() printImageWarnings()
printGeneratedImages() printGeneratedImages()
@ -360,7 +370,7 @@ final class ImageGenerator {
createMultiImages(from: baseImage, path: path) createMultiImages(from: baseImage, path: path)
count += 1 count += 1
} }
print(String(format: " \r", count, sort.count), terminator: "") print(" \r", terminator: "")
} }
private func createMultiImages(from source: String, path: String) { private func createMultiImages(from source: String, path: String) {
@ -414,4 +424,33 @@ final class ImageGenerator {
addWarning("Failed to compress image", destination: destination, path: destination) addWarning("Failed to compress image", destination: destination, path: destination)
} }
} }
private func optimizeImages() {
let all = generatedImages
.filter { imageOptimSupportedFileExtensions.contains($0.lastComponentAfter(".")) }
.map { output.appendingPathComponent($0).path }
for i in stride(from: 0, to: all.count, by: imageOptimizationBatchSize) {
let endIndex = min(i+imageOptimizationBatchSize, all.count)
let batch = all[i..<endIndex]
print(String(format: "Optimizing images: %4d / %d\r", endIndex, all.count), terminator: "")
fflush(stdout)
if optimizeImageBatch(batch) {
optimizedImages.formUnion(batch)
}
}
print(" \r", terminator: "")
fflush(stdout)
print("\(optimizedImages.count) images optimized")
}
private func optimizeImageBatch(_ batch: ArraySlice<String>) -> Bool {
let command = "imageoptim " + batch.joined(separator: " ")
do {
_ = try FileSystem.safeShell(command)
return true
} catch {
addWarning("Failed to optimize images", destination: "", path: "")
return false
}
}
} }