mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-08-20 09:21:57 +08:00
Remove decode parameter application from Stencil color space for consistency
This commit is contained in:
parent
a5e92cd11c
commit
692641671c
@ -172,11 +172,12 @@
|
|||||||
var decodedBytes = ImageHelpers.LoadFileBytes("ccittfax-decoded.bin");
|
var decodedBytes = ImageHelpers.LoadFileBytes("ccittfax-decoded.bin");
|
||||||
var image = new TestPdfImage
|
var image = new TestPdfImage
|
||||||
{
|
{
|
||||||
ColorSpaceDetails = IndexedColorSpaceDetails.Stencil(DeviceGrayColorSpaceDetails.Instance, new[] { 1.0, 0 }),
|
ColorSpaceDetails = IndexedColorSpaceDetails.Stencil(DeviceGrayColorSpaceDetails.Instance),
|
||||||
DecodedBytes = decodedBytes,
|
DecodedBytes = decodedBytes,
|
||||||
WidthInSamples = 1800,
|
WidthInSamples = 1800,
|
||||||
HeightInSamples = 3113,
|
HeightInSamples = 3113,
|
||||||
BitsPerComponent = 1
|
BitsPerComponent = 1,
|
||||||
|
Decode = [1.0, 0]
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.True(PngFromPdfImageFactory.TryGenerate(image, out var bytes));
|
Assert.True(PngFromPdfImageFactory.TryGenerate(image, out var bytes));
|
||||||
|
|||||||
@ -10,13 +10,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool NeedsReverseDecode(this IPdfImage pdfImage)
|
public static bool NeedsReverseDecode(this IPdfImage pdfImage)
|
||||||
{
|
{
|
||||||
if (pdfImage.ColorSpaceDetails?.IsStencil == true)
|
return pdfImage.Decode?.Count >= 2 && pdfImage.Decode[0] == 1 && pdfImage.Decode[1] == 0;
|
||||||
{
|
|
||||||
// Stencil color space already takes care of reversing.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdfImage.Decode.Count >= 2 && pdfImage.Decode[0] == 1 && pdfImage.Decode[1] == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,12 +15,6 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ColorSpaceDetails
|
public abstract class ColorSpaceDetails
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Is the color space a stencil indexed color space.
|
|
||||||
/// <para>Stencil color spaces take care of inverting colors based on the Decode array.</para>
|
|
||||||
/// </summary>
|
|
||||||
public bool IsStencil { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of the ColorSpace.
|
/// The type of the ColorSpace.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -45,11 +39,10 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="ColorSpaceDetails"/>.
|
/// Create a new <see cref="ColorSpaceDetails"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal ColorSpaceDetails(ColorSpace type, bool isStencil = false)
|
protected internal ColorSpaceDetails(ColorSpace type)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
BaseType = type;
|
BaseType = type;
|
||||||
IsStencil = isStencil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -278,15 +271,12 @@
|
|||||||
private readonly ConcurrentDictionary<double, IColor> cache = new ConcurrentDictionary<double, IColor>();
|
private readonly ConcurrentDictionary<double, IColor> cache = new ConcurrentDictionary<double, IColor>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a indexed color space useful for extracting stencil masks as black-and-white images,
|
/// Creates an indexed color space useful for extracting stencil masks as black-and-white images,
|
||||||
/// i.e. with a color palette of two colors (black and white). If the decode parameter array is
|
/// i.e. with a color palette of two colors (black and white).
|
||||||
/// [0, 1] it indicates that black is at index 0 in the color palette, whereas [1, 0] indicates
|
|
||||||
/// that the black color is at index 1.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static ColorSpaceDetails Stencil(ColorSpaceDetails colorSpaceDetails, double[] decode)
|
internal static ColorSpaceDetails Stencil(ColorSpaceDetails colorSpaceDetails)
|
||||||
{
|
{
|
||||||
var blackIsOne = decode.Length >= 2 && decode[0] == 1 && decode[1] == 0;
|
return new IndexedColorSpaceDetails(colorSpaceDetails, 1, [0, 255]);
|
||||||
return new IndexedColorSpaceDetails(colorSpaceDetails, 1, blackIsOne ? [255, 0] : [0, 255], true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -321,14 +311,7 @@
|
|||||||
/// Create a new <see cref="IndexedColorSpaceDetails"/>.
|
/// Create a new <see cref="IndexedColorSpaceDetails"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IndexedColorSpaceDetails(ColorSpaceDetails baseColorSpaceDetails, byte hiVal, byte[] colorTable)
|
public IndexedColorSpaceDetails(ColorSpaceDetails baseColorSpaceDetails, byte hiVal, byte[] colorTable)
|
||||||
: this(baseColorSpaceDetails, hiVal, colorTable, false)
|
: base(ColorSpace.Indexed)
|
||||||
{ }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new <see cref="IndexedColorSpaceDetails"/>.
|
|
||||||
/// </summary>
|
|
||||||
private IndexedColorSpaceDetails(ColorSpaceDetails baseColorSpaceDetails, byte hiVal, byte[] colorTable, bool isStencil)
|
|
||||||
: base(ColorSpace.Indexed, isStencil)
|
|
||||||
{
|
{
|
||||||
BaseColorSpace = baseColorSpaceDetails ?? throw new ArgumentNullException(nameof(baseColorSpaceDetails));
|
BaseColorSpace = baseColorSpaceDetails ?? throw new ArgumentNullException(nameof(baseColorSpaceDetails));
|
||||||
HiVal = hiVal;
|
HiVal = hiVal;
|
||||||
|
|||||||
@ -159,13 +159,28 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int col = 0; col < image.HeightInSamples; col++)
|
if (!image.NeedsReverseDecode()) // TODO - Need to properly implement decode for other numberOfComponents
|
||||||
{
|
{
|
||||||
for (int row = 0; row < image.WidthInSamples; row++)
|
for (int col = 0; col < image.HeightInSamples; col++)
|
||||||
{
|
{
|
||||||
byte a = getAlphaChannel(i);
|
for (int row = 0; row < image.WidthInSamples; row++)
|
||||||
byte pixel = bytesPure[i++];
|
{
|
||||||
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
|
byte a = getAlphaChannel(i);
|
||||||
|
byte pixel = bytesPure[i++];
|
||||||
|
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int col = 0; col < image.HeightInSamples; col++)
|
||||||
|
{
|
||||||
|
for (int row = 0; row < image.WidthInSamples; row++)
|
||||||
|
{
|
||||||
|
byte a = getAlphaChannel(i);
|
||||||
|
byte pixel = (byte)(255 - bytesPure[i++]); // Inverse decode
|
||||||
|
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,11 +54,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var colorSpaceDetails = GetColorSpaceDetails(colorSpace, imageDictionary.Without(NameToken.Filter).Without(NameToken.F), scanner, resourceStore, filterProvider, true);
|
var colorSpaceDetails = GetColorSpaceDetails(colorSpace, imageDictionary.Without(NameToken.Filter).Without(NameToken.F), scanner, resourceStore, filterProvider, true);
|
||||||
|
return IndexedColorSpaceDetails.Stencil(colorSpaceDetails);
|
||||||
var decodeRaw = imageDictionary.GetObjectOrDefault(NameToken.Decode, NameToken.D) as ArrayToken ?? new ArrayToken([]);
|
|
||||||
var decode = decodeRaw.Data.OfType<NumericToken>().Select(static x => x.Double).ToArray();
|
|
||||||
|
|
||||||
return IndexedColorSpaceDetails.Stencil(colorSpaceDetails, decode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!colorSpace.HasValue)
|
if (!colorSpace.HasValue)
|
||||||
|
|||||||
@ -92,7 +92,6 @@
|
|||||||
null);
|
null);
|
||||||
|
|
||||||
softMaskImage = ReadImage(maskImageRecord, pdfScanner, filterProvider, resourceStore);
|
softMaskImage = ReadImage(maskImageRecord, pdfScanner, filterProvider, resourceStore);
|
||||||
System.Diagnostics.Debug.Assert(softMaskImage.ColorSpaceDetails?.IsStencil == true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var isJpxDecode = dictionary.TryGet(NameToken.Filter, out NameToken filterName) && filterName.Equals(NameToken.JpxDecode);
|
var isJpxDecode = dictionary.TryGet(NameToken.Filter, out NameToken filterName) && filterName.Equals(NameToken.JpxDecode);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user