Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to TIFF extra sample. #136

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/iTextSharp.LGPLv2.Core.FunctionalTests/TiffImageTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.IO;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.codec;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Document = iTextSharp.text.Document;

namespace iTextSharp.LGPLv2.Core.FunctionalTests;

[TestClass]
public class TiffImageTests
{
private RandomAccessFileOrArray _s;

[TestInitialize]
public void TIFF_extra_samples()
{
var filename = Path.Combine(TestUtils.GetBaseDir(), "iTextExamples", "resources", "img", "sampleRGBA.tif");
_s = new RandomAccessFileOrArray(filename);
}

[TestMethod]
public void Verify_TIFF_extra_samples_CanBeRead()
{
var numberOfPages = TiffImage.GetNumberOfPages(_s);
Assert.AreEqual(1, numberOfPages);

var image = TiffImage.GetTiffImage(_s, 1);
Assert.IsNotNull(image);
}

[TestMethod]
public void Verify_TIFF_extra_samples_CanBeAddedToPdfDocument()
{
var pdfFilePath = TestUtils.GetOutputFileName();
using (var stream = new FileStream(pdfFilePath, FileMode.Create))
{
var margin = 50f;
using (var document = new Document())
{
var pageWidth = document.PageSize.Width - margin;
var pageHeight = document.PageSize.Height - margin;
var image = TiffImage.GetTiffImage(_s, 1);
image.ScaleToFit(pageWidth, pageHeight);

PdfWriter.GetInstance(document, stream);
document.Open();
document.AddAuthor(TestUtils.Author);
document.Add(image);
}
}

TestUtils.VerifyPdfFileIsReadable(pdfFilePath);
}
}
Binary file not shown.
47 changes: 43 additions & 4 deletions src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/codec/TiffImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,10 @@
throw new InvalidOperationException("Planar images are not supported.");
}

var extraSamples = 0;
if (dir.IsTagPresent(TiffConstants.TIFFTAG_EXTRASAMPLES))
{
throw new InvalidOperationException("Extra samples are not supported.");
extraSamples = 1;
}

var samplePerPixel = 1;
Expand Down Expand Up @@ -487,7 +488,15 @@

var rowsLeft = h;
MemoryStream stream = null;
MemoryStream mstream = null;
ZDeflaterOutputStream zip = null;
ZDeflaterOutputStream mzip = null;

if (extraSamples > 0) {
mstream = new MemoryStream();
mzip = new ZDeflaterOutputStream(mstream);
}

Ccittg4Encoder g4 = null;
if (bitsPerSample == 1 && samplePerPixel == 1)
{
Expand Down Expand Up @@ -584,7 +593,10 @@
}
else
{
zip.Write(outBuf, 0, outBuf.Length);
if (extraSamples > 0)
processExtraSamples(zip, mzip, outBuf, samplePerPixel, bitsPerSample, w, height);
else
zip.Write(outBuf, 0, outBuf.Length);

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
zip
may be null at this access because of
this
assignment.
Variable
zip
may be null at this access because of
this
assignment.

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
outBuf
may be null at this access because of
this
assignment.
Variable
outBuf
may be null at this access because of
this
assignment.
Variable
outBuf
may be null at this access because of
this
assignment.
Variable
outBuf
may be null at this access because of
this
assignment.
}

rowsLeft -= rowsStrip;
Expand All @@ -600,7 +612,7 @@
else
{
zip.Close();
img = Image.GetInstance(w, h, samplePerPixel, bitsPerSample, stream.ToArray());
img = Image.GetInstance(w, h, samplePerPixel - extraSamples, bitsPerSample, stream.ToArray());

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
stream
may be null at this access because of
this
assignment.
img.Deflated = true;
}
}
Expand All @@ -614,7 +626,7 @@
{
var fd = dir.GetField(TiffConstants.TIFFTAG_ICCPROFILE);
var iccProf = IccProfile.GetInstance(fd.GetAsBytes());
if (samplePerPixel == iccProf.NumComponents)
if (samplePerPixel - extraSamples == iccProf.NumComponents)
{
img.TagIcc = iccProf;
}
Expand Down Expand Up @@ -661,10 +673,37 @@
{
img.InitialRotation = rotation;
}

if (extraSamples > 0) {
mzip.Close();

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
mzip
may be null at this access because of
this
assignment.
var mimg = Image.GetInstance(w, h, 1, bitsPerSample, mstream.ToArray());

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
mstream
may be null at this access because of
this
assignment.
mimg.MakeMask();
mimg.Deflated = true;
img.ImageMask = mimg;
}

return img;
}

private static void processExtraSamples(ZDeflaterOutputStream zip, ZDeflaterOutputStream mzip, byte[] outBuf, int samplePerPixel, int bitsPerSample, int width, int height) {
if (bitsPerSample == 8) {
var mask = new byte[width * height];
var mptr = 0;
var optr = 0;
var total = width * height * samplePerPixel;
for (var k = 0; k < total; k += samplePerPixel) {
for (var s = 0; s < samplePerPixel - 1; ++s) {
outBuf[optr++] = outBuf[k + s];
}
mask[mptr++] = outBuf[k + samplePerPixel - 1];
}
zip.Write(outBuf, 0, optr);
mzip.Write(mask, 0, mptr);
}
else
throw new InvalidOperationException("Extra samples are not supported.");
}

private static long[] getArrayLongShort(TiffDirectory dir, int tag)
{
var field = dir.GetField(tag);
Expand Down