2

I am trying to attach some of my own fields to an image I capture. I seem to be able to change existing EXIF entries, but I can't add new ones, either within the EXIF dictionary or as a separate dictionary added to the image. When I make my additions, I can see them as part of the image data, but they never get saved to the image file. However, when I change existing EXIF entries, those do get saved to the image file.

I have already studied:

Here's my code:

        CMAttachmentMode attachmentMode;
        CFDictionaryRef exifDict =  CMGetAttachment(imageDataSampleBuffer, (CFStringRef) @"{Exif}", &attachmentMode);

        NSMutableDictionary *exifMutableDict = [((__bridge NSDictionary*)exifDict) mutableCopy];
        [exifMutableDict setObject: @"MyApp" forKey:@"AppName"];
        [exifMutableDict setObject:lockedDate forKey:@"CaptureDate"];
        [exifMutableDict setObject:@(55555) forKey:@"MeteringMode"];
        [exifMutableDict setObject:@"Peach" forKey:@"LensMake"];

        CFMutableDictionaryRef newCFDict = (__bridge CFMutableDictionaryRef)exifMutableDict;
        CMSetAttachment(imageDataSampleBuffer, (CFStringRef) @"{Exif}", newCFDict, attachmentMode);

        NSMutableDictionary *anotherMutableDict = @{}.mutableCopy;
        [anotherMutableDict setObject: @"MyApp" forKey:@"AppName"];
        [anotherMutableDict setObject:lockedDate forKey:@"CaptureDate"];
        [anotherMutableDict setObject:@(55555) forKey:@"MeteringMode"];
        [anotherMutableDict setObject:@"Peach" forKey:@"Lens Make"];
        CMSetAttachment(imageDataSampleBuffer, (CFStringRef) @"another", (__bridge CFMutableDictionaryRef)anotherMutableDict, kCMAttachmentMode_ShouldPropagate);

        NSLog(@"metadata:  %@ mutable dict %@, another %@", imageDataSampleBuffer, newCFDict, anotherMutableDict);
        imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

I successfully get the EXIF dictionary. I add a couple of fields, AppName and CaptureDate, and then modify two existing ones, MeteringMode and LensMake.

I add this modified EXIF dictionary to the imageDataSampleBuffer.

I also create a new dictionary, in case the EXIF dictionary is somehow restrictive to new additions, anotherMutableDict and add it to the imageDataSampleBuffer.

I then get the JPEG representation and write it to a file in my sandbox.

When I look at the resulting image using image editing apps, including Photoshop, Preview and Pixelmator, I see these changes:

LensMake = Peach MeteringMode = 55555

I don't see other additions to the EXIF, nor do I see another dictionary.

I have also tried completely removing the EXIF and replacing it with a different one, and the only affect there is that the resulting file has a significantly smaller EXIF without any of my additions, and only the changes.

I'm at a loss what is going on. Anyone see what I am doing wrong?

Here is the full output of the NSLog statement. As you can see, the changes and additions are clearly reflected in the EXIF dictionary and are also hanging off of another dictionary that is added to the imageDataSampleBuffer. Yet none of the additions make it into the final saved file, and I only see the changes to existing fields.

