def gray_response(curves=None, unit=None): """ Returns the MIX GrayResponse element. :curves: The optical density of pixels as a list (of integers) :unit: The precision recorded in grayResponseCurve Returns the following ElementTree structure:: <mix:GrayResponse> <mix:grayResponseCurve>10</mix:grayResponseCurve> <mix:grayResponseUnit> Number represents tenths of a unit </mix:grayResponseUnit> </mix:GrayResponse> """ container = _element('GrayResponse') if curves: curves = _ensure_list(curves) for item in curves: curve_el = _subelement(container, 'grayResponseCurve') curve_el.text = six.text_type(item) if unit: if unit in GRAY_RESPONSE_UNITS: unit_el = _subelement(container, 'grayResponseUnit') unit_el.text = unit else: raise RestrictedElementError(unit, 'grayResponseUnit', GRAY_RESPONSE_UNITS) return container
def color_map(reference=None, embedded=None): """ Returns the MIX Colormap element. :reference: The location of the referenced color map as a string :embedded: The embedded color map as base64-encoded data Returns the following ElementTree structure:: <mix:Colormap> <mix:colormapReference>http://foo</mix:colormapReference> <mix:embeddedColormap>foo</mix:embeddedColormap> </mix:Colormap> """ container = _element('Colormap') if reference: reference_el = _subelement(container, 'colormapReference') reference_el.text = reference if embedded: embedded_el = _subelement(container, 'embeddedColormap') embedded_el.text = six.text_type(embedded) return container
def scanning_software(name=None, version=None): """ Returns the MIX ScanningSystemSoftware element. :name: The scanning software name as a string :version: The scanning software version as a string Returns the following sorted ElementTree structure:: <mix:ScanningSystemSoftware> <mix:scanningSoftwareName>foo</mix:scanningSoftwareName> <mix:scanningSoftwareVersionNo>foo</mix:scanningSoftwareVersionNo> </mix:ScanningSystemSoftware> """ container = _element('ScanningSystemSoftware') if name: name_el = _subelement(container, 'scanningSoftwareName') name_el.text = name if version: version_el = _subelement(container, 'scanningSoftwareVersionNo') version_el.text = version return container
def format_designation(format_name=None, format_version=None): """ Returns the MIX FormatDesignation element. :format_name: The file format name as a string :format_version: The file format version as a string Returns the following ElementTree structure:: <mix:FormatDesignation> <mix:formatName>image/jpeg</mix:formatName> <mix:formatVersion>1.01</mix:formatVersion> </mix:FormatDesignation> """ container = _element('FormatDesignation') if format_name: format_name_el = _subelement(container, 'formatName') format_name_el.text = format_name if format_version: format_version_el = _subelement(container, 'formatVersion') format_version_el.text = format_version return container
def format_registry(registry_name=None, registry_key=None): """ Returns the MIX FormatRegistry element. :registry_name: The file format registry name as a string :registry_key: The file format registry key as a string Returns the following ElementTree structure:: <mix:FormatRegistry> <mix:formatRegistryName>pronom</mix:formatRegistryName> <mix:formatRegistryKey>fmt/43</mix:formatRegistryKey> </mix:FormatRegistry> """ container = _element('FormatRegistry') if registry_name: registry_name_el = _subelement(container, 'formatRegistryName') registry_name_el.text = registry_name if registry_key: registry_key_el = _subelement(container, 'formatRegistryKey') registry_key_el.text = registry_key return container
def identifier(id_type=None, id_value=None): """ Returns the MIX ObjectIdentifier element. :id_type: The identifier type as a string :id_value: The identifier value as a string Returns the following ElementTree structure:: <mix:ObjectIdentifier> <mix:objectIdentifierType>local</mix:objectIdentifierType> <mix:objectIdentifierValue>foo</mix:objectIdentifierValue> </mix:ObjectIdentifier> """ container = _element('ObjectIdentifier') if id_type: id_type_el = _subelement(container, 'objectIdentifierType') id_type_el.text = id_type if id_value: id_value_el = _subelement(container, 'objectIdentifierValue') id_value_el.text = id_value return container
def image_characteristics(width=None, height=None, child_elements=None): """ Returns the MIX BasicImageCharacteristics element. :width: The image width in pixels as an integer :height: The image height in pixels as an integer :child_elements: Child elements as a list Returns the following sorted ElementTree structure:: <mix:BasicImageCharacteristics> <mix:imageWidth>20</mix:imageWidth> <mix:imageHeight>10</mix:imageHeight> <mix:PhotometricInterpretation/> </mix:BasicImageCharacteristics> """ container = _element('BasicImageCharacteristics') if width: width_el = _subelement(container, 'imageWidth') width_el.text = six.text_type(width) if height: height_el = _subelement(container, 'imageHeight') height_el.text = six.text_type(height) if child_elements: for element in child_elements: container.append(element) return container
def bits_per_sample(sample_values=None, sample_unit=None): """ Returns the MIX BitsPerSample element. :sample_values: The bits per sample values as a list :sample_unit: The bits per sample unit as a string Returns the following ElementTree structure:: <mix:BitsPerSample> <mix:bitsPerSampleValue>8</mix:bitsPerSampleValue> <mix:bitsPerSampleUnit>integer</mix:bitsPerSampleUnit> </mix:BitsPerSample> """ container = _element('BitsPerSample') if sample_values: sample_values = _ensure_list(sample_values) for item in sample_values: value_el = _subelement(container, 'bitsPerSampleValue') value_el.text = six.text_type(item) if sample_unit: if sample_unit in BITS_PER_SAMPLE_UNITS: unit_el = _subelement(container, 'bitsPerSampleUnit') unit_el.text = sample_unit else: raise RestrictedElementError(sample_unit, 'bitsPerSampleUnit', BITS_PER_SAMPLE_UNITS) return container
def source_id(source_idtype=None, source_idvalue=None): """ Returns the MIX SourceID element. :source_idtype: The source ID type as a string :source_idvalue: The source ID value as a string Returns the following sorted ElementTree structure:: <mix:SourceID> <mix:sourceIDType>local</mix:sourceIDType> <mix:sourceIDValue>foo</mix:sourceIDValue> </mix:SourceID> """ container = _element('SourceID') if source_idtype: source_idtype_el = _subelement(container, 'sourceIDType') source_idtype_el.text = source_idtype if source_idvalue: source_idvalue_el = _subelement(container, 'sourceIDValue') source_idvalue_el.text = source_idvalue return container
def spatial_metrics(plane=None, unit=None, x_sampling=None, y_sampling=None): """ Returns the MIX SpatialMetrics element. :plane: The sampling frequency plane as a string :unit: The sampling frequency unit as a string :x_sampling: The y sampling frequency as a list (or integer) :y_sampling: The x sampling frequency as a list (or integer) Returns the following ElementTree structure:: <mix:SpatialMetrics> <mix:samplingFrequencyPlane> object plane </mix:samplingFrequencyPlane> <mix:samplingFrequencyUnit>cm</mix:samplingFrequencyUnit> <mix:xSamplingFrequency> <mix:numerator>10</mix:numerator> <mix:denominator>1</mix:denominator> </mix:xSamplingFrequency> <mix:ySamplingFrequency> <mix:numerator>10</mix:numerator> <mix:denominator>1</mix:denominator> </mix:ySamplingFrequency> </mix:SpatialMetrics> """ container = _element('SpatialMetrics') if plane: plane_el = _subelement(container, 'samplingFrequencyPlane') if plane in SAMPLING_FREQUENCY_PLANES: plane_el.text = plane else: raise RestrictedElementError(plane, 'samplingFrequencyPlane', SAMPLING_FREQUENCY_PLANES) if unit: unit_el = _subelement(container, 'samplingFrequencyUnit') if unit in SAMPLING_FREQUENCY_UNITS: unit_el.text = unit else: raise RestrictedElementError(unit, 'samplingFrequencyUnit', SAMPLING_FREQUENCY_UNITS) if x_sampling: _rationaltype_element('xSamplingFrequency', x_sampling, parent=container) if y_sampling: _rationaltype_element('ySamplingFrequency', y_sampling, parent=container) return container
def processing_software(name=None, version=None, os_name=None, os_version=None): """ Returns the MIX ProcessingSoftware element. :name: The processing software name as a string :version: The processing software version as a string :os_name: The operating system name as a string :os_version: The operating system version as a string Returns the following ElementTree structure:: <mix:ProcessingSoftware> <mix:processingSoftwareName> my software </mix:processingSoftwareName> <mix:processingsoftwareversion> 1.0 </mix:processingsoftwareversion> <mix:processingOperatingSystemName> CentOS </mix:processingOperatingSystemName> <mix:processingOperatingSystemVersion> 7.0 </mix:processingOperatingSystemVersion> </mix:ProcessingSoftware> """ container = _element('ProcessingSoftware') if name: name_el = _subelement(container, 'processingSoftwareName') name_el.text = name if version: version_el = _subelement(container, 'processingSoftwareVersion') version_el.text = version if os_name: os_name_el = _subelement(container, 'processingOperatingSystemName') os_name_el.text = os_name if os_version: os_version_el = _subelement(container, 'processingOperatingSystemVersion') os_version_el.text = os_version return container
def compression(compression_scheme=None, local_list=None, local_value=None, compression_ratio=None): """ Returns the MIX Compression element. :compression_scheme: The compression scheme as a string :local_list: The location of the local enumerated list of compression schemes as a string :local_value: The local compression scheme as a string :compression_ratio: The compression ratio as a list (or integer) Returns the following ElementTree structure:: <mix:Compression> <mix:compressionScheme> JPEG 2000 Lossless </mix:compressionScheme> <mix:compressionSchemeLocalList> </mix:compressionSchemeLocalList> <mix:compressionSchemeLocalValue> </mix:compressionSchemeLocalValue> <mix:compressionRatio> <mix:numerator>10</mix:numerator> <mix:denominator>1</mix:denominator> </mix:compressionRatio> </mix:Compression> """ container = _element('Compression') if compression_scheme: compression_scheme_el = _subelement(container, 'compressionScheme') compression_scheme_el.text = compression_scheme if compression_scheme == 'enumerated in local list': local_list_el = _subelement(container, 'compressionSchemeLocalList') local_list_el.text = local_list local_value_el = _subelement(container, 'compressionSchemeLocalValue') local_value_el.text = local_value if compression_ratio: _rationaltype_element('compressionRatio', compression_ratio, parent=container) return container
def djvu(djvu_format=None): """ Returns the MIX Djvu element. Djvu format supports only a specific set of types. :djvu_format: The DjVu file format as a string Returns the following ElementTree structure:: <mix:Djvu> <mix:djvuFormat>indirect</mix:djvuFormat> </mix:Djvu> """ container = _element('Djvu') if djvu_format: if djvu_format in DJVU_FORMATS: djvu_format_el = _subelement(container, 'djvuFormat') djvu_format_el.text = djvu_format else: raise RestrictedElementError(djvu_format, 'djvuFormat', DJVU_FORMATS) return container
def photometric_interpretation(color_space=None, child_elements=None): """" Returns the MIX PhotometricInterpretation element. :color_space: The color space as a string :child_elements: Child elements as a list Returns the following sorted ElementTree structure:: <mix:PhotometricInterpretation> <mix:colorSpace>RGB</mix:colorSpace> <mix:ColorProfile/> <mix:YCbCr/> <mix:ReferenceBlackWhite/> </mix:PhotometricInterpretation> """ container = _element('PhotometricInterpretation') if color_space: color_space_el = _subelement(container, 'colorSpace') color_space_el.text = color_space if child_elements: child_elements.sort(key=photom_interpret_order) for element in child_elements: container.append(element) return container
def device_model(device_type, name=None, number=None, serialno=None): """ Returns either the MIX ScannerModel or the DigitalCameraModel element depending on the device_type. :device_type: The type of capture device, e.g. 'scanner' or 'camera' :name: The model name of the capture device as a string :number: The model number of the capture device as a string :serialno: The serial number of the capture device as a string """ prefixes = {'scanner': 'scanner', 'camera': 'digitalCamera'} if device_type not in prefixes: raise ValueError('Invalid value. Only "scanner" or "camera" are ' 'valid device types.') container = _element('model', prefix=prefixes[device_type][0].capitalize() + prefixes[device_type][1:]) if name: device_name_el = _subelement(container, 'modelName', prefix=prefixes[device_type]) device_name_el.text = name if number: device_number_el = _subelement(container, 'modelNumber', prefix=prefixes[device_type]) device_number_el.text = number if serialno: device_serialno_el = _subelement(container, 'modelSerialNo', prefix=prefixes[device_type]) device_serialno_el.text = serialno return container
def target_id(manufacturer=None, name=None, target_no=None, media=None): """ Returns MIX TargetID element. :manufacturer: The target manufacturer as a string :name: The target name as a string :target_no: The target version or number as a string :media: The target media as a string Returns the following ElementTree structure:: <mix:TargetID> <mix:targetManufacturer>acme</mix:targetManufacturer> <mix:targetName>my target</mix:targetName> <mix:targetNo>1.0</mix:targetNo> <mix:targetMedia>foo</mix:targetMedia> </mix:TargetID> """ container = _element('TargetID') if manufacturer: manufacturer_el = _subelement(container, 'targetManufacturer') manufacturer_el.text = manufacturer if name: name_el = _subelement(container, 'targetName') name_el.text = name if target_no: target_no_el = _subelement(container, 'targetNo') target_no_el.text = target_no if media: media_el = _subelement(container, 'targetMedia') media_el.text = media return container
def capture_information(created=None, producer=None, device=None): """ Returns the MIX GeneralCaptureInformation element. :created: The image datetime created as a string :producer: The image producer as a string :device: The image creation device classification as a string Returns the following sorted ElementTree structure:: <mix:GeneralCaptureInformation> <mix:dateTimeCreated>foo</mix:dateTimeCreated> <mix:imageProducer>foo</mix:imageProducer> <mix:captureDevice>foo</mix:captureDevice> </mix:GeneralCaptureInformation> """ container = _element('GeneralCaptureInformation') if created: created_el = _subelement(container, 'dateTimeCreated') created_el.text = created if producer: producer = _ensure_list(producer) for item in producer: producer_el = _subelement(container, 'imageProducer') producer_el.text = item if device: if device in CAPTURE_DEVICE_TYPES: device_el = _subelement(container, 'captureDevice') device_el.text = device else: raise RestrictedElementError(device, 'captureDevice', CAPTURE_DEVICE_TYPES) return container
def fixity(algorithm=None, digest=None, originator=None): """ Returns the MIX Fixity element. :algorithm: The message digest algorithm as a string :digest: The message digest as a string :originator: The message digest creator agent as a string Returns the following ElementTree structure:: <mix:Fixity> <mix:messageDigestAlgorithm>MD5</mix:messageDigestAlgorithm> <mix:messageDigest>foo</mix:messageDigest> <mix:messageDigestOriginator>foo</mix:messageDigestOriginator> </mix:Fixity> """ container = _element('Fixity') if algorithm: if algorithm in DIGEST_ALGORITHMS: algorithm_el = _subelement(container, 'messageDigestAlgorithm') algorithm_el.text = algorithm else: raise RestrictedElementError(algorithm, 'messageDigestAlgorithm', DIGEST_ALGORITHMS) if digest: digest_el = _subelement(container, 'messageDigest') digest_el.text = digest if originator: originator_el = _subelement(container, 'messageDigestOriginator') originator_el.text = originator return container
def max_optical_resolution(x_resolution=None, y_resolution=None, unit=None): """ Returns the MIX MaximumOpticalResolution element. :x_resolution: The x resolution of the scanning sensor as an integer :y_resolution: The y resolution of the scanning sensor as an integer :unit: The unit of the scanning sensor resolution as a string Returns the following sorted ElementTree structure:: <mix:MaximumOpticalResolution> <mix:xOpticalResolution>foo</mix:xOpticalResolution> <mix:yOpticalResolution>foo</mix:yOpticalResolution> <mix:opticalResolutionUnit>foo</mix:opticalResolutionUnit> </mix:MaximumOpticalResolution> """ container = _element('MaximumOpticalResolution') if x_resolution: x_resolution_el = _subelement(container, 'xOpticalResolution') x_resolution_el.text = six.text_type(x_resolution) if y_resolution: y_resolution_el = _subelement(container, 'yOpticalResolution') y_resolution_el.text = six.text_type(y_resolution) if unit: if unit in OPTICAL_RESOLUTION_UNITS: unit_el = _subelement(container, 'opticalResolutionUnit') unit_el.text = unit else: raise RestrictedElementError(unit, 'opticalResolutionUnit', OPTICAL_RESOLUTION_UNITS) return container
def test_subelement(): """ Tests the _subelement function by asserting that the element was created correctly as a child element of its given parent element and that the parent element contains the created subelement. """ elem = _element('test') subelem = _subelement(elem, 'test', 'pre') assert subelem.tag == '{http://www.loc.gov/mix/v20}preTest' assert subelem.getparent() == elem assert elem.xpath('./*')[0] == subelem assert len(elem) == 1 assert ET.tostring(elem) == ET.tostring(ET.fromstring( '<mix:test xmlns:mix="http://www.loc.gov/mix/v20">' '<mix:preTest/></mix:test>'))
def component(c_photometric_interpretation=None, footroom=None, headroom=None): """ Returns MIX Component element. :c_photometric_interpretation: The component photometric interpretation type as a string :footroom: The footroom as a list (or integer) :headroom: The headroom as a list (or integer) Returns the following ElementTree structure:: <mix:Component> <mix:componentPhotometricInterpretation> R </mix:componentPhotometricInterpretation> <mix:footroom> <mix:numerator>10</mix:numerator> <mix:denominator>1</mix:denominator> </mix:footroom> <mix:headroom> <mix:numerator>20</mix:numerator> <mix:denominator>1</mix:denominator> </mix:headroom> </mix:Component> """ container = _element('Component') if c_photometric_interpretation: if c_photometric_interpretation in COMPONENT_INTERPRETATION_TYPES: cpi_el = _subelement(container, 'componentPhotometricInterpretation') cpi_el.text = c_photometric_interpretation else: raise RestrictedElementError(c_photometric_interpretation, 'componentPhotometricInterpretation', COMPONENT_INTERPRETATION_TYPES) if footroom: _rationaltype_element('footroom', footroom, parent=container) if headroom: _rationaltype_element('headroom', headroom, parent=container) return container
def mrsid(zoom_levels=None): """ Returns the MIX MrSID element. :zoom_levels: The number of available zoom levels as an integer Returns the following ElementTree structure:: <mix:MrSID> <mix:zoomLevels>3</mix:zoomLevels> </mix:MrSID> """ container = _element('MrSID') if zoom_levels: zoom_levels_el = _subelement(container, 'zoomLevels') zoom_levels_el.text = six.text_type(zoom_levels) return container
def jpeg2000(codec=None, codec_version=None, codestream_profile=None, compliance_class=None, tile_width=None, tile_height=None, quality_layers=None, resolution_levels=None): """ Returns the MIX JPEG2000 element. :codec: The codec name as a string :codec_version: The codec version as a string :codestream_profile: The codestream profile as a string :compliance_class: The compliance class as a string :tile_width: The width in pixels of the tiles as an integer :tile_height: The height in pixels of the tiles as an integer :quality_layers: The number of quality layers as an integer :resolution_levels: The number of lower resolution levels as an integer Returns the following ElementTree structure:: <mix:JPEG2000> <mix:CodecCompliance> <mix:codec></mix:codec> <mix:codecVersion></mix:codecVersion> <mix:codestreamProfile></mix:codestreamProfile> <mix:complianceClass></mix:complianceClass> </mix:CodecCompliance> <mix:EncodingOptions> <mix:Tiles> <mix:tileWidth>2</mix:tileWidth> <mix:tileHeight>2</mix:tileHeight> </mix:Tiles> <mix:qualityLayers>10</mix:qualityLayers> <mix:resolutionLevels>10</mix:resolutionLevels> </mix:EncodingOptions> </mix:JPEG2000> """ container = _element('JPEG2000') if codec or codec_version or codestream_profile or compliance_class: codec_container = _subelement(container, 'CodecCompliance') if codec: codec_el = _subelement(codec_container, 'codec') codec_el.text = codec if codec_version: codec_version_el = _subelement(codec_container, 'codecVersion') codec_version_el.text = codec_version if codestream_profile: codestream_profile_el = _subelement(codec_container, 'codestreamProfile') codestream_profile_el.text = codestream_profile if compliance_class: compliance_class_el = _subelement(codec_container, 'complianceClass') compliance_class_el.text = compliance_class tiles_container = None if tile_width or tile_height: tiles_container = _element('Tiles') if tile_width: tile_width_el = _subelement(tiles_container, 'tileWidth') tile_width_el.text = six.text_type(tile_width) if tile_height: tile_height_el = _subelement(tiles_container, 'tileHeight') tile_height_el.text = six.text_type(tile_height) if tiles_container is not None or quality_layers or resolution_levels: encoding_options = _subelement(container, 'EncodingOptions') if tiles_container is not None: encoding_options.append(tiles_container) if quality_layers: quality_layers_el = _subelement(encoding_options, 'qualityLayers') quality_layers_el.text = six.text_type(quality_layers) if resolution_levels: resolution_levels_el = _subelement(encoding_options, 'resolutionLevels') resolution_levels_el.text = six.text_type(resolution_levels) return container
def ycbcr(subsample_horiz=None, subsample_vert=None, positioning=None, luma_red=None, luma_green=None, luma_blue=None): """ Returns the MIX YCbCr element and its subelements. :subsample_horiz: The horizontal subsample factor as a string :subsample_vert: The vertical subsample factor as a string :positioning: The positions of subsamples as a string :luma_red: The red luminance value as a list (or integer) :luma_green: The green luminane value as a list (or integer) :luma_blue: The blue luminance value as a list (or integer) Returns the following sorted ElementTree structure:: <mix:YCbCr> <mix:YCbCrSubSampling> <mix:yCbCrSubsampleHoriz>1</mix:yCbCrSubsampleHoriz> <mix:yCbCrSubsampleVert>2</mix:yCbCrSubsampleVert> </mix:YCbCrSubSampling/> <mix:yCbCrPositioning>1</mix:yCbCrPositioning> <mix:YCbCrCoefficients> <mix:lumaRed> <mix:numerator>10</mix:numerator> <mix:denominator>1</mix:denominator> </mix:lumaRed> <mix:lumaGreen> <mix:numerator>20</mix:numerator> <mix:denominator>1</mix:denominator> </mix:lumaGreen> <mix:lumaBlue> <mix:numerator>30</mix:numerator> <mix:denominator>1</mix:denominator> </mix:lumaBlue> </mix:YCbCrCoefficients/> </mix:YCbCr> """ container = _element('YCbCr') if subsample_horiz or subsample_vert: subsample_container = _subelement(container, 'YCbCrSubSampling') if subsample_horiz: if subsample_horiz in YCBCR_SUBSAMPLE_TYPES: subsample_horiz_el = _subelement(subsample_container, 'yCbCrSubsampleHoriz') subsample_horiz_el.text = subsample_horiz else: raise RestrictedElementError(subsample_horiz, 'yCbCrSubsampleHoriz', YCBCR_SUBSAMPLE_TYPES) if subsample_vert: if subsample_vert in YCBCR_SUBSAMPLE_TYPES: subsample_vert_el = _subelement(subsample_container, 'yCbCrSubsampleVert') subsample_vert_el.text = subsample_vert else: raise RestrictedElementError(subsample_vert, 'yCbCrSubsampleVert', YCBCR_SUBSAMPLE_TYPES) if positioning: if positioning in YCBCR_POSITIONING_TYPES: positioning_el = _subelement(container, 'yCbCrPositioning') positioning_el.text = positioning else: raise RestrictedElementError(positioning, 'yCbCrPositioning', YCBCR_POSITIONING_TYPES) if luma_red or luma_green or luma_blue: luma_container = _subelement(container, 'YCbCrCoefficients') if luma_red: _rationaltype_element('lumaRed', luma_red, parent=luma_container) if luma_green: _rationaltype_element('lumaGreen', luma_green, parent=luma_container) if luma_blue: _rationaltype_element('lumaBlue', luma_blue, parent=luma_container) return container
def color_profile(icc_name=None, icc_version=None, icc_uri=None, local_name=None, local_url=None, embedded_profile=None): """ Returns the MIX ColorProfile element and its subelements. :icc_name: The name of the used ICC profile as a string :icc_version: The version of the used ICC profile as a string :icc_uri: The URL/URN of the used ICC profile as a string :local_name: The name of the used local color profile as a string :local_url: The URL/URN of the used local color profile as a string :embedded_profile: The embedded color profile as base64-encoded data Returns the following sorted ElementTree structure:: <mix:ColorProfile> <mix:IccProfile> <mix:iccProfileName>sRGB</mix:iccProfileName> <mix:iccProfileVersion>1</mix:iccProfileVersion> <mix:iccProfileURI>http://...</mix:iccProfileURI> </mix:IccProfile/> <mix:LocalProfile> <mix:localProfileName>local RGB</mix:localProfileName> <mix:localProfileURL>http://...</mix:localProfileURL> </mix:LocalProfile/> <mix:embeddedProfile> [Base64-encoded data] </mix:embeddedProfile> </mix:ColorProfile> """ container = _element('ColorProfile') if icc_name or icc_version or icc_uri: icc_container = _subelement(container, 'IccProfile') if icc_name: icc_name_el = _subelement(icc_container, 'iccProfileName') icc_name_el.text = icc_name if icc_version: icc_version_el = _subelement(icc_container, 'iccProfileVersion') icc_version_el.text = icc_version if icc_uri: icc_uri_el = _subelement(icc_container, 'iccProfileURI') icc_uri_el.text = icc_uri if local_name or local_url: local_container = _subelement(container, 'LocalProfile') if local_name: local_name_el = _subelement(local_container, 'localProfileName') local_name_el.text = local_name if local_url: local_url_el = _subelement(local_container, 'localProfileURL') local_url_el.text = local_url if embedded_profile: embedded_profile_el = _subelement(container, 'embeddedProfile') embedded_profile_el.text = six.text_type(embedded_profile) return container
def source_size(x_value=None, x_unit=None, y_value=None, y_unit=None, z_value=None, z_unit=None): """ Returns the MIX SourceSize element. :x_value: The source X value (width) as an integer :x_unit: The unit of the source X value (width) as a string :y_value: The source Y value (height) as an integer :y_unit: The unit of the source Y value (height) as a string :z_value: The source Z value (depth) as an integer :z_unit: The unit of the source z value (depth) as a string Returns the following sorted ElementTree structure:: <mix:SourceSize> <mix:SourceXDimension> <mix:sourceXDimensionValue>1.23</mix:sourceXDimensionValue> <mix:sourceXDimensionUnit>mm.</mix:sourceXDimensionUnit> </mix:SourceXDimension> <mix:SourceYDimension> <mix:sourceYDimensionValue>1.23</mix:sourceXDimensionValue> <mix:sourceYDimensionUnit>mm.</mix:sourceXDimensionUnit> </mix:SourceYDimension> <mix:SourceZDimension> <mix:sourceZDimensionValue>1.23</mix:sourceXDimensionValue> <mix:sourceZDimensionUnit>mm.</mix:sourceXDimensionUnit> </mix:SourceZDimension> </mix:SourceSize> """ container = _element('SourceSize') if x_value or x_unit: x_dimension = _subelement(container, 'SourceXDimension') if x_value: x_value_el = _subelement(x_dimension, 'sourceXDimensionValue') x_value_el.text = x_value if x_unit: if x_unit in DIMENSION_UNITS: x_unit_el = _subelement(x_dimension, 'sourceXDimensionUnit') x_unit_el.text = x_unit else: raise RestrictedElementError(x_unit, 'sourceXDimensionUnit', DIMENSION_UNITS) if y_value or y_unit: y_dimension = _subelement(container, 'SourceYDimension') if y_value: y_value_el = _subelement(y_dimension, 'sourceYDimensionValue') y_value_el.text = y_value if y_unit: if y_unit in DIMENSION_UNITS: y_unit_el = _subelement(y_dimension, 'sourceYDimensionUnit') y_unit_el.text = y_unit else: raise RestrictedElementError(y_unit, 'sourceYDimensionUnit', DIMENSION_UNITS) if z_value or z_unit: z_dimension = _subelement(container, 'SourceZDimension') if z_value: z_value_el = _subelement(z_dimension, 'sourceZDimensionValue') z_value_el.text = z_value if z_unit: if z_unit in DIMENSION_UNITS: z_unit_el = _subelement(z_dimension, 'sourceZDimensionUnit') z_unit_el.text = z_unit else: raise RestrictedElementError(z_unit, 'sourceZDimensionUnit', DIMENSION_UNITS) return container
def image_data(contents=None): """ Returns the MIX ImageData element. The function argument contents is a dict, that can be retrieved from nisomix.IMAGE_DATA_CONTENTS. The keys from contents are matched to create the MIX element and its substructure. The dict should look like this:: contents = {"fnumber": None, "exposure_time": None, "exposure_program": None, "spectral_sensitivity": None, "isospeed_ratings": None, "oecf": None, "exif_version": None, "shutter_speed_value": None, "aperture_value": None, "brightness_value": None, "exposure_bias_value": None, "max_aperture_value": None, "distance": None, "min_distance": None, "max_distance": None, "metering_mode": None, "light_source": None, "flash": None, "focal_length": None, "flash_energy": None, "back_light": None, "exposure_index": None, "sensing_method": None, "cfa_pattern": None, "auto_focus": None, "x_print_aspect_ratio": None, "y_print_aspect_ratio": None} """ tags = { 'fnumber': 'fNumber', 'exposure_time': 'exposureTime', 'exposure_program': 'exposureProgram', 'isospeed_ratings': 'isoSpeedRatings', 'exif_version': 'exifVersion', 'metering_mode': 'meteringMode', 'light_source': 'lightSource', 'flash': 'flash', 'focal_length': 'focalLength', 'back_light': 'backLight', 'exposure_index': 'exposureIndex', 'sensing_method': 'sensingMethod', 'cfa_pattern': 'cfaPattern', 'auto_focus': 'autoFocus' } rationals = { 'oecf': 'oECF', 'shutter_speed_value': 'shutterSpeedValue', 'aperture_value': 'apertureValue', 'brightness_value': 'brightnessValue', 'exposure_bias_value': 'exposureBiasValue', 'max_aperture_value': 'maxApertureValue', 'flash_energy': 'flashEnergy' } for key in contents: if key not in IMAGE_DATA_CONTENTS: raise ValueError('Key "%s" not in supported keys for ' 'image_data.' % key) container = _element('ImageData') child_elements = [] for key, value in six.iteritems(contents): if key in tags and value: elem = _element(tags[key]) elem.text = six.text_type(value) child_elements.append(elem) if key in rationals and value: elem = _rationaltype_element(rationals[key], value) child_elements.append(elem) if contents.get("spectral_sensitivity"): spect_sens = _ensure_list(contents["spectral_sensitivity"]) for item in spect_sens: spect_sens_el = _element('spectralSensitivity') spect_sens_el.text = item child_elements.append(spect_sens_el) if contents.get("distance") or contents.get("min_distance") \ or contents.get("max_distance"): subject_distance = _element('SubjectDistance') child_elements.append(subject_distance) if contents.get("distance"): distance_el = _subelement(subject_distance, 'distance') distance_el.text = contents["distance"] if contents.get("min_distance") or contents.get("max_distance"): min_max_distance = _subelement(subject_distance, 'MinMaxDistance') if contents.get("min_distance"): min_distance_el = _subelement(min_max_distance, 'minDistance') min_distance_el.text = contents["min_distance"] if contents.get("max_distance"): max_distance_el = _subelement(min_max_distance, 'maxDistance') max_distance_el.text = contents["max_distance"] if contents.get("x_print_aspect_ratio") or \ contents.get("y_print_aspect_ratio"): print_ratio = _element('PrintAspectRatio') child_elements.append(print_ratio) if contents.get("x_print_aspect_ratio"): x_print_aspect_ratio_el = _subelement(print_ratio, 'xPrintAspectRatio') x_print_aspect_ratio_el.text = contents["x_print_aspect_ratio"] if contents.get("y_print_aspect_ratio"): y_print_aspect_ratio_el = _subelement(print_ratio, 'yPrintAspectRatio') y_print_aspect_ratio_el.text = contents["y_print_aspect_ratio"] child_elements.sort(key=image_data_order) for element in child_elements: container.append(element) return container