add support for extracting grayscale images and inline images

This commit is contained in:
Eliot Jones
2020-08-22 15:08:59 +01:00
parent 52104b6580
commit 54f227ea95
5 changed files with 71 additions and 48 deletions

View File

@@ -8,6 +8,7 @@
using Graphics.Colors; using Graphics.Colors;
using Graphics.Core; using Graphics.Core;
using Tokens; using Tokens;
using Images.Png;
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
@@ -112,11 +113,7 @@
} }
/// <inheritdoc /> /// <inheritdoc />
public bool TryGetPng(out byte[] bytes) public bool TryGetPng(out byte[] bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes);
{
bytes = null;
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()

View File

@@ -0,0 +1,61 @@
namespace UglyToad.PdfPig.Images.Png
{
using Content;
using Graphics.Colors;
internal static class PngFromPdfImageFactory
{
public static bool TryGenerate(IPdfImage image, out byte[] bytes)
{
bytes = null;
var isColorSpaceSupported = image.ColorSpace == ColorSpace.DeviceGray || image.ColorSpace == ColorSpace.DeviceRGB;
if (!isColorSpaceSupported || !image.TryGetBytes(out var bytesPure))
{
return false;
}
try
{
var is3Byte = image.ColorSpace == ColorSpace.DeviceRGB;
var multiplier = is3Byte ? 3 : 1;
var builder = PngBuilder.Create(image.WidthInSamples, image.HeightInSamples, false);
var isCorrectlySized = bytesPure.Count == (image.WidthInSamples * image.HeightInSamples * (image.BitsPerComponent / 8) * multiplier);
if (!isCorrectlySized)
{
return false;
}
var i = 0;
for (var y = 0; y < image.HeightInSamples; y++)
{
for (var x = 0; x < image.WidthInSamples; x++)
{
if (is3Byte)
{
builder.SetPixel(bytesPure[i++], bytesPure[i++], bytesPure[i++], x, y);
}
else
{
var pixel = bytesPure[i++];
builder.SetPixel(pixel, pixel, pixel, x, y);
}
}
}
bytes = builder.Save();
return true;
}
catch
{
// ignored.
}
return false;
}
}
}

View File

@@ -38,7 +38,4 @@
<ProjectReference Include="..\UglyToad.PdfPig.Tokenization\UglyToad.PdfPig.Tokenization.csproj" /> <ProjectReference Include="..\UglyToad.PdfPig.Tokenization\UglyToad.PdfPig.Tokenization.csproj" />
<ProjectReference Include="..\UglyToad.PdfPig.Tokens\UglyToad.PdfPig.Tokens.csproj" /> <ProjectReference Include="..\UglyToad.PdfPig.Tokens\UglyToad.PdfPig.Tokens.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Images\Png\" />
</ItemGroup>
</Project> </Project>

View File

@@ -333,7 +333,13 @@
/// </summary> /// </summary>
/// <param name="image">An image previously added to this page or another page.</param> /// <param name="image">An image previously added to this page or another page.</param>
/// <param name="placementRectangle">The size and location to draw the image on this page.</param> /// <param name="placementRectangle">The size and location to draw the image on this page.</param>
public void AddJpeg(AddedImage image, PdfRectangle placementRectangle) public void AddJpeg(AddedImage image, PdfRectangle placementRectangle) => AddImage(image, placementRectangle);
/// <summary>
/// Adds the image previously added using <see cref="AddJpeg(byte[], PdfRectangle)"/>
/// or <see cref="AddPng(byte[], PdfRectangle)"/> sharing the same image to prevent duplication.
/// </summary>
public void AddImage(AddedImage image, PdfRectangle placementRectangle)
{ {
if (!resourcesDictionary.TryGetValue(NameToken.Xobject, out var xobjectsDict) if (!resourcesDictionary.TryGetValue(NameToken.Xobject, out var xobjectsDict)
|| !(xobjectsDict is DictionaryToken xobjects)) || !(xobjectsDict is DictionaryToken xobjects))

View File

@@ -109,45 +109,7 @@
} }
/// <inheritdoc /> /// <inheritdoc />
public bool TryGetPng(out byte[] bytes) public bool TryGetPng(out byte[] bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes);
{
bytes = null;
if (ColorSpace != Graphics.Colors.ColorSpace.DeviceRGB || !TryGetBytes(out var bytesPure))
{
return false;
}
try
{
var builder = PngBuilder.Create(WidthInSamples, HeightInSamples, false);
var isCorrectlySized = bytesPure.Count == (WidthInSamples * HeightInSamples * (BitsPerComponent / 8) * 3);
if (!isCorrectlySized)
{
return false;
}
var i = 0;
for (var y = 0; y < HeightInSamples; y++)
{
for (var x = 0; x < WidthInSamples; x++)
{
builder.SetPixel(bytesPure[i++], bytesPure[i++], bytesPure[i++], x, y);
}
}
bytes = builder.Save();
return true;
}
catch
{
// ignored.
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()