General support for extraction of images with BitsPerComponent < 8

This commit is contained in:
Kasper Frank
2021-05-11 10:06:17 +02:00
parent 92a00782bf
commit a56be02cfd
2 changed files with 45 additions and 30 deletions

View File

@@ -30,30 +30,46 @@
return decoded.ToArray(); return decoded.ToArray();
} }
switch (details)
{
case IndexedColorSpaceDetails indexed:
if (bitsPerComponent != 8) if (bitsPerComponent != 8)
{ {
// To ease unwrapping further below the indices are unpacked to occupy a single byte each // Unpack components such that they occupy one byte each
decoded = UnpackIndices(decoded, bitsPerComponent); decoded = UnpackComponents(decoded, bitsPerComponent);
}
// Remove padding bytes when the stride width differs from the image width // Remove padding bytes when the stride width differs from the image width
var stride = (imageWidth * bitsPerComponent + 7) / 8; var bytesPerPixel = details is IndexedColorSpaceDetails ? 1 : GetBytesPerPixel(details);
var strideWidth = stride * (8 / bitsPerComponent); var strideWidth = decoded.Count / imageHeight / bytesPerPixel;
if (strideWidth != imageWidth) if (strideWidth != imageWidth)
{ {
decoded = RemoveStridePadding(decoded.ToArray(), strideWidth, imageWidth, imageHeight); decoded = RemoveStridePadding(decoded.ToArray(), strideWidth, imageWidth, imageHeight, bytesPerPixel);
}
} }
return UnwrapIndexedColorSpaceBytes(indexed, decoded); // In case of indexed color space images, unwrap indices to actual pixel component values
if (details is IndexedColorSpaceDetails indexed)
{
decoded = UnwrapIndexedColorSpaceBytes(indexed, decoded);
} }
return decoded.ToArray(); return decoded.ToArray();
} }
private static byte[] UnpackIndices(IReadOnlyList<byte> input, int bitsPerComponent) private static int GetBytesPerPixel(ColorSpaceDetails details)
{
var colorSpace = (details is IndexedColorSpaceDetails indexed) ? indexed.BaseColorSpaceDetails.Type : details.Type;
switch (colorSpace)
{
case ColorSpace.DeviceRGB:
return 3;
case ColorSpace.DeviceCMYK:
return 4;
default:
return 1;
}
}
private static byte[] UnpackComponents(IReadOnlyList<byte> input, int bitsPerComponent)
{ {
IEnumerable<byte> Unpack(byte b) IEnumerable<byte> Unpack(byte b)
{ {
@@ -67,9 +83,9 @@
return input.SelectMany(b => Unpack(b)).ToArray(); return input.SelectMany(b => Unpack(b)).ToArray();
} }
private static byte[] RemoveStridePadding(byte[] input, int strideWidth, int imageWidth, int imageHeight) private static byte[] RemoveStridePadding(byte[] input, int strideWidth, int imageWidth, int imageHeight, int multiplier)
{ {
var result = new byte[imageWidth * imageHeight]; var result = new byte[imageWidth * imageHeight * multiplier];
for (int y = 0; y < imageHeight; y++) for (int y = 0; y < imageHeight; y++)
{ {
int sourceIndex = y * strideWidth; int sourceIndex = y * strideWidth;

View File

@@ -2,7 +2,6 @@
{ {
using Content; using Content;
using Graphics.Colors; using Graphics.Colors;
using System.Collections.Generic;
using UglyToad.PdfPig.Core; using UglyToad.PdfPig.Core;
internal static class PngFromPdfImageFactory internal static class PngFromPdfImageFactory