Browse Source

Use standard HEIF ownership arrays

pull/2633/head
James Jackson-South 1 month ago
parent
commit
dfb43927ad
  1. 1
      HEIF_IMPLEMENTATION_PLAN.md
  2. 2
      src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs
  3. 6
      src/ImageSharp/Formats/Heif/HeifDecoderCore.cs

1
HEIF_IMPLEMENTATION_PLAN.md

@ -71,6 +71,7 @@ Current cICP failure correction evidence from 2026-08-31:
- The direct embedded-ICC case and every row of the 12-case profile matrix passed: 13 of 13 net11.0 Release cases. - The direct embedded-ICC case and every row of the 12-case profile matrix passed: 13 of 13 net11.0 Release cases.
- The exact 34 cases reported by CI passed: 34 of 34 net11.0 Release cases, with zero failures and zero skips. - The exact 34 cases reported by CI passed: 34 of 34 net11.0 Release cases, with zero failures and zero skips.
- Roslynk reported zero compiler errors after the fix, and `git diff --check` passed. - Roslynk reported zero compiler errors after the fix, and `git diff --check` passed.
- The remaining four branch-introduced `GC.AllocateUninitializedArray` calls are removed from AV1 configuration, pixel-information, XMP, and Exif ownership boundaries. Each retained value still receives exactly one array and one copy because its source span belongs to pooled storage; no second materialization was introduced. The exact net11 Release rebuild remains at 1,005 warnings and zero errors, 166 focused configuration and metadata cases pass, and all 9,181 HEIF tests pass through direct VSTest.
Recovered task-history evidence from 2026-08-31: Recovered task-history evidence from 2026-08-31:

2
src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs

@ -109,7 +109,7 @@ internal sealed class Av1CodecConfiguration
{ {
// The property-reader span is pooled and reused. Retain only the sequence-header bytes required for // The property-reader span is pooled and reused. Retain only the sequence-header bytes required for
// item/sample equivalence instead of materializing every optional configuration OBU. // item/sample equivalence instead of materializing every optional configuration OBU.
this.configSequenceHeader = GC.AllocateUninitializedArray<byte>(configSequenceHeaderLength); this.configSequenceHeader = new byte[configSequenceHeaderLength];
configObus.Slice(configSequenceHeaderOffset, configSequenceHeaderLength).CopyTo(this.configSequenceHeader); configObus.Slice(configSequenceHeaderOffset, configSequenceHeaderLength).CopyTo(this.configSequenceHeader);
} }
} }

6
src/ImageSharp/Formats/Heif/HeifDecoderCore.cs

@ -1370,7 +1370,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore
// Property associations are resolved after the pooled box buffer is reused, so retain the // Property associations are resolved after the pooled box buffer is reused, so retain the
// exact channel vector once at this ownership boundary. // exact channel vector once at this ownership boundary.
byte[] channelBitDepths = GC.AllocateUninitializedArray<byte>(channelCount); byte[] channelBitDepths = new byte[channelCount];
boxBuffer.Slice(offset, channelCount).CopyTo(channelBitDepths); boxBuffer.Slice(offset, channelCount).CopyTo(channelBitDepths);
for (int i = 0; i < channelBitDepths.Length; i++) for (int i = 0; i < channelBitDepths.Length; i++)
{ {
@ -2530,7 +2530,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore
Span<byte> itemData = itemMemory.GetSpan(); Span<byte> itemData = itemMemory.GetSpan();
// XmpProfile retains its input array after the assembled item buffer is returned to its pool. // XmpProfile retains its input array after the assembled item buffer is returned to its pool.
byte[] ownedData = GC.AllocateUninitializedArray<byte>(itemData.Length); byte[] ownedData = new byte[itemData.Length];
itemData.CopyTo(ownedData); itemData.CopyTo(ownedData);
metadata.XmpProfile = new XmpProfile(ownedData); metadata.XmpProfile = new XmpProfile(ownedData);
}); });
@ -2583,7 +2583,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore
ReadOnlySpan<byte> tiffData = exifData[actualTiffHeaderOffset..]; ReadOnlySpan<byte> tiffData = exifData[actualTiffHeaderOffset..];
// ExifProfile retains its input array after the assembled item buffers are disposed at the end of decode. // ExifProfile retains its input array after the assembled item buffers are disposed at the end of decode.
byte[] ownedData = GC.AllocateUninitializedArray<byte>(tiffData.Length); byte[] ownedData = new byte[tiffData.Length];
tiffData.CopyTo(ownedData); tiffData.CopyTo(ownedData);
metadata.ExifProfile = new ExifProfile(ownedData); metadata.ExifProfile = new ExifProfile(ownedData);
} }

Loading…
Cancel
Save