@@ -14,23 +14,28 @@ namespace SixLabors.ImageSharp.Formats.Png
1414 internal static class PngEncoderOptionsHelpers
1515 {
1616 /// <summary>
17- /// Adjusts the options.
17+ /// Adjusts the options based upon the given metadata .
1818 /// </summary>
1919 /// <param name="options">The options.</param>
2020 /// <param name="pngMetadata">The PNG metadata.</param>
2121 /// <param name="use16Bit">if set to <c>true</c> [use16 bit].</param>
2222 /// <param name="bytesPerPixel">The bytes per pixel.</param>
23- public static void AdjustOptions (
23+ public static void AdjustOptions < TPixel > (
2424 PngEncoderOptions options ,
2525 PngMetadata pngMetadata ,
2626 out bool use16Bit ,
2727 out int bytesPerPixel )
28+ where TPixel : struct , IPixel < TPixel >
2829 {
2930 // Always take the encoder options over the metadata values.
30- options . Gamma = options . Gamma ?? pngMetadata . Gamma ;
31- options . ColorType = options . ColorType ?? pngMetadata . ColorType ;
32- options . BitDepth = options . BitDepth ?? pngMetadata . BitDepth ;
33- options . InterlaceMethod = options . InterlaceMethod ?? pngMetadata . InterlaceMethod ;
31+ options . Gamma ??= pngMetadata . Gamma ;
32+
33+ // Use options, then check metadata, if nothing set there then we suggest
34+ // a sensible default based upon the pixel format.
35+ options . ColorType ??= pngMetadata . ColorType ?? SuggestColorType < TPixel > ( ) ;
36+ options . BitDepth ??= pngMetadata . BitDepth ?? SuggestBitDepth < TPixel > ( ) ;
37+
38+ options . InterlaceMethod ??= pngMetadata . InterlaceMethod ;
3439
3540 use16Bit = options . BitDepth == PngBitDepth . Bit16 ;
3641 bytesPerPixel = CalculateBytesPerPixel ( options . ColorType , use16Bit ) ;
@@ -129,24 +134,68 @@ public static byte CalculateBitDepth<TPixel>(
129134 /// <returns>Bytes per pixel.</returns>
130135 private static int CalculateBytesPerPixel ( PngColorType ? pngColorType , bool use16Bit )
131136 {
132- switch ( pngColorType )
137+ return pngColorType switch
133138 {
134- case PngColorType . Grayscale :
135- return use16Bit ? 2 : 1 ;
139+ PngColorType . Grayscale => use16Bit ? 2 : 1 ,
140+ PngColorType . GrayscaleWithAlpha => use16Bit ? 4 : 2 ,
141+ PngColorType . Palette => 1 ,
142+ PngColorType . Rgb => use16Bit ? 6 : 3 ,
136143
137- case PngColorType . GrayscaleWithAlpha :
138- return use16Bit ? 4 : 2 ;
139-
140- case PngColorType . Palette :
141- return 1 ;
144+ // PngColorType.RgbWithAlpha
145+ _ => use16Bit ? 8 : 4 ,
146+ } ;
147+ }
142148
143- case PngColorType . Rgb :
144- return use16Bit ? 6 : 3 ;
149+ /// <summary>
150+ /// Returns a suggested <see cref="PngColorType"/> for the given <typeparamref name="TPixel"/>
151+ /// This is not exhaustive but covers many common pixel formats.
152+ /// </summary>
153+ private static PngColorType SuggestColorType < TPixel > ( )
154+ where TPixel : struct , IPixel < TPixel >
155+ {
156+ return typeof ( TPixel ) switch
157+ {
158+ Type t when t == typeof ( A8 ) => PngColorType . GrayscaleWithAlpha ,
159+ Type t when t == typeof ( Argb32 ) => PngColorType . RgbWithAlpha ,
160+ Type t when t == typeof ( Bgr24 ) => PngColorType . Rgb ,
161+ Type t when t == typeof ( Bgra32 ) => PngColorType . RgbWithAlpha ,
162+ Type t when t == typeof ( L8 ) => PngColorType . Grayscale ,
163+ Type t when t == typeof ( L16 ) => PngColorType . Grayscale ,
164+ Type t when t == typeof ( La16 ) => PngColorType . GrayscaleWithAlpha ,
165+ Type t when t == typeof ( La32 ) => PngColorType . GrayscaleWithAlpha ,
166+ Type t when t == typeof ( Rgb24 ) => PngColorType . Rgb ,
167+ Type t when t == typeof ( Rgba32 ) => PngColorType . RgbWithAlpha ,
168+ Type t when t == typeof ( Rgb48 ) => PngColorType . Rgb ,
169+ Type t when t == typeof ( Rgba64 ) => PngColorType . RgbWithAlpha ,
170+ Type t when t == typeof ( RgbaVector ) => PngColorType . RgbWithAlpha ,
171+ _ => PngColorType . RgbWithAlpha
172+ } ;
173+ }
145174
146- // PngColorType.RgbWithAlpha
147- default :
148- return use16Bit ? 8 : 4 ;
149- }
175+ /// <summary>
176+ /// Returns a suggested <see cref="PngBitDepth"/> for the given <typeparamref name="TPixel"/>
177+ /// This is not exhaustive but covers many common pixel formats.
178+ /// </summary>
179+ private static PngBitDepth SuggestBitDepth < TPixel > ( )
180+ where TPixel : struct , IPixel < TPixel >
181+ {
182+ return typeof ( TPixel ) switch
183+ {
184+ Type t when t == typeof ( A8 ) => PngBitDepth . Bit8 ,
185+ Type t when t == typeof ( Argb32 ) => PngBitDepth . Bit8 ,
186+ Type t when t == typeof ( Bgr24 ) => PngBitDepth . Bit8 ,
187+ Type t when t == typeof ( Bgra32 ) => PngBitDepth . Bit8 ,
188+ Type t when t == typeof ( L8 ) => PngBitDepth . Bit8 ,
189+ Type t when t == typeof ( L16 ) => PngBitDepth . Bit16 ,
190+ Type t when t == typeof ( La16 ) => PngBitDepth . Bit8 ,
191+ Type t when t == typeof ( La32 ) => PngBitDepth . Bit16 ,
192+ Type t when t == typeof ( Rgb24 ) => PngBitDepth . Bit8 ,
193+ Type t when t == typeof ( Rgba32 ) => PngBitDepth . Bit8 ,
194+ Type t when t == typeof ( Rgb48 ) => PngBitDepth . Bit16 ,
195+ Type t when t == typeof ( Rgba64 ) => PngBitDepth . Bit16 ,
196+ Type t when t == typeof ( RgbaVector ) => PngBitDepth . Bit16 ,
197+ _ => PngBitDepth . Bit8
198+ } ;
150199 }
151200 }
152201}
0 commit comments