Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add comment on image file header

I want to add a comment(s) in image file header. As I able to add a comment on EXIF metadata under UserComment but I want to add multiple comments in image file header.

Which framework do I use? For UserComment, I am using ImageIO framework.

like image 290
Diken Shah Avatar asked Apr 18 '17 06:04

Diken Shah


1 Answers

Here's how to add a comment (i.e. not an EXIF UserComment) to a JPEG image in Swift. I don't think it can be done using the ImageIO framework.

The code comes from the wrjpgcom command-line tool, written in C. It's part of the libjpeg library. Check the source code for more detailed comments (it doesn't actually use libjpeg).

We will insert the new comment marker just before SOFn. This (a) causes the new comment to appear after, rather than before, existing comments; and (b) ensures that comments come after any JFIF or JFXX markers, as required by the JFIF specification.

import Foundation

func addJPEGComment(to jpegData: inout Data, _ comment: String) {

    // find index of first SOF marker, or EOI
    let sofMarkers: [UInt8] = [
        0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6,
        0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE,
        0xCF, 0xD9 // EOI
    ]

    var firstSOFRange: Range<Data.Index>?
    for marker in sofMarkers {
        if let range = jpegData.range(of: Data(bytes: [ 0xFF, marker ])) {
            firstSOFRange = range
            break
        }
    }

    guard let firstSOFIndex = firstSOFRange?.lowerBound
        else { fatalError("No SOF or EOI marker found.") }

    // create comment byte array
    let length = comment.lengthOfBytes(using: .utf8) + 2
    let l1 = UInt8((length >> 8) & 0xFF)
    let l2 = UInt8(length & 0xFF)
    let commentArray = [ 0xFF, 0xFE /* COM marker */, l1, l2 ] + [UInt8](comment.utf8)

    // insert comment array into image data object
    jpegData.insert(contentsOf: commentArray, at: firstSOFIndex)
}

guard let jpegURL = Bundle.main.url(forResource: "no_com", withExtension: "jpg")
    else { fatalError("File not found.") }

guard var jpegData = try? Data(contentsOf: jpegURL)
    else { fatalError("File could not be read.") }

addJPEGComment(to: &jpegData, "This is a JPEG comment.")

guard let jpegOutputURL = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("with_com.jpg")
    else { fatalError("Destination URL not created") }

try jpegData.write(to: jpegOutputURL)

print(jpegOutputURL)

(Gist)

Comment is shown when the output JPEG is uploaded to this website:

enter image description here

like image 69
nyg Avatar answered Nov 08 '22 14:11

nyg