mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-04-05 20:55:01 +08:00
General support for extraction of images with BitsPerComponent < 8
This commit is contained in:
parent
92a00782bf
commit
a56be02cfd
@ -28,48 +28,64 @@
|
||||
if (details == null)
|
||||
{
|
||||
return decoded.ToArray();
|
||||
}
|
||||
|
||||
if (bitsPerComponent != 8)
|
||||
{
|
||||
// Unpack components such that they occupy one byte each
|
||||
decoded = UnpackComponents(decoded, bitsPerComponent);
|
||||
}
|
||||
|
||||
// Remove padding bytes when the stride width differs from the image width
|
||||
var bytesPerPixel = details is IndexedColorSpaceDetails ? 1 : GetBytesPerPixel(details);
|
||||
var strideWidth = decoded.Count / imageHeight / bytesPerPixel;
|
||||
if (strideWidth != imageWidth)
|
||||
{
|
||||
decoded = RemoveStridePadding(decoded.ToArray(), strideWidth, imageWidth, imageHeight, bytesPerPixel);
|
||||
}
|
||||
|
||||
switch (details)
|
||||
// In case of indexed color space images, unwrap indices to actual pixel component values
|
||||
if (details is IndexedColorSpaceDetails indexed)
|
||||
{
|
||||
case IndexedColorSpaceDetails indexed:
|
||||
if (bitsPerComponent != 8)
|
||||
{
|
||||
// To ease unwrapping further below the indices are unpacked to occupy a single byte each
|
||||
decoded = UnpackIndices(decoded, bitsPerComponent);
|
||||
|
||||
// Remove padding bytes when the stride width differs from the image width
|
||||
var stride = (imageWidth * bitsPerComponent + 7) / 8;
|
||||
var strideWidth = stride * (8 / bitsPerComponent);
|
||||
if (strideWidth != imageWidth)
|
||||
{
|
||||
decoded = RemoveStridePadding(decoded.ToArray(), strideWidth, imageWidth, imageHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return UnwrapIndexedColorSpaceBytes(indexed, decoded);
|
||||
decoded = UnwrapIndexedColorSpaceBytes(indexed, decoded);
|
||||
}
|
||||
|
||||
return decoded.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] UnpackIndices(IReadOnlyList<byte> input, int bitsPerComponent)
|
||||
{
|
||||
IEnumerable<byte> Unpack(byte b)
|
||||
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)
|
||||
{
|
||||
// Enumerate bits in bitsPerComponent-sized chunks from MSB to LSB, masking on the appropriate bits
|
||||
for (int i = 8 - bitsPerComponent; i >= 0; i -= bitsPerComponent)
|
||||
{
|
||||
// Enumerate bits in bitsPerComponent-sized chunks from MSB to LSB, masking on the appropriate bits
|
||||
for (int i = 8 - bitsPerComponent; i >= 0; i -= bitsPerComponent)
|
||||
{
|
||||
yield return (byte)((b >> i) & ((int)Math.Pow(2, bitsPerComponent) - 1));
|
||||
}
|
||||
yield return (byte)((b >> i) & ((int)Math.Pow(2, bitsPerComponent) - 1));
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
int sourceIndex = y * strideWidth;
|
||||
|
@ -2,7 +2,6 @@
|
||||
{
|
||||
using Content;
|
||||
using Graphics.Colors;
|
||||
using System.Collections.Generic;
|
||||
using UglyToad.PdfPig.Core;
|
||||
|
||||
internal static class PngFromPdfImageFactory
|
||||
|
Loading…
Reference in New Issue
Block a user