mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Better organisation, handles all color types + maintains image quality. Former-commit-id: 27d65b60f5e468e9678d0f9dd0314700e658036e Former-commit-id: 1ed0afaccc0218f60cdc749a83725c9f9693ab4a Former-commit-id: d20d7fd77362ad6cbb570b46105f2817df99c85caf/merge-core
7 changed files with 265 additions and 491 deletions
@ -1,76 +0,0 @@ |
|||
// <copyright file="GrayscaleReader.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Color reader for reading grayscale colors from a png file.
|
|||
/// </summary>
|
|||
internal sealed class GrayscaleReader : IColorReader |
|||
{ |
|||
/// <summary>
|
|||
/// Whether t also read the alpha channel.
|
|||
/// </summary>
|
|||
private readonly bool useAlpha; |
|||
|
|||
/// <summary>
|
|||
/// The current row.
|
|||
/// </summary>
|
|||
private int row; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GrayscaleReader"/> class.
|
|||
/// </summary>
|
|||
/// <param name="useAlpha">
|
|||
/// If set to <c>true</c> the color reader will also read the
|
|||
/// alpha channel from the scanline.
|
|||
/// </param>
|
|||
public GrayscaleReader(bool useAlpha) |
|||
{ |
|||
this.useAlpha = useAlpha; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ReadScanline<T, TP>(byte[] scanline, T[] pixels, PngHeader header) |
|||
where T : IPackedVector<TP> |
|||
where TP : struct |
|||
{ |
|||
int offset; |
|||
|
|||
byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); |
|||
|
|||
// Stored in r-> g-> b-> a order.
|
|||
if (this.useAlpha) |
|||
{ |
|||
for (int x = 0; x < header.Width / 2; x++) |
|||
{ |
|||
offset = (this.row * header.Width) + x; |
|||
|
|||
byte rgb = newScanline[x * 2]; |
|||
byte a = newScanline[(x * 2) + 1]; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(rgb, rgb, rgb, a); |
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < header.Width; x++) |
|||
{ |
|||
offset = (this.row * header.Width) + x; |
|||
byte rgb = newScanline[x]; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(rgb, rgb, rgb, 255); |
|||
|
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
|
|||
this.row++; |
|||
} |
|||
} |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
// <copyright file="IColorReader.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Encapsulates methods for color readers, which are responsible for reading
|
|||
/// different color formats from a png file.
|
|||
/// </summary>
|
|||
public interface IColorReader |
|||
{ |
|||
/// <summary>
|
|||
/// Reads the specified scanline.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The pixel format.</typeparam>
|
|||
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
|||
/// <param name="scanline">The scanline.</param>
|
|||
/// <param name="pixels">The pixels to read the image row to.</param>
|
|||
/// <param name="header">
|
|||
/// The header, which contains information about the png file, like
|
|||
/// the width of the image and the height.
|
|||
/// </param>
|
|||
void ReadScanline<T, TP>(byte[] scanline, T[] pixels, PngHeader header) |
|||
where T : IPackedVector<TP> |
|||
where TP : struct; |
|||
} |
|||
} |
|||
@ -1,95 +0,0 @@ |
|||
// <copyright file="PaletteIndexReader.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// A color reader for reading palette indices from the png file.
|
|||
/// </summary>
|
|||
internal sealed class PaletteIndexReader : IColorReader |
|||
{ |
|||
/// <summary>
|
|||
/// The palette.
|
|||
/// </summary>
|
|||
private readonly byte[] palette; |
|||
|
|||
/// <summary>
|
|||
/// The alpha palette.
|
|||
/// </summary>
|
|||
private readonly byte[] paletteAlpha; |
|||
|
|||
/// <summary>
|
|||
/// The current row.
|
|||
/// </summary>
|
|||
private int row; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PaletteIndexReader"/> class.
|
|||
/// </summary>
|
|||
/// <param name="palette">The palette as simple byte array. It will contains 3 values for each
|
|||
/// color, which represents the red-, the green- and the blue channel.</param>
|
|||
/// <param name="paletteAlpha">The alpha palette. Can be null, if the image does not have an
|
|||
/// alpha channel and can contain less entries than the number of colors in the palette.</param>
|
|||
public PaletteIndexReader(byte[] palette, byte[] paletteAlpha) |
|||
{ |
|||
this.palette = palette; |
|||
this.paletteAlpha = paletteAlpha; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ReadScanline<T, TP>(byte[] scanline, T[] pixels, PngHeader header) |
|||
where T : IPackedVector<TP> |
|||
where TP : struct |
|||
{ |
|||
byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); |
|||
int offset, index; |
|||
|
|||
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) |
|||
{ |
|||
// If the alpha palette is not null and does one or
|
|||
// more entries, this means, that the image contains and alpha
|
|||
// channel and we should try to read it.
|
|||
for (int i = 0; i < header.Width; i++) |
|||
{ |
|||
index = newScanline[i]; |
|||
|
|||
offset = (this.row * header.Width) + i; |
|||
int pixelOffset = index * 3; |
|||
|
|||
byte r = this.palette[pixelOffset]; |
|||
byte g = this.palette[pixelOffset + 1]; |
|||
byte b = this.palette[pixelOffset + 2]; |
|||
byte a = this.paletteAlpha.Length > index |
|||
? this.paletteAlpha[index] |
|||
: (byte)255; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(r, g, b, a); |
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int i = 0; i < header.Width; i++) |
|||
{ |
|||
index = newScanline[i]; |
|||
|
|||
offset = (this.row * header.Width) + i; |
|||
int pixelOffset = index * 3; |
|||
|
|||
byte r = this.palette[pixelOffset]; |
|||
byte g = this.palette[pixelOffset + 1]; |
|||
byte b = this.palette[pixelOffset + 2]; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(r, g, b, 255); |
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
|
|||
this.row++; |
|||
} |
|||
} |
|||
} |
|||
@ -1,61 +0,0 @@ |
|||
// <copyright file="PngColorTypeInformation.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Contains information that are required when loading a png with a specific color type.
|
|||
/// </summary>
|
|||
internal sealed class PngColorTypeInformation |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PngColorTypeInformation"/> class with
|
|||
/// the scanline factory, the function to create the color reader and the supported bit depths.
|
|||
/// </summary>
|
|||
/// <param name="scanlineFactor">The scanline factor.</param>
|
|||
/// <param name="supportedBitDepths">The supported bit depths.</param>
|
|||
/// <param name="scanlineReaderFactory">The factory to create the color reader.</param>
|
|||
public PngColorTypeInformation(int scanlineFactor, int[] supportedBitDepths, Func<byte[], byte[], IColorReader> scanlineReaderFactory) |
|||
{ |
|||
this.ChannelsPerColor = scanlineFactor; |
|||
this.ScanlineReaderFactory = scanlineReaderFactory; |
|||
this.SupportedBitDepths = supportedBitDepths; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets an array with the bit depths that are supported for the color type
|
|||
/// where this object is created for.
|
|||
/// </summary>
|
|||
/// <value>The supported bit depths that can be used in combination with this color type.</value>
|
|||
public int[] SupportedBitDepths { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a function that is used the create the color reader for the color type where
|
|||
/// this object is created for.
|
|||
/// </summary>
|
|||
/// <value>The factory function to create the color type.</value>
|
|||
public Func<byte[], byte[], IColorReader> ScanlineReaderFactory { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a factor that is used when iterating through the scan lines.
|
|||
/// </summary>
|
|||
/// <value>The scanline factor.</value>
|
|||
public int ChannelsPerColor { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Creates the color reader for the color type where this object is create for.
|
|||
/// </summary>
|
|||
/// <param name="palette">The palette of the image. Can be null when no palette is used.</param>
|
|||
/// <param name="paletteAlpha">The alpha palette of the image. Can be null when
|
|||
/// no palette is used for the image or when the image has no alpha.</param>
|
|||
/// <returns>The color reader for the image.</returns>
|
|||
public IColorReader CreateColorReader(byte[] palette, byte[] paletteAlpha) |
|||
{ |
|||
return this.ScanlineReaderFactory(palette, paletteAlpha); |
|||
} |
|||
} |
|||
} |
|||
@ -1,81 +0,0 @@ |
|||
// <copyright file="TrueColorReader.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Color reader for reading true colors from a png file. Only colors
|
|||
/// with 24 or 32 bit (3 or 4 bytes) per pixel are supported at the moment.
|
|||
/// </summary>
|
|||
internal sealed class TrueColorReader : IColorReader |
|||
{ |
|||
/// <summary>
|
|||
/// Whether t also read the alpha channel.
|
|||
/// </summary>
|
|||
private readonly bool useAlpha; |
|||
|
|||
/// <summary>
|
|||
/// The current row.
|
|||
/// </summary>
|
|||
private int row; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="TrueColorReader"/> class.
|
|||
/// </summary>
|
|||
/// <param name="useAlpha">if set to <c>true</c> the color reader will also read the
|
|||
/// alpha channel from the scanline.</param>
|
|||
public TrueColorReader(bool useAlpha) |
|||
{ |
|||
this.useAlpha = useAlpha; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ReadScanline<T, TP>(byte[] scanline, T[] pixels, PngHeader header) |
|||
where T : IPackedVector<TP> |
|||
where TP : struct |
|||
{ |
|||
int offset; |
|||
|
|||
byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth); |
|||
|
|||
if (this.useAlpha) |
|||
{ |
|||
for (int x = 0; x < newScanline.Length; x += 4) |
|||
{ |
|||
offset = (this.row * header.Width) + (x >> 2); |
|||
|
|||
// We want to convert to premultiplied alpha here.
|
|||
byte r = newScanline[x]; |
|||
byte g = newScanline[x + 1]; |
|||
byte b = newScanline[x + 2]; |
|||
byte a = newScanline[x + 3]; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(r, g, b, a); |
|||
|
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < newScanline.Length / 3; x++) |
|||
{ |
|||
offset = (this.row * header.Width) + x; |
|||
int pixelOffset = x * 3; |
|||
|
|||
byte r = newScanline[pixelOffset]; |
|||
byte g = newScanline[pixelOffset + 1]; |
|||
byte b = newScanline[pixelOffset + 2]; |
|||
|
|||
T color = default(T); |
|||
color.PackFromBytes(r, g, b, 255); |
|||
pixels[offset] = color; |
|||
} |
|||
} |
|||
|
|||
this.row++; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue