How can I generate a barcode from a string in Swift? How can I generate a barcode from a string in Swift? ios ios

How can I generate a barcode from a string in Swift?


You could use a CoreImage (import CoreImage) filter to do that!

    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")

A newer version, with guard and failable initialiser:

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)    }}

Usage:

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

According to the docs :

Generates an output image representing the input data according to the ISO/IEC 15417:2007 standard. The width of each module (vertical line) of the barcode in the output image is one pixel. The height of the barcode is 32 pixels. To create a barcode from a string or URL, convert it to an NSData object using the NSASCIIStringEncoding string encoding.


Improved code:

  • Barcode scaling
  • Set barcode image margin
  • Convert the UIImage to NSData (for some reason it wasn't possible with the code above).
  • It won't fail when sharing the barcode image (probably because of the same bug)

Swift 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}


If your deployment target is at least iOS 8, you can use Core Image. Here is my BarcodeGenerator class (you need to 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    }}

It can be used like this

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