xmp 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +9 -5
- data/.rspec +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +27 -0
- data/README.md +8 -5
- data/lib/xmp/convenience.rb +1 -1
- data/lib/xmp/document.rb +14 -5
- data/lib/xmp/error.rb +0 -1
- data/lib/xmp/handler/exifr_jpeg.rb +15 -0
- data/lib/xmp/handler/exifr_tiff.rb +14 -0
- data/lib/xmp/namespace.rb +2 -2
- data/lib/xmp/version.rb +1 -1
- data/lib/xmp.rb +4 -2
- data/spec/document_spec.rb +18 -0
- data/spec/exifr_jpeg_spec.rb +4 -1
- data/spec/exifr_tiff_spec.rb +4 -1
- data/spec/fixtures/no-xmp-metadata.jpg +0 -0
- data/spec/fixtures/no-xmp-metadata.tiff +0 -0
- data/spec/fixtures/xmp-with-empty-attribute.xml +240 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/xmp_spec.rb +35 -1
- data/xmp.gemspec +4 -3
- metadata +31 -6
- data/lib/xmp/handler/exifr.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08b4db6fe980f2c71919cc1c18c5890aede35ae7314c63e3831da8acb297d631'
|
4
|
+
data.tar.gz: 1d98136da2cec12516e85fb8e7b0e70bd3fe95311c7a03c09b630e8cd7cc129a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6f9598473a15eb47e65ce5659810576eafecafb8c399abcbecc07f8e1a6c3e64f0f386a4363830706ca4ddb2be1809406b1df4a245fefbf31076bf6c7b42b21
|
7
|
+
data.tar.gz: 3061122b945a464fe39d23ce115dfe2df0617f570f76ba8858d90a5bc12d0113de3d2a13fafaded4652eaf8f78eddcfb36644baca2505b416d1893128efee6cf
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.3.5
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [Unreleased]
|
4
|
+
|
5
|
+
TBA
|
6
|
+
|
7
|
+
## 2.0.0
|
8
|
+
|
9
|
+
- `XMP.new` and `.parse` return an empty XMP::Document when a JPEG or TIFF image has no XMP metadata.
|
10
|
+
(In 0.2 and earlier, those methods returned `nil` in that case.
|
11
|
+
In 1.0 and 1.0.1 they intended to raise a custom exception, but raised `NoMethodError`.)
|
12
|
+
- Add `XMP::Document#empty?`
|
13
|
+
|
14
|
+
## 1.0.1
|
15
|
+
|
16
|
+
- Reinstate support for Ruby 2.6 (the version included with current macOS, macOS 14, Sonoma)
|
17
|
+
- Fix unintended exception, introduced in 1.0, in `XMP::Document#respond_to_missing?` and
|
18
|
+
`XMP::Namespace#respond_to_missing?`
|
19
|
+
|
20
|
+
## 1.0
|
21
|
+
|
22
|
+
- Support TIFF images
|
23
|
+
- Support standalone properties with attributes, for example `Iptc4xmpCore.CreatorContactInfo`
|
24
|
+
- Namespaces and attributes may be accessed with more Ruby-style underscore identifiers,
|
25
|
+
for example ExampleNamespace as example_namespace
|
26
|
+
- `XMP.new` and `.parse` accept `Pathname` and `File` as well as a `String` path
|
27
|
+
- Remove support for Ruby 2.6 and earlier
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# xmp - Extensible Metadata Platform (XMP) parser
|
2
2
|
|
3
|
-
|
3
|
+
XMP provides an object oriented interface to [XMP data](http://en.wikipedia.org/wiki/Extensible_Metadata_Platform). XMP data can be found in PDF, JPEG, GIF, PNG, and many other formats.
|
4
4
|
|
5
5
|
## Supported Formats
|
6
6
|
|
@@ -59,9 +59,12 @@ gem 'exifr', '~> 1.3'
|
|
59
59
|
```
|
60
60
|
|
61
61
|
## Requirements
|
62
|
-
* Ruby 2 or Ruby 3
|
63
|
-
*
|
64
|
-
*
|
62
|
+
* Ruby 2 (supported on >= 2.6, though xmp may work on earlier versions) or Ruby 3
|
63
|
+
* nokogiri (>= 1.10). The xmp gem depends on this gem. It will be installed automatically.
|
64
|
+
* On Ruby 2.6, nokogiri 1.13.10 will be installed; nokogiri >= 1.14 require Ruby 2.7.
|
65
|
+
* On Ruby 2.7, nokogiri 1.15.5 will be installed; nokogiri >= 1.16 require Ruby 3.
|
66
|
+
* See https://nokogiri.org/CHANGELOG.html for nokogiri support for older or newer Ruby versions.
|
67
|
+
* exifr (>= 1.3). This gem is optional. If you need it, add it to your Gemfile.
|
65
68
|
|
66
69
|
## Development
|
67
70
|
|
@@ -73,6 +76,6 @@ $ rake spec # run specs
|
|
73
76
|
```
|
74
77
|
|
75
78
|
## License
|
76
|
-
Ruby's license.
|
79
|
+
[Ruby's license.](https://www.ruby-lang.org/en/about/license.txt)
|
77
80
|
|
78
81
|
Copyright (c) 2011 Wojciech Piekutowski, AmberBit (<http://amberbit.com>) and contributors.
|
data/lib/xmp/convenience.rb
CHANGED
data/lib/xmp/document.rb
CHANGED
@@ -4,14 +4,23 @@ class XMP::Document
|
|
4
4
|
attr_reader :namespaces
|
5
5
|
attr_reader :xml
|
6
6
|
|
7
|
-
def initialize(doc)
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
|
7
|
+
def initialize(doc = nil)
|
8
|
+
if doc
|
9
|
+
@xml = doc.root
|
10
|
+
@namespaces = doc.collect_namespaces.map do |ns, url|
|
11
|
+
@xml.add_namespace_definition ns, url
|
12
|
+
ns[/^(?:xmlns:)?xmlns:(.+)/, 1]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
@xml = nil
|
16
|
+
@namespaces = []
|
12
17
|
end
|
13
18
|
end
|
14
19
|
|
20
|
+
def empty?
|
21
|
+
@xml.nil?
|
22
|
+
end
|
23
|
+
|
15
24
|
private
|
16
25
|
|
17
26
|
def list
|
data/lib/xmp/error.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
begin
|
2
|
+
require 'exifr/jpeg'
|
3
|
+
rescue LoadError => exception
|
4
|
+
raise exception unless exception.path == 'exifr/jpeg'
|
5
|
+
end
|
6
|
+
|
7
|
+
module XMP::Handler
|
8
|
+
class ExifrJPEG
|
9
|
+
def call(object)
|
10
|
+
return unless defined?(EXIFR::JPEG) && object.is_a?(EXIFR::JPEG)
|
11
|
+
xmp_chunk = object.app1s.find { |a| a =~ %r|\Ahttp://ns.adobe.com/xap/1.0/| }
|
12
|
+
xmp_chunk ? xmp_chunk.split("\000")[1] : XMP::Document.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'exifr/tiff'
|
3
|
+
rescue LoadError => exception
|
4
|
+
raise exception unless exception.path == 'exifr/tiff'
|
5
|
+
end
|
6
|
+
|
7
|
+
module XMP::Handler
|
8
|
+
class ExifrTIFF
|
9
|
+
def call(object)
|
10
|
+
return unless defined?(EXIFR::TIFF) && object.is_a?(EXIFR::TIFF)
|
11
|
+
object.xmp || XMP::Document.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/xmp/namespace.rb
CHANGED
@@ -29,12 +29,12 @@ class XMP::Namespace
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def get_embedded(name)
|
32
|
-
|
32
|
+
element = xml.at("//rdf:Description[@#{namespace}:#{name}]")
|
33
33
|
element.attribute(name.to_s).text
|
34
34
|
end
|
35
35
|
|
36
36
|
def get_standalone(name)
|
37
|
-
|
37
|
+
attribute = xml.xpath("//#{namespace}:#{name}").first
|
38
38
|
if list = attribute.xpath("./rdf:Bag | ./rdf:Seq | ./rdf:Alt").first
|
39
39
|
return list.xpath("./rdf:li").map(&:text)
|
40
40
|
end
|
data/lib/xmp/version.rb
CHANGED
data/lib/xmp.rb
CHANGED
@@ -3,7 +3,8 @@ module XMP
|
|
3
3
|
require 'xmp/document'
|
4
4
|
require 'xmp/error'
|
5
5
|
require 'xmp/handler'
|
6
|
-
require 'xmp/handler/
|
6
|
+
require 'xmp/handler/exifr_jpeg'
|
7
|
+
require 'xmp/handler/exifr_tiff'
|
7
8
|
require 'xmp/handler/file'
|
8
9
|
require 'xmp/handler/xml'
|
9
10
|
require 'xmp/namespace'
|
@@ -14,7 +15,8 @@ module XMP
|
|
14
15
|
Handler::File.new('.jpg', '.jpeg') { |file| EXIFR::JPEG.new(file) },
|
15
16
|
Handler::File.new('.tif', '.tiff') { |file| EXIFR::TIFF.new(file) },
|
16
17
|
Handler::File.new('.xmp', '.xml') { |file| Nokogiri::XML(file) },
|
17
|
-
Handler::
|
18
|
+
Handler::ExifrJPEG.new,
|
19
|
+
Handler::ExifrTIFF.new,
|
18
20
|
Handler::XML.new
|
19
21
|
]
|
20
22
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
describe XMP::Document do
|
2
|
+
describe '.new' do
|
3
|
+
it "should convert a Nokogiri::XML::Document to an XMP::Document with the expected XML and namespaces" do
|
4
|
+
xml_doc = Nokogiri::XML(File.open('spec/fixtures/xmp.xml'))
|
5
|
+
xmp_doc = XMP::Document.new(xml_doc)
|
6
|
+
xmp_doc.xml.should eq(xml_doc.root)
|
7
|
+
xmp_doc.namespaces.should =~ %w{rdf x tiff exif xap aux Iptc4xmpCore photoshop crs dc}
|
8
|
+
xmp_doc.should_not be_empty
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should, given no args, create an empty XMP::Document" do
|
12
|
+
xmp_doc = XMP::Document.new
|
13
|
+
xmp_doc.xml.should be_nil
|
14
|
+
xmp_doc.namespaces.should be_empty
|
15
|
+
xmp_doc.should be_empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/exifr_jpeg_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require './spec/spec_helper.rb'
|
2
1
|
require 'exifr/jpeg'
|
3
2
|
|
4
3
|
describe "XMP with EXIFR::JPEG" do
|
@@ -20,4 +19,8 @@ describe "XMP with EXIFR::JPEG" do
|
|
20
19
|
xmp.should be_instance_of(XMP::Document)
|
21
20
|
xmp.namespaces.should =~ %w{dc iX pdf photoshop rdf tiff x xap xapRights}
|
22
21
|
end
|
22
|
+
|
23
|
+
it "should return an empty XMP::Document for an image without XMP metadata" do
|
24
|
+
XMP.parse('spec/fixtures/no-xmp-metadata.jpg').should be_instance_of(XMP::Document)
|
25
|
+
end
|
23
26
|
end
|
data/spec/exifr_tiff_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require './spec/spec_helper.rb'
|
2
1
|
require 'exifr/tiff'
|
3
2
|
|
4
3
|
describe "XMP with EXIFR::TIFF" do
|
@@ -14,4 +13,8 @@ describe "XMP with EXIFR::TIFF" do
|
|
14
13
|
xmp.should be_instance_of(XMP::Document)
|
15
14
|
xmp.namespaces.should =~ %w{dc iX pdf photoshop rdf tiff x xap xapRights}
|
16
15
|
end
|
16
|
+
|
17
|
+
it "should return an empty XMP::Document for an image without XMP metadata" do
|
18
|
+
XMP.parse('spec/fixtures/no-xmp-metadata.tiff').should be_instance_of(XMP::Document)
|
19
|
+
end
|
17
20
|
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,240 @@
|
|
1
|
+
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
2
|
+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2-c020 1.124078, Tue Sep 11 2007 23:21:40 ">
|
3
|
+
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
4
|
+
<rdf:Description rdf:about=""
|
5
|
+
xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
|
6
|
+
xmlns:exif="http://ns.adobe.com/exif/1.0/"
|
7
|
+
xmlns:xap="http://ns.adobe.com/xap/1.0/"
|
8
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
9
|
+
xmlns:aux="http://ns.adobe.com/exif/1.0/aux/"
|
10
|
+
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
|
11
|
+
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
|
12
|
+
xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/"
|
13
|
+
tiff:Make="Canon"
|
14
|
+
tiff:Model="Canon EOS-1D Mark III"
|
15
|
+
tiff:ImageWidth="800"
|
16
|
+
tiff:ImageLength="533"
|
17
|
+
tiff:XResolution="72/1"
|
18
|
+
tiff:YResolution="72/1"
|
19
|
+
tiff:ResolutionUnit="2"
|
20
|
+
exif:ExifVersion="0221"
|
21
|
+
exif:ExposureTime="1/320"
|
22
|
+
exif:ShutterSpeedValue="8321928/1000000"
|
23
|
+
exif:FNumber="35/10"
|
24
|
+
exif:ApertureValue="361471/100000"
|
25
|
+
exif:ExposureProgram="1"
|
26
|
+
exif:DateTimeOriginal="2011-01-18T15:48:52.00+01:00"
|
27
|
+
exif:DateTimeDigitized="2011-01-18T15:48:52.00+01:00"
|
28
|
+
exif:ExposureBiasValue="0/1"
|
29
|
+
exif:MaxApertureValue="175/100"
|
30
|
+
exif:SubjectDistance="727/100"
|
31
|
+
exif:MeteringMode="5"
|
32
|
+
exif:FocalLength="85/1"
|
33
|
+
exif:CustomRendered="0"
|
34
|
+
exif:ExposureMode="1"
|
35
|
+
exif:WhiteBalance="0"
|
36
|
+
exif:SceneCaptureType="0"
|
37
|
+
exif:FocalPlaneXResolution="3888000/1107"
|
38
|
+
exif:FocalPlaneYResolution="2592000/736"
|
39
|
+
exif:FocalPlaneResolutionUnit="2"
|
40
|
+
exif:PixelXDimension="800"
|
41
|
+
exif:PixelYDimension="533"
|
42
|
+
xap:ModifyDate="2011-02-04T11:12:00+01:00"
|
43
|
+
xap:CreateDate="2011-01-18T15:48:52.00+01:00"
|
44
|
+
xap:CreatorTool="Adobe Photoshop Lightroom"
|
45
|
+
aux:SerialNumber="562133"
|
46
|
+
aux:LensInfo="85/1 85/1 0/0 0/0"
|
47
|
+
aux:Lens="EF85mm f/1.8 USM"
|
48
|
+
aux:LensID="155"
|
49
|
+
aux:ImageNumber="0"
|
50
|
+
aux:FlashCompensation="0/1"
|
51
|
+
aux:OwnerName="John Doe"
|
52
|
+
aux:Firmware="1.2.3"
|
53
|
+
Iptc4xmpCore:Location="Miejsce"
|
54
|
+
photoshop:Category="Kategoria"
|
55
|
+
photoshop:LegacyIPTCDigest="7220E75D669D5F417F2D6C9ADA130467"
|
56
|
+
crs:Version="6.1"
|
57
|
+
crs:ProcessVersion="5.7"
|
58
|
+
crs:WhiteBalance="As Shot"
|
59
|
+
crs:Temperature="4950"
|
60
|
+
crs:Tint="-6"
|
61
|
+
crs:Exposure="-0.75"
|
62
|
+
crs:Shadows="15"
|
63
|
+
crs:Brightness="+92"
|
64
|
+
crs:Contrast="+27"
|
65
|
+
crs:Saturation="+5"
|
66
|
+
crs:Sharpness="25"
|
67
|
+
crs:LuminanceSmoothing="0"
|
68
|
+
crs:ColorNoiseReduction="25"
|
69
|
+
crs:ChromaticAberrationR="0"
|
70
|
+
crs:ChromaticAberrationB="0"
|
71
|
+
crs:VignetteAmount="-61"
|
72
|
+
crs:VignetteMidpoint="50"
|
73
|
+
crs:ShadowTint="0"
|
74
|
+
crs:RedHue="+14"
|
75
|
+
crs:RedSaturation="+18"
|
76
|
+
crs:GreenHue="0"
|
77
|
+
crs:GreenSaturation="0"
|
78
|
+
crs:BlueHue="-7"
|
79
|
+
crs:BlueSaturation="-7"
|
80
|
+
crs:FillLight="31"
|
81
|
+
crs:Vibrance="0"
|
82
|
+
crs:HighlightRecovery="30"
|
83
|
+
crs:Clarity="+100"
|
84
|
+
crs:Defringe="0"
|
85
|
+
crs:HueAdjustmentRed="0"
|
86
|
+
crs:HueAdjustmentOrange="+33"
|
87
|
+
crs:HueAdjustmentYellow="0"
|
88
|
+
crs:HueAdjustmentGreen="0"
|
89
|
+
crs:HueAdjustmentAqua="0"
|
90
|
+
crs:HueAdjustmentBlue="0"
|
91
|
+
crs:HueAdjustmentPurple="0"
|
92
|
+
crs:HueAdjustmentMagenta="0"
|
93
|
+
crs:SaturationAdjustmentRed="-2"
|
94
|
+
crs:SaturationAdjustmentOrange="-30"
|
95
|
+
crs:SaturationAdjustmentYellow="0"
|
96
|
+
crs:SaturationAdjustmentGreen="0"
|
97
|
+
crs:SaturationAdjustmentAqua="0"
|
98
|
+
crs:SaturationAdjustmentBlue="0"
|
99
|
+
crs:SaturationAdjustmentPurple="0"
|
100
|
+
crs:SaturationAdjustmentMagenta="0"
|
101
|
+
crs:LuminanceAdjustmentRed="0"
|
102
|
+
crs:LuminanceAdjustmentOrange="0"
|
103
|
+
crs:LuminanceAdjustmentYellow="0"
|
104
|
+
crs:LuminanceAdjustmentGreen="0"
|
105
|
+
crs:LuminanceAdjustmentAqua="0"
|
106
|
+
crs:LuminanceAdjustmentBlue="0"
|
107
|
+
crs:LuminanceAdjustmentPurple="0"
|
108
|
+
crs:LuminanceAdjustmentMagenta="0"
|
109
|
+
crs:SplitToningShadowHue="0"
|
110
|
+
crs:SplitToningShadowSaturation="0"
|
111
|
+
crs:SplitToningHighlightHue="0"
|
112
|
+
crs:SplitToningHighlightSaturation="0"
|
113
|
+
crs:SplitToningBalance="+64"
|
114
|
+
crs:ParametricShadows="+60"
|
115
|
+
crs:ParametricDarks="-11"
|
116
|
+
crs:ParametricLights="+15"
|
117
|
+
crs:ParametricHighlights="+70"
|
118
|
+
crs:ParametricShadowSplit="25"
|
119
|
+
crs:ParametricMidtoneSplit="50"
|
120
|
+
crs:ParametricHighlightSplit="80"
|
121
|
+
crs:SharpenRadius="+1.0"
|
122
|
+
crs:SharpenDetail="25"
|
123
|
+
crs:SharpenEdgeMasking="0"
|
124
|
+
crs:PostCropVignetteAmount="0"
|
125
|
+
crs:GrainAmount="0"
|
126
|
+
crs:ColorNoiseReductionDetail="50"
|
127
|
+
crs:LensProfileEnable="0"
|
128
|
+
crs:LensManualDistortionAmount="0"
|
129
|
+
crs:PerspectiveVertical="0"
|
130
|
+
crs:PerspectiveHorizontal="0"
|
131
|
+
crs:PerspectiveRotate="0.0"
|
132
|
+
crs:PerspectiveScale="100"
|
133
|
+
crs:ConvertToGrayscale="False"
|
134
|
+
crs:ToneCurveName="Medium Contrast"
|
135
|
+
crs:CameraProfile="Adobe Standard"
|
136
|
+
crs:CameraProfileDigest="631F0C9CC003981496182C3DD10EF165"
|
137
|
+
crs:LensProfileSetup="LensDefaults"
|
138
|
+
crs:HasSettings="True"
|
139
|
+
crs:CropTop="0.024828"
|
140
|
+
crs:CropLeft="0.012414"
|
141
|
+
crs:CropBottom="1"
|
142
|
+
crs:CropRight="0.987586"
|
143
|
+
crs:CropAngle="0"
|
144
|
+
crs:CropConstrainToWarp="0"
|
145
|
+
crs:CropWidth="800"
|
146
|
+
crs:CropHeight="533"
|
147
|
+
crs:CropUnit="0"
|
148
|
+
crs:HasCrop="True"
|
149
|
+
crs:AlreadyApplied="True">
|
150
|
+
<exif:ISOSpeedRatings>
|
151
|
+
<rdf:Seq>
|
152
|
+
<rdf:li>100</rdf:li>
|
153
|
+
</rdf:Seq>
|
154
|
+
</exif:ISOSpeedRatings>
|
155
|
+
<dc:creator>
|
156
|
+
<rdf:Seq>
|
157
|
+
<rdf:li>John Doe</rdf:li>
|
158
|
+
</rdf:Seq>
|
159
|
+
</dc:creator>
|
160
|
+
<dc:title>
|
161
|
+
<rdf:Alt>
|
162
|
+
<rdf:li xml:lang="x-default">Tytuł zdjęcia</rdf:li>
|
163
|
+
</rdf:Alt>
|
164
|
+
</dc:title>
|
165
|
+
<dc:rights>
|
166
|
+
<rdf:Alt>
|
167
|
+
<rdf:li xml:lang="x-default">Autor</rdf:li>
|
168
|
+
</rdf:Alt>
|
169
|
+
</dc:rights>
|
170
|
+
<dc:subject>
|
171
|
+
<rdf:Bag>
|
172
|
+
<rdf:li>Słowa kluczowe i numery startowe.</rdf:li>
|
173
|
+
</rdf:Bag>
|
174
|
+
</dc:subject>
|
175
|
+
<dc:description>
|
176
|
+
<rdf:Alt>
|
177
|
+
<rdf:li xml:lang="x-default">Opis zdjęcia</rdf:li>
|
178
|
+
</rdf:Alt>
|
179
|
+
</dc:description>
|
180
|
+
<photoshop:SupplementalCategories>
|
181
|
+
<rdf:Bag>
|
182
|
+
<rdf:li>Nazwa imprezy</rdf:li>
|
183
|
+
</rdf:Bag>
|
184
|
+
</photoshop:SupplementalCategories>
|
185
|
+
<crs:ToneCurve>
|
186
|
+
<rdf:Seq>
|
187
|
+
<rdf:li>0, 0</rdf:li>
|
188
|
+
<rdf:li>32, 22</rdf:li>
|
189
|
+
<rdf:li>64, 56</rdf:li>
|
190
|
+
<rdf:li>128, 128</rdf:li>
|
191
|
+
<rdf:li>192, 196</rdf:li>
|
192
|
+
<rdf:li>255, 255</rdf:li>
|
193
|
+
</rdf:Seq>
|
194
|
+
</crs:ToneCurve>
|
195
|
+
<Iptc4xmpCore:CreatorContactInfo/>
|
196
|
+
</rdf:Description>
|
197
|
+
</rdf:RDF>
|
198
|
+
</x:xmpmeta>
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
<?xpacket end="w"?>
|
data/spec/spec_helper.rb
CHANGED
data/spec/xmp_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
require './spec/spec_helper.rb'
|
3
2
|
|
4
3
|
describe XMP do
|
5
4
|
describe "with xmp.xml" do
|
@@ -26,6 +25,14 @@ describe XMP do
|
|
26
25
|
@xmp['photoshop']['SupplementalCategories'].should eq(['Nazwa imprezy'])
|
27
26
|
end
|
28
27
|
|
28
|
+
it "should respond to standalone attributes" do
|
29
|
+
@xmp.should respond_to(:dc)
|
30
|
+
@xmp.dc.should respond_to(:title)
|
31
|
+
@xmp.should respond_to(:photoshop)
|
32
|
+
@xmp.photoshop.should respond_to(:SupplementalCategories)
|
33
|
+
@xmp.photoshop.should respond_to(:supplemental_categories)
|
34
|
+
end
|
35
|
+
|
29
36
|
it "should return standalone attribute hash" do
|
30
37
|
@xmp.Iptc4xmpCore.CreatorContactInfo.should eq({'CiAdrCtry' => 'Germany', 'CiAdrCity' => 'Berlin'})
|
31
38
|
end
|
@@ -40,6 +47,13 @@ describe XMP do
|
|
40
47
|
@xmp.photoshop['UnknownAttribute'].should eq(nil)
|
41
48
|
end
|
42
49
|
|
50
|
+
it "should raise if an attribute is called with any argument" do
|
51
|
+
lambda { XMP.new('spec/fixtures/xmp.xml').dc('Comics') }.
|
52
|
+
should raise_error(ArgumentError, "wrong number of arguments (given 1, expected 0)")
|
53
|
+
lambda { XMP.new('spec/fixtures/xmp.xml').dc.title('Amazing Stories') }.
|
54
|
+
should raise_error(ArgumentError, "wrong number of arguments (given 1, expected 0)")
|
55
|
+
end
|
56
|
+
|
43
57
|
describe "namespace 'tiff'" do
|
44
58
|
before { @namespace = @xmp.tiff }
|
45
59
|
|
@@ -117,4 +131,24 @@ describe XMP do
|
|
117
131
|
@xmp.to_h.keys.should =~ %w{Iptc4xmpExt aux crs dc exifEX mwg-rs photoshop rdf stArea stDim stEvt stRef x xmp xmpMM}
|
118
132
|
end
|
119
133
|
end
|
134
|
+
|
135
|
+
it "should read from an IO" do
|
136
|
+
xmp = XMP.new(File.open('spec/fixtures/xmp.xml'))
|
137
|
+
xmp.namespaces.should =~ %w{rdf x tiff exif xap aux Iptc4xmpCore photoshop crs dc}
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should raise if the file doesn't exist" do
|
141
|
+
nonexistent_file = 'nonexistent.xml'
|
142
|
+
lambda { XMP.new(nonexistent_file) }.should raise_error(XMP::Error, "cannot read file #{nonexistent_file}")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should return nil for an unknown attribute" do
|
146
|
+
xmp = XMP.new('spec/fixtures/xmp-with-empty-attribute.xml')
|
147
|
+
lambda { xmp.Iptc4xmpCore.CreatorContactInfo }.
|
148
|
+
should raise_error(XMP::Error, "Don't know how to handle: \n<Iptc4xmpCore:CreatorContactInfo/>")
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should raise for an unknown input type" do
|
152
|
+
lambda { XMP.new(0) }.should raise_error(XMP::Error, "cannot handle 0")
|
153
|
+
end
|
120
154
|
end
|
data/xmp.gemspec
CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.email = ["wojciech.piekutowski@amberbit.com"]
|
11
11
|
s.homepage = "https://github.com/amberbit/xmp"
|
12
12
|
s.summary = %q{Extensible Metadata Platform (XMP) parser for JPEG, TIFF and raw XML files}
|
13
|
-
s.description = %q{Extensible Metadata Platform (XMP) parser extracts metadata from
|
14
|
-
s.licenses = ["
|
13
|
+
s.description = %q{Extensible Metadata Platform (XMP) parser extracts metadata from JPEG and TIFF image files. It also supports parsing raw XML files containing XMP.}
|
14
|
+
s.licenses = ["Ruby"]
|
15
15
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.extra_rdoc_files = %w(README.md)
|
22
22
|
|
23
|
-
s.required_ruby_version = '>= 2.
|
23
|
+
s.required_ruby_version = '>= 2.6.0'
|
24
24
|
|
25
25
|
s.add_dependency 'nokogiri', '~> 1.0'
|
26
26
|
|
@@ -28,4 +28,5 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.add_development_dependency 'rspec', '~> 3.0'
|
29
29
|
s.add_development_dependency 'logger', '~> 1.0'
|
30
30
|
s.add_development_dependency 'rake'
|
31
|
+
s.add_development_dependency 'simplecov'
|
31
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wojciech Piekutowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -86,7 +86,21 @@ dependencies:
|
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
|
-
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: simplecov
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
description: Extensible Metadata Platform (XMP) parser extracts metadata from JPEG
|
90
104
|
and TIFF image files. It also supports parsing raw XML files containing XMP.
|
91
105
|
email:
|
92
106
|
- wojciech.piekutowski@amberbit.com
|
@@ -97,7 +111,9 @@ extra_rdoc_files:
|
|
97
111
|
files:
|
98
112
|
- ".gitignore"
|
99
113
|
- ".rspec"
|
114
|
+
- ".tool-versions"
|
100
115
|
- ".travis.yml"
|
116
|
+
- CHANGELOG.md
|
101
117
|
- Gemfile
|
102
118
|
- README.md
|
103
119
|
- Rakefile
|
@@ -106,16 +122,21 @@ files:
|
|
106
122
|
- lib/xmp/document.rb
|
107
123
|
- lib/xmp/error.rb
|
108
124
|
- lib/xmp/handler.rb
|
109
|
-
- lib/xmp/handler/
|
125
|
+
- lib/xmp/handler/exifr_jpeg.rb
|
126
|
+
- lib/xmp/handler/exifr_tiff.rb
|
110
127
|
- lib/xmp/handler/file.rb
|
111
128
|
- lib/xmp/handler/xml.rb
|
112
129
|
- lib/xmp/namespace.rb
|
113
130
|
- lib/xmp/version.rb
|
131
|
+
- spec/document_spec.rb
|
114
132
|
- spec/exifr_jpeg_spec.rb
|
115
133
|
- spec/exifr_tiff_spec.rb
|
116
134
|
- spec/fixtures/UPPERCASE.JPG
|
117
135
|
- spec/fixtures/multiple-app1.jpg
|
118
136
|
- spec/fixtures/multiple-app1.tiff
|
137
|
+
- spec/fixtures/no-xmp-metadata.jpg
|
138
|
+
- spec/fixtures/no-xmp-metadata.tiff
|
139
|
+
- spec/fixtures/xmp-with-empty-attribute.xml
|
119
140
|
- spec/fixtures/xmp.xml
|
120
141
|
- spec/fixtures/xmp2.xml
|
121
142
|
- spec/fixtures/xmp3.xml
|
@@ -126,7 +147,7 @@ files:
|
|
126
147
|
- xmp.gemspec
|
127
148
|
homepage: https://github.com/amberbit/xmp
|
128
149
|
licenses:
|
129
|
-
-
|
150
|
+
- Ruby
|
130
151
|
metadata: {}
|
131
152
|
post_install_message:
|
132
153
|
rdoc_options: []
|
@@ -136,7 +157,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
157
|
requirements:
|
137
158
|
- - ">="
|
138
159
|
- !ruby/object:Gem::Version
|
139
|
-
version: 2.
|
160
|
+
version: 2.6.0
|
140
161
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
162
|
requirements:
|
142
163
|
- - ">="
|
@@ -148,11 +169,15 @@ signing_key:
|
|
148
169
|
specification_version: 4
|
149
170
|
summary: Extensible Metadata Platform (XMP) parser for JPEG, TIFF and raw XML files
|
150
171
|
test_files:
|
172
|
+
- spec/document_spec.rb
|
151
173
|
- spec/exifr_jpeg_spec.rb
|
152
174
|
- spec/exifr_tiff_spec.rb
|
153
175
|
- spec/fixtures/UPPERCASE.JPG
|
154
176
|
- spec/fixtures/multiple-app1.jpg
|
155
177
|
- spec/fixtures/multiple-app1.tiff
|
178
|
+
- spec/fixtures/no-xmp-metadata.jpg
|
179
|
+
- spec/fixtures/no-xmp-metadata.tiff
|
180
|
+
- spec/fixtures/xmp-with-empty-attribute.xml
|
156
181
|
- spec/fixtures/xmp.xml
|
157
182
|
- spec/fixtures/xmp2.xml
|
158
183
|
- spec/fixtures/xmp3.xml
|
data/lib/xmp/handler/exifr.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'exifr/jpeg'
|
3
|
-
require 'exifr/tiff'
|
4
|
-
rescue LoadError => exception
|
5
|
-
raise exception unless exception.path == 'exifr/jpeg'
|
6
|
-
end
|
7
|
-
|
8
|
-
module XMP::Handler
|
9
|
-
class Exifr
|
10
|
-
def call(object)
|
11
|
-
return unless defined?(EXIFR::JPEG)
|
12
|
-
case object
|
13
|
-
when EXIFR::JPEG then format, xmp_data = 'jpeg', object.app1s.find { |a| a =~ %r|\Ahttp://ns.adobe.com/xap/1.0/| }&.split("\000")[1]
|
14
|
-
when EXIFR::TIFF then format, xmp_data = 'tiff', object.xmp
|
15
|
-
else return
|
16
|
-
end
|
17
|
-
|
18
|
-
raise XMP::NoXMP, "XMP section missing from #{format}" unless xmp_data
|
19
|
-
xmp_data
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|