2015-02-09 12:18:42.960 MyApp[1720:209034] metadata:  CMSampleBuffer 0x15cd2a060 retainCount: 1 allocator: 0x1991dfc80
    invalid = NO
    dataReady = YES
    makeDataReadyCallback = 0x0
    makeDataReadyRefcon = 0x0
    buffer-level attachments:
        another   (P) = {
    AppName = MyApp;
    CaptureDate = "2015-02-09 20:18:25 +0000";
    "Lens Make" = Peach;
    MeteringMode = 55555;
}
        Orientation(P) = 6
        {Exif}    (P) = <CFBasicHash 0x171479200 [0x1991dfc80]>{type = mutable dict, count = 24,
entries =>
    0 : <CFString 0x100163398 [0x1991dfc80]>{contents = "MeteringMode"} = <CFNumber 0xb0000000000d9032 [0x1991dfc80]>{value = +55555, type = kCFNumberSInt32Type}
    1 : <CFString 0x1001633d8 [0x1991dfc80]>{contents = "LensMake"} = <CFString 0x1001633b8 [0x1991dfc80]>{contents = "Peach"}
    3 : <CFString 0x1992e4fa0 [0x1991dfc80]>{contents = "BrightnessValue"} = <CFNumber 0x17423b620 [0x1991dfc80]>{value = +3.50483639710326944083, type = kCFNumberFloat64Type}
    4 : <CFString 0x100163358 [0x1991dfc80]>{contents = "AppName"} = <CFString 0x100163338 [0x1991dfc80]>{contents = "MyApp"}
    6 : <CFString 0x19950b368 [0x1991dfc80]>{contents = "FNumber"} = <CFNumber 0x174223b00 [0x1991dfc80]>{value = +2.20000000000000017764, type = kCFNumberFloat64Type}
    7 : <CFString 0x19950b688 [0x1991dfc80]>{contents = "FocalLength"} = <CFNumber 0x1742295c0 [0x1991dfc80]>{value = +4.15000000000000035527, type = kCFNumberFloat64Type}
    8 : <CFString 0x19950b568 [0x1991dfc80]>{contents = "ShutterSpeedValue"} = <CFNumber 0x1742386e0 [0x1991dfc80]>{value = +4.90764099214979498953, type = kCFNumberFloat64Type}
    9 : <CFString 0x19950b908 [0x1991dfc80]>{contents = "SceneType"} = <CFNumber 0xb000000000000012 [0x1991dfc80]>{value = +1, type = kCFNumberSInt32Type}
    10 : <CFString 0x19950b588 [0x1991dfc80]>{contents = "ApertureValue"} = <CFNumber 0x17423c080 [0x1991dfc80]>{value = +2.27500704749987026076, type = kCFNumberFloat64Type}
    11 : <CFString 0x19950b6a8 [0x1991dfc80]>{contents = "SubjectArea"} = <CFArray 0x174443720 [0x1991dfc80]>{type = mutable-small, count = 4, values = (
    0 : <CFNumber 0xb0000000000065f1 [0x1991dfc80]>{value = +1631, type = kCFNumberSInt16Type}
    1 : <CFNumber 0xb000000000004c71 [0x1991dfc80]>{value = +1223, type = kCFNumberSInt16Type}
    2 : <CFNumber 0xb000000000007031 [0x1991dfc80]>{value = +1795, type = kCFNumberSInt16Type}
    3 : <CFNumber 0xb000000000004351 [0x1991dfc80]>{value = +1077, type = kCFNumberSInt16Type}
)}
    17 : <CFString 0x19950bb28 [0x1991dfc80]>{contents = "LensSpecification"} = <CFArray 0x174245760 [0x1991dfc80]>{type = mutable-small, count = 4, values = (
    0 : <CFNumber 0x17423bba0 [0x1991dfc80]>{value = +4.15000000000000035527, type = kCFNumberFloat64Type}
    1 : <CFNumber 0x17423a0e0 [0x1991dfc80]>{value = +4.15000000000000035527, type = kCFNumberFloat64Type}
    2 : <CFNumber 0x174232900 [0x1991dfc80]>{value = +2.20000000000000017764, type = kCFNumberFloat64Type}
    3 : <CFNumber 0x174235560 [0x1991dfc80]>{value = +2.20000000000000017764, type = kCFNumberFloat64Type}
)}
    18 : <CFString 0x19950b7c8 [0x1991dfc80]>{contents = "PixelYDimension"} = <CFNumber 0xb000000000009902 [0x1991dfc80]>{value = +2448, type = kCFNumberSInt32Type}
    19 : <CFString 0x19950b988 [0x1991dfc80]>{contents = "WhiteBalance"} = <CFNumber 0xb000000000000002 [0x1991dfc80]>{value = +0, type = kCFNumberSInt32Type}
    22 : <CFString 0x100163378 [0x1991dfc80]>{contents = "CaptureDate"} = 2015-02-09 20:18:25 +0000
    28 : <CFString 0x19950b3c8 [0x1991dfc80]>{contents = "ISOSpeedRatings"} = <CFArray 0x174249b70 [0x1991dfc80]>{type = mutable-small, count = 1, values = (
    0 : <CFNumber 0xb000000000000401 [0x1991dfc80]>{value = +64, type = kCFNumberSInt16Type}
)}
    29 : <CFString 0x19950b968 [0x1991dfc80]>{contents = "ExposureMode"} = <CFNumber 0xb000000000000002 [0x1991dfc80]>{value = +0, type = kCFNumberSInt32Type}
    31 : <CFString 0x19950b7a8 [0x1991dfc80]>{contents = "PixelXDimension"} = <CFNumber 0xb00000000000cc02 [0x1991dfc80]>{value = +3264, type = kCFNumberSInt32Type}
    32 : <CFString 0x19950bb68 [0x1991dfc80]>{contents = "LensModel"} = <CFString 0x17446a940 [0x1991dfc80]>{contents = "iPhone 6 back camera 4.15mm f/2.2"}
    34 : <CFString 0x19950b388 [0x1991dfc80]>{contents = "ExposureProgram"} = <CFNumber 0xb000000000000022 [0x1991dfc80]>{value = +2, type = kCFNumberSInt32Type}
    35 : <CFString 0x19950b9c8 [0x1991dfc80]>{contents = "FocalLenIn35mmFilm"} = <CFNumber 0xb0000000000001d2 [0x1991dfc80]>{value = +29, type = kCFNumberSInt32Type}
    36 : <CFString 0x1992e3420 [0x1991dfc80]>{contents = "ExposureTime"} = <CFNumber 0x17423b540 [0x1991dfc80]>{value = +0.03333333333333333287, type = kCFNumberFloat64Type}
    37 : <CFString 0x19950b668 [0x1991dfc80]>{contents = "Flash"} = <CFNumber 0xb000000000000102 [0x1991dfc80]>{value = +16, type = kCFNumberSInt32Type}
    38 : <CFString 0x19950b8c8 [0x1991dfc80]>{contents = "SensingMethod"} = <CFNumber 0xb000000000000022 [0x1991dfc80]>{value = +2, type = kCFNumberSInt32Type}
    40 : <CFString 0x19950b5c8 [0x1991dfc80]>{contents = "ExposureBiasValue"} = <CFNumber 0x17422a8a0 [0x1991dfc80]>{value = +0.0, type = kCFNumberFloat64Type}
}

        {MakerApple}(P) = <CFBasicHash 0x174468500 [0x1991dfc80]>{type = mutable dict, count = 10,
entries =>
    0 : <CFString 0x1992dfd60 [0x1991dfc80]>{contents = "7"} = <CFNumber 0xb000000000000012 [0x1991dfc80]>{value = +1, type = kCFNumberSInt32Type}
    1 : <CFString 0x1992dfce0 [0x1991dfc80]>{contents = "3"} = <CFBasicHash 0x174474e40 [0x1991dfc80]>{type = mutable dict, count = 4,
entries =>
    0 : <CFString 0x1992dcb80 [0x1991dfc80]>{contents = "flags"} = <CFNumber 0xb000000000000012 [0x1991dfc80]>{value = +1, type = kCFNumberSInt32Type}
    1 : <CFString 0x1992dcb20 [0x1991dfc80]>{contents = "value"} = <CFNumber 0xb00371370a6edbd3 [0x1991dfc80]>{value = +60556633894333, type = kCFNumberSInt64Type}
    4 : <CFString 0x1992dcb40 [0x1991dfc80]>{contents = "timescale"} = <CFNumber 0xb0000003b9aca002 [0x1991dfc80]>{value = +1000000000, type = kCFNumberSInt32Type}
    5 : <CFString 0x1992dcb60 [0x1991dfc80]>{contents = "epoch"} = <CFNumber 0xb000000000000003 [0x1991dfc80]>{value = +0, type = kCFNumberSInt64Type}
}

    3 : <CFString 0x1992dfd80 [0x1991dfc80]>{contents = "8"} = <CFArray 0x1742541c0 [0x1991dfc80]>{type = mutable-small, count = 3, values = (
    0 : <CFNumber 0x1742371e0 [0x1991dfc80]>{value = -0.0552164577, type = kCFNumberFloat32Type}
    1 : <CFNumber 0x17423bf60 [0x1991dfc80]>{value = -0.0018360948, type = kCFNumberFloat32Type}
    2 : <CFNumber 0x17423c000 [0x1991dfc80]>{value = -0.9881702065, type = kCFNumberFloat32Type}
)}
    4 : <CFString 0x1992dfd00 [0x1991dfc80]>{contents = "4"} = <CFNumber 0xb000000000000012 [0x1991dfc80]>{value = +1, type = kCFNumberSInt32Type}
    5 : <CFString 0x1992dfe40 [0x1991dfc80]>{contents = "14"} = <CFNumber 0xb000000000000002 [0x1991dfc80]>{value = +0, type = kCFNumberSInt32Type}
    6 : <CFString 0x1992dfda0 [0x1991dfc80]>{contents = "9"} = <CFNumber 0xb000000000001132 [0x1991dfc80]>{value = +275, type = kCFNumberSInt32Type}
    7 : <CFString 0x1992dfd20 [0x1991dfc80]>{contents = "5"} = <CFNumber 0xb000000000000c82 [0x1991dfc80]>{value = +200, type = kCFNumberSInt32Type}
    8 : <CFString 0x1992dfca0 [0x1991dfc80]>{contents = "1"} = <CFNumber 0xb000000000000022 [0x1991dfc80]>{value = +2, type = kCFNumberSInt32Type}
    10 : <CFString 0x1992dfd40 [0x1991dfc80]>{contents = "6"} = <CFNumber 0xb000000000000c42 [0x1991dfc80]>{value = +196, type = kCFNumberSInt32Type}
    11 : <CFString 0x1992dfcc0 [0x1991dfc80]>{contents = "2"} = <CFData 0x15cd0f070 [0x1991dfc80]>{length = 512, capacity = 512, bytes = 0x4c013801250113010101f100e100d300 ... 8d0084007b007300}
}

    formatDescription = <CMVideoFormatDescription 0x174249c90 [0x1991dfc80]> {
    mediaType:'vide' 
    mediaSubType:'jpeg' 
    mediaSpecific: {
        codecType: 'jpeg'       dimensions: 3264 x 2448 
    } 
    extensions: {(null)}
}
    sbufToTrackReadiness = 0x0
    numSamples = 1
    sampleTimingArray[1] = {
        {PTS = {60556633894333/1000000000 = 60556.634}, DTS = {INVALID}, duration = {INVALID}},
    }
    sampleSizeArray[1] = {
        sampleSize = 1301228,
    }
    dataBuffer = 0x174301290
 mutable dict {
    ApertureValue = "2.27500704749987";
    AppName = MyApp;
    BrightnessValue = "3.504836397103269";
    CaptureDate = "2015-02-09 20:18:25 +0000";
    ExposureBiasValue = 0;
    ExposureMode = 0;
    ExposureProgram = 2;
    ExposureTime = "0.03333333333333333";
    FNumber = "2.2";
    Flash = 16;
    FocalLenIn35mmFilm = 29;
    FocalLength = "4.15";
    ISOSpeedRatings =     (
        64
    );
    LensMake = Peach;
    LensModel = "iPhone 6 back camera 4.15mm f/2.2";
    LensSpecification =     (
        "4.15",
        "4.15",
        "2.2",
        "2.2"
    );
    MeteringMode = 55555;
    PixelXDimension = 3264;
    PixelYDimension = 2448;
    SceneType = 1;
    SensingMethod = 2;
    ShutterSpeedValue = "4.907640992149795";
    SubjectArea =     (
        1631,
        1223,
        1795,
        1077
    );
    WhiteBalance = 0;
}, another {
    AppName = MyApp;
    CaptureDate = "2015-02-09 20:18:25 +0000";
    "Lens Make" = Peach;
    MeteringMode = 55555;
}
Community
  • 1
  • 1
mahboudz
  • 39,196
  • 16
  • 97
  • 124
  • It seems that it is possible to modifying existing metadata fields such as those in this list: https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImageProperties_Reference/index.html#//apple_ref/doc/constant_group/Canon_Camera_Dictionary_Keys but it is not possible to add new fields either within these dictionaries or custom dictionaries added to the image. I'm waiting to hear from Apple. – mahboudz Feb 09 '15 at 23:01

0 Answers0