Last active
February 21, 2021 05:17
-
-
Save nyg/bdeae8190a41b4b56bde8e13dd471ecc to your computer and use it in GitHub Desktop.
Add a JPEG comment marker to file in pure Swift.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Inspired by wrjpgcom of libjpeg | |
// https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/wrjpgcom.c | |
// | |
// https://stackoverflow.com/a/46045524/5536516 | |
// | |
// Note: To add an EXIF UserComment go here: | |
// https://gist.github.com/nyg/c90f36abbd30f72c8b6681ef23db886b | |
import Foundation | |
/** | |
Adds a comment to the given JPEG image. | |
The comment marker (COM) will be insert just before the first SOF | |
marker found. | |
1. It causes the new comment to appear after, rather than before, | |
existing comments, | |
2. and ensures that comments come after any JFIF or JFXX markers, | |
as required by the JFIF specification. | |
- parameters: | |
- jpegData: The JPEG image as a Data instance. Will be modified | |
by the function. | |
- comment: The comment that will be added to the image. | |
*/ | |
func addJPEGComment(to jpegData: inout Data, _ comment: String) { | |
// Define JPEG markers. | |
let markerStart: UInt8 = 0xFF | |
let comMarker: UInt8 = 0xFE | |
let sofMarkers: [UInt8] = [ | |
0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF, | |
0xD9 // End of Image | |
] | |
// Find range of first SOF marker, or EOI. | |
var firstSOFRange: Range<Data.Index>? | |
for marker in sofMarkers { | |
if let range = jpegData.range(of: Data(bytes: [ markerStart, marker ])) { | |
firstSOFRange = range | |
break | |
} | |
} | |
guard let firstSOFIndex = firstSOFRange?.lowerBound | |
else { fatalError("No SOF or EOI marker found.") } | |
// Create the comment byte array. | |
let length = comment.lengthOfBytes(using: .utf8) + 2 | |
let l1 = UInt8(length >> 8) & markerStart | |
let l2 = UInt8(length) & markerStart | |
let commentArray = [ markerStart, comMarker, l1, l2 ] + [UInt8](comment.utf8) | |
// Insert the comment array into image data object. | |
jpegData.insert(contentsOf: commentArray, at: firstSOFIndex) | |
} | |
/* Usage example */ | |
guard let jpegURL = Bundle.main.url(forResource: "image", 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("image_com.jpg") | |
else { fatalError("Destination URL not created") } | |
try jpegData.write(to: jpegOutputURL) | |
print("rdjpgcom \(jpegOutputURL.path)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment