Skip to content

Commit 6a06452

Browse files
committed
Remove decode parameter application from Stencil color space for consistency
1 parent a5e92cd commit 6a06452

File tree

6 files changed

+31
-43
lines changed

6 files changed

+31
-43
lines changed

src/UglyToad.PdfPig.Tests/Images/PngFromPdfImageFactoryTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,12 @@ public void CanGeneratePngFromCcittFaxDecodedImageData()
172172
var decodedBytes = ImageHelpers.LoadFileBytes("ccittfax-decoded.bin");
173173
var image = new TestPdfImage
174174
{
175-
ColorSpaceDetails = IndexedColorSpaceDetails.Stencil(DeviceGrayColorSpaceDetails.Instance, new[] { 1.0, 0 }),
175+
ColorSpaceDetails = IndexedColorSpaceDetails.Stencil(DeviceGrayColorSpaceDetails.Instance),
176176
DecodedBytes = decodedBytes,
177177
WidthInSamples = 1800,
178178
HeightInSamples = 3113,
179-
BitsPerComponent = 1
179+
BitsPerComponent = 1,
180+
Decode = [1.0, 0]
180181
};
181182

182183
Assert.True(PngFromPdfImageFactory.TryGenerate(image, out var bytes));

src/UglyToad.PdfPig/Content/PdfImageExtensions.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ public static class PdfImageExtensions
1010
/// </summary>
1111
public static bool NeedsReverseDecode(this IPdfImage pdfImage)
1212
{
13-
if (pdfImage.ColorSpaceDetails?.IsStencil == true)
14-
{
15-
// Stencil color space already takes care of reversing.
16-
return false;
17-
}
18-
19-
return pdfImage.Decode.Count >= 2 && pdfImage.Decode[0] == 1 && pdfImage.Decode[1] == 0;
13+
return pdfImage.Decode?.Count >= 2 && pdfImage.Decode[0] == 1 && pdfImage.Decode[1] == 0;
2014
}
2115
}
2216
}

src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceDetails.cs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@
1515
/// </summary>
1616
public abstract class ColorSpaceDetails
1717
{
18-
/// <summary>
19-
/// Is the color space a stencil indexed color space.
20-
/// <para>Stencil color spaces take care of inverting colors based on the Decode array.</para>
21-
/// </summary>
22-
public bool IsStencil { get; }
23-
2418
/// <summary>
2519
/// The type of the ColorSpace.
2620
/// </summary>
@@ -45,11 +39,10 @@ public abstract class ColorSpaceDetails
4539
/// <summary>
4640
/// Create a new <see cref="ColorSpaceDetails"/>.
4741
/// </summary>
48-
protected internal ColorSpaceDetails(ColorSpace type, bool isStencil = false)
42+
protected internal ColorSpaceDetails(ColorSpace type)
4943
{
5044
Type = type;
5145
BaseType = type;
52-
IsStencil = isStencil;
5346
}
5447

5548
/// <summary>
@@ -278,15 +271,12 @@ public sealed class IndexedColorSpaceDetails : ColorSpaceDetails
278271
private readonly ConcurrentDictionary<double, IColor> cache = new ConcurrentDictionary<double, IColor>();
279272

280273
/// <summary>
281-
/// Creates a indexed color space useful for extracting stencil masks as black-and-white images,
282-
/// i.e. with a color palette of two colors (black and white). If the decode parameter array is
283-
/// [0, 1] it indicates that black is at index 0 in the color palette, whereas [1, 0] indicates
284-
/// that the black color is at index 1.
274+
/// Creates an indexed color space useful for extracting stencil masks as black-and-white images,
275+
/// i.e. with a color palette of two colors (black and white).
285276
/// </summary>
286-
internal static ColorSpaceDetails Stencil(ColorSpaceDetails colorSpaceDetails, double[] decode)
277+
internal static ColorSpaceDetails Stencil(ColorSpaceDetails colorSpaceDetails)
287278
{
288-
var blackIsOne = decode.Length >= 2 && decode[0] == 1 && decode[1] == 0;
289-
return new IndexedColorSpaceDetails(colorSpaceDetails, 1, blackIsOne ? [255, 0] : [0, 255], true);
279+
return new IndexedColorSpaceDetails(colorSpaceDetails, 1, [0, 255]);
290280
}
291281

292282
/// <inheritdoc/>
@@ -321,14 +311,7 @@ internal static ColorSpaceDetails Stencil(ColorSpaceDetails colorSpaceDetails, d
321311
/// Create a new <see cref="IndexedColorSpaceDetails"/>.
322312
/// </summary>
323313
public IndexedColorSpaceDetails(ColorSpaceDetails baseColorSpaceDetails, byte hiVal, byte[] colorTable)
324-
: this(baseColorSpaceDetails, hiVal, colorTable, false)
325-
{ }
326-
327-
/// <summary>
328-
/// Create a new <see cref="IndexedColorSpaceDetails"/>.
329-
/// </summary>
330-
private IndexedColorSpaceDetails(ColorSpaceDetails baseColorSpaceDetails, byte hiVal, byte[] colorTable, bool isStencil)
331-
: base(ColorSpace.Indexed, isStencil)
314+
: base(ColorSpace.Indexed)
332315
{
333316
BaseColorSpace = baseColorSpaceDetails ?? throw new ArgumentNullException(nameof(baseColorSpaceDetails));
334317
HiVal = hiVal;

src/UglyToad.PdfPig/Images/Png/PngFromPdfImageFactory.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,28 @@ public static bool TryGenerate(IPdfImage image, [NotNullWhen(true)] out byte[]?
159159
else
160160
{
161161
int i = 0;
162-
for (int col = 0; col < image.HeightInSamples; col++)
162+
if (!image.NeedsReverseDecode()) // TODO - Need to properly implement decode for other numberOfComponents
163163
{
164-
for (int row = 0; row < image.WidthInSamples; row++)
164+
for (int col = 0; col < image.HeightInSamples; col++)
165+
{
166+
for (int row = 0; row < image.WidthInSamples; row++)
167+
{
168+
byte a = getAlphaChannel(i);
169+
byte pixel = bytesPure[i++];
170+
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
171+
}
172+
}
173+
}
174+
else
175+
{
176+
for (int col = 0; col < image.HeightInSamples; col++)
165177
{
166-
byte a = getAlphaChannel(i);
167-
byte pixel = bytesPure[i++];
168-
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
178+
for (int row = 0; row < image.WidthInSamples; row++)
179+
{
180+
byte a = getAlphaChannel(i);
181+
byte pixel = (byte)(255 - bytesPure[i++]); // Inverse decode
182+
builder.SetPixel(new Pixel(pixel, pixel, pixel, a, false), row, col);
183+
}
169184
}
170185
}
171186
}

src/UglyToad.PdfPig/Util/ColorSpaceDetailsParser.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace,
5454
}
5555

5656
var colorSpaceDetails = GetColorSpaceDetails(colorSpace, imageDictionary.Without(NameToken.Filter).Without(NameToken.F), scanner, resourceStore, filterProvider, true);
57-
58-
var decodeRaw = imageDictionary.GetObjectOrDefault(NameToken.Decode, NameToken.D) as ArrayToken ?? new ArrayToken([]);
59-
var decode = decodeRaw.Data.OfType<NumericToken>().Select(static x => x.Double).ToArray();
60-
61-
return IndexedColorSpaceDetails.Stencil(colorSpaceDetails, decode);
57+
return IndexedColorSpaceDetails.Stencil(colorSpaceDetails);
6258
}
6359

6460
if (!colorSpace.HasValue)

src/UglyToad.PdfPig/XObjects/XObjectFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ public static XObjectImage ReadImage(XObjectContentRecord xObject,
9292
null);
9393

9494
softMaskImage = ReadImage(maskImageRecord, pdfScanner, filterProvider, resourceStore);
95-
System.Diagnostics.Debug.Assert(softMaskImage.ColorSpaceDetails?.IsStencil == true);
9695
}
9796

9897
var isJpxDecode = dictionary.TryGet(NameToken.Filter, out NameToken filterName) && filterName.Equals(NameToken.JpxDecode);

0 commit comments

Comments
 (0)