生成 Code 39 条形码

4
我有这段代码来生成条形码:
func generateBarcode(from string: String) -> UIImage?
{
    let data = string.data(using: String.Encoding.ascii)
    if let filter = CIFilter(name: "CICode128BarcodeGenerator")
    {
        filter.setValue(data, forKey: "inputMessage")
        let transform = CGAffineTransform(scaleX: 3, y: 3)
        if let output = filter.outputImage?.transformed(by: transform)
        {
            return UIImage(ciImage: output)
        }
    }
    return nil
}

我需要生成Code39条形码。我没有找到"CICode128BarcodeGenerator"的Code 39等效物。

我该如何修改这段代码以生成Code 39条形码?

谢谢。


你有找到任何关于Code 39的资料吗? - Sunil Targe
这个回答解决了你的问题吗?使用CoreImage生成CI 39条形码 - Terry Burton
2个回答

2
如果我正确阅读了苹果文档,它们编码的类型如下:
Aztec
CheckerBoard
Code128
ConstantColor
LenticularHalo
PDF417Barcode
Random
Starshine
Stripes
Sunbeams

没有一个是我要找的插件,我正在为你寻找一个插件。我之前列出的那个不对。 - Jake
1
根据我所读到的,苹果没有原生提供 Code 39。 - Jake

0

仅限Code39示例。完整版本请查看RSBarcodes_Swift

import Foundation
import UIKit
import AVFoundation
import CoreImage

// http://www.barcodesymbols.com/code39.htm
// http://www.barcodeisland.com/code39.phtml
public final class Code39Generator {
    
    // Resize image
    private static func resizeImage(_ source: UIImage, targetSize: CGSize, contentMode: UIView.ContentMode) -> UIImage? {
        var x: CGFloat = 0
        var y: CGFloat = 0
        var width = targetSize.width
        var height = targetSize.height
        if contentMode == .scaleToFill { // contents scaled to fill
            // Nothing to do
        } else if contentMode == .scaleAspectFill { // contents scaled to fill with fixed aspect. some portion of content may be clipped.
            let targtLength = (targetSize.height > targetSize.width) ? targetSize.height : targetSize.width
            let sourceLength = (source.size.height < source.size.width) ? source.size.height : source.size.width
            let fillScale = targtLength / sourceLength
            width = source.size.width * fillScale
            height = source.size.height * fillScale
            x = (targetSize.width - width) / 2
            y = (targetSize.height - height) / 2
        } else { // contents scaled to fit with fixed aspect. remainder is transparent
            let scaledRect = AVMakeRect(aspectRatio: source.size, insideRect: CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height))
            width = scaledRect.width
            height = scaledRect.height
            if contentMode == .scaleAspectFit || contentMode == .redraw || contentMode == .center {
                x = (targetSize.width - width) / 2
                y = (targetSize.height - height) / 2
            } else if contentMode == .top {
                x = (targetSize.width - width) / 2
                y = 0
            } else if contentMode == .bottom {
                x = (targetSize.width - width) / 2
                y = targetSize.height - height
            } else if contentMode == .left {
                x = 0
                y = (targetSize.height - height) / 2
            } else if contentMode == .right {
                x = targetSize.width - width
                y = (targetSize.height - height) / 2
            } else if contentMode == .topLeft {
                x = 0
                y = 0
            } else if contentMode == .topRight {
                x = targetSize.width - width
                y = 0
            } else if contentMode == .bottomLeft {
                x = 0
                y = targetSize.height - height
            } else if contentMode == .bottomRight {
                x = targetSize.width - width
                y = targetSize.height - height
            }
        }
        
        UIGraphicsBeginImageContextWithOptions(targetSize, false, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.interpolationQuality = CGInterpolationQuality.none
        source.draw(in: CGRect(x: x, y: y, width: width, height: height))
        let target = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return target
    }
    
