Browse Source

Fix transparency chunk identification

pull/1861/head
James Jackson-South 5 years ago
parent
commit
8fd9b7224c
  1. 120
      src/ImageSharp/Formats/Png/PngDecoder.cs
  2. 6
      src/ImageSharp/Formats/Png/PngDecoderCore.cs

120
src/ImageSharp/Formats/Png/PngDecoder.cs

@ -34,26 +34,48 @@ namespace SixLabors.ImageSharp.Formats.Png
PngMetadata meta = info.Metadata.GetPngMetadata(); PngMetadata meta = info.Metadata.GetPngMetadata();
PngColorType color = meta.ColorType.GetValueOrDefault(); PngColorType color = meta.ColorType.GetValueOrDefault();
PngBitDepth bits = meta.BitDepth.GetValueOrDefault(); PngBitDepth bits = meta.BitDepth.GetValueOrDefault();
return color switch switch (color)
{ {
PngColorType.Grayscale => (bits == PngBitDepth.Bit16) case PngColorType.Grayscale:
? this.Decode<L16>(configuration, stream) if (bits == PngBitDepth.Bit16)
: this.Decode<L8>(configuration, stream), {
return !meta.HasTransparency
PngColorType.Rgb => this.Decode<Rgb24>(configuration, stream), ? this.Decode<L16>(configuration, stream)
: this.Decode<La32>(configuration, stream);
PngColorType.Palette => this.Decode<Rgba32>(configuration, stream), }
PngColorType.GrayscaleWithAlpha => (bits == PngBitDepth.Bit16) return !meta.HasTransparency
? this.Decode<La32>(configuration, stream) ? this.Decode<L8>(configuration, stream)
: this.Decode<La16>(configuration, stream), : this.Decode<La16>(configuration, stream);
PngColorType.RgbWithAlpha => (bits == PngBitDepth.Bit16) case PngColorType.Rgb:
? this.Decode<Rgba64>(configuration, stream) if (bits == PngBitDepth.Bit16)
: this.Decode<Rgba32>(configuration, stream), {
return !meta.HasTransparency
_ => this.Decode<Rgba32>(configuration, stream), ? this.Decode<Rgb48>(configuration, stream)
}; : this.Decode<Rgba64>(configuration, stream);
}
return !meta.HasTransparency
? this.Decode<Rgb24>(configuration, stream)
: this.Decode<Rgba32>(configuration, stream);
case PngColorType.Palette:
return this.Decode<Rgba32>(configuration, stream);
case PngColorType.GrayscaleWithAlpha:
return (bits == PngBitDepth.Bit16)
? this.Decode<La32>(configuration, stream)
: this.Decode<La16>(configuration, stream);
case PngColorType.RgbWithAlpha:
return (bits == PngBitDepth.Bit16)
? this.Decode<Rgba64>(configuration, stream)
: this.Decode<Rgba32>(configuration, stream);
default:
return this.Decode<Rgba32>(configuration, stream);
}
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -74,26 +96,48 @@ namespace SixLabors.ImageSharp.Formats.Png
PngMetadata meta = info.Metadata.GetPngMetadata(); PngMetadata meta = info.Metadata.GetPngMetadata();
PngColorType color = meta.ColorType.GetValueOrDefault(); PngColorType color = meta.ColorType.GetValueOrDefault();
PngBitDepth bits = meta.BitDepth.GetValueOrDefault(); PngBitDepth bits = meta.BitDepth.GetValueOrDefault();
return color switch switch (color)
{ {
PngColorType.Grayscale => (bits == PngBitDepth.Bit16) case PngColorType.Grayscale:
? await this.DecodeAsync<L16>(configuration, stream, cancellationToken).ConfigureAwait(false) if (bits == PngBitDepth.Bit16)
: await this.DecodeAsync<L8>(configuration, stream, cancellationToken).ConfigureAwait(false), {
return !meta.HasTransparency
PngColorType.Rgb => await this.DecodeAsync<Rgb24>(configuration, stream, cancellationToken).ConfigureAwait(false), ? await this.DecodeAsync<L16>(configuration, stream, cancellationToken).ConfigureAwait(false)
: await this.DecodeAsync<La32>(configuration, stream, cancellationToken).ConfigureAwait(false);
PngColorType.Palette => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false), }
PngColorType.GrayscaleWithAlpha => (bits == PngBitDepth.Bit16) return !meta.HasTransparency
? await this.DecodeAsync<La32>(configuration, stream, cancellationToken).ConfigureAwait(false) ? await this.DecodeAsync<L8>(configuration, stream, cancellationToken).ConfigureAwait(false)
: await this.DecodeAsync<La16>(configuration, stream, cancellationToken).ConfigureAwait(false), : await this.DecodeAsync<La16>(configuration, stream, cancellationToken).ConfigureAwait(false);
PngColorType.RgbWithAlpha => (bits == PngBitDepth.Bit16) case PngColorType.Rgb:
? await this.DecodeAsync<Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false) if (bits == PngBitDepth.Bit16)
: await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false), {
return !meta.HasTransparency
_ => await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false), ? await this.DecodeAsync<Rgb48>(configuration, stream, cancellationToken).ConfigureAwait(false)
}; : await this.DecodeAsync<Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false);
}
return !meta.HasTransparency
? await this.DecodeAsync<Rgb24>(configuration, stream, cancellationToken).ConfigureAwait(false)
: await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false);
case PngColorType.Palette:
return await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false);
case PngColorType.GrayscaleWithAlpha:
return (bits == PngBitDepth.Bit16)
? await this.DecodeAsync<La32>(configuration, stream, cancellationToken).ConfigureAwait(false)
: await this.DecodeAsync<La16>(configuration, stream, cancellationToken).ConfigureAwait(false);
case PngColorType.RgbWithAlpha:
return (bits == PngBitDepth.Bit16)
? await this.DecodeAsync<Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false)
: await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false);
default:
return await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false);
}
} }
/// <inheritdoc/> /// <inheritdoc/>

6
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -258,6 +258,12 @@ namespace SixLabors.ImageSharp.Formats.Png
case PngChunkType.Data: case PngChunkType.Data:
this.SkipChunkDataAndCrc(chunk); this.SkipChunkDataAndCrc(chunk);
break; break;
case PngChunkType.Transparency:
byte[] alpha = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(alpha);
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha, pngMetadata);
break;
case PngChunkType.Text: case PngChunkType.Text:
this.ReadTextChunk(pngMetadata, chunk.Data.GetSpan()); this.ReadTextChunk(pngMetadata, chunk.Data.GetSpan());
break; break;

Loading…
Cancel
Save