From 3fdd82420195708a10fb041d9a1e3b213e97223a Mon Sep 17 00:00:00 2001 From: josch Date: Mon, 16 Feb 2015 07:39:07 +0100 Subject: [PATCH] support file objects as input --- src/img2pdf.py | 158 ++++++++++---------- src/tests/{test-CMYK.jpg => input/CMYK.jpg} | Bin src/tests/{test-CMYK.tif => input/CMYK.tif} | Bin src/tests/{test.jpg => input/normal.jpg} | Bin src/tests/{test.png => input/normal.png} | Bin src/tests/test.pdf | Bin 3289 -> 0 bytes src/tests/test_img2pdf.py | 20 --- 7 files changed, 83 insertions(+), 95 deletions(-) rename src/tests/{test-CMYK.jpg => input/CMYK.jpg} (100%) rename src/tests/{test-CMYK.tif => input/CMYK.tif} (100%) rename src/tests/{test.jpg => input/normal.jpg} (100%) rename src/tests/{test.png => input/normal.png} (100%) delete mode 100644 src/tests/test.pdf delete mode 100644 src/tests/test_img2pdf.py diff --git a/src/img2pdf.py b/src/img2pdf.py index a6a1adc..abd2c81 100755 --- a/src/img2pdf.py +++ b/src/img2pdf.py @@ -24,6 +24,10 @@ import struct from PIL import Image from datetime import datetime from jp2 import parsejp2 +try: + from cStringIO import cStringIO +except ImportError: + from io import BytesIO as cStringIO # XXX: Switch to use logging module. def debug_out(message, verbose=True): @@ -214,85 +218,89 @@ def convert(images, dpi=None, x=None, y=None, title=None, author=None, for imfilename in images: debug_out("Reading %s"%imfilename, verbose) - with open(imfilename, "rb") as im: - rawdata = im.read() - im.seek(0) - try: - imgdata = Image.open(im) - except IOError as e: - # test if it is a jpeg2000 image - if rawdata[:12] != "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A": - error_out("cannot read input image (not jpeg2000)") - error_out("PIL: %s"%e) - exit(1) - # image is jpeg2000 - width, height, ics = parsejp2(rawdata) - imgformat = "JPEG2000" + try: + rawdata = imfilename.read() + im = cStringIO(rawdata) + except: + with open(imfilename, "rb") as im: + rawdata = im.read() + im = cStringIO(rawdata) + try: + imgdata = Image.open(im) + except IOError as e: + # test if it is a jpeg2000 image + if rawdata[:12] != "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A": + error_out("cannot read input image (not jpeg2000)") + error_out("PIL: %s"%e) + exit(1) + # image is jpeg2000 + width, height, ics = parsejp2(rawdata) + imgformat = "JPEG2000" - if dpi: - ndpi = dpi, dpi - debug_out("input dpi (forced) = %d x %d"%ndpi, verbose) - else: - ndpi = (96, 96) # TODO: read real dpi - debug_out("input dpi = %d x %d"%ndpi, verbose) - - if colorspace: - color = colorspace - debug_out("input colorspace (forced) = %s"%(ics)) - else: - color = ics - debug_out("input colorspace = %s"%(ics), verbose) + if dpi: + ndpi = dpi, dpi + debug_out("input dpi (forced) = %d x %d"%ndpi, verbose) else: - width, height = imgdata.size - imgformat = imgdata.format + ndpi = (96, 96) # TODO: read real dpi + debug_out("input dpi = %d x %d"%ndpi, verbose) - if dpi: - ndpi = dpi, dpi - debug_out("input dpi (forced) = %d x %d"%ndpi, verbose) - else: - ndpi = imgdata.info.get("dpi", (96, 96)) - debug_out("input dpi = %d x %d"%ndpi, verbose) - - if colorspace: - color = colorspace - debug_out("input colorspace (forced) = %s"%(color), verbose) - else: - color = imgdata.mode - if color == "CMYK" and imgformat == "JPEG": - # Adobe inverts CMYK JPEGs for some reason, and others - # have followed suit as well. Some software assumes the - # JPEG is inverted if the Adobe tag (APP14), while other - # software assumes all CMYK JPEGs are inverted. I don't - # have enough experience with these to know which is - # better for images currently in the wild, so I'm going - # with the first approach for now. - if "adobe" in imgdata.info: - color = "CMYK;I" - debug_out("input colorspace = %s"%(color), verbose) - - debug_out("width x height = %d x %d"%(width,height), verbose) - debug_out("imgformat = %s"%imgformat, verbose) - - # depending on the input format, determine whether to pass the raw - # image or the zlib compressed color information - if imgformat is "JPEG" or imgformat is "JPEG2000": - if color == '1': - error_out("jpeg can't be monochrome") - exit(1) - imgdata = rawdata + if colorspace: + color = colorspace + debug_out("input colorspace (forced) = %s"%(ics)) else: - # because we do not support /CCITTFaxDecode - if color == '1': - debug_out("Converting colorspace 1 to L", verbose) - imgdata = imgdata.convert('L') - color = 'L' - elif color in ("RGB", "L", "CMYK", "CMYK;I"): - debug_out("Colorspace is OK: %s"%color, verbose) - else: - debug_out("Converting colorspace %s to RGB"%color, verbose) - imgdata = imgdata.convert('RGB') - color = imgdata.mode - imgdata = zlib.compress(imgdata.tostring()) + color = ics + debug_out("input colorspace = %s"%(ics), verbose) + else: + width, height = imgdata.size + imgformat = imgdata.format + + if dpi: + ndpi = dpi, dpi + debug_out("input dpi (forced) = %d x %d"%ndpi, verbose) + else: + ndpi = imgdata.info.get("dpi", (96, 96)) + debug_out("input dpi = %d x %d"%ndpi, verbose) + + if colorspace: + color = colorspace + debug_out("input colorspace (forced) = %s"%(color), verbose) + else: + color = imgdata.mode + if color == "CMYK" and imgformat == "JPEG": + # Adobe inverts CMYK JPEGs for some reason, and others + # have followed suit as well. Some software assumes the + # JPEG is inverted if the Adobe tag (APP14), while other + # software assumes all CMYK JPEGs are inverted. I don't + # have enough experience with these to know which is + # better for images currently in the wild, so I'm going + # with the first approach for now. + if "adobe" in imgdata.info: + color = "CMYK;I" + debug_out("input colorspace = %s"%(color), verbose) + + debug_out("width x height = %d x %d"%(width,height), verbose) + debug_out("imgformat = %s"%imgformat, verbose) + + # depending on the input format, determine whether to pass the raw + # image or the zlib compressed color information + if imgformat is "JPEG" or imgformat is "JPEG2000": + if color == '1': + error_out("jpeg can't be monochrome") + exit(1) + imgdata = rawdata + else: + # because we do not support /CCITTFaxDecode + if color == '1': + debug_out("Converting colorspace 1 to L", verbose) + imgdata = imgdata.convert('L') + color = 'L' + elif color in ("RGB", "L", "CMYK", "CMYK;I"): + debug_out("Colorspace is OK: %s"%color, verbose) + else: + debug_out("Converting colorspace %s to RGB"%color, verbose) + imgdata = imgdata.convert('RGB') + color = imgdata.mode + imgdata = zlib.compress(imgdata.tostring()) # pdf units = 1/72 inch if not x and not y: diff --git a/src/tests/test-CMYK.jpg b/src/tests/input/CMYK.jpg similarity index 100% rename from src/tests/test-CMYK.jpg rename to src/tests/input/CMYK.jpg diff --git a/src/tests/test-CMYK.tif b/src/tests/input/CMYK.tif similarity index 100% rename from src/tests/test-CMYK.tif rename to src/tests/input/CMYK.tif diff --git a/src/tests/test.jpg b/src/tests/input/normal.jpg similarity index 100% rename from src/tests/test.jpg rename to src/tests/input/normal.jpg diff --git a/src/tests/test.png b/src/tests/input/normal.png similarity index 100% rename from src/tests/test.png rename to src/tests/input/normal.png diff --git a/src/tests/test.pdf b/src/tests/test.pdf deleted file mode 100644 index c3a315457ac3bae554504be32df1cbd739e67704..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3289 zcmb7H2~-p37M^S@Nq~feO;85}0TszY5D*oTumlK%fVBl{31Pq>B#?wnY*_@v1w|I2 zC{#d@Mckj-Csh_tRjg8~f`GLkXieGPmXhbpMiVz8yl4Lj@ z3Vbjat7#yOzMA3y2lg=oN9Wglox$ z5=BCY@5NMa&9S7>9pK?AfefHYAipK=aiN zN(h&$o)%85vJfAGRyaxCWR207@Cb0@2XKXrbXP z@}Jd8grX0?qYwa+fFb|@;(5N>3i%b+uk!uIb&*qj-syFuAe*#Rz>0#ZS!rNbWJc$c zBQivAvC+8l@+u$4YjGejwG(s3qU|w1VU%&MfKjU+;^4*E&eVZCnRoD2cGv(s6##*OCRM%&o z*%`SfCeOC*C|zCKy_wx_df%Wt)aSJ%L3tIEw*W~=xAfye45Fgy&gpw+oFo_>i0C`D zwSwx;mcCXYp}o0-{7Mb^7Kcps$V=GmNp1b0z34>abK6ACv(YudmahiGA3FutxtAOD zC`&{9Q^nw=jGK6AqNdpkU~GS8i2^81>n2!s^KYL+oV2JnUX9Nw4;$rzokn<;)`K$l4w?Js z7uIrupmoPunK^=2D17+U$Vbulnun@Pc9mEcF(z?_FU6Nl%|sHb^KbV4f^!bx*jw1- z2Rol^0_aOF;GceBTXKngyqzSI-AD*(Hb-)yRsEDjk5?Sb9JnFs);)hWM|P&^5@j^T zanK2WuDDRVJEddAHlL+B{fp`L@47ZPk^448KXb!n<(>%2TPxii@&wV!Wfjd@AOczh zBnNqM8}F?VZ}`P={I9~$I6?P=*tYG3<$1BKyFvvQwOgv!>>hIDm*@{-yS|f;@8385 zIxX1bhwr{I`t({mDcr0#!sS35GwkMG zSlj4o1tWKUQTpVVZ?9cJeZg_vRw5~AZ1&la`1gy zb{Vm+U(AHi+Pb1OHgniTCXK;pcVl82S2Ef@7InGhvxSEt;v*(_1oUIqUPbC2k<1rP!nL zWtC0Pc~5uty_!F+pN@3c^2*pGhiJOCDRCzHZR0OP6@eB%{wDj0)5NH|XMTIeM4U{Z zXT7s-DV<&=KKPz6T;9{1WZ~UOu0U>|Spgd$+A|7~8x40|$vsvkr}-kexKYL(fOGRk z>RM6zjS|HB5?$QE{ooQdadq6$;uo%yg3;eMU1<|}Z?!yIK}+R|s3zM^RUh9ou^CHZ z?Jr0T09;~ajgbh< z{2K~EG^YY^i8DY-{FyGn_=ge`rWHW%$dujJ(|!#Fw$FH;m`Kdi_vU3)HVve{eLWP5 zv*D-3*-eLs$%%K8KO4bc9#||xu3WxSV z=y+TRInPua$n5>*d`G=SMKL<;ldvt4Hj@U6J(cU~ZqIw@o&0U0-iBn#Pv2zYIMwzx z%YQ2uNcPdaV```!Y*Y)RHIvE%ZiLWynKk6;RM(h^aZ&k!(ucTZ*{-Sg(j)8kG-SWo z8%8ib<0sFxh;S$BTGiOsj@N(XHGRF=NAL69-8qihJl;?!x^e95q>|p=p{P8LTWMbr z@>}Gd7_fAd*gSk@57KD1b zd>QH*yU}7vQI&yq+yR&Ieg7f_x>poS)*I1ZP2(~k>8S%>ZG!*$7TeMEXujFpx8&v+ z&ec~=qgmdN-uCmVO9DSH1t_BsA#>{CrmB8iv{ z&rYBX+l5A