@@ -1466,23 +1466,48 @@ private void SanitizeAndSetEncoderOptions<TPixel>(
1466
1466
1467
1467
// Use options, then check metadata, if nothing set there then we suggest
1468
1468
// a sensible default based upon the pixel format.
1469
- this . colorType = encoder . ColorType ?? pngMetadata . ColorType ?? SuggestColorType < TPixel > ( ) ;
1470
- if ( ! encoder . FilterMethod . HasValue )
1469
+ PngColorType ? colorType = encoder . ColorType ?? pngMetadata . ColorType ;
1470
+ byte ? bits = ( byte ? ) ( encoder . BitDepth ?? pngMetadata . BitDepth ) ;
1471
+
1472
+ if ( colorType is null || bits is null )
1471
1473
{
1472
- // Specification recommends default filter method None for paletted images and Paeth for others.
1473
- this . filterMethod = this . colorType is PngColorType . Palette ? PngFilterMethod . None : PngFilterMethod . Paeth ;
1474
+ PixelTypeInfo info = TPixel . GetPixelTypeInfo ( ) ;
1475
+ PixelComponentInfo ? componentInfo = info . ComponentInfo ;
1476
+
1477
+ colorType ??= SuggestColorType < TPixel > ( in info ) ;
1478
+
1479
+ if ( bits is null )
1480
+ {
1481
+ // TODO: Update once we stop abusing PixelTypeInfo in decoders.
1482
+ if ( componentInfo . HasValue )
1483
+ {
1484
+ PixelComponentInfo c = componentInfo . Value ;
1485
+ bits = ( byte ) SuggestBitDepth < TPixel > ( in c ) ;
1486
+ }
1487
+ else
1488
+ {
1489
+ bits = ( byte ) PngBitDepth . Bit8 ;
1490
+ }
1491
+ }
1474
1492
}
1475
1493
1476
1494
// Ensure bit depth and color type are a supported combination.
1477
1495
// Bit8 is the only bit depth supported by all color types.
1478
- byte bits = ( byte ) ( encoder . BitDepth ?? pngMetadata . BitDepth ?? SuggestBitDepth < TPixel > ( ) ) ;
1479
- byte [ ] validBitDepths = PngConstants . ColorTypes [ this . colorType ] ;
1496
+ byte [ ] validBitDepths = PngConstants . ColorTypes [ colorType . Value ] ;
1480
1497
if ( Array . IndexOf ( validBitDepths , bits ) == - 1 )
1481
1498
{
1482
1499
bits = ( byte ) PngBitDepth . Bit8 ;
1483
1500
}
1484
1501
1485
- this . bitDepth = bits ;
1502
+ this . colorType = colorType . Value ;
1503
+ this . bitDepth = bits . Value ;
1504
+
1505
+ if ( ! encoder . FilterMethod . HasValue )
1506
+ {
1507
+ // Specification recommends default filter method None for paletted images and Paeth for others.
1508
+ this . filterMethod = this . colorType is PngColorType . Palette ? PngFilterMethod . None : PngFilterMethod . Paeth ;
1509
+ }
1510
+
1486
1511
use16Bit = bits == ( byte ) PngBitDepth . Bit16 ;
1487
1512
bytesPerPixel = CalculateBytesPerPixel ( this . colorType , use16Bit ) ;
1488
1513
@@ -1611,53 +1636,44 @@ private static int CalculateBytesPerPixel(PngColorType? pngColorType, bool use16
1611
1636
1612
1637
/// <summary>
1613
1638
/// Returns a suggested <see cref="PngColorType"/> for the given <typeparamref name="TPixel"/>
1614
- /// This is not exhaustive but covers many common pixel formats.
1615
1639
/// </summary>
1640
+ /// <param name="info">The pixel type info.</param>
1616
1641
/// <typeparam name="TPixel">The type of pixel format.</typeparam>
1617
- private static PngColorType SuggestColorType < TPixel > ( )
1642
+ private static PngColorType SuggestColorType < TPixel > ( in PixelTypeInfo info )
1618
1643
where TPixel : unmanaged, IPixel < TPixel >
1619
- => default ( TPixel ) switch
1620
- {
1621
- A8 => PngColorType . GrayscaleWithAlpha ,
1622
- Argb32 => PngColorType . RgbWithAlpha ,
1623
- Bgr24 => PngColorType . Rgb ,
1624
- Bgra32 => PngColorType . RgbWithAlpha ,
1625
- L8 => PngColorType . Grayscale ,
1626
- L16 => PngColorType . Grayscale ,
1627
- La16 => PngColorType . GrayscaleWithAlpha ,
1628
- La32 => PngColorType . GrayscaleWithAlpha ,
1629
- Rgb24 => PngColorType . Rgb ,
1630
- Rgba32 => PngColorType . RgbWithAlpha ,
1631
- Rgb48 => PngColorType . Rgb ,
1632
- Rgba64 => PngColorType . RgbWithAlpha ,
1633
- RgbaVector => PngColorType . RgbWithAlpha ,
1634
- _ => PngColorType . RgbWithAlpha
1644
+ {
1645
+ if ( info . AlphaRepresentation == PixelAlphaRepresentation . None )
1646
+ {
1647
+ return info . ColorType switch
1648
+ {
1649
+ PixelColorType . Grayscale => PngColorType . Grayscale ,
1650
+ _ => PngColorType . Rgb ,
1651
+ } ;
1652
+ }
1653
+
1654
+ return info . ColorType switch
1655
+ {
1656
+ PixelColorType . Grayscale | PixelColorType . Alpha or PixelColorType . Alpha => PngColorType . GrayscaleWithAlpha ,
1657
+ _ => PngColorType . RgbWithAlpha ,
1635
1658
} ;
1659
+ }
1636
1660
1637
1661
/// <summary>
1638
1662
/// Returns a suggested <see cref="PngBitDepth"/> for the given <typeparamref name="TPixel"/>
1639
- /// This is not exhaustive but covers many common pixel formats.
1640
1663
/// </summary>
1664
+ /// <param name="info">The pixel type info.</param>
1641
1665
/// <typeparam name="TPixel">The type of pixel format.</typeparam>
1642
- private static PngBitDepth SuggestBitDepth < TPixel > ( )
1666
+ private static PngBitDepth SuggestBitDepth < TPixel > ( in PixelComponentInfo info )
1643
1667
where TPixel : unmanaged, IPixel < TPixel >
1644
- => default ( TPixel ) switch
1645
- {
1646
- A8 => PngBitDepth . Bit8 ,
1647
- Argb32 => PngBitDepth . Bit8 ,
1648
- Bgr24 => PngBitDepth . Bit8 ,
1649
- Bgra32 => PngBitDepth . Bit8 ,
1650
- L8 => PngBitDepth . Bit8 ,
1651
- L16 => PngBitDepth . Bit16 ,
1652
- La16 => PngBitDepth . Bit8 ,
1653
- La32 => PngBitDepth . Bit16 ,
1654
- Rgb24 => PngBitDepth . Bit8 ,
1655
- Rgba32 => PngBitDepth . Bit8 ,
1656
- Rgb48 => PngBitDepth . Bit16 ,
1657
- Rgba64 => PngBitDepth . Bit16 ,
1658
- RgbaVector => PngBitDepth . Bit16 ,
1659
- _ => PngBitDepth . Bit8
1660
- } ;
1668
+ {
1669
+ int bits = info . GetMaximumComponentPrecision ( ) ;
1670
+ if ( bits > ( int ) PixelComponentBitDepth . Bit8 )
1671
+ {
1672
+ return PngBitDepth . Bit16 ;
1673
+ }
1674
+
1675
+ return PngBitDepth . Bit8 ;
1676
+ }
1661
1677
1662
1678
private unsafe struct ScratchBuffer
1663
1679
{
0 commit comments