SwiftUI: UIImage (QRCode) does not load after calling function
This seems to do the trick:
func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
var uiImage: UIImage?
if let filter = CIFilter(name: "CIQRCodeGenerator",
parameters: ["inputMessage": data,
"inputCorrectionLevel": "L"]) {
if let outputImage = filter.outputImage,
let cgImage = CIContext().createCGImage(outputImage,
from: outputImage.extent) {
let size = CGSize(width: outputImage.extent.width * 3.0,
height: outputImage.extent.height * 3.0)
UIGraphicsBeginImageContext(size)
if let context = UIGraphicsGetCurrentContext() {
context.interpolationQuality = .none
context.draw(cgImage,
in: CGRect(origin: .zero,
size: size))
uiImage = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
}
}
return uiImage
}
Generating QR Code with SwiftUI shows empty picture
I guess the problem is that your CIImage
is not actually "produced". You see, a CIImage
is just a recipe for an image that needs to be rendered by a CIContext
into an actual bitmap image.
The (poorly documented) convenient initializer UIImage(ciImage:)
only works if the destination you assign the image to understands that the pixels of the UIImage
are not yet there and need to be rendered first. UIImageView
could handle this, but it seems SwiftUI's Image
doesn't.
What you need to do is to create a CIContext
(once, maybe as a property of your view) and use it to render your barcode image into a bitmap like this:
let cgImage = self.ciContext.createCGImage(scaledQrImage, from: scaledQrImage.extent)
self.image = Image(uiImage: UIImage(cgImage: cgImage))
imageView.image = UIImage(ciImage: ) won't update a second time
Quick searching ... seems to be either a "bug" or a change...
Changing your generator code to this seems to correct the issue:
func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
let context = CIContext()
if let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 3, y: 3)
if let output = filter.outputImage?.transformed(by: transform) {
if let retImg = context.createCGImage(output, from: output.extent) {
return UIImage(cgImage: retImg)
}
}
}
return nil
}
func generateBarcode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
let context = CIContext()
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) {
if let retImg = context.createCGImage(output, from: output.extent) {
return UIImage(cgImage: retImg)
}
}
}
return nil
}
overlay image in the middle of qr code ios
Try something like this, which will center it inside the view.
The important lines of code to center the UIImageView
is as follows:
overlayImageView.translatesAutoresizingMaskIntoConstraints = false
overlayImageView.contentMode = .center
qrCodeImageView.addSubview(overlayImageView)
let centerXConst = NSLayoutConstraint(item: overlayImageView, attribute: .centerX, relatedBy: .equal, toItem: qrCodeImageView, attribute: .centerX, multiplier: 1, constant: 0)
let centerYConst = NSLayoutConstraint(item: overlayImageView, attribute: .centerY, relatedBy: .equal, toItem: qrCodeImageView, attribute: .centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([centerXConst, centerYConst])
I use this exact code to center an icon on the QR Code:
class ViewController: UIViewController {
@IBOutlet weak var qrCodeImageView: UIImageView!
var qrCodeImage: CIImage!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let textField = "fooqarcode"
let data = textField.data(using: String.Encoding.isoLatin1, allowLossyConversion: false)
let filter = CIFilter(name: "CIQRCodeGenerator")
filter?.setValue(data, forKey: "inputMessage")
filter?.setValue("Q", forKey: "inputCorrectionLevel")
qrCodeImage = (filter?.outputImage)!
let scaleX = qrCodeImageView.frame.size.width / qrCodeImage.extent.size.width
let scaleY = qrCodeImageView.frame.size.height / qrCodeImage.extent.size.height
let transformedImage = qrCodeImage.transformed(by: CGAffineTransform(scaleX: scaleX, y: scaleY))
qrCodeImageView.image = UIImage(ciImage: transformedImage)
let overlayImageView = UIImageView(image: UIImage(named: "block.png"))
overlayImageView.translatesAutoresizingMaskIntoConstraints = false
overlayImageView.contentMode = .center
qrCodeImageView.addSubview(overlayImageView)
let centerXConst = NSLayoutConstraint(item: overlayImageView, attribute: .centerX, relatedBy: .equal, toItem: qrCodeImageView, attribute: .centerX, multiplier: 1, constant: 0)
let centerYConst = NSLayoutConstraint(item: overlayImageView, attribute: .centerY, relatedBy: .equal, toItem: qrCodeImageView, attribute: .centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([centerXConst, centerYConst])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Why does putting an SF symbol in a UIImage and then in a SwiftUI Image View result in a blurry image?
When you use Image(systemName:)
the system draws to the screen using vector graphics, resulting in sharp, un-blurry renderings.
However, UIImage
, including, it seems UIImage(systemName:)
is a bitmapped image, at a set resolution. If you scale it up (as you're doing in your second block of code), you'll get blurriness, because you're not getting the benefits of the vector graphics.
Using a pattern like the following would allow you to conditionally display a Image(uiImage:)
or Image(systemName:)
and still use the same set of modifiers for each:
struct ContentView: View {
@State var displayedImage : UIImage?
var imageToDisplay: Image {
if let displayedImage = displayedImage {
return Image(uiImage: displayedImage)
} else {
return Image(systemName: "camera.circle")
}
}
var body: some View {
imageToDisplay
.resizable()
.scaledToFill()
.aspectRatio(contentMode: .fit)
.frame(width: 400, height: 400)
}
}
iOS 7 Core Image QR Code generation too blur
I was about to start bounty on this question but i found the answer.
What you need is a scale filter. To achieve this with CoreImage, you need to do something like this:
CIImage *input = [CIImage imageWithCGImage: ImageView.Image.CGImage]; // input image is 100 X 100
CGAffineTransform transform = CGAffineTransformMakeScale(5.0f, 5.0f); // Scale by 5 times along both dimensions
CIImage *output = [input imageByApplyingTransform: transform];
// output image is now 500 X 500
FROM THIS SO ANSWER: https://stackoverflow.com/a/16316701/2859764
Related Topics
Views Are Merged Instead of Showing Them Separately
Windownibname Error in Swift/Cocoa
What Are The Benefits of an Immutable Struct Over a Mutable One
How to Detect Hash Changes in Wkwebview
How to a Convert a Dictionary Slice to a Dictionary in Swift
How to Disable The Automatic Activation of an Arcoachingoverlayview
How to Use The Snapchat Sdk (Snapkit) with Swiftui
Is There Any Reasonable Way to Access The Contents of a Characterset
Position of Mouse Click Relative to Scene, Not Window
How to Spin and Add a Linear Force to an Entity Loaded from Reality Composer
Filter on Calayer Except for a Shape Which Is an Union of (Non Necessarily Distinct) Rectangles
Alamofire Https Change in 10.3
Instantiating a Nested Class Using Nsclassfromstring in Swift
Error: 'string' Is Not Convertible to 'string!'
Decoding a Nested Array in Swift 4