Reputation: 43
I'm trying to create a simple EAN13 image to show a barcode from a String.
I tried with this code but it can only generate a code128. What can I use to generate a EAN13?
class Barcode {
class func fromString(string : String) -> UIImage? {
let data = string.dataUsingEncoding(NSASCIIStringEncoding)
let filter = CIFilter(name: "CICode128BarcodeGenerator")
filter.setValue(data, forKey: "inputMessage")
return UIImage(CIImage: filter.outputImage)
}
}
let img = Barcode.fromString("1234567890123")
Upvotes: 4
Views: 8128
Reputation: 5015
Here is a Swift rendition of @ale_stro's answer that uses the original Objective-C code: (https://github.com/astrokin/EAN13BarcodeGenerator)
Create Swift File: "BarcodeEAN13.swift"
import Foundation
enum Parity {
case odd
case even
}
let kBarCodeLength: Int = 12
let bQuiteZone: [Bool] = [false, false, false, false, false, false, false, false, false]
let bLeadTrailer: [Bool] = [true, false, true]
let bSeporator: [Bool] = [false, true, false, true, false]
let bOddLeft: [[Bool]] = [
[false, false, false, true, true, false, true],
[false, false, true, true, false, false, true],
[false, false, true, false, false, true, true],
[false, true, true, true, true, false, true],
[false, true, false, false, false, true, true],
[false, true, true, false, false, false, true],
[false, true, false, true, true, true, true],
[false, true, true, true, false, true, true],
[false, true, true, false, true, true, true],
[false, false, false, true, false, true, true]
]
let bEvenLeft: [[Bool]] = [
[false, true, false, false, true, true, true],
[false, true, true, false, false, true, true],
[false, false, true, true, false, true, true],
[false, true, false, false, false, false, true],
[false, false, true, true, true, false, true],
[false, true, true, true, false, false, true],
[false, false, false, false, true, false, true],
[false, false, true, false, false, false, true],
[false, false, false, true, false, false, true],
[false, false, true, false, true, true, true]
]
let bRight: [[Bool]] = [
[true, true, true, false, false, true, false],
[true, true, false, false, true, true, false],
[true, true, false, true, true, false, false],
[true, false, false, false, false, true, false],
[true, false, true, true, true, false, false],
[true, false, false, true, true, true, false],
[true, false, true, false, false, false, false],
[true, false, false, false, true, false, false],
[true, false, false, true, false, false, false],
[true, true, true, false, true, false, false]
]
let bParity: [[Bool]] = [
[false, false, false, false, false], [false, true, false, true, true],
[false, true, true, false, true], [false, true, true, true, false],
[true, false, false, true, true], [true, true, false, false, true],
[true, true, true, false, false], [true, false, true, false, true],
[true, false, true, true, false], [true, true, false, true, false]
]
func initializeBarCode(barCodeString: String) -> [Int] {
var barCode: [Int] = Array(repeating: 0, count: kBarCodeLength)
for (index, char) in barCodeString.prefix(kBarCodeLength).enumerated() {
barCode[index] = Int(String(char)) ?? 0
}
return barCode
}
func calculateBarCodeEAN13(barCodeString: String) -> [Bool] {
var buffer: [Bool] = []
let barCode = initializeBarCode(barCodeString: barCodeString)
buffer.append(contentsOf: bQuiteZone)
buffer.append(contentsOf: bLeadTrailer)
let countryCode = barCode[1]
buffer.append(contentsOf: bOddLeft[countryCode])
// Manufacture Code
for i in 2..<7 {
let num = barCode[i]
let parity = bParity[barCode[0]][i - 2] ? Parity.even : Parity.odd
let bin = (parity == .odd) ? bOddLeft[num] : bEvenLeft[num]
buffer.append(contentsOf: bin)
}
buffer.append(contentsOf: bSeporator)
// Product Code
for i in 7..<12 {
let num = barCode[i]
buffer.append(contentsOf: bRight[num])
}
// Checksum
var sum = 0
for (index, num) in barCode.enumerated() {
let factor = (index % 2 == 0) ? 1 : 3
sum += num * factor
}
let checksum = (10 - (sum % 10)) % 10
buffer.append(contentsOf: bRight[checksum])
buffer.append(contentsOf: bLeadTrailer)
buffer.append(contentsOf: bQuiteZone)
return buffer
}
func isValidBarCode(barCode: String) -> Bool {
guard barCode.count == 13 else { return false }
let sum = barCode.prefix(12).enumerated().reduce(0) { result, item in
let (index, char) = item
guard let digit = Int(String(char)) else { return result }
return result + digit * ((index % 2 == 0) ? 1 : 3)
}
let checkDigit = 10 - (sum % 10)
return checkDigit == Int(String(barCode.last!))
}
Create Swift File: "BarCodeView.swift"
import UIKit
class BarCodeView: UIView {
var binaryCode: [Bool] = []
var barCode: String = "" {
didSet {
if isValidBarCode(barCode: barCode) {
binaryCode = calculateBarCodeEAN13(barCodeString: barCode)
setNeedsDisplay()
} else {
binaryCode = Array(repeating: false, count: 113)
setNeedsDisplay()
}
}
}
override func draw(_ rect: CGRect) {
guard binaryCode.count == 113 else { return }
let context = UIGraphicsGetCurrentContext()
context?.clear(rect)
context?.setAllowsAntialiasing(false)
// Draw each bar
let barWidth = rect.width / CGFloat(binaryCode.count)
for (index, bit) in binaryCode.enumerated() {
let xPosition = CGFloat(index) * barWidth
let color: UIColor = bit ? .black : .white
color.setFill()
context?.fill(CGRect(x: xPosition, y: 0, width: barWidth, height: rect.height))
}
}
}
Usage:
let barCodeView = BarCodeView()
view.addSubview(barCodeView) // adjust view as needed
// Display EAN13 Code:
barCodeView.barCode = "7611330732917" // sample code
Upvotes: 0
Reputation: 11646
my two cents for osx..
func barCodeFromString(string : String, destSize: NSSize) -> NSImage? {
let data = string.data(using: .ascii)
guard let filter = CIFilter(name: "CICode128BarcodeGenerator") else{
return nil
}
filter.setValue(data, forKey: "inputMessage")
guard let ciImage : CIImage = filter.outputImage else{
return nil
}
let c_size = ciImage.extent.size
let w_ratio = destSize.width/c_size.width
let h_ratio = destSize.height/c_size.height
let ratio = w_ratio>h_ratio ? h_ratio : w_ratio
let transform = CGAffineTransform(scaleX: ratio, y: ratio)
let scaled = ciImage.transformed(by: transform)
let rep = NSCIImageRep(ciImage: scaled)
let nsImage = NSImage(size: rep.size)
nsImage.addRepresentation(rep)
return nsImage
}
Upvotes: -6
Reputation: 816
you can try this EAN13BarcodeGenerator
Usage is pretty simple:
BarCodeView *barCodeView = [[BarCodeView alloc] initWithFrame:kBarCodeFrame];
[self.view addSubview:barCodeView];
[barCodeView setBarCode:GetNewRandomEAN13BarCode()];
Upvotes: 3