1
1
<?php
2
2
namespace CSD \Image \Metadata ;
3
3
4
- use CSD \Image \Metadata \UnsupportedException ;
4
+ use CSD \Image \Metadata \Xmp \ImageRegion ;
5
+ use CSD \Image \Metadata \Xmp \RoleFilter ;
6
+ use CSD \Image \Metadata \Xmp \ShapeFilter ;
5
7
6
8
/**
7
9
* Class to read XMP metadata from an image.
@@ -1403,11 +1405,10 @@ public function setFeaturedOrganisationCode($featuredOrganisationCode)
1403
1405
* @param string $roleFilter
1404
1406
*
1405
1407
* @return array
1406
- * @throws UnsupportedException
1407
1408
*/
1408
1409
public function getImageRegions (
1409
- $ shapeFilter = XmpShapeFilter ::ANY ,
1410
- $ roleFilter = XmpRoleFilter ::ANY )
1410
+ $ shapeFilter = ShapeFilter ::ANY ,
1411
+ $ roleFilter = RoleFilter ::ANY )
1411
1412
{
1412
1413
$ imageRegionNode = $ this ->getNode (
1413
1414
'Iptc4xmpExt:ImageRegion ' ,
@@ -1426,7 +1427,7 @@ public function getImageRegions(
1426
1427
1427
1428
$ results = [];
1428
1429
foreach ($ imageRegionBag ->childNodes as $ imageRegionItem ) {
1429
- $ imageRegion = new XmpImageRegion ($ this ->xpath , $ imageRegionItem );
1430
+ $ imageRegion = new ImageRegion ($ this ->xpath , $ imageRegionItem );
1430
1431
array_push ($ results , $ imageRegion );
1431
1432
}
1432
1433
@@ -1451,322 +1452,3 @@ public function hasChanges()
1451
1452
return $ this ->hasChanges ;
1452
1453
}
1453
1454
}
1454
-
1455
- /**
1456
- * PHP5 enum.
1457
- */
1458
- abstract class XmpShapeFilter
1459
- {
1460
- const ANY = '' ;
1461
- const RECTANGLE = 'rectangle ' ;
1462
- const CIRCLE = 'circle ' ;
1463
- const POLYGON = 'polygon ' ;
1464
-
1465
- /**
1466
- * @param string $value RECTANGLE, CIRCLE or POLYGON.
1467
- *
1468
- * @return string The corresponding value of the <Iptc4xmpExt:rbShape>
1469
- * element.
1470
- * @throws UnsupportedException
1471
- */
1472
- public static function getXmlRbShape ($ value )
1473
- {
1474
- switch ($ value ) {
1475
- case self ::RECTANGLE :
1476
- case self ::CIRCLE :
1477
- case self ::POLYGON :
1478
- return $ value ;
1479
- }
1480
- throw new UnsupportedException ('Unsupported region shape ' );
1481
- }
1482
- }
1483
-
1484
- /**
1485
- * PHP5 enum.
1486
- */
1487
- abstract class XmpRoleFilter
1488
- {
1489
- const ANY = '' ;
1490
- const CROP = 'crop ' ;
1491
-
1492
- /**
1493
- * @param string $value CROP.
1494
- *
1495
- * @return array The list of <Iptc4xmpExt:rRole><Iptc4xmpExt:Name> or
1496
- * <Iptc4xmpExt:rRole><Iptc4xmpExt:Identifier> values
1497
- * that would match the filter.
1498
- * @throws UnsupportedException
1499
- */
1500
- public static function getMatchingXmlRoles ($ value )
1501
- {
1502
- switch ($ value ) {
1503
- case self ::CROP :
1504
- // See https://cv.iptc.org/newscodes/imageregionrole/
1505
- return [
1506
- 'cropping ' ,
1507
- 'recommended cropping ' ,
1508
- 'landscape format cropping ' ,
1509
- 'portrait format cropping ' ,
1510
- 'square format cropping ' ,
1511
- 'http://cv.iptc.org/newscodes/imageregionrole/cropping ' ,
1512
- 'http://cv.iptc.org/newscodes/imageregionrole/recomCropping ' ,
1513
- 'http://cv.iptc.org/newscodes/imageregionrole/landscapeCropping ' ,
1514
- 'http://cv.iptc.org/newscodes/imageregionrole/portraitCropping ' ,
1515
- 'http://cv.iptc.org/newscodes/imageregionrole/squareCropping ' ,
1516
- ];
1517
- }
1518
- throw new UnsupportedException ('Unsupported region role filter ' );
1519
- }
1520
- }
1521
-
1522
- /**
1523
- * Represents an Image Region read from XMP metadata.
1524
- * See https://iptc.org/std/photometadata/specification/IPTC-PhotoMetadata#image-region
1525
- */
1526
- class XmpImageRegion
1527
- {
1528
- /**
1529
- * @var string|null
1530
- */
1531
- public $ id ;
1532
-
1533
- /**
1534
- * @var array|null
1535
- */
1536
- public $ names ;
1537
-
1538
- /**
1539
- * @var array|null
1540
- */
1541
- public $ types ;
1542
-
1543
- /**
1544
- * @var array|null
1545
- */
1546
- public $ roles ;
1547
-
1548
- /**
1549
- * 'rectangle', 'circle' or 'polygon'.
1550
- *
1551
- * @var string|null
1552
- */
1553
- public $ rbShape ;
1554
-
1555
- /**
1556
- * E.g. 'relative'.
1557
- *
1558
- * @var string|null
1559
- */
1560
- public $ rbUnit ;
1561
-
1562
- /**
1563
- * Rectangle or circle's coordinates.
1564
- *
1565
- * @var XmpImageRegionPoint
1566
- */
1567
- public $ rbXY ;
1568
-
1569
- /**
1570
- * Rectangle's height.
1571
- *
1572
- * @var string|null
1573
- */
1574
- public $ rbH ;
1575
-
1576
- /**
1577
- * Rectangle's width.
1578
- *
1579
- * @var string|null
1580
- */
1581
- public $ rbW ;
1582
-
1583
- /**
1584
- * Circle's radius.
1585
- *
1586
- * @var string|null
1587
- */
1588
- public $ rbRx ;
1589
-
1590
- /**
1591
- * Polygon's vertices.
1592
- *
1593
- * @var array|null
1594
- */
1595
- public $ rbVertices ;
1596
-
1597
- /**
1598
- * @param \DOMXPath $xpath
1599
- * @param \DOMNode $node <rdf:li> node.
1600
- */
1601
- public function __construct ($ xpath , $ node )
1602
- {
1603
- $ this ->id = self ::getNodeValue ($ xpath , 'Iptc4xmpExt:rId ' , $ node );
1604
- $ this ->names = self ::getNodeValues (
1605
- $ xpath ,
1606
- 'Iptc4xmpExt:Name/rdf:Alt/rdf:li ' ,
1607
- $ node
1608
- );
1609
- $ this ->types = self ::getEntityOrConceptValues (
1610
- $ xpath ,
1611
- 'Iptc4xmpExt:rCtype ' ,
1612
- $ node
1613
- );
1614
- $ this ->roles = self ::getEntityOrConceptValues (
1615
- $ xpath ,
1616
- 'Iptc4xmpExt:rRole ' ,
1617
- $ node
1618
- );
1619
-
1620
- $ xpathToRb = 'Iptc4xmpExt:RegionBoundary ' ;
1621
-
1622
- foreach ([
1623
- 'rbShape ' ,
1624
- 'rbUnit ' ,
1625
- 'rbH ' ,
1626
- 'rbW ' ,
1627
- 'rbRx ' ,
1628
- ] as $ property ) {
1629
- $ this ->$ property = self ::getNodeValue (
1630
- $ xpath ,
1631
- "$ xpathToRb/Iptc4xmpExt: $ property " ,
1632
- $ node
1633
- );
1634
- }
1635
-
1636
- $ this ->rbXY = new XmpImageRegionPoint (
1637
- self ::getNodeValue ($ xpath , "$ xpathToRb/Iptc4xmpExt:rbX " , $ node ),
1638
- self ::getNodeValue ($ xpath , "$ xpathToRb/Iptc4xmpExt:rbY " , $ node )
1639
- );
1640
-
1641
- $ verticesNodes = $ xpath ->query (
1642
- "$ xpathToRb/Iptc4xmpExt:rbVertices/rdf:Seq/rdf:li " ,
1643
- $ node
1644
- );
1645
- if ($ verticesNodes ->length ) {
1646
- $ this ->rbVertices = [];
1647
- foreach ($ verticesNodes as $ verticesNode ) {
1648
- $ point = new XmpImageRegionPoint (
1649
- self ::getNodeValue ($ xpath , "Iptc4xmpExt:rbX " , $ verticesNode ),
1650
- self ::getNodeValue ($ xpath , "Iptc4xmpExt:rbY " , $ verticesNode )
1651
- );
1652
- array_push ($ this ->rbVertices , $ point );
1653
- }
1654
- }
1655
- }
1656
-
1657
- /**
1658
- * @param string $filter One of the XmpShapeFilter constants.
1659
- *
1660
- * @return bool
1661
- */
1662
- public function matchesShapeFilter ($ filter ) {
1663
- return (
1664
- $ filter === XmpShapeFilter::ANY ||
1665
- XmpShapeFilter::getXmlRbShape ($ filter ) === $ this ->rbShape
1666
- );
1667
- }
1668
-
1669
- /**
1670
- * @param string $filter One of the XmpRoleFilter constants.
1671
- *
1672
- * @return bool
1673
- */
1674
- public function matchesRoleFilter ($ filter ) {
1675
- return (
1676
- $ filter === XmpRoleFilter::ANY ||
1677
- count (array_intersect (
1678
- XmpRoleFilter::getMatchingXmlRoles ($ filter ),
1679
- $ this ->roles
1680
- )) > 0
1681
- );
1682
- }
1683
-
1684
- /**
1685
- * @param \DOMXPath $xpath
1686
- * @param string $expression XPath expression leading to one single node.
1687
- * @param \DOMNode $contextNode
1688
- *
1689
- * @return string|null
1690
- */
1691
- private static function getNodeValue ($ xpath , $ expression , $ contextNode ) {
1692
- $ node = $ xpath ->query ($ expression , $ contextNode )->item (0 );
1693
- return $ node ? $ node ->nodeValue : null ;
1694
- }
1695
-
1696
- /**
1697
- * @param \DOMXPath $xpath
1698
- * @param string $expression XPath expression leading to several nodes.
1699
- * @param \DOMNode $contextNode
1700
- *
1701
- * @return array|null
1702
- */
1703
- private static function getNodeValues ($ xpath , $ expression , $ contextNode ) {
1704
- $ nodes = $ xpath ->query ($ expression , $ contextNode );
1705
- if (!$ nodes ->length ) {
1706
- return null ;
1707
- }
1708
-
1709
- $ result = [];
1710
- foreach ($ nodes as $ node ) {
1711
- array_push ($ result , $ node ->nodeValue );
1712
- }
1713
- return $ result ;
1714
- }
1715
-
1716
- /**
1717
- * See https://iptc.org/std/photometadata/specification/IPTC-PhotoMetadata#entity-or-concept-structure
1718
- *
1719
- * @param \DOMXPath $xpath
1720
- * @param string $expression XPath expression leading to the parent of an
1721
- * <rdf:Bag> of an Identity or Concept structure.
1722
- * @param \DOMNode $contextNode
1723
- *
1724
- * @return array|null
1725
- */
1726
- private static function getEntityOrConceptValues (
1727
- $ xpath ,
1728
- $ expression ,
1729
- $ contextNode
1730
- ) {
1731
- $ names = self ::getNodeValues (
1732
- $ xpath ,
1733
- "$ expression/rdf:Bag/rdf:li/Iptc4xmpExt:Name/rdf:Alt/rdf:li " ,
1734
- $ contextNode
1735
- );
1736
- $ identifiers = self ::getNodeValues (
1737
- $ xpath ,
1738
- "$ expression/rdf:Bag/rdf:li/xmp:Identifier/rdf:Bag/rdf:li " ,
1739
- $ contextNode
1740
- );
1741
-
1742
- if (!$ names ) {
1743
- return $ identifiers ;
1744
- }
1745
- if (!$ identifiers ) {
1746
- return $ names ;
1747
- }
1748
- return array_merge ($ names , $ identifiers );
1749
- }
1750
- }
1751
-
1752
- /**
1753
- * (X, Y) pair of coordinates.
1754
- */
1755
- class XmpImageRegionPoint
1756
- {
1757
- /**
1758
- * @var string|null
1759
- */
1760
- public $ rbX ;
1761
-
1762
- /**
1763
- * @var string|null
1764
- */
1765
- public $ rbY ;
1766
-
1767
- public function __construct ($ x , $ y )
1768
- {
1769
- $ this ->rbX = $ x ;
1770
- $ this ->rbY = $ y ;
1771
- }
1772
- }
0 commit comments