From fed33d13a7bcb71000a90bab945db34edcce7fb6 Mon Sep 17 00:00:00 2001 From: payotte Date: Fri, 15 Dec 2023 09:54:36 -0500 Subject: [PATCH] Add support to TIFF extra sample. --- .../TiffImageTests.cs | 54 ++++++++++++++++++ .../resources/img/sampleRGBA.tif | Bin 0 -> 1418 bytes .../iTextSharp/text/pdf/codec/TiffImage.cs | 47 +++++++++++++-- 3 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 src/iTextSharp.LGPLv2.Core.FunctionalTests/TiffImageTests.cs create mode 100644 src/iTextSharp.LGPLv2.Core.FunctionalTests/iTextExamples/resources/img/sampleRGBA.tif diff --git a/src/iTextSharp.LGPLv2.Core.FunctionalTests/TiffImageTests.cs b/src/iTextSharp.LGPLv2.Core.FunctionalTests/TiffImageTests.cs new file mode 100644 index 0000000..300b7f5 --- /dev/null +++ b/src/iTextSharp.LGPLv2.Core.FunctionalTests/TiffImageTests.cs @@ -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); + } +} \ No newline at end of file diff --git a/src/iTextSharp.LGPLv2.Core.FunctionalTests/iTextExamples/resources/img/sampleRGBA.tif b/src/iTextSharp.LGPLv2.Core.FunctionalTests/iTextExamples/resources/img/sampleRGBA.tif new file mode 100644 index 0000000000000000000000000000000000000000..a48d982fb6c740bdaaab7abccb31416c8681c57d GIT binary patch literal 1418 zcmaiwUx<}O7{;G(R@SY=PlqzXq7McnO5)UX5ftXBN%5|ugXvXqU?gZGI5vS1A$xK* zB8ug}fT$45>UW`}=IW@_jj}b$iXLQPY?UHqWj4^gDf+;R=By{Mt7iD|KJ(7|yz^(% zre`q(U?q?ZAWLdRB6~oSq?e@JFNuMEzE?Nc*Cgqc*^))?mucg%e!k~f)z`hAkN0bO z&7ORq&*lgEY)QK3`#rI|y$k~>&L>7bUxvXHN$P)ebO1%tFD89#bQyZ*w~{_SN)}%- zl5}qj^=FoD)|>ao!fXGH{q+Ba+WLP>?)O@X-bJ%?dV1FV{^=Vt%&o|Vj*q5Y3@)y} zW)BS=8|`@>S&YCJAADq=nrQXzBdtvbwWiPl@X^z z#7{ip3X7PfF}qD-zEB0+i2*l4z$G7W+69c40oDezO~5BQp#nx^z?ca5mIs_-A)BTl zpCzG~uRP|W$Cco5%6lAe9(ziUVe7HYcx=)h8G7WM7~wwK&wPG@`r9El{JYyW5&d6IY+DN?eO2&V&-y zml$>>Hk2ivwk2Q^I-wG>%vOssU(d^82Pq)^}0cI7n>sa%FHO8XOJ=JH5f1&R|t(l0RV*+GJ2BhcpF* zsV(QGzK)s3Fg49_Vp`LcPJWH?pwaR=`8Af8I{6buXV5x_(gmchLFoD**Ns=1ZVpr3 zIzV)Lx>Cun()kLzyuwDOu)0*quQC{wL#qNx)gV}H_(jHkuVj@C|= zw0_Xi#y&%vW16uaDlKmY?em9U}&Xd}#BlT`c o8W$~To-?F%R+IKwMLOpsnYbv(WS5hvSw?1VQ8IUjkiY)?2U&H<5dZ)H literal 0 HcmV?d00001 diff --git a/src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/codec/TiffImage.cs b/src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/codec/TiffImage.cs index 9c1eb42..ae0f22b 100644 --- a/src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/codec/TiffImage.cs +++ b/src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/codec/TiffImage.cs @@ -393,9 +393,10 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra 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; @@ -487,7 +488,15 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra 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) { @@ -584,7 +593,10 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra } 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); } rowsLeft -= rowsStrip; @@ -600,7 +612,7 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra else { zip.Close(); - img = Image.GetInstance(w, h, samplePerPixel, bitsPerSample, stream.ToArray()); + img = Image.GetInstance(w, h, samplePerPixel - extraSamples, bitsPerSample, stream.ToArray()); img.Deflated = true; } } @@ -614,7 +626,7 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra { 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; } @@ -661,10 +673,37 @@ private static Image GetTiffImageColor(TiffDirectory dir, RandomAccessFileOrArra { img.InitialRotation = rotation; } + + if (extraSamples > 0) { + mzip.Close(); + var mimg = Image.GetInstance(w, h, 1, bitsPerSample, mstream.ToArray()); + 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);