Browse Source

Update options helper to use switch and complete tests

pull/1019/head
James Jackson-South 6 years ago
parent
commit
b485452630
  1. 136
      src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
  2. 65
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  3. 10
      tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs

136
src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs

@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Formats.Png
internal static class PngEncoderOptionsHelpers
{
/// <summary>
/// Adjusts the options.
/// Adjusts the options based upon the given metadata.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="pngMetadata">The PNG metadata.</param>
@ -28,12 +28,12 @@ namespace SixLabors.ImageSharp.Formats.Png
where TPixel : struct, IPixel<TPixel>
{
// Always take the encoder options over the metadata values.
options.Gamma = options.Gamma ?? pngMetadata.Gamma;
options.Gamma ??= pngMetadata.Gamma;
options.ColorType = options.ColorType ?? SuggestColorType<TPixel>() ?? pngMetadata.ColorType;
options.BitDepth = options.BitDepth ?? SuggestBitDepth<TPixel>() ?? pngMetadata.BitDepth;
options.ColorType ??= SuggestColorType<TPixel>() ?? pngMetadata.ColorType;
options.BitDepth ??= SuggestBitDepth<TPixel>() ?? pngMetadata.BitDepth;
options.InterlaceMethod = options.InterlaceMethod ?? pngMetadata.InterlaceMethod;
options.InterlaceMethod ??= pngMetadata.InterlaceMethod;
use16Bit = options.BitDepth == PngBitDepth.Bit16;
bytesPerPixel = CalculateBytesPerPixel(options.ColorType, use16Bit);
@ -132,100 +132,68 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <returns>Bytes per pixel.</returns>
private static int CalculateBytesPerPixel(PngColorType? pngColorType, bool use16Bit)
{
switch (pngColorType)
return pngColorType switch
{
case PngColorType.Grayscale:
return use16Bit ? 2 : 1;
case PngColorType.GrayscaleWithAlpha:
return use16Bit ? 4 : 2;
case PngColorType.Palette:
return 1;
case PngColorType.Rgb:
return use16Bit ? 6 : 3;
PngColorType.Grayscale => use16Bit ? 2 : 1,
PngColorType.GrayscaleWithAlpha => use16Bit ? 4 : 2,
PngColorType.Palette => 1,
PngColorType.Rgb => use16Bit ? 6 : 3,
// PngColorType.RgbWithAlpha
default:
return use16Bit ? 8 : 4;
}
_ => use16Bit ? 8 : 4,
};
}
/// <summary>
/// Comes up with the appropriate PngColorType for some kinds of
/// IPixel. This is not exhaustive because not all options have
/// reasonable defaults
/// Returns a suggested <see cref="PngColorType"/> for the given <typeparamref name="TPixel"/>
/// This is not exhaustive but covers many common pixel formats.
/// </summary>
private static PngColorType? SuggestColorType<TPixel>()
where TPixel : struct, IPixel<TPixel>
where TPixel : struct, IPixel<TPixel>
{
Type tPixel = typeof(TPixel);
if (tPixel == typeof(Alpha8))
{
return PngColorType.GrayscaleWithAlpha;
}
if (tPixel == typeof(Argb32))
{
return PngColorType.RgbWithAlpha;
}
if (tPixel == typeof(Rgb24))
{
return PngColorType.Rgb;
}
if (tPixel == typeof(Gray16))
{
return PngColorType.Grayscale;
}
if (tPixel == typeof(Gray8))
{
return PngColorType.Grayscale;
}
return default;
return typeof(TPixel) switch
{
Type t when t == typeof(A8) => PngColorType.GrayscaleWithAlpha,
Type t when t == typeof(Argb32) => PngColorType.RgbWithAlpha,
Type t when t == typeof(Bgr24) => PngColorType.Rgb,
Type t when t == typeof(Bgra32) => PngColorType.RgbWithAlpha,
Type t when t == typeof(L8) => PngColorType.Grayscale,
Type t when t == typeof(L16) => PngColorType.Grayscale,
Type t when t == typeof(La16) => PngColorType.GrayscaleWithAlpha,
Type t when t == typeof(La32) => PngColorType.GrayscaleWithAlpha,
Type t when t == typeof(Rgb24) => PngColorType.Rgb,
Type t when t == typeof(Rgba32) => PngColorType.RgbWithAlpha,
Type t when t == typeof(Rgb48) => PngColorType.Rgb,
Type t when t == typeof(Rgba64) => PngColorType.RgbWithAlpha,
Type t when t == typeof(RgbaVector) => PngColorType.RgbWithAlpha,
_ => default(PngColorType?)
};
}
/// <summary>
/// Comes up with the appropriate PngBitDepth for some kinds of
/// IPixel. This is not exhaustive because not all options have
/// reasonable defaults
/// Returns a suggested <see cref="PngBitDepth"/> for the given <typeparamref name="TPixel"/>
/// This is not exhaustive but covers many common pixel formats.
/// </summary>
private static PngBitDepth? SuggestBitDepth<TPixel>()
where TPixel : struct, IPixel<TPixel>
where TPixel : struct, IPixel<TPixel>
{
Type tPixel = typeof(TPixel);
if (tPixel == typeof(Alpha8))
{
return PngBitDepth.Bit8;
}
if (tPixel == typeof(Argb32))
{
return PngBitDepth.Bit8;
}
if (tPixel == typeof(Rgb24))
{
return PngBitDepth.Bit8;
}
if (tPixel == typeof(Gray16))
{
return PngBitDepth.Bit16;
}
if (tPixel == typeof(Gray8))
{
return PngBitDepth.Bit8;
}
return default;
return typeof(TPixel) switch
{
Type t when t == typeof(A8) => PngBitDepth.Bit8,
Type t when t == typeof(Argb32) => PngBitDepth.Bit8,
Type t when t == typeof(Bgr24) => PngBitDepth.Bit8,
Type t when t == typeof(Bgra32) => PngBitDepth.Bit8,
Type t when t == typeof(L8) => PngBitDepth.Bit8,
Type t when t == typeof(L16) => PngBitDepth.Bit16,
Type t when t == typeof(La16) => PngBitDepth.Bit8,
Type t when t == typeof(La32) => PngBitDepth.Bit16,
Type t when t == typeof(Rgb24) => PngBitDepth.Bit8,
Type t when t == typeof(Rgba32) => PngBitDepth.Bit8,
Type t when t == typeof(Rgb48) => PngBitDepth.Bit16,
Type t when t == typeof(Rgba64) => PngBitDepth.Bit16,
Type t when t == typeof(RgbaVector) => PngBitDepth.Bit16,
_ => default(PngBitDepth?)
};
}
}
}

