Browse Source

MakeTransparentBlack option now work with all png color type

pull/1574/head
Brian Popow 6 years ago
parent
commit
bc1e8b6353
  1. 109
      src/ImageSharp/Formats/Png/PngEncoderCore.cs

109
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -144,7 +144,14 @@ namespace SixLabors.ImageSharp.Formats.Png
PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance);
PngEncoderOptionsHelpers.AdjustOptions<TPixel>(this.options, pngMetadata, out this.use16Bit, out this.bytesPerPixel);
IndexedImageFrame<TPixel> quantized = this.CreateQuantizedImage(image);
Image<TPixel> clonedImage = null;
if (this.options.MakeTransparentBlack)
{
clonedImage = image.Clone();
MakeTransparentPixelsBlack(clonedImage);
}
IndexedImageFrame<TPixel> quantized = this.CreateQuantizedImage(image, clonedImage);
stream.Write(PngConstants.HeaderBytes);
@ -155,12 +162,55 @@ namespace SixLabors.ImageSharp.Formats.Png
this.WritePhysicalChunk(stream, metadata);
this.WriteExifChunk(stream, metadata);
this.WriteTextChunks(stream, pngMetadata);
this.WriteDataChunks(image.Frames.RootFrame, quantized, stream);
this.WriteDataChunks(this.options.MakeTransparentBlack ? clonedImage : image, quantized, stream);
this.WriteEndChunk(stream);
stream.Flush();
quantized?.Dispose();
clonedImage?.Dispose();
}
/// <inheritdoc />
public void Dispose()
{
this.previousScanline?.Dispose();
this.currentScanline?.Dispose();
this.subFilter?.Dispose();
this.averageFilter?.Dispose();
this.paethFilter?.Dispose();
this.filterBuffer?.Dispose();
this.previousScanline = null;
this.currentScanline = null;
this.subFilter = null;
this.averageFilter = null;
this.paethFilter = null;
this.filterBuffer = null;
}
/// <summary>
/// Makes transparent pixels black.
/// </summary>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="image">The cloned image where the transparent pixels will be changed.</param>
private static void MakeTransparentPixelsBlack<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
Rgba32 rgba32 = default;
for (int y = 0; y < image.Height; y++)
{
Span<TPixel> span = image.GetPixelRowSpan(y);
for (int x = 0; x < image.Width; x++)
{
span[x].ToRgba32(ref rgba32);
if (rgba32.A == 0)
{
span[x].FromRgba32(Color.Black);
}
}
}
}
/// <summary>
@ -168,37 +218,16 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </summary>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="image">The image to quantize.</param>
/// <param name="clonedImage">Cloned image with transparent pixels are changed to black.</param>
/// <returns>The quantized image.</returns>
private IndexedImageFrame<TPixel> CreateQuantizedImage<TPixel>(Image<TPixel> image)
private IndexedImageFrame<TPixel> CreateQuantizedImage<TPixel>(Image<TPixel> image, Image<TPixel> clonedImage)
where TPixel : unmanaged, IPixel<TPixel>
{
IndexedImageFrame<TPixel> quantized;
if (this.options.MakeTransparentBlack)
{
using (Image<TPixel> tempImage = image.Clone())
{
for (int y = 0; y < image.Height; y++)
{
Span<TPixel> span = tempImage.GetPixelRowSpan(y);
for (int x = 0; x < image.Width; x++)
{
Rgba32 rgba32 = default;
span[x].ToRgba32(ref rgba32);
if (rgba32.A == 0)
{
rgba32.R = 0;
rgba32.G = 0;
rgba32.B = 0;
}
span[x].FromRgba32(rgba32);
}
}
quantized = PngEncoderOptionsHelpers.CreateQuantizedFrame(this.options, tempImage);
this.bitDepth = PngEncoderOptionsHelpers.CalculateBitDepth(this.options, tempImage, quantized);
}
quantized = PngEncoderOptionsHelpers.CreateQuantizedFrame(this.options, clonedImage);
this.bitDepth = PngEncoderOptionsHelpers.CalculateBitDepth(this.options, clonedImage, quantized);
}
else
{
@ -209,24 +238,6 @@ namespace SixLabors.ImageSharp.Formats.Png
return quantized;
}
/// <inheritdoc />
public void Dispose()
{
this.previousScanline?.Dispose();
this.currentScanline?.Dispose();
this.subFilter?.Dispose();
this.averageFilter?.Dispose();
this.paethFilter?.Dispose();
this.filterBuffer?.Dispose();
this.previousScanline = null;
this.currentScanline = null;
this.subFilter = null;
this.averageFilter = null;
this.paethFilter = null;
this.filterBuffer = null;
}
/// <summary>Collects a row of grayscale pixels.</summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="rowSpan">The image row span.</param>
@ -859,7 +870,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <param name="pixels">The image.</param>
/// <param name="quantized">The quantized pixel data. Can be null.</param>
/// <param name="stream">The stream.</param>
private void WriteDataChunks<TPixel>(ImageFrame<TPixel> pixels, IndexedImageFrame<TPixel> quantized, Stream stream)
private void WriteDataChunks<TPixel>(Image<TPixel> pixels, IndexedImageFrame<TPixel> quantized, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
byte[] buffer;
@ -957,8 +968,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <param name="pixels">The pixels.</param>
/// <param name="quantized">The quantized pixels span.</param>
/// <param name="deflateStream">The deflate stream.</param>
private void EncodePixels<TPixel>(ImageFrame<TPixel> pixels, IndexedImageFrame<TPixel> quantized, ZlibDeflateStream deflateStream)
where TPixel : unmanaged, IPixel<TPixel>
private void EncodePixels<TPixel>(Image<TPixel> pixels, IndexedImageFrame<TPixel> quantized, ZlibDeflateStream deflateStream)
where TPixel : unmanaged, IPixel<TPixel>
{
int bytesPerScanline = this.CalculateScanlineLength(this.width);
int resultLength = bytesPerScanline + 1;
@ -981,7 +992,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="pixels">The pixels.</param>
/// <param name="deflateStream">The deflate stream.</param>
private void EncodeAdam7Pixels<TPixel>(ImageFrame<TPixel> pixels, ZlibDeflateStream deflateStream)
private void EncodeAdam7Pixels<TPixel>(Image<TPixel> pixels, ZlibDeflateStream deflateStream)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = pixels.Width;

Loading…
Cancel
Save