@@ -748,6 +748,11 @@ impl MediaContext {
748
748
pub struct AvifContext {
749
749
/// The collected data indicated by the `pitm` box, See ISO 14496-12:2015 § 8.11.4
750
750
pub primary_item : TryVec < u8 > ,
751
+ /// Associated alpha channel for the primary item, if any
752
+ pub alpha_item : Option < TryVec < u8 > > ,
753
+ /// If true, divide RGB values by the alpha value.
754
+ /// See `prem` in MIAF § 7.3.5.2
755
+ pub premultiplied_alpha : bool ,
751
756
}
752
757
753
758
impl AvifContext {
@@ -757,6 +762,8 @@ impl AvifContext {
757
762
}
758
763
759
764
struct AvifMeta {
765
+ item_references : TryVec < ItemReferenceEntry > ,
766
+ properties : TryVec < AssociatedProperty > ,
760
767
primary_item_id : u32 ,
761
768
iloc_items : TryVec < ItemLocationBoxItem > ,
762
769
}
@@ -1258,16 +1265,52 @@ pub fn read_avif<T: Read>(f: &mut T, context: &mut AvifContext) -> Result<()> {
1258
1265
1259
1266
let meta = meta. ok_or ( Error :: InvalidData ( "missing meta" ) ) ?;
1260
1267
1268
+ let alpha_item_id = meta
1269
+ . item_references
1270
+ . iter ( )
1271
+ // Auxiliary image for the primary image
1272
+ . filter ( |iref| {
1273
+ iref. to_item_id == meta. primary_item_id
1274
+ && iref. from_item_id != meta. primary_item_id
1275
+ && iref. item_type == b"auxl"
1276
+ } )
1277
+ . map ( |iref| iref. from_item_id )
1278
+ // which has the alpha property
1279
+ . filter ( |& item_id| {
1280
+ meta. properties . iter ( ) . any ( |prop| {
1281
+ prop. item_id == item_id
1282
+ && match & prop. property {
1283
+ ImageProperty :: AuxiliaryType ( urn) => {
1284
+ urn. as_slice ( )
1285
+ == "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha" . as_bytes ( )
1286
+ }
1287
+ _ => false ,
1288
+ }
1289
+ } )
1290
+ } )
1291
+ . next ( ) ;
1292
+
1293
+ context. premultiplied_alpha = alpha_item_id. map_or ( false , |alpha_item_id| {
1294
+ meta. item_references . iter ( ) . any ( |iref| {
1295
+ iref. from_item_id == meta. primary_item_id
1296
+ && iref. to_item_id == alpha_item_id
1297
+ && iref. item_type == b"prem"
1298
+ } )
1299
+ } ) ;
1300
+
1261
1301
// load data of relevant items
1262
1302
for loc in meta. iloc_items . iter ( ) {
1263
- if loc. item_id != meta. primary_item_id {
1303
+ let mut item_data = if loc. item_id == meta. primary_item_id {
1304
+ & mut context. primary_item
1305
+ } else if Some ( loc. item_id ) == alpha_item_id {
1306
+ context. alpha_item . get_or_insert_with ( TryVec :: new)
1307
+ } else {
1264
1308
continue ;
1265
- }
1309
+ } ;
1266
1310
1267
1311
if loc. construction_method != ConstructionMethod :: File {
1268
1312
return Err ( Error :: Unsupported ( "unsupported construction_method" ) ) ;
1269
1313
}
1270
- let mut item_data = TryVec :: new ( ) ;
1271
1314
for extent in loc. extents . iter ( ) {
1272
1315
let mut found = false ;
1273
1316
// try to find an overlapping mdat
@@ -1283,13 +1326,11 @@ pub fn read_avif<T: Read>(f: &mut T, context: &mut AvifContext) -> Result<()> {
1283
1326
}
1284
1327
}
1285
1328
if !found {
1286
- return Err ( Error :: InvalidData ( "iloc contains an extent that is not in mdat" ) ) ;
1329
+ return Err ( Error :: InvalidData (
1330
+ "iloc contains an extent that is not in mdat" ,
1331
+ ) ) ;
1287
1332
}
1288
1333
}
1289
-
1290
- if loc. item_id == meta. primary_item_id {
1291
- context. primary_item = item_data;
1292
- }
1293
1334
}
1294
1335
1295
1336
Ok ( ( ) )
@@ -1369,6 +1410,8 @@ fn read_avif_meta<T: Read + Offset>(src: &mut BMFFBox<T>) -> Result<AvifMeta> {
1369
1410
}
1370
1411
1371
1412
Ok ( AvifMeta {
1413
+ properties,
1414
+ item_references,
1372
1415
primary_item_id,
1373
1416
iloc_items : iloc_items. ok_or ( Error :: InvalidData ( "iloc missing" ) ) ?,
1374
1417
} )
@@ -1541,8 +1584,8 @@ pub enum ImageProperty {
1541
1584
impl ImageProperty {
1542
1585
fn clone ( & self ) -> Result < Self > {
1543
1586
Ok ( match self {
1544
- Self :: Channels ( val) => Self :: Channels ( val. clone ( ) ?) ,
1545
- Self :: AuxiliaryType ( val) => Self :: AuxiliaryType ( val. clone ( ) ?) ,
1587
+ Self :: Channels ( val) => Self :: Channels ( val. try_clone ( ) ?) ,
1588
+ Self :: AuxiliaryType ( val) => Self :: AuxiliaryType ( val. try_clone ( ) ?) ,
1546
1589
Self :: Unsupported => Self :: Unsupported ,
1547
1590
} )
1548
1591
}
0 commit comments