Im working on a bakground removal app , where Im doing the task using this function , but this is not so accurate . I found that Im not requesting accurate output here . I need to implement two line in my function .
Two line :
var segmentationRequest = VNGeneratePersonSegmentationRequest()
segmentationRequest.qualityLevel = . accurate
My Function :
func removeBackground(image:UIImage) -> UIImage?{
let resizedImage = image.resized(to: CGSize(width: 513, height: 513))
if let pixelBuffer = resizedImage.pixelBuffer(width:
Int(resizedImage.size.width), height: Int(resizedImage.size.height)){
if let outputImage = (try? modelCore.prediction(image:
pixelBuffer))?.semanticPredictions.image(min: 0, max: 1, axes: (0,0,1)),
let outputCIImage = CIImage(image:outputImage){
if let maskImage = removeWhitePixels(image:outputCIImage),
let resizedCIImage = CIImage(image: resizedImage), let compositedImage =
composite(image: resizedCIImage, mask: maskImage){
return UIImage(ciImage: compositedImage).resized(to: CGSize(width:
image.size.width, height: image.size.height))
}
}
}
return nil
}
You Can use .accurate Quality level in your request like this
but if you will use .accurate it will take more time to give you proper output. and I geuss the quality can be used only in non-Custom Models .
func generatePhoto(Image: Image?) {
//generating instance of request
let request = VNGeneratePersonSegmentationRequest()
guard
//Convert Input image to CgImg
let originalImage = Image?.foregroundImage.cgImage else {
print("missing require image")
return
}
//Setting quality level
request.qualityLevel = .accurate
request.revision = VNGeneratePersonSegmentationRequestRevision1
request.outputPixelFormat = kCVPixelFormatType_OneComponent8
//Create reqhandler
let requestHandler = VNImageRequestHandler(cgImage: originalImage, options: [:])
do{
//Process request
try requestHandler.perform([request])
guard let mask = request.results?.first else {
print("error")
return
}
//Convert the pixelbuffer to maskImg to get maskImg
let maskImage = CIImage(cvPixelBuffer: mask.pixelBuffer)
print(maskImage)
self.mskImage = maskImage
let foreground = CIImage(cgImage: originalImage).oriented(.up)
guard let output = blendImages(foreground: foreground, mask: maskImage) else {
print("Error4")
return
}
//update photoOutput
print(output)
//Convert the CIImg to UIImg
if let photoResult = renderAsUIImage(output){
print("output",photoResult.size)
self.outputImage = photoResult
print(outputImage)
}
}
catch {
print("Error processing person segmentation request")
}
}
Related
I am trying to convert a PDF file and all its pages to png images.
I have put together the code below filling the example on this thread
How to convert PDF to PNG efficiently?
When I run the code, it crashes on the pdf file source (sourceURL) there is definitely a file there. and when I print sourceURl it prints the URL to the file.
The crash says it found nil - My understanding is that means it could not find the file? even though I can physically see and open the file and also print the URL to the file.
Can someone point out what I'm doing wrong?
Code:
func convertPDFtoPNG() {
let sourceURL = pptURL
print("pptURL:", pptURL!)
let destinationURL = pngURL
let urls = try? convertPDF(at: sourceURL!, to: destinationURL!, fileType: .png, dpi: 200)
}
func convertPDF(at sourceURL: URL, to destinationURL: URL, fileType: ImageFileType, dpi: CGFloat = 200) throws -> [URL] {
let pdfDocument: CGPDFDocument! = CGPDFDocument(sourceURL as CFURL)! //Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGImageAlphaInfo.noneSkipLast.rawValue
var urls = [URL](repeating: URL(fileURLWithPath : "/"), count: pdfDocument.numberOfPages)
DispatchQueue.concurrentPerform(iterations: pdfDocument.numberOfPages) { i in
let pdfPage = pdfDocument.page(at: i + 1)!
let mediaBoxRect = pdfPage.getBoxRect(.mediaBox)
let scale = dpi / 72.0
let width = Int(mediaBoxRect.width * scale)
let height = Int(mediaBoxRect.height * scale)
let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo)!
context.interpolationQuality = .high
context.fill(CGRect(x: 0, y: 0, width: width, height: height))
context.scaleBy(x: scale, y: scale)
context.drawPDFPage(pdfPage)
let image = context.makeImage()!
let imageName = sourceURL.deletingPathExtension().lastPathComponent
let imageURL = destinationURL.appendingPathComponent("\(imageName)-Page\(i+1).\(fileType.fileExtention)")
let imageDestination = CGImageDestinationCreateWithURL(imageURL as CFURL, fileType.uti, 1, nil)!
CGImageDestinationAddImage(imageDestination, image, nil)
CGImageDestinationFinalize(imageDestination)
urls[i] = imageURL
}
return urls
}
import Foundation
import Photos
// 1: 目前主要用来操作pdf转为图片
// 2: 图片保存到自定义相册中
struct HBPhotosAlbumHelperUtil {
static let shared = HBPhotosAlbumHelperUtil()
// url链接的pdf转为image
// pageNumber :表示pdf的对应的页面,默认为第一页
func drawToImagePDFFromURL(pdfurl url: String?, pageNumber index: Int = 1, scaleX scalex: CGFloat = 1.0, scaleY scaley: CGFloat = -1.0) -> UIImage? {
guard let pdfUrl = url, pdfUrl.count > 0, let formatterUrl = pdfUrl.urlValue else {
return nil
}
guard let document = CGPDFDocument(formatterUrl as CFURL) else {
return nil
}
guard let page = document.page(at: index) else {
return nil
}
let pageRect = page.getBoxRect(.mediaBox)
if #available(iOS 10.0, *) {
let renderGraph = UIGraphicsImageRenderer(size: pageRect.size)
let drawImage = renderGraph.image { context in
UIColor.white.set()
context.fill(pageRect)
context.cgContext.translateBy(x: 0.0, y: pageRect.size.height)
context.cgContext.scaleBy(x: scalex, y: scaley)
context.cgContext.drawPDFPage(page)
}
return drawImage
} else {
UIGraphicsBeginImageContextWithOptions(pageRect.size, false, 1.0)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.white.cgColor)
context?.fill(pageRect)
context?.translateBy(x: 0.0, y: pageRect.size.height)
context?.scaleBy(x: scalex, y: scaley)
context?.drawPDFPage(page)
let pdfImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return pdfImage
}
}
}
// 用来表示保存图片到自定义相册或者系统相册的操作结果
enum HBPhotosAlbumUtilResult {
case success, error, denied
}
extension HBPhotosAlbumHelperUtil {
// 请求获取操作系统相册权限
// 返回true说明已经得到授权
static var photoAlbumAuthorized: Bool {
return PHPhotoLibrary.authorizationStatus() == .authorized || PHPhotoLibrary.authorizationStatus() == .notDetermined
}
// 保存图片到自定义相册中
func saveImageToCustomAlbum(saveImage markImage: UIImage, customAlbumName albumName: String = "丰巢管家电子发票", completion: ((_ result: HBPhotosAlbumUtilResult) -> Void)?) {
guard HBPhotosAlbumHelperUtil.photoAlbumAuthorized else {
completion?(.denied)
return
}
var assetAlbum: PHAssetCollection?
// 如果相册名称为空,则图片默认保存到系统相册里面
if albumName.isEmpty {
let assetCollection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary,
options: nil)
assetAlbum = assetCollection.firstObject
} else {
// 获取指定的相册是否存在
let assetList = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
assetList.enumerateObjects { albumOption, _, stop in
let assetCollection = albumOption
if albumName == assetCollection.localizedTitle {
assetAlbum = assetCollection
stop.initialize(to: true)
}
}
// 自定义相册不存在就创建
if assetAlbum == nil {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
}) { _, _ in
self.saveImageToCustomAlbum(saveImage: markImage, customAlbumName: albumName, completion: completion)
}
}
}
// 保存图片
PHPhotoLibrary.shared().performChanges({
let result = PHAssetChangeRequest.creationRequestForAsset(from: markImage)
if !albumName.isEmpty {
if let assetPlaceHolder = result.placeholderForCreatedAsset,
let lastAssetAlbum = assetAlbum,
let albumChangeRequset = PHAssetCollectionChangeRequest(for:
lastAssetAlbum) {
albumChangeRequset.addAssets([assetPlaceHolder] as NSArray)
}
}
}) { isSuccess, _ in
guard isSuccess else {
completion?(.error)
return
}
completion?(.success)
}
}
}
extension String {
/// URL legalization
public var urlValue: URL? {
if let url = URL(string: self) {
return url
}
var set = CharacterSet()
set.formUnion(.urlHostAllowed)
set.formUnion(.urlPathAllowed)
set.formUnion(.urlQueryAllowed)
set.formUnion(.urlFragmentAllowed)
return self.addingPercentEncoding(withAllowedCharacters: set).flatMap { URL(string: $0) }
}
}
You can use the api like this:
// Use this way to achieve pdf to image
HBPhotosAlbumHelperUtil.shared.drawToImagePDFFromURL(pdfurl: "link to pdf file")
// In this way, you can save pictures to the system custom album.
HBPhotosAlbumHelperUtil.shared.saveImageToCustomAlbum(saveImage: UIImage()) { (result) in
}
Make sure that your pptURL is file url.
URL(string: "path/to/pdf") and URL(fileURLWithPath: "path/to/pdf") are different things and you must use the last one while initiating your url.
The output should start with "file:///" prefix, f.e.
file:///Users/dev/Library/Developer/CoreSimulator/Devices/4FF18699-D82F-4308-88D6-44E3C11C955A/data/Containers/Bundle/Application/8F230041-AC15-45D9-863F-5778B565B12F/myApp.app/example.pdf
I am a new iOS developer. I was wondering how can I generate a barcode in Swift.
I have the code already, there are multiple resources from where to learn how to read a barcode, but I didn't find any that talks about generating one from a string.
Thanks a lot!
P.S. I know there is a similar question about this, but it's for Objective-C. I don't know Obj-C and I find it difficult coming from .NET.
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))
Use like this,
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
}
Before I asking this question, I have searched the related post:
"unrecognized selector" when attempting to access CIFilter's outputImage
I don't know if is because of using swift or extension, I will get error. I have tested two methods to get the CIImage, but fails in EXC_BAD_INSTRUCTION:
Attention
my url is not http:// prefix, but weixin://wxpay/bizpayurl?pr=ZwBVaW0, and I think this is not the reason of the error.
Method one:
extension String {
func initQRImage() ->UIImage {
let filter:CIFilter = CIFilter.init(name: "CIQRCodeGenerator")!
filter.setDefaults()
let data:Data = self.data(using: String.Encoding.utf8)!
filter.setValue(data, forKey: "inputMessage")
let outputImage:CGImage = filter.outputImage as! CGImage // EXC_BAD_INSTRUCTION here
let qr_image = UIImage.init(cgImage: outputImage)
return qr_image
}
}
Method two:
extension String {
func initQRImage() ->UIImage {
let url:URL = URL.init(fileURLWithPath: self)
let inputImage:CIImage = CIImage.init(contentsOf: url)! // EXC_BAD_INSTRUCTION here
let filter: CIFilter = CIFilter.init(name: "CIAreaAverage")!
filter.setValue(inputImage, forKey: kCIInputImageKey)
let inputExtent:CGRect = inputImage.extent
let extent:CIVector = CIVector.init(x: inputExtent.origin.x, y: inputExtent.origin.y, z: inputExtent.size.width, w: inputExtent.size.height)
filter.setValue(extent, forKey: kCIInputExtentKey)
let outputImage:CIImage = filter.value(forKey: "outputImage") as! CIImage
let qr_image = UIImage.init(cgImage: outputImage as! CGImage)
return qr_image
}
}
Two method will report EXC_BAD_INSTRUCTION error here, you can see the annotation I write after the report error line.
EDIT - 1
I have tried in my project again, not using extension, there is the error too, and data is not nil:
I think the data is nil.
let data:Data = self.data(using: String.Encoding.utf8)!
Also an UIImage instantiated with CIImage has no bitmap, it has no actual image, it's just a set of instructions for applying a filter. So your methods to convert to UIImage shouldn't work.
Finally I found a outdated method to generate QR code, after my improvement, it becomes this:
// quality can modify the defintion
class func generateQRImage(stringQR:NSString, withSizeRate rate:CGFloat, quality:CGFloat?) -> UIImage
{
let filter:CIFilter = CIFilter(name:"CIQRCodeGenerator")!
filter.setDefaults()
let data:NSData = stringQR.data(using: String.Encoding.utf8.rawValue)! as NSData
filter.setValue(data, forKey: "inputMessage")
let outputImg:CIImage = filter.outputImage!
let context:CIContext = CIContext(options: nil)
var tmp_quality = quality
if quality == nil {
tmp_quality = 1.0
}
let transform: CGAffineTransform = CGAffineTransform(scaleX: tmp_quality!, y: tmp_quality!);
let outputImg_after = outputImg.applying(transform)
let cgimg:CGImage = context.createCGImage(outputImg_after, from: outputImg_after.extent)!
var img:UIImage = UIImage(cgImage: cgimg, scale: 1.0, orientation: UIImageOrientation.up)
let width = img.size.width * rate
let height = img.size.height * rate
UIGraphicsBeginImageContext(CGSize.init(width: width, height: height))
let cgContxt:CGContext = UIGraphicsGetCurrentContext()!
cgContxt.interpolationQuality = .high // cgContxt kCGInterpolationNone
img.draw(in: CGRect.init(x: 0, y: 0, width: width, height: height)) // (0, 0, width, height)
img = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return img
}
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")
you can try this EAN13BarcodeGenerator
Usage is pretty simple:
BarCodeView *barCodeView = [[BarCodeView alloc] initWithFrame:kBarCodeFrame];
[self.view addSubview:barCodeView];
[barCodeView setBarCode:GetNewRandomEAN13BarCode()];
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
}
I am a new iOS developer. I was wondering how can I generate a barcode in Swift.
I have the code already, there are multiple resources from where to learn how to read a barcode, but I didn't find any that talks about generating one from a string.
Thanks a lot!
P.S. I know there is a similar question about this, but it's for Objective-C. I don't know Obj-C and I find it difficult coming from .NET.
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))
Use like this,
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
}