You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
3.3 KiB

import SwiftUI
import CoreImage
import CoreImage.CIFilterBuiltins
// MARK: -
struct BarcodePreviewView: View {
let content: String
let barcodeType: BarcodeType
var body: some View {
Group {
if let barcodeImage = generateBarcodeImage() {
Image(uiImage: barcodeImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)
.background(Color.white)
.cornerRadius(8)
.shadow(color: .black.opacity(0.1), radius: 2, x: 0, y: 1)
} else {
//
VStack(spacing: 8) {
Image(systemName: "barcode.viewfinder")
.font(.system(size: 32))
.foregroundColor(.gray)
Text("无法生成条形码")
.font(.caption)
.foregroundColor(.gray)
Text("请检查输入内容格式")
.font(.caption2)
.foregroundColor(.gray)
}
.frame(maxWidth: .infinity)
.frame(height: 120)
.background(Color(.systemGray5))
.cornerRadius(8)
}
}
}
// MARK: -
private func generateBarcodeImage() -> UIImage? {
guard !content.isEmpty else { return nil }
let context = CIContext()
let filter: CIFilter?
//
switch barcodeType {
case .ean13, .ean8, .upce, .itf14:
filter = CIFilter.code128BarcodeGenerator()
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
case .code39:
// Code 39 使 Code 128 Core Image Code 39
filter = CIFilter.code128BarcodeGenerator()
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
case .code128:
filter = CIFilter.code128BarcodeGenerator()
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
case .pdf417:
filter = CIFilter.pdf417BarcodeGenerator()
filter?.setValue(content.data(using: .utf8), forKey: "inputMessage")
}
guard let filter = filter,
let outputImage = filter.outputImage else { return nil }
//
let scale = CGAffineTransform(scaleX: 3, y: 3)
let scaledImage = outputImage.transformed(by: scale)
// UIImage
guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else {
return nil
}
return UIImage(cgImage: cgImage)
}
}
#Preview {
VStack(spacing: 20) {
BarcodePreviewView(content: "1234567890123", barcodeType: .ean13)
BarcodePreviewView(content: "12345678", barcodeType: .ean8)
BarcodePreviewView(content: "CODE39", barcodeType: .code39)
BarcodePreviewView(content: "123456789012345678901234567890", barcodeType: .pdf417)
}
.padding()
}