【问题标题】:How can I generate a barcode from a string in Swift?如何从 Swift 中的字符串生成条形码?
【发布时间】:2015-04-17 00:17:12
【问题描述】:

我是一名新的 iOS 开发人员。我想知道如何在 Swift 中生成条形码。

我已经有了代码,有多种资源可以从中学习如何读取条形码,但我没有找到任何关于从字符串生成条形码的资源。

非常感谢!

附:我知道有一个类似的问题,但它是针对 Objective-C 的。我不了解 Obj-C,而且我发现来自 .NET 很困难。

【问题讨论】:

    标签: ios swift barcode core-image


    【解决方案1】:

    您可以使用 CoreImage (import CoreImage) 过滤器来做到这一点!

        class Barcode {
            class func fromString(string : String) -> UIImage? {
                 let data = string.data(using: .ascii)
                 if let filter = CIFilter(name: "CICode128BarcodeGenerator") {
                      filter.setValue(data, forKey: "inputMessage")
                      if let outputCIImage = filter.outputImage {
                           return UIImage(ciImage: outputCIImage)
                      }
                 }
                 return nil
            }
        }
    
        let img = Barcode.fromString("whateva")
    

    较新的版本,带有guard 和可失败的初始化程序:

    extension UIImage {
    
        convenience init?(barcode: String) {
            let data = barcode.data(using: .ascii)
            guard let filter = CIFilter(name: "CICode128BarcodeGenerator") else {
                return nil
            }
            filter.setValue(data, forKey: "inputMessage")
            guard let ciImage = filter.outputImage else {
                return nil
            }
            self.init(ciImage: ciImage)
        }
    
    }
    

    用法:

    let barcode = UIImage(barcode: "some text") // yields UIImage?
    

    根据docs

    根据输入数据生成输出图像 ISO/IEC 15417:2007 标准。每个模块的宽度(垂直线) 输出图像中的条形码为 1 个像素。的高度 条形码为 32 像素。要从字符串或 URL 创建条形码, 使用 NSASCIIStringEncoding 字符串将其转换为 NSData 对象 编码。

    【讨论】:

    • 太棒了!!但是,我想知道为什么人们创建或多或少复杂的库来处理条形码生成。 this 和 libs 的区别在哪里?
    • @PAD 好吧,这些 Core Image 过滤器是相当新的(iOS >= 8.0)。在 iOS 8 之前,我猜想通过这些库来生成条形码。
    • 需要注意的是Code128有三种不同的类型。此实现使用子类型 C。如果您希望生成 Code 128 类型 A 或 B,您可能需要查看 ZXing 库。
    • 太棒了!!谢谢,如果我想创建其他条形码,如 UPCA、带有 HRI 值的 UPCE,是否可以这样做?
    • Barcode Code28、Code39 和 CODABAR 的 CIFilter 名称是什么?
    【解决方案2】:

    改进的代码:

    • 条码缩放
    • 设置条码图片边距
    • 将 UIImage 转换为 NSData(由于某种原因,上面的代码无法实现)。
    • 分享条码图片时不会失败(可能是同一个bug)

    斯威夫特 3

    func generateBarcode(from string: String) -> UIImage? {
    
        let data = string.data(using: String.Encoding.ascii)
    
        if let filter = CIFilter(name: "CICode128BarcodeGenerator") {
            filter.setDefaults()
            //Margin
            filter.setValue(7.00, forKey: "inputQuietSpace")
            filter.setValue(data, forKey: "inputMessage")
            //Scaling
            let transform = CGAffineTransform(scaleX: 3, y: 3)
    
            if let output = filter.outputImage?.applying(transform) {
                let context:CIContext = CIContext.init(options: nil)
                let cgImage:CGImage = context.createCGImage(output, from: output.extent)!
                let rawImage:UIImage = UIImage.init(cgImage: cgImage)
    
                //Refinement code to allow conversion to NSData or share UIImage. Code here:
                //http://stackoverflow.com/questions/2240395/uiimage-created-from-cgimageref-fails-with-uiimagepngrepresentation
                let cgimage: CGImage = (rawImage.cgImage)!
                let cropZone = CGRect(x: 0, y: 0, width: Int(rawImage.size.width), height: Int(rawImage.size.height))
                let cWidth: size_t  = size_t(cropZone.size.width)
                let cHeight: size_t  = size_t(cropZone.size.height)
                let bitsPerComponent: size_t = cgimage.bitsPerComponent
                //THE OPERATIONS ORDER COULD BE FLIPPED, ALTHOUGH, IT DOESN'T AFFECT THE RESULT
                let bytesPerRow = (cgimage.bytesPerRow) / (cgimage.width  * cWidth)
    
                let context2: CGContext = CGContext(data: nil, width: cWidth, height: cHeight, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: cgimage.bitmapInfo.rawValue)!
    
                context2.draw(cgimage, in: cropZone)
    
                let result: CGImage  = context2.makeImage()!
                let finalImage = UIImage(cgImage: result)
    
                return finalImage
    
            }
        }
    
        return nil
    }
    

    【讨论】:

    • @Rushi,你是如何读取条形码的?使用扫描仪还是通过应用程序?
    • 工作完美。但当时我的图片尺寸太小,不可读。
    • 可行的解决方案,但代码不安全,需要大量强制展开。为什么首先创建一个 cgImage,然后从中创建一个 rawImage: UIImage,然后从 UIImage 中取回 cgimage?有什么区别吗?
    • 有没有办法将背景设置为透明?
    【解决方案3】:

    如果您的部署目标至少是 iOS 8,您可以使用 Core Image。这是我的 BarcodeGenerator 类(需要import CoreImage):

    class BarcodeGenerator {
        enum Descriptor: String {
            case code128 = "CICode128BarcodeGenerator"
            case pdf417 = "CIPDF417BarcodeGenerator"
            case aztec = "CIAztecCodeGenerator"
            case qr = "CIQRCodeGenerator"
        }
    
        class func generate(from string: String, 
                             descriptor: Descriptor, 
                                   size: CGSize) -> CIImage? {
            let filterName = descriptor.rawValue
    
            guard let data = string.data(using: .ascii),
                let filter = CIFilter(name: filterName) else {
                    return nil
            }
    
            filter.setValue(data, forKey: "inputMessage")
    
            guard let image = filter.outputImage else {
                return nil
            }
    
            let imageSize = image.extent.size
    
            let transform = CGAffineTransform(scaleX: size.width / imageSize.width,
                                                   y: size.height / imageSize.height)
            let scaledImage = image.transformed(by: transform)
    
            return scaledImage
        }
    }
    

    可以这样使用

    BarcodeGenerator.generate(from: "barcode-string", 
                         descriptor: .code128, 
                              size: CGSize(width: 800, height: 300))
    

    【讨论】:

    【解决方案4】:

    这样使用,

    func createBarcodeFromString(barcode:String)->UIImage?{
    
        let data = self.data(using: .isoLatin1)
        guard let filter = CIFilter(name: "CICode128BarcodeGenerator") else {
            return nil
        }
        filter.setValue(data, forKey: "inputMessage")
        filter.setValue(7.0, forKey:"inputQuietSpace")
        guard var ciImage = filter.outputImage else {
            return nil
        }
    
        let imageSize = ciImage.extent.integral
        let outputSize = CGSize(width:320, height: 60)
        ciImage = ciImage.transformed(by:CGAffineTransform(scaleX: outputSize.width/imageSize.width, y: outputSize.height/imageSize.height))
    
        let image = convertCIImageToUIImage(ciimage: ciImage)
        return image
    }
    
    func convertCIImageToUIImage(ciimage:CIImage)->UIImage{
        let context:CIContext = CIContext.init(options: nil)
        let cgImage:CGImage = context.createCGImage(ciimage, from: ciimage.extent)!
        let image:UIImage = UIImage.init(cgImage: cgImage)
        return image
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多