From eedf73e73eb0be2a2e2cc54e21e8235b47016006 Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Thu, 21 Jul 2016 16:33:26 -0700 Subject: [PATCH] Add test cases for CCITT G4 --- src/tests/__init__.py | 43 +++++++++++++++++++++++++++++++++- src/tests/input/mono.png | Bin 0 -> 444 bytes src/tests/output/mono.png.pdf | Bin 0 -> 1005 bytes 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/tests/input/mono.png create mode 100644 src/tests/output/mono.png.pdf diff --git a/src/tests/__init__.py b/src/tests/__init__.py index b668054..6b468aa 100644 --- a/src/tests/__init__.py +++ b/src/tests/__init__.py @@ -4,6 +4,8 @@ import os import img2pdf import zlib from PIL import Image +from io import BytesIO +import struct HERE = os.path.dirname(__file__) @@ -396,6 +398,28 @@ layout_test_cases = [ ] +def tiff_header_for_ccitt(width, height, img_size, ccitt_group=4): + # Quick and dirty TIFF header builder from + # https://stackoverflow.com/questions/2641770/extracting-image-from-pdf-with-ccittfaxdecode-filter + tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h' + return struct.pack( + tiff_header_struct, + b'II', # Byte order indication: Little indian + 42, # Version number (always 42) + 8, # Offset to first IFD + 8, # Number of tags in IFD + 256, 4, 1, width, # ImageWidth, LONG, 1, width + 257, 4, 1, height, # ImageLength, LONG, 1, lenght + 258, 3, 1, 1, # BitsPerSample, SHORT, 1, 1 + 259, 3, 1, ccitt_group, # Compression, SHORT, 1, 4 = CCITT Group 4 + 262, 3, 1, 1, # Threshholding, SHORT, 1, 0 = WhiteIsZero + 273, 4, 1, struct.calcsize(tiff_header_struct), # StripOffsets, LONG, 1, len of header + 278, 4, 1, height, # RowsPerStrip, LONG, 1, lenght + 279, 4, 1, img_size, # StripByteCounts, LONG, 1, size of image + 0 # last IFD + ) + + def test_suite(): class TestImg2Pdf(unittest.TestCase): pass @@ -485,7 +509,8 @@ def test_suite(): # test if the filter is valid: self.assertIn( imgprops.Filter, [[PdfName.DCTDecode], [PdfName.JPXDecode], - [PdfName.FlateDecode]]) + [PdfName.FlateDecode], + [PdfName.CCITTFaxDecode]]) # test if the colorspace is valid self.assertIn( imgprops.ColorSpace, [PdfName.DeviceGray, PdfName.DeviceRGB, @@ -500,6 +525,22 @@ def test_suite(): self.assertEqual( x.Root.Pages.Kids[0].Resources.XObject.Im0.stream, convert_load(orig_imgdata)) + elif imgprops.Filter == [PdfName.CCITTFaxDecode]: + tiff_header = tiff_header_for_ccitt( + int(imgprops.Width), int(imgprops.Height), + int(imgprops.Length), 4) + imgio = BytesIO() + imgio.write(tiff_header) + imgio.write(convert_store( + x.Root.Pages.Kids[0].Resources.XObject.Im0.stream)) + imgio.seek(0) + im = Image.open(imgio) + self.assertEqual(im.tobytes(), orig_img.tobytes()) + try: + im.close() + except AttributeError: + pass + elif imgprops.Filter == [PdfName.FlateDecode]: # otherwise, the data is flate encoded and has to be equal to # the pixel data of the input image diff --git a/src/tests/input/mono.png b/src/tests/input/mono.png new file mode 100644 index 0000000000000000000000000000000000000000..59b17ad025a5f769412b50a731b70e11a44a5956 GIT binary patch literal 444 zcmeAS@N?(olHy`uVBq!ia0vp^#XxMp2qYM|zEpGqDVB6cUq=Rpjs4tz5?O(Kg=CK) zUj~LMH3o);76yi2K%s^g3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&V7%KUyadSO zEbxc~8qX~Z!i)^F=12eq*-JcqUD+Qn3NTq|EGf)=02J!-ba4#PIDhuiL0%?B0oDuq zA8v5>ULfMNQADHn2%Ao#_kqd93N_Q$1lon0PP|;--gw4f!5rTIuU6Z~Fid|qW7@p9 zyoMd~wjIuyCw{5v>zA^eM?x!~rEhy_$K7lkR{W}K^Nz%+zxKv&bv!F_HFXnf>EBiF zYZo==U;cgc`9}Nj4IR1vFJ1Kc_wxR`>&zR|e6GA(wGS|xv6<249-QV zi6yBi3gww484B*6z5(HleBwYwsvt!vKq;$aunGnv14A=i14CUyvk(I#D^m+A69ZiX m3o8SId1|{|Q8eV{r(~v8;@0rKn)xSC1B0ilpUXO@geCy>)t2r6 literal 0 HcmV?d00001 diff --git a/src/tests/output/mono.png.pdf b/src/tests/output/mono.png.pdf new file mode 100644 index 0000000000000000000000000000000000000000..67ed8a843f06ffb77f12fba0a4a05dcd61906227 GIT binary patch literal 1005 zcmZ{j&ubGw6vsUjg~5V{o;=ux5^0cTepSl=Gl^m@KdPnDB=KqE z-3Ow93aqkBCMFb%Q(Jf}$k~FzNba1jYGbOYYnox08SQ!!lo{s!FGv8CB4=*Xp&Uj$ zzos|bDyS(vr6sdjLIYQ-=zX=KU85nS(NO|rex*S{v20=2S*@QgqrJniW*|TVW!iH? zSj@<}8@73VLJ#kNAGwJy~OPmxp$aLaZq25 zwTQz^)otfiA=E(drlim6O+N@@D9SX9Vy_ar8{!$WSwxig>Vk4vs#sQGem-xvIxR7F znR>M)ftjFmXVz35lyb8o;)^Z#c-b9X@}2a6D%U(0`5=)#pwp|ZWE5>4*?6+$zBzV( z^;P=U?DmP_^~#qQlNZ)2(Q5SV{ErCjcl+m`M?>$Awr{>3-hSAA`(UB{`S{$9b+!F5 z`W~&xlxXYl#?xr9{q^PAM@THA|d6~?3KTmMmt0Q#zI}1UT;r+(nrNo#3`IqqP Yl)ZZt%ow1}MLdQ%u8~CI;%uJm0#KJS{r~^~ literal 0 HcmV?d00001