    private let CODE39_ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*"
    private let CODE39_CHARACTER_ENCODINGS = [
        "1010011011010",
        "1101001010110",
        "1011001010110",
        "1101100101010",
        "1010011010110",
        "1101001101010",
        "1011001101010",
        "1010010110110",
        "1101001011010",
        "1011001011010",
        "1101010010110",
        "1011010010110",
        "1101101001010",
        "1010110010110",
        "1101011001010",
        "1011011001010",
        "1010100110110",
        "1101010011010",
        "1011010011010",
        "1010110011010",
        "1101010100110",
        "1011010100110",
        "1101101010010",
        "1010110100110",
        "1101011010010",
        "1011011010010",
        "1010101100110",
        "1101010110010",
        "1011010110010",
        "1010110110010",
        "1100101010110",
        "1001101010110",
        "1100110101010",
        "1001011010110",
        "1100101101010",
        "1001101101010",
        "1001010110110",
        "1100101011010",
        "1001101011010",
        "1001001001010",
        "1001001010010",
        "1001010010010",
        "1010010010010",
        "1001011011010"
    ]
    
    private let BARCODE_DEFAULT_HEIGHT: CGFloat = 28
    private let fillColor: UIColor = UIColor.white
    private let strokeColor: UIColor = UIColor.black
    
    private func isValid(_ contents: String) -> Bool {
        guard !contents.isEmpty && !contents.contains("*") else { return false }
        return contents.allSatisfy({ CODE39_ALPHABET_STRING.contains($0) })
    }
    
    private func encodeCharacter(_ character: Character) -> String {
        guard let characterIndex: String.Index = CODE39_ALPHABET_STRING.firstIndex(of: character) else { return "" }
        let index: Int = CODE39_ALPHABET_STRING.distance(from: CODE39_ALPHABET_STRING.startIndex, to: characterIndex)
        return CODE39_CHARACTER_ENCODINGS[index]
    }
    
    private func barcode(_ contents: String) -> String {
        let initialCharacter = self.encodeCharacter("*")
        var barcode = initialCharacter
        for character in contents {
            barcode += self.encodeCharacter(character)
        }
        barcode += initialCharacter
        return barcode
    }
    
    // Drawer for completed barcode.
    private func drawCompleteBarcode(_ completeBarcode: String, targetSize: CGSize? = nil) -> UIImage? {
        guard !completeBarcode.isEmpty else { return nil }
        
        // Values taken from CIImage generated AVMetadataObjectTypePDF417Code type image
        // Top spacing          = 1.5
        // Bottom spacing       = 2
        // Left & right spacing = 2
        let width: CGFloat = CGFloat(completeBarcode.count + 4)
        // Calculate the correct aspect ratio, so that the resulting image can be resized to the target size
        var height = BARCODE_DEFAULT_HEIGHT
        if let targetSize = targetSize {
            height = ((targetSize.height / targetSize.width) * width).rounded()
        }
        let size = CGSize(width: width, height: height)
        UIGraphicsBeginImageContextWithOptions(size, false, 1)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.setShouldAntialias(false)
        
        self.fillColor.setFill()
        self.strokeColor.setStroke()
        
        context.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
        context.setLineWidth(1)
        
        for (i, character) in completeBarcode.enumerated() where character == "1" {
            let x: CGFloat = CGFloat(i + (2 + 1))
            context.move(to: CGPoint(x: x, y: 1.5))
            context.addLine(to: CGPoint(x: x, y: size.height - 2))
        }
        context.drawPath(using: CGPathDrawingMode.fillStroke)
        let barcode = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        if let targetSize = targetSize, let barcode = barcode {
            return Self.resizeImage(barcode, targetSize: targetSize, contentMode: UIView.ContentMode.bottomRight)
        }
        
        return barcode
    }
    
    public func generateCode(_ contents: String, targetSize: CGSize? = nil) -> UIImage? {
        guard self.isValid(contents) else { return nil }
        return self.drawCompleteBarcode(self.barcode(contents), targetSize: targetSize)
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接