无法将数据转换为 UIImage
Cannot convert Data to UIImage
我在将存储为数据和 NSData 的 PDF 转换为 UIImage 时遇到问题。 pdf 是由一些 API 生成的,这些 API 将其吐出为 meme 类型 PDF。 data/PDF 没有任何问题,因为我可以将它直接附加到电子邮件中并查看它,而无需额外的转换或问题。我做了很多搜索,似乎以下脚本是转换为 UIImage 的方法。
var image = UIImage(data: data)
其中数据是保存 PDF 的变量。然而,这对我不起作用。 :(
我的代码如下所示:
//file.data is where the PDF data is stored as Data
print(file.data) //returns: 31108 bytes
store1 = file.data as NSData
print(store1) //returns: Optional(<25504446 2d312e34 0a2520e2.......>)
var image1 = UIImage(data: store1! as Data)
print(image1) //returns: nil
//similarly.....
print(file.data) //returns: 31108 bytes
store2 = file.data
print(store2) //returns: Optional(31380 bytes)
var image2 = UIImage(data: store2!)
print(image2) //returns: nil
不确定我哪里出错了。有什么想法吗?
谢谢。
编辑 - 完整代码
//
// ViewPDF.swift
// MA01
//
// Created by Michael Szabo on 9/25/21.
//
import UIKit
import GoogleAPIClientForREST
import GoogleSignIn
class ViewPDF: UIViewController, GIDSignInDelegate {
@IBOutlet weak var PDF: UIImageView!
var spreadsheetID = ""
var store:NSData? = nil
var image:Data? = nil
private let scopes = [kGTLRAuthScopeSheetsSpreadsheets, kGTLRAuthScopeSheetsDrive]
private let service = GTLRDriveService()
let signInButton = GIDSignInButton()
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().clientID = "private..."
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().scopes = scopes
GIDSignIn.sharedInstance().restorePreviousSignIn()
}
@IBAction func test(_ sender: Any)
{
DispatchQueue.main.asyncAfter(deadline: .now() + 0.0)
{ [self] in
spreadsheetID = GlobalVariable.spreadsheetID
exportFile()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0)
{ [self] in
print("it started")
var image = UIImage(data: store as! Data)
PDF.image = image
}
}
}
//========================================================================================================
//Export File As PDF
func exportFile() {
print("started")
service.authorizer = GIDSignIn.sharedInstance().currentUser.authentication.fetcherAuthorizer()
let request = GTLRDriveQuery_FilesExport.queryForMedia(withFileId: spreadsheetID, mimeType: "application/pdf")
let query = GTLRDriveQuery_FilesExport.queryForMedia(withFileId: spreadsheetID, mimeType: "application/pdf")
service.executeQuery(query, delegate: self, didFinish: #selector(processDownloadedPDF(ticket:finishedWithObject:error:))
)
}
@objc func processDownloadedPDF(ticket: GTLRServiceTicket,
finishedWithObject file: GTLRDataObject,
error : NSError?) {
if let error = error {
print("Drive Download Error: \(error)")
//self.navigationController?.navigationBar.stop()
let alert = UIAlertController(title: "Google Drive Download Error", message:
"Oops - Something went wrong! Error \(error.code): \(error.localizedDescription)", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
}))
self.present(alert, animated: true, completion: nil)
return
}
store = file.data as NSData
//self.navigationController?.navigationBar.stop()
print("Drive Download Worked")
//Process downloaded file
return
}
//=========================================================================================================
//Signin Authentication
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
withError error: Error!) {
if let error = error {
showAlert(title: "Authentication Error", message: error.localizedDescription)
self.service.authorizer = nil
} else {
self.signInButton.isHidden = true
//self.output.isHidden = false
self.service.authorizer = user.authentication.fetcherAuthorizer()
}
}
// Display (in the UITextView) the names and majors of students in a sample
// spreadsheet:
func listMajors() {
let range = "A1:Q"
let query = GTLRSheetsQuery_SpreadsheetsValuesGet
.query(withSpreadsheetId: spreadsheetID, range:range)
service.executeQuery(query) { (ticket, result, error) in
if let error = error {
self.showAlert(title: "Error", message: error.localizedDescription)
return
}
guard let result = result as? GTLRSheets_ValueRange else {
return
}
let rows = result.values!
if rows.isEmpty {
return
}
// self.output.text = "Number of rows in sheet: \(rows.count)"
}
}
// Process the response and display output
func displayResultWithTicket(ticket: GTLRServiceTicket,
finishedWithObject result : GTLRSheets_ValueRange,
error : NSError?) {
if let error = error {
showAlert(title: "Error", message: error.localizedDescription)
return
}
var majorsString = ""
let rows = result.values!
if rows.isEmpty {
// output.text = "No data found."
return
}
majorsString += "Name, Major:\n"
for row in rows {
let name = row[0]
let major = row[4]
majorsString += "\(name), \(major)\n"
}
// output.text = majorsString
}
// Helper for showing an alert
func showAlert(title : String, message: String)
{
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertController.Style.alert
)
let ok = UIAlertAction(
title: "OK",
style: UIAlertAction.Style.default,
handler: nil
)
alert.addAction(ok)
present(alert, animated: true, completion: nil)
}
}
您可以尝试这样的操作来获取 pdf 文档中页面的图像。
var img = UIImage()
if let theUrl = Bundle.main.url(forResource: "welcome", withExtension: "pdf"),
let doc = PDFDocument(url: theUrl),
let thePage = doc.page(at: 0) {
img = getUIImage(from: thePage)
}
func getUIImage(from page: PDFPage) -> UIImage {
let rect = page.bounds(for: PDFDisplayBox.mediaBox)
let renderer = UIGraphicsImageRenderer(size: rect.size)
let image = renderer.image(actions: { context in
let cgContext = context.cgContext
cgContext.setFillColor(gray: 1, alpha: 1)
cgContext.fill(rect)
cgContext.translateBy(x: 0, y: rect.size.height)
cgContext.scaleBy(x: 1, y: -1)
page.draw(with: PDFDisplayBox.mediaBox, to: cgContext)
})
return image
}
然后您可以对所有您想要的页面执行相同的操作。
编辑 1:
鉴于 file.data
或 store
包含您的 pdf 文档,请使用:
if let doc = PDFDocument(data: file.data),
let thePage = doc.page(at: 0) {
img = getUIImage(from: thePage)
}
我在将存储为数据和 NSData 的 PDF 转换为 UIImage 时遇到问题。 pdf 是由一些 API 生成的,这些 API 将其吐出为 meme 类型 PDF。 data/PDF 没有任何问题,因为我可以将它直接附加到电子邮件中并查看它,而无需额外的转换或问题。我做了很多搜索,似乎以下脚本是转换为 UIImage 的方法。
var image = UIImage(data: data)
其中数据是保存 PDF 的变量。然而,这对我不起作用。 :(
我的代码如下所示:
//file.data is where the PDF data is stored as Data
print(file.data) //returns: 31108 bytes
store1 = file.data as NSData
print(store1) //returns: Optional(<25504446 2d312e34 0a2520e2.......>)
var image1 = UIImage(data: store1! as Data)
print(image1) //returns: nil
//similarly.....
print(file.data) //returns: 31108 bytes
store2 = file.data
print(store2) //returns: Optional(31380 bytes)
var image2 = UIImage(data: store2!)
print(image2) //returns: nil
不确定我哪里出错了。有什么想法吗?
谢谢。
编辑 - 完整代码
//
// ViewPDF.swift
// MA01
//
// Created by Michael Szabo on 9/25/21.
//
import UIKit
import GoogleAPIClientForREST
import GoogleSignIn
class ViewPDF: UIViewController, GIDSignInDelegate {
@IBOutlet weak var PDF: UIImageView!
var spreadsheetID = ""
var store:NSData? = nil
var image:Data? = nil
private let scopes = [kGTLRAuthScopeSheetsSpreadsheets, kGTLRAuthScopeSheetsDrive]
private let service = GTLRDriveService()
let signInButton = GIDSignInButton()
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().clientID = "private..."
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().scopes = scopes
GIDSignIn.sharedInstance().restorePreviousSignIn()
}
@IBAction func test(_ sender: Any)
{
DispatchQueue.main.asyncAfter(deadline: .now() + 0.0)
{ [self] in
spreadsheetID = GlobalVariable.spreadsheetID
exportFile()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0)
{ [self] in
print("it started")
var image = UIImage(data: store as! Data)
PDF.image = image
}
}
}
//========================================================================================================
//Export File As PDF
func exportFile() {
print("started")
service.authorizer = GIDSignIn.sharedInstance().currentUser.authentication.fetcherAuthorizer()
let request = GTLRDriveQuery_FilesExport.queryForMedia(withFileId: spreadsheetID, mimeType: "application/pdf")
let query = GTLRDriveQuery_FilesExport.queryForMedia(withFileId: spreadsheetID, mimeType: "application/pdf")
service.executeQuery(query, delegate: self, didFinish: #selector(processDownloadedPDF(ticket:finishedWithObject:error:))
)
}
@objc func processDownloadedPDF(ticket: GTLRServiceTicket,
finishedWithObject file: GTLRDataObject,
error : NSError?) {
if let error = error {
print("Drive Download Error: \(error)")
//self.navigationController?.navigationBar.stop()
let alert = UIAlertController(title: "Google Drive Download Error", message:
"Oops - Something went wrong! Error \(error.code): \(error.localizedDescription)", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
}))
self.present(alert, animated: true, completion: nil)
return
}
store = file.data as NSData
//self.navigationController?.navigationBar.stop()
print("Drive Download Worked")
//Process downloaded file
return
}
//=========================================================================================================
//Signin Authentication
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
withError error: Error!) {
if let error = error {
showAlert(title: "Authentication Error", message: error.localizedDescription)
self.service.authorizer = nil
} else {
self.signInButton.isHidden = true
//self.output.isHidden = false
self.service.authorizer = user.authentication.fetcherAuthorizer()
}
}
// Display (in the UITextView) the names and majors of students in a sample
// spreadsheet:
func listMajors() {
let range = "A1:Q"
let query = GTLRSheetsQuery_SpreadsheetsValuesGet
.query(withSpreadsheetId: spreadsheetID, range:range)
service.executeQuery(query) { (ticket, result, error) in
if let error = error {
self.showAlert(title: "Error", message: error.localizedDescription)
return
}
guard let result = result as? GTLRSheets_ValueRange else {
return
}
let rows = result.values!
if rows.isEmpty {
return
}
// self.output.text = "Number of rows in sheet: \(rows.count)"
}
}
// Process the response and display output
func displayResultWithTicket(ticket: GTLRServiceTicket,
finishedWithObject result : GTLRSheets_ValueRange,
error : NSError?) {
if let error = error {
showAlert(title: "Error", message: error.localizedDescription)
return
}
var majorsString = ""
let rows = result.values!
if rows.isEmpty {
// output.text = "No data found."
return
}
majorsString += "Name, Major:\n"
for row in rows {
let name = row[0]
let major = row[4]
majorsString += "\(name), \(major)\n"
}
// output.text = majorsString
}
// Helper for showing an alert
func showAlert(title : String, message: String)
{
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertController.Style.alert
)
let ok = UIAlertAction(
title: "OK",
style: UIAlertAction.Style.default,
handler: nil
)
alert.addAction(ok)
present(alert, animated: true, completion: nil)
}
}
您可以尝试这样的操作来获取 pdf 文档中页面的图像。
var img = UIImage()
if let theUrl = Bundle.main.url(forResource: "welcome", withExtension: "pdf"),
let doc = PDFDocument(url: theUrl),
let thePage = doc.page(at: 0) {
img = getUIImage(from: thePage)
}
func getUIImage(from page: PDFPage) -> UIImage {
let rect = page.bounds(for: PDFDisplayBox.mediaBox)
let renderer = UIGraphicsImageRenderer(size: rect.size)
let image = renderer.image(actions: { context in
let cgContext = context.cgContext
cgContext.setFillColor(gray: 1, alpha: 1)
cgContext.fill(rect)
cgContext.translateBy(x: 0, y: rect.size.height)
cgContext.scaleBy(x: 1, y: -1)
page.draw(with: PDFDisplayBox.mediaBox, to: cgContext)
})
return image
}
然后您可以对所有您想要的页面执行相同的操作。
编辑 1:
鉴于 file.data
或 store
包含您的 pdf 文档,请使用:
if let doc = PDFDocument(data: file.data),
let thePage = doc.page(at: 0) {
img = getUIImage(from: thePage)
}