Writing Exposure Bias isn't returning the expected result

106 views Asked by At

I am trying to use SwiftUI to write Exif data. When writing in the exposure bias image property

kCGImagePropertyExifExposureBiasValue

It seems to work just fine for all values I've tried except for 2/3.

var exifDictionary: [CFString: Any] = [:]

let expBias: Double = 2/3
exifDictionary[kCGImagePropertyExifExposureBiasValue] = expBias

When inspecting the image in Apples Preview, Photos and using ExifTool each application shows the value as either 0.5 or 1/2 not 0.66 or 2/3 as you'd expect. Similar values such as

let expBias: Double = 5/3

create no problems and are shown as expected either as 1.7, 1.667 or 5/3.

Has anyone else had any experience with this?

In the debug area after writing the data I get one of these messages per image, it doesn't appear to change with the value of the exposure bias.

CleanupRecodeProperties:3604: IIOReadPlugin::CleanupRecodeProperties: top: 1 tiff: 1

CleanupRecodeProperties:3604: IIOReadPlugin::CleanupRecodeProperties: top: 6 tiff: 6

That is the gist of what's going on, the exif seems to be writing correctly however below I will post my code for writing the data to the image file.

import SwiftUI

struct WriteDataView: View {
    
    @State var chosenFileName = "Filename"
    @State var realURL: URL?
    @State var directoryURLS: [URL] = []
    @State var finished = false
    
    func fetchFileURLs() {
        do {
            let directoryURLS = try FileManager.default.contentsOfDirectory(
                at: realURL!,
                includingPropertiesForKeys: nil,
                options: .skipsHiddenFiles
            )
            
            let extensions = ["tif", "tiff", "jpg", "jpeg", "png", "JPG"]
            
            var wantedURLs: [URL] = []
            
            for i in (directoryURLS) {
                if extensions.contains(i.pathExtension) {
                    wantedURLs.append(i)
                }
            }
            
            let sortedDirectoryURLS = wantedURLs.sorted { $0.lastPathComponent < $1.lastPathComponent }
            
            self.directoryURLS = sortedDirectoryURLS
            
        } catch {
            print("Error fetching file URLs: \(error.localizedDescription)")
        }
    }
    
    public func writeExifFunction(_ directoryURLS: [URL]) {
        for (index, _) in directoryURLS.enumerated() {
            
            var exifDictionary: [CFString: Any] = [:]
            
            let expBias: Double = 2/3
            
            exifDictionary[kCGImagePropertyExifExposureBiasValue] = expBias
            
            var exifData: [CFString: Any] = [:]
            
            exifData[kCGImagePropertyExifDictionary] = exifDictionary
            
            let imageURL = directoryURLS[index]
            
            addEXIFDataToImage(imageURL: imageURL, exifData: exifData)
        }
    }
    
    public func addEXIFDataToImage(imageURL: URL, exifData: [CFString: Any]) {
        guard let imageData = try? Data(contentsOf: imageURL),
              let source = CGImageSourceCreateWithData(imageData as CFData, nil),
              let imageType = CGImageSourceGetType(source) else {
            print("Failed to load image data or determine image type.")
            return
        }
        
        let destinationData = NSMutableData()
        guard let destination = CGImageDestinationCreateWithData(destinationData, imageType, 1, nil) else {
            print("Failed to create image destination.")
            return
        }
        
        CGImageDestinationAddImageFromSource(destination, source, 0, exifData as CFDictionary)
        CGImageDestinationFinalize(destination)
        
        try? destinationData.write(to: imageURL, options: .atomic)
        
        finished = true
    }
    
    var body: some View {
        if !finished {
            VStack{
                if chosenFileName == "Filename" {
                    Spacer()
                    Button(action: {
                        let panel = NSOpenPanel()
                        panel.title = "Find Images to add Exif"
                        panel.allowsMultipleSelection = false
                        panel.canChooseDirectories = true
                        panel.canChooseFiles = false
                        if case .OK = panel.runModal() {
                            if !panel.urls.isEmpty {
                                realURL = panel.urls.first
                                fetchFileURLs()
                                chosenFileName = "FilesGot"
                            }
                            else {
                                print("No files selected")
                            }
                        }
                    }) {
                        VStack{
                            HStack{
                                Image(systemName: "film")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .frame(width: 30, height: 30)
                                    .foregroundColor(Color.gray)
                                Text("FolderSelect")
                                    .foregroundColor(Color.gray)
                            }
                            .padding()
                            .background(RoundedRectangle(cornerRadius: 8))
                            
                        }
                    }
                    .buttonStyle(PlainButtonStyle())
                    .help("FileBrowserHelp")
                    Spacer()
                        .toolbar {
                            ToolbarItemGroup {
                                Button {
                                } label: {
                                    EmptyView()
                                }
                            }
                        }
                }
                else if chosenFileName != "Filename" {
                    Text(directoryURLS.count.description)
                        .toolbar {
                            ToolbarItemGroup {
                                Button(action: {
                                    writeExifFunction(directoryURLS)
                                }) {
                                    Image(systemName: "play")
                                }
                                .keyboardShortcut(KeyEquivalent.return, modifiers: [.command])
                                .help("PlayButtonHelp")
                            }
                        }
                }
            }
        }
        else {
            VStack{
                Text("Done")
            }
        }
    }
}

Writing the Double as 0.6 defaults back to 0.5 a value larger than 0.6000003 displays as 0.6 so why doesn't 2/3 write as expected?

When googling the line printed in the debug area nothing comes up.

I simply don't understand why a value like 5/3 or even -2/3 works but 2/3 doesn't.

0

There are 0 answers