dahlia/wand — pull request #56 by wronglink (2012-09-13 13:01:37+00:00)
Title: Metadata support

Added dict-like `metadata` property to `Image` class. It allows to iterate metadata properties and get their values.

At first I wanted to make a normal dict-like object (with setting and deleting metadata header options). But unfortunately ImageMagick [doesn't support](http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=14234&p=49078) writing of image properties to file. So it sets and deletes options, but it doesn't save any changes to metadata (even if image is saved to a new file).

Here are some usage examples:

```python
>>> img = Image(filename='/Users/wronglink/Src/wand/wandtests/assets/beach.jpg')
>>> #count metadata headers
>>> len(img.metadata)
52
>>> #get list of available metadata headers
>>> list(img.metadata)
['date:create', 'date:modify', 'exif:ApertureValue', 'exif:ColorSpace',
'exif:ComponentsConfiguration', 'exif:CompressedBitsPerPixel',
'exif:Compression', 'exif:CustomRendered', 'exif:DateTime',
'exif:DateTimeDigitized', 'exif:DateTimeOriginal', 'exif:DigitalZoomRatio',
'exif:ExifImageLength', 'exif:ExifImageWidth', 'exif:ExifOffset',
'exif:ExifVersion', 'exif:ExposureBiasValue', 'exif:ExposureMode',
'exif:ExposureTime', 'exif:FileSource', 'exif:Flash', 'exif:FlashPixVersion',
'exif:FNumber', 'exif:FocalLength', 'exif:FocalPlaneResolutionUnit',
'exif:FocalPlaneXResolution', 'exif:FocalPlaneYResolution',
'exif:InteroperabilityIndex', 'exif:InteroperabilityOffset',
'exif:InteroperabilityVersion', 'exif:ISOSpeedRatings',
'exif:JPEGInterchangeFormat', 'exif:JPEGInterchangeFormatLength', 'exif:Make',
'exif:MakerNote', 'exif:MaxApertureValue', 'exif:MeteringMode', 'exif:Model',
'exif:Orientation', 'exif:RelatedImageLength', 'exif:RelatedImageWidth',
'exif:ResolutionUnit', 'exif:SceneCaptureType', 'exif:SensingMethod',
'exif:ShutterSpeedValue', 'exif:UserComment', 'exif:WhiteBalance',
'exif:XResolution', 'exif:YCbCrPositioning', 'exif:YResolution',
'jpeg:colorspace', 'jpeg:sampling-factor']
>>> #work with specific headers
>>> 'exif:ApertureValue' in img.metadata
True
>>> 'exif:UnknownValue' in img.metadata
False
>>> img.metadata.get('exif:ApertureValue')
'192/32'
>>> img.metadata.get('exif:UnknownValue', "I don't know")
"I don't know"
>>> #iterate all metadata values
>>> for i in img.metadata.keys():
... print i + ": " + img.metadata[i]
...
...
date:create: 2012-08-14T12:58:35+06:00
date:modify: 2012-08-14T12:58:35+06:00
exif:ApertureValue: 192/32
exif:ColorSpace: 1
exif:ComponentsConfiguration: 1, 2, 3, 0
exif:CompressedBitsPerPixel: 2/1
exif:Compression: 6
exif:CustomRendered: 0
exif:DateTime: 2012:05:08 12:11:35
exif:DateTimeDigitized: 2011:03:11 11:52:47
exif:DateTimeOriginal: 2011:03:11 11:52:47
exif:DigitalZoomRatio: 3072/3072
exif:ExifImageLength: 600
exif:ExifImageWidth: 800
exif:ExifOffset: 186
exif:ExifVersion: 48, 50, 50, 48
exif:ExposureBiasValue: 0/3
exif:ExposureMode: 0
exif:ExposureTime: 1/400
exif:FileSource: 3
exif:Flash: 24
exif:FlashPixVersion: 48, 49, 48, 48
exif:FNumber: 80/10
exif:FocalLength: 5800/1000
exif:FocalPlaneResolutionUnit: 2
exif:FocalPlaneXResolution: 3072000/225
exif:FocalPlaneYResolution: 2304000/169
exif:InteroperabilityIndex: R98
exif:InteroperabilityOffset: 3338
exif:InteroperabilityVersion: 48, 49, 48, 48
exif:ISOSpeedRatings: 80
exif:JPEGInterchangeFormat: 3486
exif:JPEGInterchangeFormatLength: 4896
exif:Make: Canon
exif:MakerNote: 26, 0, 1, 0, 3, 0, 46, 0, 0, 0, 230,
# ... other values ...
4, 0, 9, 0,
exif:MaxApertureValue: 95/32
exif:MeteringMode: 5
exif:Model: Canon PowerShot SD750
exif:Orientation: 1
exif:RelatedImageLength: 3072
exif:RelatedImageWidth: 2304
exif:ResolutionUnit: 2
exif:SceneCaptureType: 0
exif:SensingMethod: 2
exif:ShutterSpeedValue: 277/32
exif:UserComment: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
# ... other values ...
0, 0, 0, 0, 0, 0, 0
exif:WhiteBalance: 0
exif:XResolution: 72/1
exif:YCbCrPositioning: 1
exif:YResolution: 72/1
jpeg:colorspace: 2
jpeg:sampling-factor: 2x2,1x1,1x1
```