65
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

@ -202,46 +202,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}
[Theory]
// does the following make sense? Or is it supposed to encode a 16bpp with two 8bit channels?
[WithBlankImages(1, 1, PixelTypes.Alpha8, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.A8, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Argb32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
// [WithBlankImages(1, 1, PixelTypes.Bgr565, Can't reasonably be inferred)]
// [WithBlankImages(1, 1, PixelTypes.Bgra4444, Can't reasonably be inferred)]
// [WithBlankImages(1, 1, PixelTypes.Byte4, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.HalfSingle, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.HalfVector2, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.HalfVector4, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.NormalizedByte2, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.NormalizedByte4, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.NormalizedShort4, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Rg32, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Rgba1010102, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Rgba32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
// [WithBlankImages(1, 1, PixelTypes.Rgba64, PngColorType.RgbWithAlpha, PngBitDepth.Bit16)]
// [WithBlankImages(1, 1, PixelTypes.RgbaVector, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Short2, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Short4, I'm not sure)]
[WithBlankImages(1, 1, PixelTypes.Bgr565, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Bgra4444, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Byte4, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.HalfSingle, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.HalfVector2, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.HalfVector4, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.NormalizedByte2, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.NormalizedByte4, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.NormalizedShort4, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rg32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rgba1010102, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rgba32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.RgbaVector, PngColorType.RgbWithAlpha, PngBitDepth.Bit16)]
[WithBlankImages(1, 1, PixelTypes.Short2, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Short4, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rgb24, PngColorType.Rgb, PngBitDepth.Bit8)]
// [WithBlankImages(1, 1, PixelTypes.Bgr24, I'm not sure)]
// [WithBlankImages(1, 1, PixelTypes.Bgra32, I'm not sure)]
[WithBlankImages(1, 1, PixelTypes.Bgr24, PngColorType.Rgb, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Bgra32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rgb48, PngColorType.Rgb, PngBitDepth.Bit16)]
// [WithBlankImages(1, 1, PixelTypes.Bgra5551, I'm not sure)]
[WithBlankImages(1, 1, PixelTypes.Gray8, PngColorType.Grayscale, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Gray16, PngColorType.Grayscale, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.Rgba64, PngColorType.RgbWithAlpha, PngBitDepth.Bit16)]
[WithBlankImages(1, 1, PixelTypes.Bgra5551, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.L8, PngColorType.Grayscale, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.L16, PngColorType.Grayscale, PngBitDepth.Bit16)]
[WithBlankImages(1, 1, PixelTypes.La16, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit8)]
[WithBlankImages(1, 1, PixelTypes.La32, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit16)]
public void InfersColorTypeAndBitDepth<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
where TPixel : struct, IPixel<TPixel>
{
Stream stream = new MemoryStream();
PngEncoder encoder = new PngEncoder();
encoder.Encode<TPixel>(provider.GetImage(), stream);
using (Stream stream = new MemoryStream())
{
var encoder = new PngEncoder();
encoder.Encode(provider.GetImage(), stream);
stream.Seek(0, SeekOrigin.Begin);
stream.Seek(0, SeekOrigin.Begin);
PngDecoder decoder = new PngDecoder();
var decoder = new PngDecoder();
Image image = decoder.Decode(Configuration.Default, stream);
Image image = decoder.Decode(Configuration.Default, stream);
Assert.True(image is Image<TPixel>);
PngMetadata metadata = image.Metadata.GetPngMetadata();
Assert.Equal(pngColorType, metadata.ColorType);
Assert.Equal(pngBitDepth, metadata.BitDepth);
}
}
[Theory]

10
tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -62,11 +62,15 @@ namespace SixLabors.ImageSharp.Tests
L8 = 1 << 23,
Gray16 = 1 << 24,
L16 = 1 << 24,
La16 = 1 << 25,
La32 = 1 << 26,
// TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper
// "All" is handled as a separate, individual case instead of using bitwise OR
All = 30
}
}
}

Loading…
Cancel
Save