Reputation: 177
When I try to get a higher resolution image from the google books API it only gives me the small thumbnail size that is 128 X 209 and I can't get a larger image
This is my url:
if let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q=colleen+hoover")
My Structs:
struct Book: Identifiable, Codable {
let id = UUID()
let volumeInfo: VolumeInfo
}
struct VolumeInfo: Codable {
let title, publishedDate: String?
let authors: [String]?
let publisher, description: String?
let imageLinks: ImageLinks?
let averageRating: Double?
}
struct ApiResponse: Codable {
let kind: String
let totalItems: Int
let items: [Book]
}
struct ImageLinks: Codable {
let smallThumbnail, thumbnail: String
}
and this is how I'm downloading the image from the url
extension UIImageView {
func downloaded(from url: URL, contentMode mode: ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
Upvotes: 3
Views: 2355
Reputation: 41
Most of the time replacing zoom=1
by zoom=10
in the response coming from volumeInfo.imageLinks.thumbnail
would do the trick, but it doesn't work always. Sometimes you get that "image not found" image from Google, like this one.
And when this happens there's no way around it since it probably means Google itself doesn't have a larger file to show.
I solved this with something that is a little overkill, but it works 100% of the time:
image not found
" I just replace it by my own default image.I don't think Google will replace this 404 image anytime soon, but if it does I would need to adapt my code.
This is an example of text detection on images:
private func performOCR(on imageURL: URL, completionHandler: @escaping ([String]?, Error?) -> Void) {
guard let image = CIImage(contentsOf: imageURL) else {
completionHandler(nil, NSError(domain: "OCR", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to load image from URL."]))
return
}
let handler = VNImageRequestHandler(ciImage: image, options: [:])
// Create a text recognition request
let textRecognitionRequest = VNRecognizeTextRequest { request, error in
if let error = error {
completionHandler(nil, error)
return
}
guard let observations = request.results as? [VNRecognizedTextObservation],
!observations.isEmpty else {
completionHandler(nil, NSError(domain: "OCR", code: 2, userInfo: [NSLocalizedDescriptionKey: "No text found in the image."]))
return
}
var detectedText: [String] = []
for observation in observations {
guard let topCandidate = observation.topCandidates(1).first else { continue }
detectedText.append(topCandidate.string)
}
completionHandler(detectedText, nil)
}
textRecognitionRequest.recognitionLevel = .accurate
textRecognitionRequest.usesLanguageCorrection = true
do {
try handler.perform([textRecognitionRequest])
} catch {
completionHandler(nil, error)
}
}
And you can use this function like this:
private func googleImageNotFound(url: String, completion: @escaping (Bool) -> Void) {
// These are the words that appears on Google's default "image not found" image
let keywords = ["image", "not", "found"]
guard let imageUrl = URL(string: url) else {
completion(true)
return
}
performOCR(on: imageUrl) { detectedTexts, error in
if let error = error {
print("OCR Error: \(error)")
completion(true) // Return true if there's an error
} else if let detectedTexts = detectedTexts {
let containsWords = detectedTexts.contains { detectedText in
keywords.allSatisfy { word in
detectedText.localizedCaseInsensitiveContains(word)
}
}
completion(!containsWords) // Return true if words are not found
} else {
completion(true) // Return true if detectedTexts is nil
}
}
}
Don't forget to import Vision:
import Vision
Upvotes: 1
Reputation: 177
Ok, I figured out a way to fix this but I'm not sure if it's the best solution.
Instead of getting the image URL from the struct and using the thumbnail, I used this URL instead and just change the bookImgId variable to your book id
https://books.google.com/books/publisher/content/images/frontcover/\(bookImgId)?fife=w400-h600&source=gbs_api
This part of the URL is where you will change the image size to whatever you want
?fife=w400-h600
Upvotes: 5