Создать код 39 штрих-код
У меня есть этот код для создания штрих-кода:
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" для кода 39.
Как я могу изменить этот код для кода 39?
Спасибо
2 ответа
Если я правильно читаю Документацию Apple, это те типы, которые они кодируют:
Aztec
CheckerBoard
Code128
ConstantColor
LenticularHalo
PDF417Barcode
Random
Starshine
Stripes
Sunbeams
Пример только для 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)
}
}