@@ -13,6 +13,7 @@ extern crate fallible_collections;
13
13
extern crate num_traits;
14
14
use bitreader:: { BitReader , ReadInto } ;
15
15
use byteorder:: { ReadBytesExt , WriteBytesExt } ;
16
+ use fallible_collections:: TryClone ;
16
17
use fallible_collections:: TryRead ;
17
18
use num_traits:: Num ;
18
19
use std:: convert:: { TryFrom , TryInto as _} ;
@@ -1294,6 +1295,7 @@ fn read_avif_meta<T: Read + Offset>(src: &mut BMFFBox<T>) -> Result<AvifMeta> {
1294
1295
let mut item_infos = None ;
1295
1296
let mut iloc_items = None ;
1296
1297
let mut item_references = TryVec :: new ( ) ;
1298
+ let mut properties = TryVec :: new ( ) ;
1297
1299
1298
1300
let mut iter = src. box_iter ( ) ;
1299
1301
while let Some ( mut b) = iter. next_box ( ) ? {
@@ -1325,6 +1327,9 @@ fn read_avif_meta<T: Read + Offset>(src: &mut BMFFBox<T>) -> Result<AvifMeta> {
1325
1327
BoxType :: ImageReferenceBox => {
1326
1328
item_references = read_iref ( & mut b) ?;
1327
1329
}
1330
+ BoxType :: ImagePropertiesBox => {
1331
+ properties = read_iprp ( & mut b) ?;
1332
+ }
1328
1333
_ => skip_box_content ( & mut b) ?,
1329
1334
}
1330
1335
@@ -1490,6 +1495,147 @@ fn read_iref<T: Read>(src: &mut BMFFBox<T>) -> Result<TryVec<ItemReferenceEntry>
1490
1495
Ok ( entries)
1491
1496
}
1492
1497
1498
+ fn read_iprp < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < AssociatedProperty > > {
1499
+ let mut iter = src. box_iter ( ) ;
1500
+ let mut properties = TryVec :: new ( ) ;
1501
+ let mut associations = TryVec :: new ( ) ;
1502
+
1503
+ while let Some ( mut b) = iter. next_box ( ) ? {
1504
+ match b. head . name {
1505
+ BoxType :: ItemPropertyContainerBox => {
1506
+ properties = read_ipco ( & mut b) ?;
1507
+ }
1508
+ BoxType :: ItemPropertyAssociationBox => {
1509
+ associations = read_ipma ( & mut b) ?;
1510
+ }
1511
+ _ => return Err ( Error :: InvalidData ( "unexpected ipco child" ) ) ,
1512
+ }
1513
+ }
1514
+
1515
+ let mut associated = TryVec :: new ( ) ;
1516
+ for a in associations {
1517
+ let index = match a. property_index {
1518
+ 0 => continue ,
1519
+ x => x as usize - 1 ,
1520
+ } ;
1521
+ if let Some ( prop) = properties. get ( index) {
1522
+ if * prop != ImageProperty :: Unsupported {
1523
+ associated. push ( AssociatedProperty {
1524
+ item_id : a. item_id ,
1525
+ property : prop. clone ( ) ?,
1526
+ } ) ?;
1527
+ }
1528
+ }
1529
+ }
1530
+ Ok ( associated)
1531
+ }
1532
+
1533
+ #[ derive( Debug , PartialEq ) ]
1534
+ pub enum ImageProperty {
1535
+ Channels ( TryVec < u8 > ) ,
1536
+ AuxiliaryType ( TryString ) ,
1537
+ Unsupported ,
1538
+ }
1539
+
1540
+ impl ImageProperty {
1541
+ fn clone ( & self ) -> Result < Self > {
1542
+ Ok ( match self {
1543
+ Self :: Channels ( val) => Self :: Channels ( val. clone ( ) ?) ,
1544
+ Self :: AuxiliaryType ( val) => Self :: AuxiliaryType ( val. clone ( ) ?) ,
1545
+ Self :: Unsupported => Self :: Unsupported ,
1546
+ } )
1547
+ }
1548
+ }
1549
+
1550
+ struct Association {
1551
+ item_id : u32 ,
1552
+ property_index : u16 ,
1553
+ }
1554
+
1555
+ pub struct AssociatedProperty {
1556
+ pub item_id : u32 ,
1557
+ pub property : ImageProperty ,
1558
+ }
1559
+
1560
+ fn read_ipma < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < Association > > {
1561
+ let ( version, flags) = read_fullbox_extra ( src) ?;
1562
+
1563
+ let mut associations = TryVec :: new ( ) ;
1564
+
1565
+ let entry_count = be_u32 ( src) ?;
1566
+ for _ in 0 ..entry_count {
1567
+ let item_id = if version == 0 {
1568
+ be_u16 ( src) ? as u32
1569
+ } else {
1570
+ be_u32 ( src) ?
1571
+ } ;
1572
+ let association_count = src. read_u8 ( ) ?;
1573
+ for _ in 0 ..association_count {
1574
+ let first_byte = src. read_u8 ( ) ?;
1575
+ let essential_flag = first_byte & 1 << 7 ;
1576
+ let value = first_byte - essential_flag;
1577
+ let property_index = if flags & 1 != 0 {
1578
+ ( ( value as u16 ) << 8 ) | src. read_u8 ( ) ? as u16
1579
+ } else {
1580
+ value as u16
1581
+ } ;
1582
+ associations. push ( Association {
1583
+ item_id,
1584
+ property_index,
1585
+ } ) ?;
1586
+ }
1587
+ }
1588
+ Ok ( associations)
1589
+ }
1590
+
1591
+ fn read_ipco < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < ImageProperty > > {
1592
+ let mut properties = TryVec :: new ( ) ;
1593
+
1594
+ let mut iter = src. box_iter ( ) ;
1595
+ while let Some ( mut b) = iter. next_box ( ) ? {
1596
+ // Must push for every property to have correct index for them
1597
+ properties. push ( match b. head . name {
1598
+ BoxType :: PixelInformationBox => ImageProperty :: Channels ( read_pixi ( & mut b) ?) ,
1599
+ BoxType :: AuxiliaryTypeProperty => ImageProperty :: AuxiliaryType ( read_auxc ( & mut b) ?) ,
1600
+ _ => {
1601
+ skip_box_remain ( & mut b) ?;
1602
+ ImageProperty :: Unsupported
1603
+ }
1604
+ } ) ?;
1605
+ }
1606
+ Ok ( properties)
1607
+ }
1608
+
1609
+ fn read_pixi < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < u8 > > {
1610
+ let version = read_fullbox_version_no_flags ( src) ?;
1611
+ if version != 0 {
1612
+ return Err ( Error :: Unsupported ( "pixi version" ) ) ;
1613
+ }
1614
+
1615
+ let mut channels = TryVec :: new ( ) ;
1616
+ let channel_count = src. read_u8 ( ) ?;
1617
+ for _ in 0 ..channel_count {
1618
+ channels. push ( src. read_u8 ( ) ?) ?;
1619
+ }
1620
+ Ok ( channels)
1621
+ }
1622
+
1623
+ fn read_auxc < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryString > {
1624
+ let version = read_fullbox_version_no_flags ( src) ?;
1625
+ if version != 0 {
1626
+ return Err ( Error :: Unsupported ( "auxC version" ) ) ;
1627
+ }
1628
+
1629
+ let mut aux = TryString :: new ( ) ;
1630
+ loop {
1631
+ match src. read_u8 ( ) ? {
1632
+ 0 => break ,
1633
+ c => aux. push ( c) ?,
1634
+ }
1635
+ }
1636
+ Ok ( aux)
1637
+ }
1638
+
1493
1639
/// Parse an item location box inside a meta box
1494
1640
/// See ISO 14496-12:2015 § 8.11.3
1495
1641
fn read_iloc < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < ItemLocationBoxItem > > {
0 commit comments