png.py 154 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857
  1. #!/usr/bin/env python
  2. # $URL$
  3. # $Rev$
  4. # png.py - PNG encoder/decoder in pure Python
  5. #
  6. # Copyright (C) 2006 Johann C. Rocholl <johann@browsershots.org>
  7. # Portions Copyright (C) 2009 David Jones <drj@pobox.com>
  8. # And probably portions Copyright (C) 2006 Nicko van Someren <nicko@nicko.org>
  9. #
  10. # Original concept by Johann C. Rocholl.
  11. #
  12. # LICENSE (The MIT License)
  13. #
  14. # Permission is hereby granted, free of charge, to any person
  15. # obtaining a copy of this software and associated documentation files
  16. # (the "Software"), to deal in the Software without restriction,
  17. # including without limitation the rights to use, copy, modify, merge,
  18. # publish, distribute, sublicense, and/or sell copies of the Software,
  19. # and to permit persons to whom the Software is furnished to do so,
  20. # subject to the following conditions:
  21. #
  22. # The above copyright notice and this permission notice shall be
  23. # included in all copies or substantial portions of the Software.
  24. #
  25. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32. # SOFTWARE.
  33. #
  34. # Changelog (recent first):
  35. # 2009-03-11 David: interlaced bit depth < 8 (writing).
  36. # 2009-03-10 David: interlaced bit depth < 8 (reading).
  37. # 2009-03-04 David: Flat and Boxed pixel formats.
  38. # 2009-02-26 David: Palette support (writing).
  39. # 2009-02-23 David: Bit-depths < 8; better PNM support.
  40. # 2006-06-17 Nicko: Reworked into a class, faster interlacing.
  41. # 2006-06-17 Johann: Very simple prototype PNG decoder.
  42. # 2006-06-17 Nicko: Test suite with various image generators.
  43. # 2006-06-17 Nicko: Alpha-channel, grey-scale, 16-bit/plane support.
  44. # 2006-06-15 Johann: Scanline iterator interface for large input files.
  45. # 2006-06-09 Johann: Very simple prototype PNG encoder.
  46. # Incorporated into Bangai-O Development Tools by drj on 2009-02-11 from
  47. # http://trac.browsershots.org/browser/trunk/pypng/lib/png.py?rev=2885
  48. # Incorporated into pypng by drj on 2009-03-12 from
  49. # //depot/prj/bangaio/master/code/png.py#67
  50. """
  51. Pure Python PNG Reader/Writer
  52. This Python module implements support for PNG images (see PNG
  53. specification at http://www.w3.org/TR/2003/REC-PNG-20031110/ ). It reads
  54. and writes PNG files with all allowable bit depths (1/2/4/8/16/24/32/48/64
  55. bits per pixel) and colour combinations: greyscale (1/2/4/8/16 bit); RGB,
  56. RGBA, LA (greyscale with alpha) with 8/16 bits per channel; colour mapped
  57. images (1/2/4/8 bit). Adam7 interlacing is supported for reading and
  58. writing. A number of optional chunks can be specified (when writing)
  59. and understood (when reading): ``tRNS``, ``bKGD``, ``gAMA``.
  60. For help, type ``import png; help(png)`` in your python interpreter.
  61. A good place to start is the :class:`Reader` and :class:`Writer` classes.
  62. Requires Python 2.3. Limited support is available for Python 2.2, but
  63. not everything works. Best with Python 2.4 and higher. Installation is
  64. trivial, but see the ``README.txt`` file (with the source distribution)
  65. for details.
  66. This file can also be used as a command-line utility to convert
  67. `Netpbm <http://netpbm.sourceforge.net/>`_ PNM files to PNG, and the reverse conversion from PNG to
  68. PNM. The interface is similar to that of the ``pnmtopng`` program from
  69. Netpbm. Type ``python png.py --help`` at the shell prompt
  70. for usage and a list of options.
  71. A note on spelling and terminology
  72. ----------------------------------
  73. Generally British English spelling is used in the documentation. So
  74. that's "greyscale" and "colour". This not only matches the author's
  75. native language, it's also used by the PNG specification.
  76. The major colour models supported by PNG (and hence by PyPNG) are:
  77. greyscale, RGB, greyscale--alpha, RGB--alpha. These are sometimes
  78. referred to using the abbreviations: L, RGB, LA, RGBA. In this case
  79. each letter abbreviates a single channel: *L* is for Luminance or Luma or
  80. Lightness which is the channel used in greyscale images; *R*, *G*, *B* stand
  81. for Red, Green, Blue, the components of a colour image; *A* stands for
  82. Alpha, the opacity channel (used for transparency effects, but higher
  83. values are more opaque, so it makes sense to call it opacity).
  84. A note on formats
  85. -----------------
  86. When getting pixel data out of this module (reading) and presenting
  87. data to this module (writing) there are a number of ways the data could
  88. be represented as a Python value. Generally this module uses one of
  89. three formats called "flat row flat pixel", "boxed row flat pixel", and
  90. "boxed row boxed pixel". Basically the concern is whether each pixel
  91. and each row comes in its own little tuple (box), or not.
  92. Consider an image that is 3 pixels wide by 2 pixels high, and each pixel
  93. has RGB components:
  94. Boxed row flat pixel::
  95. list([R,G,B, R,G,B, R,G,B],
  96. [R,G,B, R,G,B, R,G,B])
  97. Each row appears as its own list, but the pixels are flattened so that
  98. three values for one pixel simply follow the three values for the previous
  99. pixel. This is the most common format used, because it provides a good
  100. compromise between space and convenience. PyPNG regards itself as
  101. at liberty to replace any sequence type with any sufficiently compatible
  102. other sequence type; in practice each row is an array (from the array
  103. module), and the outer list is sometimes an iterator rather than an
  104. explicit list (so that streaming is possible).
  105. Flat row flat pixel::
  106. [R,G,B, R,G,B, R,G,B,
  107. R,G,B, R,G,B, R,G,B]
  108. The entire image is one single giant sequence of colour values.
  109. Generally an array will be used (to save space), not a list.
  110. Boxed row boxed pixel::
  111. list([ (R,G,B), (R,G,B), (R,G,B) ],
  112. [ (R,G,B), (R,G,B), (R,G,B) ])
  113. Each row appears in its own list, but each pixel also appears in its own
  114. tuple. A serious memory burn in Python.
  115. In all cases the top row comes first, and for each row the pixels are
  116. ordered from left-to-right. Within a pixel the values appear in the
  117. order, R-G-B-A (or L-A for greyscale--alpha).
  118. There is a fourth format, mentioned because it is used internally,
  119. is close to what lies inside a PNG file itself, and has some support
  120. from the public API. This format is called packed. When packed,
  121. each row is a sequence of bytes (integers from 0 to 255), just as
  122. it is before PNG scanline filtering is applied. When the bit depth
  123. is 8 this is essentially the same as boxed row flat pixel; when the
  124. bit depth is less than 8, several pixels are packed into each byte;
  125. when the bit depth is 16 (the only value more than 8 that is supported
  126. by the PNG image format) each pixel value is decomposed into 2 bytes
  127. (and `packed` is a misnomer). This format is used by the
  128. :meth:`Writer.write_packed` method. It isn't usually a convenient
  129. format, but may be just right if the source data for the PNG image
  130. comes from something that uses a similar format (for example, 1-bit
  131. BMPs, or another PNG file).
  132. And now, my famous members
  133. --------------------------
  134. """
  135. # http://www.python.org/doc/2.2.3/whatsnew/node5.html
  136. from __future__ import generators
  137. __version__ = "$URL$ $Rev$"
  138. from array import array
  139. try: # See :pyver:old
  140. import itertools
  141. except:
  142. pass
  143. import math
  144. # http://www.python.org/doc/2.4.4/lib/module-operator.html
  145. import operator
  146. import struct
  147. import sys
  148. import zlib
  149. # http://www.python.org/doc/2.4.4/lib/module-warnings.html
  150. import warnings
  151. try:
  152. import pyximport
  153. pyximport.install()
  154. import cpngfilters as pngfilters
  155. except ImportError:
  156. pass
  157. __all__ = ['Image', 'Reader', 'Writer', 'write_chunks', 'from_array']
  158. # The PNG signature.
  159. # http://www.w3.org/TR/PNG/#5PNG-file-signature
  160. _signature = struct.pack('8B', 137, 80, 78, 71, 13, 10, 26, 10)
  161. _adam7 = ((0, 0, 8, 8),
  162. (4, 0, 8, 8),
  163. (0, 4, 4, 8),
  164. (2, 0, 4, 4),
  165. (0, 2, 2, 4),
  166. (1, 0, 2, 2),
  167. (0, 1, 1, 2))
  168. def group(s, n):
  169. # See
  170. # http://www.python.org/doc/2.6/library/functions.html#zip
  171. return zip(*[iter(s)]*n)
  172. def isarray(x):
  173. """Same as ``isinstance(x, array)`` except on Python 2.2, where it
  174. always returns ``False``. This helps PyPNG work on Python 2.2.
  175. """
  176. try:
  177. return isinstance(x, array)
  178. except:
  179. return False
  180. try: # see :pyver:old
  181. array.tostring
  182. except:
  183. def tostring(row):
  184. l = len(row)
  185. return struct.pack('%dB' % l, *row)
  186. else:
  187. def tostring(row):
  188. """Convert row of bytes to string. Expects `row` to be an
  189. ``array``.
  190. """
  191. return row.tostring()
  192. # Conditionally convert to bytes. Works on Python 2 and Python 3.
  193. try:
  194. bytes('', 'ascii')
  195. def strtobytes(x): return bytes(x, 'iso8859-1')
  196. def bytestostr(x): return str(x, 'iso8859-1')
  197. except:
  198. strtobytes = str
  199. bytestostr = str
  200. def interleave_planes(ipixels, apixels, ipsize, apsize):
  201. """
  202. Interleave (colour) planes, e.g. RGB + A = RGBA.
  203. Return an array of pixels consisting of the `ipsize` elements of data
  204. from each pixel in `ipixels` followed by the `apsize` elements of data
  205. from each pixel in `apixels`. Conventionally `ipixels` and
  206. `apixels` are byte arrays so the sizes are bytes, but it actually
  207. works with any arrays of the same type. The returned array is the
  208. same type as the input arrays which should be the same type as each other.
  209. """
  210. itotal = len(ipixels)
  211. atotal = len(apixels)
  212. newtotal = itotal + atotal
  213. newpsize = ipsize + apsize
  214. # Set up the output buffer
  215. # See http://www.python.org/doc/2.4.4/lib/module-array.html#l2h-1356
  216. out = array(ipixels.typecode)
  217. # It's annoying that there is no cheap way to set the array size :-(
  218. out.extend(ipixels)
  219. out.extend(apixels)
  220. # Interleave in the pixel data
  221. for i in range(ipsize):
  222. out[i:newtotal:newpsize] = ipixels[i:itotal:ipsize]
  223. for i in range(apsize):
  224. out[i+ipsize:newtotal:newpsize] = apixels[i:atotal:apsize]
  225. return out
  226. def check_palette(palette):
  227. """Check a palette argument (to the :class:`Writer` class) for validity.
  228. Returns the palette as a list if okay; raises an exception otherwise.
  229. """
  230. # None is the default and is allowed.
  231. if palette is None:
  232. return None
  233. p = list(palette)
  234. if not (0 < len(p) <= 256):
  235. raise ValueError("a palette must have between 1 and 256 entries")
  236. seen_triple = False
  237. for i,t in enumerate(p):
  238. if len(t) not in (3,4):
  239. raise ValueError(
  240. "palette entry %d: entries must be 3- or 4-tuples." % i)
  241. if len(t) == 3:
  242. seen_triple = True
  243. if seen_triple and len(t) == 4:
  244. raise ValueError(
  245. "palette entry %d: all 4-tuples must precede all 3-tuples" % i)
  246. for x in t:
  247. if int(x) != x or not(0 <= x <= 255):
  248. raise ValueError(
  249. "palette entry %d: values must be integer: 0 <= x <= 255" % i)
  250. return p
  251. class Error(Exception):
  252. prefix = 'Error'
  253. def __str__(self):
  254. return self.prefix + ': ' + ' '.join(self.args)
  255. class FormatError(Error):
  256. """Problem with input file format. In other words, PNG file does
  257. not conform to the specification in some way and is invalid.
  258. """
  259. prefix = 'FormatError'
  260. class ChunkError(FormatError):
  261. prefix = 'ChunkError'
  262. class Writer:
  263. """
  264. PNG encoder in pure Python.
  265. """
  266. def __init__(self, width=None, height=None,
  267. size=None,
  268. greyscale=False,
  269. alpha=False,
  270. bitdepth=8,
  271. palette=None,
  272. transparent=None,
  273. background=None,
  274. gamma=None,
  275. compression=None,
  276. interlace=False,
  277. bytes_per_sample=None, # deprecated
  278. planes=None,
  279. colormap=None,
  280. maxval=None,
  281. chunk_limit=2**20):
  282. """
  283. Create a PNG encoder object.
  284. Arguments:
  285. width, height
  286. Image size in pixels, as two separate arguments.
  287. size
  288. Image size (w,h) in pixels, as single argument.
  289. greyscale
  290. Input data is greyscale, not RGB.
  291. alpha
  292. Input data has alpha channel (RGBA or LA).
  293. bitdepth
  294. Bit depth: from 1 to 16.
  295. palette
  296. Create a palette for a colour mapped image (colour type 3).
  297. transparent
  298. Specify a transparent colour (create a ``tRNS`` chunk).
  299. background
  300. Specify a default background colour (create a ``bKGD`` chunk).
  301. gamma
  302. Specify a gamma value (create a ``gAMA`` chunk).
  303. compression
  304. zlib compression level: 0 (none) to 9 (more compressed); default: -1 or None.
  305. interlace
  306. Create an interlaced image.
  307. chunk_limit
  308. Write multiple ``IDAT`` chunks to save memory.
  309. The image size (in pixels) can be specified either by using the
  310. `width` and `height` arguments, or with the single `size`
  311. argument. If `size` is used it should be a pair (*width*,
  312. *height*).
  313. `greyscale` and `alpha` are booleans that specify whether
  314. an image is greyscale (or colour), and whether it has an
  315. alpha channel (or not).
  316. `bitdepth` specifies the bit depth of the source pixel values.
  317. Each source pixel value must be an integer between 0 and
  318. ``2**bitdepth-1``. For example, 8-bit images have values
  319. between 0 and 255. PNG only stores images with bit depths of
  320. 1,2,4,8, or 16. When `bitdepth` is not one of these values,
  321. the next highest valid bit depth is selected, and an ``sBIT``
  322. (significant bits) chunk is generated that specifies the original
  323. precision of the source image. In this case the supplied pixel
  324. values will be rescaled to fit the range of the selected bit depth.
  325. The details of which bit depth / colour model combinations the
  326. PNG file format supports directly, are somewhat arcane
  327. (refer to the PNG specification for full details). Briefly:
  328. "small" bit depths (1,2,4) are only allowed with greyscale and
  329. colour mapped images; colour mapped images cannot have bit depth
  330. 16.
  331. For colour mapped images (in other words, when the `palette`
  332. argument is specified) the `bitdepth` argument must match one of
  333. the valid PNG bit depths: 1, 2, 4, or 8. (It is valid to have a
  334. PNG image with a palette and an ``sBIT`` chunk, but the meaning
  335. is slightly different; it would be awkward to press the
  336. `bitdepth` argument into service for this.)
  337. The `palette` option, when specified, causes a colour mapped image
  338. to be created: the PNG colour type is set to 3; greyscale
  339. must not be set; alpha must not be set; transparent must
  340. not be set; the bit depth must be 1,2,4, or 8. When a colour
  341. mapped image is created, the pixel values are palette indexes
  342. and the `bitdepth` argument specifies the size of these indexes
  343. (not the size of the colour values in the palette).
  344. The palette argument value should be a sequence of 3- or
  345. 4-tuples. 3-tuples specify RGB palette entries; 4-tuples
  346. specify RGBA palette entries. If both 4-tuples and 3-tuples
  347. appear in the sequence then all the 4-tuples must come
  348. before all the 3-tuples. A ``PLTE`` chunk is created; if there
  349. are 4-tuples then a ``tRNS`` chunk is created as well. The
  350. ``PLTE`` chunk will contain all the RGB triples in the same
  351. sequence; the ``tRNS`` chunk will contain the alpha channel for
  352. all the 4-tuples, in the same sequence. Palette entries
  353. are always 8-bit.
  354. If specified, the `transparent` and `background` parameters must
  355. be a tuple with three integer values for red, green, blue, or
  356. a simple integer (or singleton tuple) for a greyscale image.
  357. If specified, the `gamma` parameter must be a positive number
  358. (generally, a float). A ``gAMA`` chunk will be created. Note that
  359. this will not change the values of the pixels as they appear in
  360. the PNG file, they are assumed to have already been converted
  361. appropriately for the gamma specified.
  362. The `compression` argument specifies the compression level to
  363. be used by the ``zlib`` module. Values from 1 to 9 specify
  364. compression, with 9 being "more compressed" (usually smaller
  365. and slower, but it doesn't always work out that way). 0 means
  366. no compression. -1 and ``None`` both mean that the default
  367. level of compession will be picked by the ``zlib`` module
  368. (which is generally acceptable).
  369. If `interlace` is true then an interlaced image is created
  370. (using PNG's so far only interace method, *Adam7*). This does not
  371. affect how the pixels should be presented to the encoder, rather
  372. it changes how they are arranged into the PNG file. On slow
  373. connexions interlaced images can be partially decoded by the
  374. browser to give a rough view of the image that is successively
  375. refined as more image data appears.
  376. .. note ::
  377. Enabling the `interlace` option requires the entire image
  378. to be processed in working memory.
  379. `chunk_limit` is used to limit the amount of memory used whilst
  380. compressing the image. In order to avoid using large amounts of
  381. memory, multiple ``IDAT`` chunks may be created.
  382. """
  383. # At the moment the `planes` argument is ignored;
  384. # its purpose is to act as a dummy so that
  385. # ``Writer(x, y, **info)`` works, where `info` is a dictionary
  386. # returned by Reader.read and friends.
  387. # Ditto for `colormap`.
  388. # A couple of helper functions come first. Best skipped if you
  389. # are reading through.
  390. def isinteger(x):
  391. try:
  392. return int(x) == x
  393. except:
  394. return False
  395. def check_color(c, which):
  396. """Checks that a colour argument for transparent or
  397. background options is the right form. Also "corrects" bare
  398. integers to 1-tuples.
  399. """
  400. if c is None:
  401. return c
  402. if greyscale:
  403. try:
  404. l = len(c)
  405. except TypeError:
  406. c = (c,)
  407. if len(c) != 1:
  408. raise ValueError("%s for greyscale must be 1-tuple" %
  409. which)
  410. if not isinteger(c[0]):
  411. raise ValueError(
  412. "%s colour for greyscale must be integer" %
  413. which)
  414. else:
  415. if not (len(c) == 3 and
  416. isinteger(c[0]) and
  417. isinteger(c[1]) and
  418. isinteger(c[2])):
  419. raise ValueError(
  420. "%s colour must be a triple of integers" %
  421. which)
  422. return c
  423. if size:
  424. if len(size) != 2:
  425. raise ValueError(
  426. "size argument should be a pair (width, height)")
  427. if width is not None and width != size[0]:
  428. raise ValueError(
  429. "size[0] (%r) and width (%r) should match when both are used."
  430. % (size[0], width))
  431. if height is not None and height != size[1]:
  432. raise ValueError(
  433. "size[1] (%r) and height (%r) should match when both are used."
  434. % (size[1], height))
  435. width,height = size
  436. del size
  437. if width <= 0 or height <= 0:
  438. raise ValueError("width and height must be greater than zero")
  439. if not isinteger(width) or not isinteger(height):
  440. raise ValueError("width and height must be integers")
  441. # http://www.w3.org/TR/PNG/#7Integers-and-byte-order
  442. if width > 2**32-1 or height > 2**32-1:
  443. raise ValueError("width and height cannot exceed 2**32-1")
  444. if alpha and transparent is not None:
  445. raise ValueError(
  446. "transparent colour not allowed with alpha channel")
  447. if bytes_per_sample is not None:
  448. warnings.warn('please use bitdepth instead of bytes_per_sample',
  449. DeprecationWarning)
  450. if bytes_per_sample not in (0.125, 0.25, 0.5, 1, 2):
  451. raise ValueError(
  452. "bytes per sample must be .125, .25, .5, 1, or 2")
  453. bitdepth = int(8*bytes_per_sample)
  454. del bytes_per_sample
  455. if not isinteger(bitdepth) or bitdepth < 1 or 16 < bitdepth:
  456. raise ValueError("bitdepth (%r) must be a postive integer <= 16" %
  457. bitdepth)
  458. self.rescale = None
  459. if palette:
  460. if bitdepth not in (1,2,4,8):
  461. raise ValueError("with palette, bitdepth must be 1, 2, 4, or 8")
  462. if transparent is not None:
  463. raise ValueError("transparent and palette not compatible")
  464. if alpha:
  465. raise ValueError("alpha and palette not compatible")
  466. if greyscale:
  467. raise ValueError("greyscale and palette not compatible")
  468. else:
  469. # No palette, check for sBIT chunk generation.
  470. if alpha or not greyscale:
  471. if bitdepth not in (8,16):
  472. targetbitdepth = (8,16)[bitdepth > 8]
  473. self.rescale = (bitdepth, targetbitdepth)
  474. bitdepth = targetbitdepth
  475. del targetbitdepth
  476. else:
  477. assert greyscale
  478. assert not alpha
  479. if bitdepth not in (1,2,4,8,16):
  480. if bitdepth > 8:
  481. targetbitdepth = 16
  482. elif bitdepth == 3:
  483. targetbitdepth = 4
  484. else:
  485. assert bitdepth in (5,6,7)
  486. targetbitdepth = 8
  487. self.rescale = (bitdepth, targetbitdepth)
  488. bitdepth = targetbitdepth
  489. del targetbitdepth
  490. if bitdepth < 8 and (alpha or not greyscale and not palette):
  491. raise ValueError(
  492. "bitdepth < 8 only permitted with greyscale or palette")
  493. if bitdepth > 8 and palette:
  494. raise ValueError(
  495. "bit depth must be 8 or less for images with palette")
  496. transparent = check_color(transparent, 'transparent')
  497. background = check_color(background, 'background')
  498. # It's important that the true boolean values (greyscale, alpha,
  499. # colormap, interlace) are converted to bool because Iverson's
  500. # convention is relied upon later on.
  501. self.width = width
  502. self.height = height
  503. self.transparent = transparent
  504. self.background = background
  505. self.gamma = gamma
  506. self.greyscale = bool(greyscale)
  507. self.alpha = bool(alpha)
  508. self.colormap = bool(palette)
  509. self.bitdepth = int(bitdepth)
  510. self.compression = compression
  511. self.chunk_limit = chunk_limit
  512. self.interlace = bool(interlace)
  513. self.palette = check_palette(palette)
  514. self.color_type = 4*self.alpha + 2*(not greyscale) + 1*self.colormap
  515. assert self.color_type in (0,2,3,4,6)
  516. self.color_planes = (3,1)[self.greyscale or self.colormap]
  517. self.planes = self.color_planes + self.alpha
  518. # :todo: fix for bitdepth < 8
  519. self.psize = (self.bitdepth/8) * self.planes
  520. def make_palette(self):
  521. """Create the byte sequences for a ``PLTE`` and if necessary a
  522. ``tRNS`` chunk. Returned as a pair (*p*, *t*). *t* will be
  523. ``None`` if no ``tRNS`` chunk is necessary.
  524. """
  525. p = array('B')
  526. t = array('B')
  527. for x in self.palette:
  528. p.extend(x[0:3])
  529. if len(x) > 3:
  530. t.append(x[3])
  531. p = tostring(p)
  532. t = tostring(t)
  533. if t:
  534. return p,t
  535. return p,None
  536. def write(self, outfile, rows):
  537. """Write a PNG image to the output file. `rows` should be
  538. an iterable that yields each row in boxed row flat pixel format.
  539. The rows should be the rows of the original image, so there
  540. should be ``self.height`` rows of ``self.width * self.planes`` values.
  541. If `interlace` is specified (when creating the instance), then
  542. an interlaced PNG file will be written. Supply the rows in the
  543. normal image order; the interlacing is carried out internally.
  544. .. note ::
  545. Interlacing will require the entire image to be in working memory.
  546. """
  547. if self.interlace:
  548. fmt = 'BH'[self.bitdepth > 8]
  549. a = array(fmt, itertools.chain(*rows))
  550. return self.write_array(outfile, a)
  551. else:
  552. nrows = self.write_passes(outfile, rows)
  553. if nrows != self.height:
  554. raise ValueError(
  555. "rows supplied (%d) does not match height (%d)" %
  556. (nrows, self.height))
  557. def write_passes(self, outfile, rows, packed=False):
  558. """
  559. Write a PNG image to the output file.
  560. Most users are expected to find the :meth:`write` or
  561. :meth:`write_array` method more convenient.
  562. The rows should be given to this method in the order that
  563. they appear in the output file. For straightlaced images,
  564. this is the usual top to bottom ordering, but for interlaced
  565. images the rows should have already been interlaced before
  566. passing them to this function.
  567. `rows` should be an iterable that yields each row. When
  568. `packed` is ``False`` the rows should be in boxed row flat pixel
  569. format; when `packed` is ``True`` each row should be a packed
  570. sequence of bytes.
  571. """
  572. # http://www.w3.org/TR/PNG/#5PNG-file-signature
  573. outfile.write(_signature)
  574. # http://www.w3.org/TR/PNG/#11IHDR
  575. write_chunk(outfile, 'IHDR',
  576. struct.pack("!2I5B", self.width, self.height,
  577. self.bitdepth, self.color_type,
  578. 0, 0, self.interlace))
  579. # See :chunk:order
  580. # http://www.w3.org/TR/PNG/#11gAMA
  581. if self.gamma is not None:
  582. write_chunk(outfile, 'gAMA',
  583. struct.pack("!L", int(round(self.gamma*1e5))))
  584. # See :chunk:order
  585. # http://www.w3.org/TR/PNG/#11sBIT
  586. if self.rescale:
  587. write_chunk(outfile, 'sBIT',
  588. struct.pack('%dB' % self.planes,
  589. *[self.rescale[0]]*self.planes))
  590. # :chunk:order: Without a palette (PLTE chunk), ordering is
  591. # relatively relaxed. With one, gAMA chunk must precede PLTE
  592. # chunk which must precede tRNS and bKGD.
  593. # See http://www.w3.org/TR/PNG/#5ChunkOrdering
  594. if self.palette:
  595. p,t = self.make_palette()
  596. write_chunk(outfile, 'PLTE', p)
  597. if t:
  598. # tRNS chunk is optional. Only needed if palette entries
  599. # have alpha.
  600. write_chunk(outfile, 'tRNS', t)
  601. # http://www.w3.org/TR/PNG/#11tRNS
  602. if self.transparent is not None:
  603. if self.greyscale:
  604. write_chunk(outfile, 'tRNS',
  605. struct.pack("!1H", *self.transparent))
  606. else:
  607. write_chunk(outfile, 'tRNS',
  608. struct.pack("!3H", *self.transparent))
  609. # http://www.w3.org/TR/PNG/#11bKGD
  610. if self.background is not None:
  611. if self.greyscale:
  612. write_chunk(outfile, 'bKGD',
  613. struct.pack("!1H", *self.background))
  614. else:
  615. write_chunk(outfile, 'bKGD',
  616. struct.pack("!3H", *self.background))
  617. # http://www.w3.org/TR/PNG/#11IDAT
  618. if self.compression is not None:
  619. compressor = zlib.compressobj(self.compression)
  620. else:
  621. compressor = zlib.compressobj()
  622. # Choose an extend function based on the bitdepth. The extend
  623. # function packs/decomposes the pixel values into bytes and
  624. # stuffs them onto the data array.
  625. data = array('B')
  626. if self.bitdepth == 8 or packed:
  627. extend = data.extend
  628. elif self.bitdepth == 16:
  629. # Decompose into bytes
  630. def extend(sl):
  631. fmt = '!%dH' % len(sl)
  632. data.extend(array('B', struct.pack(fmt, *sl)))
  633. else:
  634. # Pack into bytes
  635. assert self.bitdepth < 8
  636. # samples per byte
  637. spb = int(8/self.bitdepth)
  638. def extend(sl):
  639. a = array('B', sl)
  640. # Adding padding bytes so we can group into a whole
  641. # number of spb-tuples.
  642. l = float(len(a))
  643. extra = math.ceil(l / float(spb))*spb - l
  644. a.extend([0]*int(extra))
  645. # Pack into bytes
  646. l = group(a, spb)
  647. l = map(lambda e: reduce(lambda x,y:
  648. (x << self.bitdepth) + y, e), l)
  649. data.extend(l)
  650. if self.rescale:
  651. oldextend = extend
  652. factor = \
  653. float(2**self.rescale[1]-1) / float(2**self.rescale[0]-1)
  654. def extend(sl):
  655. oldextend(map(lambda x: int(round(factor*x)), sl))
  656. # Build the first row, testing mostly to see if we need to
  657. # changed the extend function to cope with NumPy integer types
  658. # (they cause our ordinary definition of extend to fail, so we
  659. # wrap it). See
  660. # http://code.google.com/p/pypng/issues/detail?id=44
  661. enumrows = enumerate(rows)
  662. del rows
  663. # First row's filter type.
  664. data.append(0)
  665. # :todo: Certain exceptions in the call to ``.next()`` or the
  666. # following try would indicate no row data supplied.
  667. # Should catch.
  668. i,row = enumrows.next()
  669. try:
  670. # If this fails...
  671. extend(row)
  672. except:
  673. # ... try a version that converts the values to int first.
  674. # Not only does this work for the (slightly broken) NumPy
  675. # types, there are probably lots of other, unknown, "nearly"
  676. # int types it works for.
  677. def wrapmapint(f):
  678. return lambda sl: f(map(int, sl))
  679. extend = wrapmapint(extend)
  680. del wrapmapint
  681. extend(row)
  682. for i,row in enumrows:
  683. # Add "None" filter type. Currently, it's essential that
  684. # this filter type be used for every scanline as we do not
  685. # mark the first row of a reduced pass image; that means we
  686. # could accidentally compute the wrong filtered scanline if
  687. # we used "up", "average", or "paeth" on such a line.
  688. data.append(0)
  689. extend(row)
  690. if len(data) > self.chunk_limit:
  691. compressed = compressor.compress(tostring(data))
  692. if len(compressed):
  693. # print >> sys.stderr, len(data), len(compressed)
  694. write_chunk(outfile, 'IDAT', compressed)
  695. # Because of our very witty definition of ``extend``,
  696. # above, we must re-use the same ``data`` object. Hence
  697. # we use ``del`` to empty this one, rather than create a
  698. # fresh one (which would be my natural FP instinct).
  699. del data[:]
  700. if len(data):
  701. compressed = compressor.compress(tostring(data))
  702. else:
  703. compressed = ''
  704. flushed = compressor.flush()
  705. if len(compressed) or len(flushed):
  706. # print >> sys.stderr, len(data), len(compressed), len(flushed)
  707. write_chunk(outfile, 'IDAT', compressed + flushed)
  708. # http://www.w3.org/TR/PNG/#11IEND
  709. write_chunk(outfile, 'IEND')
  710. return i+1
  711. def write_array(self, outfile, pixels):
  712. """
  713. Write an array in flat row flat pixel format as a PNG file on
  714. the output file. See also :meth:`write` method.
  715. """
  716. if self.interlace:
  717. self.write_passes(outfile, self.array_scanlines_interlace(pixels))
  718. else:
  719. self.write_passes(outfile, self.array_scanlines(pixels))
  720. def write_packed(self, outfile, rows):
  721. """
  722. Write PNG file to `outfile`. The pixel data comes from `rows`
  723. which should be in boxed row packed format. Each row should be
  724. a sequence of packed bytes.
  725. Technically, this method does work for interlaced images but it
  726. is best avoided. For interlaced images, the rows should be
  727. presented in the order that they appear in the file.
  728. This method should not be used when the source image bit depth
  729. is not one naturally supported by PNG; the bit depth should be
  730. 1, 2, 4, 8, or 16.
  731. """
  732. if self.rescale:
  733. raise Error("write_packed method not suitable for bit depth %d" %
  734. self.rescale[0])
  735. return self.write_passes(outfile, rows, packed=True)
  736. def convert_pnm(self, infile, outfile):
  737. """
  738. Convert a PNM file containing raw pixel data into a PNG file
  739. with the parameters set in the writer object. Works for
  740. (binary) PGM, PPM, and PAM formats.
  741. """
  742. if self.interlace:
  743. pixels = array('B')
  744. pixels.fromfile(infile,
  745. (self.bitdepth/8) * self.color_planes *
  746. self.width * self.height)
  747. self.write_passes(outfile, self.array_scanlines_interlace(pixels))
  748. else:
  749. self.write_passes(outfile, self.file_scanlines(infile))
  750. def convert_ppm_and_pgm(self, ppmfile, pgmfile, outfile):
  751. """
  752. Convert a PPM and PGM file containing raw pixel data into a
  753. PNG outfile with the parameters set in the writer object.
  754. """
  755. pixels = array('B')
  756. pixels.fromfile(ppmfile,
  757. (self.bitdepth/8) * self.color_planes *
  758. self.width * self.height)
  759. apixels = array('B')
  760. apixels.fromfile(pgmfile,
  761. (self.bitdepth/8) *
  762. self.width * self.height)
  763. pixels = interleave_planes(pixels, apixels,
  764. (self.bitdepth/8) * self.color_planes,
  765. (self.bitdepth/8))
  766. if self.interlace:
  767. self.write_passes(outfile, self.array_scanlines_interlace(pixels))
  768. else:
  769. self.write_passes(outfile, self.array_scanlines(pixels))
  770. def file_scanlines(self, infile):
  771. """
  772. Generates boxed rows in flat pixel format, from the input file
  773. `infile`. It assumes that the input file is in a "Netpbm-like"
  774. binary format, and is positioned at the beginning of the first
  775. pixel. The number of pixels to read is taken from the image
  776. dimensions (`width`, `height`, `planes`) and the number of bytes
  777. per value is implied by the image `bitdepth`.
  778. """
  779. # Values per row
  780. vpr = self.width * self.planes
  781. row_bytes = vpr
  782. if self.bitdepth > 8:
  783. assert self.bitdepth == 16
  784. row_bytes *= 2
  785. fmt = '>%dH' % vpr
  786. def line():
  787. return array('H', struct.unpack(fmt, infile.read(row_bytes)))
  788. else:
  789. def line():
  790. scanline = array('B', infile.read(row_bytes))
  791. return scanline
  792. for y in range(self.height):
  793. yield line()
  794. def array_scanlines(self, pixels):
  795. """
  796. Generates boxed rows (flat pixels) from flat rows (flat pixels)
  797. in an array.
  798. """
  799. # Values per row
  800. vpr = self.width * self.planes
  801. stop = 0
  802. for y in range(self.height):
  803. start = stop
  804. stop = start + vpr
  805. yield pixels[start:stop]
  806. def array_scanlines_interlace(self, pixels):
  807. """
  808. Generator for interlaced scanlines from an array. `pixels` is
  809. the full source image in flat row flat pixel format. The
  810. generator yields each scanline of the reduced passes in turn, in
  811. boxed row flat pixel format.
  812. """
  813. # http://www.w3.org/TR/PNG/#8InterlaceMethods
  814. # Array type.
  815. fmt = 'BH'[self.bitdepth > 8]
  816. # Value per row
  817. vpr = self.width * self.planes
  818. for xstart, ystart, xstep, ystep in _adam7:
  819. if xstart >= self.width:
  820. continue
  821. # Pixels per row (of reduced image)
  822. ppr = int(math.ceil((self.width-xstart)/float(xstep)))
  823. # number of values in reduced image row.
  824. row_len = ppr*self.planes
  825. for y in range(ystart, self.height, ystep):
  826. if xstep == 1:
  827. offset = y * vpr
  828. yield pixels[offset:offset+vpr]
  829. else:
  830. row = array(fmt)
  831. # There's no easier way to set the length of an array
  832. row.extend(pixels[0:row_len])
  833. offset = y * vpr + xstart * self.planes
  834. end_offset = (y+1) * vpr
  835. skip = self.planes * xstep
  836. for i in range(self.planes):
  837. row[i::self.planes] = \
  838. pixels[offset+i:end_offset:skip]
  839. yield row
  840. def write_chunk(outfile, tag, data=strtobytes('')):
  841. """
  842. Write a PNG chunk to the output file, including length and
  843. checksum.
  844. """
  845. # http://www.w3.org/TR/PNG/#5Chunk-layout
  846. outfile.write(struct.pack("!I", len(data)))
  847. tag = strtobytes(tag)
  848. outfile.write(tag)
  849. outfile.write(data)
  850. checksum = zlib.crc32(tag)
  851. checksum = zlib.crc32(data, checksum)
  852. checksum &= 2**32-1
  853. outfile.write(struct.pack("!I", checksum))
  854. def write_chunks(out, chunks):
  855. """Create a PNG file by writing out the chunks."""
  856. out.write(_signature)
  857. for chunk in chunks:
  858. write_chunk(out, *chunk)
  859. def filter_scanline(type, line, fo, prev=None):
  860. """Apply a scanline filter to a scanline. `type` specifies the
  861. filter type (0 to 4); `line` specifies the current (unfiltered)
  862. scanline as a sequence of bytes; `prev` specifies the previous
  863. (unfiltered) scanline as a sequence of bytes. `fo` specifies the
  864. filter offset; normally this is size of a pixel in bytes (the number
  865. of bytes per sample times the number of channels), but when this is
  866. < 1 (for bit depths < 8) then the filter offset is 1.
  867. """
  868. assert 0 <= type < 5
  869. # The output array. Which, pathetically, we extend one-byte at a
  870. # time (fortunately this is linear).
  871. out = array('B', [type])
  872. def sub():
  873. ai = -fo
  874. for x in line:
  875. if ai >= 0:
  876. x = (x - line[ai]) & 0xff
  877. out.append(x)
  878. ai += 1
  879. def up():
  880. for i,x in enumerate(line):
  881. x = (x - prev[i]) & 0xff
  882. out.append(x)
  883. def average():
  884. ai = -fo
  885. for i,x in enumerate(line):
  886. if ai >= 0:
  887. x = (x - ((line[ai] + prev[i]) >> 1)) & 0xff
  888. else:
  889. x = (x - (prev[i] >> 1)) & 0xff
  890. out.append(x)
  891. ai += 1
  892. def paeth():
  893. # http://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
  894. ai = -fo # also used for ci
  895. for i,x in enumerate(line):
  896. a = 0
  897. b = prev[i]
  898. c = 0
  899. if ai >= 0:
  900. a = line[ai]
  901. c = prev[ai]
  902. p = a + b - c
  903. pa = abs(p - a)
  904. pb = abs(p - b)
  905. pc = abs(p - c)
  906. if pa <= pb and pa <= pc: Pr = a
  907. elif pb <= pc: Pr = b
  908. else: Pr = c
  909. x = (x - Pr) & 0xff
  910. out.append(x)
  911. ai += 1
  912. if not prev:
  913. # We're on the first line. Some of the filters can be reduced
  914. # to simpler cases which makes handling the line "off the top"
  915. # of the image simpler. "up" becomes "none"; "paeth" becomes
  916. # "left" (non-trivial, but true). "average" needs to be handled
  917. # specially.
  918. if type == 2: # "up"
  919. return line # type = 0
  920. elif type == 3:
  921. prev = [0]*len(line)
  922. elif type == 4: # "paeth"
  923. type = 1
  924. if type == 0:
  925. out.extend(line)
  926. elif type == 1:
  927. sub()
  928. elif type == 2:
  929. up()
  930. elif type == 3:
  931. average()
  932. else: # type == 4
  933. paeth()
  934. return out
  935. def from_array(a, mode=None, info={}):
  936. """Create a PNG :class:`Image` object from a 2- or 3-dimensional array.
  937. One application of this function is easy PIL-style saving:
  938. ``png.from_array(pixels, 'L').save('foo.png')``.
  939. .. note :
  940. The use of the term *3-dimensional* is for marketing purposes
  941. only. It doesn't actually work. Please bear with us. Meanwhile
  942. enjoy the complimentary snacks (on request) and please use a
  943. 2-dimensional array.
  944. Unless they are specified using the *info* parameter, the PNG's
  945. height and width are taken from the array size. For a 3 dimensional
  946. array the first axis is the height; the second axis is the width;
  947. and the third axis is the channel number. Thus an RGB image that is
  948. 16 pixels high and 8 wide will use an array that is 16x8x3. For 2
  949. dimensional arrays the first axis is the height, but the second axis
  950. is ``width*channels``, so an RGB image that is 16 pixels high and 8
  951. wide will use a 2-dimensional array that is 16x24 (each row will be
  952. 8*3==24 sample values).
  953. *mode* is a string that specifies the image colour format in a
  954. PIL-style mode. It can be:
  955. ``'L'``
  956. greyscale (1 channel)
  957. ``'LA'``
  958. greyscale with alpha (2 channel)
  959. ``'RGB'``
  960. colour image (3 channel)
  961. ``'RGBA'``
  962. colour image with alpha (4 channel)
  963. The mode string can also specify the bit depth (overriding how this
  964. function normally derives the bit depth, see below). Appending
  965. ``';16'`` to the mode will cause the PNG to be 16 bits per channel;
  966. any decimal from 1 to 16 can be used to specify the bit depth.
  967. When a 2-dimensional array is used *mode* determines how many
  968. channels the image has, and so allows the width to be derived from
  969. the second array dimension.
  970. The array is expected to be a ``numpy`` array, but it can be any
  971. suitable Python sequence. For example, a list of lists can be used:
  972. ``png.from_array([[0, 255, 0], [255, 0, 255]], 'L')``. The exact
  973. rules are: ``len(a)`` gives the first dimension, height;
  974. ``len(a[0])`` gives the second dimension; ``len(a[0][0])`` gives the
  975. third dimension, unless an exception is raised in which case a
  976. 2-dimensional array is assumed. It's slightly more complicated than
  977. that because an iterator of rows can be used, and it all still
  978. works. Using an iterator allows data to be streamed efficiently.
  979. The bit depth of the PNG is normally taken from the array element's
  980. datatype (but if *mode* specifies a bitdepth then that is used
  981. instead). The array element's datatype is determined in a way which
  982. is supposed to work both for ``numpy`` arrays and for Python
  983. ``array.array`` objects. A 1 byte datatype will give a bit depth of
  984. 8, a 2 byte datatype will give a bit depth of 16. If the datatype
  985. does not have an implicit size, for example it is a plain Python
  986. list of lists, as above, then a default of 8 is used.
  987. The *info* parameter is a dictionary that can be used to specify
  988. metadata (in the same style as the arguments to the
  989. :class:``png.Writer`` class). For this function the keys that are
  990. useful are:
  991. height
  992. overrides the height derived from the array dimensions and allows
  993. *a* to be an iterable.
  994. width
  995. overrides the width derived from the array dimensions.
  996. bitdepth
  997. overrides the bit depth derived from the element datatype (but
  998. must match *mode* if that also specifies a bit depth).
  999. Generally anything specified in the
  1000. *info* dictionary will override any implicit choices that this
  1001. function would otherwise make, but must match any explicit ones.
  1002. For example, if the *info* dictionary has a ``greyscale`` key then
  1003. this must be true when mode is ``'L'`` or ``'LA'`` and false when
  1004. mode is ``'RGB'`` or ``'RGBA'``.
  1005. """
  1006. # We abuse the *info* parameter by modifying it. Take a copy here.
  1007. # (Also typechecks *info* to some extent).
  1008. info = dict(info)
  1009. # Syntax check mode string.
  1010. bitdepth = None
  1011. try:
  1012. mode = mode.split(';')
  1013. if len(mode) not in (1,2):
  1014. raise Error()
  1015. if mode[0] not in ('L', 'LA', 'RGB', 'RGBA'):
  1016. raise Error()
  1017. if len(mode) == 2:
  1018. try:
  1019. bitdepth = int(mode[1])
  1020. except:
  1021. raise Error()
  1022. except Error:
  1023. raise Error("mode string should be 'RGB' or 'L;16' or similar.")
  1024. mode = mode[0]
  1025. # Get bitdepth from *mode* if possible.
  1026. if bitdepth:
  1027. if info.get('bitdepth') and bitdepth != info['bitdepth']:
  1028. raise Error("mode bitdepth (%d) should match info bitdepth (%d)." %
  1029. (bitdepth, info['bitdepth']))
  1030. info['bitdepth'] = bitdepth
  1031. # Fill in and/or check entries in *info*.
  1032. # Dimensions.
  1033. if 'size' in info:
  1034. # Check width, height, size all match where used.
  1035. for dimension,axis in [('width', 0), ('height', 1)]:
  1036. if dimension in info:
  1037. if info[dimension] != info['size'][axis]:
  1038. raise Error(
  1039. "info[%r] shhould match info['size'][%r]." %
  1040. (dimension, axis))
  1041. info['width'],info['height'] = info['size']
  1042. if 'height' not in info:
  1043. try:
  1044. l = len(a)
  1045. except:
  1046. raise Error(
  1047. "len(a) does not work, supply info['height'] instead.")
  1048. info['height'] = l
  1049. # Colour format.
  1050. if 'greyscale' in info:
  1051. if bool(info['greyscale']) != ('L' in mode):
  1052. raise Error("info['greyscale'] should match mode.")
  1053. info['greyscale'] = 'L' in mode
  1054. if 'alpha' in info:
  1055. if bool(info['alpha']) != ('A' in mode):
  1056. raise Error("info['alpha'] should match mode.")
  1057. info['alpha'] = 'A' in mode
  1058. planes = len(mode)
  1059. if 'planes' in info:
  1060. if info['planes'] != planes:
  1061. raise Error("info['planes'] should match mode.")
  1062. # In order to work out whether we the array is 2D or 3D we need its
  1063. # first row, which requires that we take a copy of its iterator.
  1064. # We may also need the first row to derive width and bitdepth.
  1065. a,t = itertools.tee(a)
  1066. row = t.next()
  1067. del t
  1068. try:
  1069. row[0][0]
  1070. threed = True
  1071. testelement = row[0]
  1072. except:
  1073. threed = False
  1074. testelement = row
  1075. if 'width' not in info:
  1076. if threed:
  1077. width = len(row)
  1078. else:
  1079. width = len(row) // planes
  1080. info['width'] = width
  1081. # Not implemented yet
  1082. assert not threed
  1083. if 'bitdepth' not in info:
  1084. try:
  1085. dtype = testelement.dtype
  1086. # goto the "else:" clause. Sorry.
  1087. except:
  1088. try:
  1089. # Try a Python array.array.
  1090. bitdepth = 8 * testelement.itemsize
  1091. except:
  1092. # We can't determine it from the array element's
  1093. # datatype, use a default of 8.
  1094. bitdepth = 8
  1095. else:
  1096. # If we got here without exception, we now assume that
  1097. # the array is a numpy array.
  1098. if dtype.kind == 'b':
  1099. bitdepth = 1
  1100. else:
  1101. bitdepth = 8 * dtype.itemsize
  1102. info['bitdepth'] = bitdepth
  1103. for thing in 'width height bitdepth greyscale alpha'.split():
  1104. assert thing in info
  1105. return Image(a, info)
  1106. # So that refugee's from PIL feel more at home. Not documented.
  1107. fromarray = from_array
  1108. class Image:
  1109. """A PNG image.
  1110. You can create an :class:`Image` object from an array of pixels by calling
  1111. :meth:`png.from_array`. It can be saved to disk with the
  1112. :meth:`save` method."""
  1113. def __init__(self, rows, info):
  1114. """
  1115. .. note ::
  1116. The constructor is not public. Please do not call it.
  1117. """
  1118. self.rows = rows
  1119. self.info = info
  1120. def save(self, file):
  1121. """Save the image to *file*. If *file* looks like an open file
  1122. descriptor then it is used, otherwise it is treated as a
  1123. filename and a fresh file is opened.
  1124. In general, you can only call this method once; after it has
  1125. been called the first time and the PNG image has been saved, the
  1126. source data will have been streamed, and cannot be streamed
  1127. again.
  1128. """
  1129. w = Writer(**self.info)
  1130. try:
  1131. file.write
  1132. def close(): pass
  1133. except:
  1134. file = open(file, 'wb')
  1135. def close(): file.close()
  1136. try:
  1137. w.write(file, self.rows)
  1138. finally:
  1139. close()
  1140. class _readable:
  1141. """
  1142. A simple file-like interface for strings and arrays.
  1143. """
  1144. def __init__(self, buf):
  1145. self.buf = buf
  1146. self.offset = 0
  1147. def read(self, n):
  1148. r = self.buf[self.offset:self.offset+n]
  1149. if isarray(r):
  1150. r = r.tostring()
  1151. self.offset += n
  1152. return r
  1153. class Reader:
  1154. """
  1155. PNG decoder in pure Python.
  1156. """
  1157. def __init__(self, _guess=None, **kw):
  1158. """
  1159. Create a PNG decoder object.
  1160. The constructor expects exactly one keyword argument. If you
  1161. supply a positional argument instead, it will guess the input
  1162. type. You can choose among the following keyword arguments:
  1163. filename
  1164. Name of input file (a PNG file).
  1165. file
  1166. A file-like object (object with a read() method).
  1167. bytes
  1168. ``array`` or ``string`` with PNG data.
  1169. """
  1170. if ((_guess is not None and len(kw) != 0) or
  1171. (_guess is None and len(kw) != 1)):
  1172. raise TypeError("Reader() takes exactly 1 argument")
  1173. # Will be the first 8 bytes, later on. See validate_signature.
  1174. self.signature = None
  1175. self.transparent = None
  1176. # A pair of (len,type) if a chunk has been read but its data and
  1177. # checksum have not (in other words the file position is just
  1178. # past the 4 bytes that specify the chunk type). See preamble
  1179. # method for how this is used.
  1180. self.atchunk = None
  1181. if _guess is not None:
  1182. if isarray(_guess):
  1183. kw["bytes"] = _guess
  1184. elif isinstance(_guess, str):
  1185. kw["filename"] = _guess
  1186. elif isinstance(_guess, file):
  1187. kw["file"] = _guess
  1188. if "filename" in kw:
  1189. self.file = open(kw["filename"], "rb")
  1190. elif "file" in kw:
  1191. self.file = kw["file"]
  1192. elif "bytes" in kw:
  1193. self.file = _readable(kw["bytes"])
  1194. else:
  1195. raise TypeError("expecting filename, file or bytes array")
  1196. def chunk(self, seek=None, lenient=False):
  1197. """
  1198. Read the next PNG chunk from the input file; returns a
  1199. (*type*,*data*) tuple. *type* is the chunk's type as a string
  1200. (all PNG chunk types are 4 characters long). *data* is the
  1201. chunk's data content, as a string.
  1202. If the optional `seek` argument is
  1203. specified then it will keep reading chunks until it either runs
  1204. out of file or finds the type specified by the argument. Note
  1205. that in general the order of chunks in PNGs is unspecified, so
  1206. using `seek` can cause you to miss chunks.
  1207. If the optional `lenient` argument evaluates to True,
  1208. checksum failures will raise warnings rather than exceptions.
  1209. """
  1210. self.validate_signature()
  1211. while True:
  1212. # http://www.w3.org/TR/PNG/#5Chunk-layout
  1213. if not self.atchunk:
  1214. self.atchunk = self.chunklentype()
  1215. length,type = self.atchunk
  1216. self.atchunk = None
  1217. data = self.file.read(length)
  1218. if len(data) != length:
  1219. raise ChunkError('Chunk %s too short for required %i octets.'
  1220. % (type, length))
  1221. checksum = self.file.read(4)
  1222. if len(checksum) != 4:
  1223. raise ValueError('Chunk %s too short for checksum.', tag)
  1224. if seek and type != seek:
  1225. continue
  1226. verify = zlib.crc32(strtobytes(type))
  1227. verify = zlib.crc32(data, verify)
  1228. # Whether the output from zlib.crc32 is signed or not varies
  1229. # according to hideous implementation details, see
  1230. # http://bugs.python.org/issue1202 .
  1231. # We coerce it to be positive here (in a way which works on
  1232. # Python 2.3 and older).
  1233. verify &= 2**32 - 1
  1234. verify = struct.pack('!I', verify)
  1235. if checksum != verify:
  1236. # print repr(checksum)
  1237. (a, ) = struct.unpack('!I', checksum)
  1238. (b, ) = struct.unpack('!I', verify)
  1239. message = "Checksum error in %s chunk: 0x%08X != 0x%08X." % (type, a, b)
  1240. if lenient:
  1241. warnings.warn(message, RuntimeWarning)
  1242. else:
  1243. raise ChunkError(message)
  1244. return type, data
  1245. def chunks(self):
  1246. """Return an iterator that will yield each chunk as a
  1247. (*chunktype*, *content*) pair.
  1248. """
  1249. while True:
  1250. t,v = self.chunk()
  1251. yield t,v
  1252. if t == 'IEND':
  1253. break
  1254. def undo_filter(self, filter_type, scanline, previous):
  1255. """Undo the filter for a scanline. `scanline` is a sequence of
  1256. bytes that does not include the initial filter type byte.
  1257. `previous` is decoded previous scanline (for straightlaced
  1258. images this is the previous pixel row, but for interlaced
  1259. images, it is the previous scanline in the reduced image, which
  1260. in general is not the previous pixel row in the final image).
  1261. When there is no previous scanline (the first row of a
  1262. straightlaced image, or the first row in one of the passes in an
  1263. interlaced image), then this argument should be ``None``.
  1264. The scanline will have the effects of filtering removed, and the
  1265. result will be returned as a fresh sequence of bytes.
  1266. """
  1267. # :todo: Would it be better to update scanline in place?
  1268. # Yes, with the Cython extension making the undo_filter fast,
  1269. # updating scanline inplace makes the code 3 times faster
  1270. # (reading 50 images of 800x800 went from 40s to 16s)
  1271. result = scanline
  1272. if filter_type == 0:
  1273. return result
  1274. if filter_type not in (1,2,3,4):
  1275. raise FormatError('Invalid PNG Filter Type.'
  1276. ' See http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters .')
  1277. # Filter unit. The stride from one pixel to the corresponding
  1278. # byte from the previous previous. Normally this is the pixel
  1279. # size in bytes, but when this is smaller than 1, the previous
  1280. # byte is used instead.
  1281. fu = max(1, self.psize)
  1282. # For the first line of a pass, synthesize a dummy previous
  1283. # line. An alternative approach would be to observe that on the
  1284. # first line 'up' is the same as 'null', 'paeth' is the same
  1285. # as 'sub', with only 'average' requiring any special case.
  1286. if not previous:
  1287. previous = array('B', [0]*len(scanline))
  1288. def sub():
  1289. """Undo sub filter."""
  1290. ai = 0
  1291. # Loops starts at index fu. Observe that the initial part
  1292. # of the result is already filled in correctly with
  1293. # scanline.
  1294. for i in range(fu, len(result)):
  1295. x = scanline[i]
  1296. a = result[ai]
  1297. result[i] = (x + a) & 0xff
  1298. ai += 1
  1299. def up():
  1300. """Undo up filter."""
  1301. for i in range(len(result)):
  1302. x = scanline[i]
  1303. b = previous[i]
  1304. result[i] = (x + b) & 0xff
  1305. def average():
  1306. """Undo average filter."""
  1307. ai = -fu
  1308. for i in range(len(result)):
  1309. x = scanline[i]
  1310. if ai < 0:
  1311. a = 0
  1312. else:
  1313. a = result[ai]
  1314. b = previous[i]
  1315. result[i] = (x + ((a + b) >> 1)) & 0xff
  1316. ai += 1
  1317. def paeth():
  1318. """Undo Paeth filter."""
  1319. # Also used for ci.
  1320. ai = -fu
  1321. for i in range(len(result)):
  1322. x = scanline[i]
  1323. if ai < 0:
  1324. a = c = 0
  1325. else:
  1326. a = result[ai]
  1327. c = previous[ai]
  1328. b = previous[i]
  1329. p = a + b - c
  1330. pa = abs(p - a)
  1331. pb = abs(p - b)
  1332. pc = abs(p - c)
  1333. if pa <= pb and pa <= pc:
  1334. pr = a
  1335. elif pb <= pc:
  1336. pr = b
  1337. else:
  1338. pr = c
  1339. result[i] = (x + pr) & 0xff
  1340. ai += 1
  1341. # Call appropriate filter algorithm. Note that 0 has already
  1342. # been dealt with.
  1343. (None,
  1344. pngfilters.undo_filter_sub,
  1345. pngfilters.undo_filter_up,
  1346. pngfilters.undo_filter_average,
  1347. pngfilters.undo_filter_paeth)[filter_type](fu, scanline, previous, result)
  1348. return result
  1349. def deinterlace(self, raw):
  1350. """
  1351. Read raw pixel data, undo filters, deinterlace, and flatten.
  1352. Return in flat row flat pixel format.
  1353. """
  1354. # print >> sys.stderr, ("Reading interlaced, w=%s, r=%s, planes=%s," +
  1355. # " bpp=%s") % (self.width, self.height, self.planes, self.bps)
  1356. # Values per row (of the target image)
  1357. vpr = self.width * self.planes
  1358. # Make a result array, and make it big enough. Interleaving
  1359. # writes to the output array randomly (well, not quite), so the
  1360. # entire output array must be in memory.
  1361. fmt = 'BH'[self.bitdepth > 8]
  1362. a = array(fmt, [0]*vpr*self.height)
  1363. source_offset = 0
  1364. for xstart, ystart, xstep, ystep in _adam7:
  1365. # print >> sys.stderr, "Adam7: start=%s,%s step=%s,%s" % (
  1366. # xstart, ystart, xstep, ystep)
  1367. if xstart >= self.width:
  1368. continue
  1369. # The previous (reconstructed) scanline. None at the
  1370. # beginning of a pass to indicate that there is no previous
  1371. # line.
  1372. recon = None
  1373. # Pixels per row (reduced pass image)
  1374. ppr = int(math.ceil((self.width-xstart)/float(xstep)))
  1375. # Row size in bytes for this pass.
  1376. row_size = int(math.ceil(self.psize * ppr))
  1377. for y in range(ystart, self.height, ystep):
  1378. filter_type = raw[source_offset]
  1379. source_offset += 1
  1380. scanline = raw[source_offset:source_offset+row_size]
  1381. source_offset += row_size
  1382. recon = self.undo_filter(filter_type, scanline, recon)
  1383. # Convert so that there is one element per pixel value
  1384. flat = self.serialtoflat(recon, ppr)
  1385. if xstep == 1:
  1386. assert xstart == 0
  1387. offset = y * vpr
  1388. a[offset:offset+vpr] = flat
  1389. else:
  1390. offset = y * vpr + xstart * self.planes
  1391. end_offset = (y+1) * vpr
  1392. skip = self.planes * xstep
  1393. for i in range(self.planes):
  1394. a[offset+i:end_offset:skip] = \
  1395. flat[i::self.planes]
  1396. return a
  1397. def iterboxed(self, rows):
  1398. """Iterator that yields each scanline in boxed row flat pixel
  1399. format. `rows` should be an iterator that yields the bytes of
  1400. each row in turn.
  1401. """
  1402. def asvalues(raw):
  1403. """Convert a row of raw bytes into a flat row. Result may
  1404. or may not share with argument"""
  1405. if self.bitdepth == 8:
  1406. return raw
  1407. if self.bitdepth == 16:
  1408. raw = tostring(raw)
  1409. return array('H', struct.unpack('!%dH' % (len(raw)//2), raw))
  1410. assert self.bitdepth < 8
  1411. width = self.width
  1412. # Samples per byte
  1413. spb = 8//self.bitdepth
  1414. out = array('B')
  1415. mask = 2**self.bitdepth - 1
  1416. shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
  1417. for o in raw:
  1418. out.extend(map(lambda i: mask&(o>>i), shifts))
  1419. return out[:width]
  1420. return itertools.imap(asvalues, rows)
  1421. def serialtoflat(self, bytes, width=None):
  1422. """Convert serial format (byte stream) pixel data to flat row
  1423. flat pixel.
  1424. """
  1425. if self.bitdepth == 8:
  1426. return bytes
  1427. if self.bitdepth == 16:
  1428. bytes = tostring(bytes)
  1429. return array('H',
  1430. struct.unpack('!%dH' % (len(bytes)//2), bytes))
  1431. assert self.bitdepth < 8
  1432. if width is None:
  1433. width = self.width
  1434. # Samples per byte
  1435. spb = 8//self.bitdepth
  1436. out = array('B')
  1437. mask = 2**self.bitdepth - 1
  1438. shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
  1439. l = width
  1440. for o in bytes:
  1441. out.extend([(mask&(o>>s)) for s in shifts][:l])
  1442. l -= spb
  1443. if l <= 0:
  1444. l = width
  1445. return out
  1446. def iterstraight(self, raw):
  1447. """Iterator that undoes the effect of filtering, and yields each
  1448. row in serialised format (as a sequence of bytes). Assumes input
  1449. is straightlaced. `raw` should be an iterable that yields the
  1450. raw bytes in chunks of arbitrary size."""
  1451. # length of row, in bytes
  1452. rb = self.row_bytes
  1453. a = array('B')
  1454. # The previous (reconstructed) scanline. None indicates first
  1455. # line of image.
  1456. recon = None
  1457. for some in raw:
  1458. a.extend(some)
  1459. while len(a) >= rb + 1:
  1460. filter_type = a[0]
  1461. scanline = a[1:rb+1]
  1462. del a[:rb+1]
  1463. recon = self.undo_filter(filter_type, scanline, recon)
  1464. yield recon
  1465. if len(a) != 0:
  1466. # :file:format We get here with a file format error: when the
  1467. # available bytes (after decompressing) do not pack into exact
  1468. # rows.
  1469. raise FormatError(
  1470. 'Wrong size for decompressed IDAT chunk.')
  1471. assert len(a) == 0
  1472. def validate_signature(self):
  1473. """If signature (header) has not been read then read and
  1474. validate it; otherwise do nothing.
  1475. """
  1476. if self.signature:
  1477. return
  1478. self.signature = self.file.read(8)
  1479. if self.signature != _signature:
  1480. raise FormatError("PNG file has invalid signature.")
  1481. def preamble(self, lenient=False):
  1482. """
  1483. Extract the image metadata by reading the initial part of the PNG
  1484. file up to the start of the ``IDAT`` chunk. All the chunks that
  1485. precede the ``IDAT`` chunk are read and either processed for
  1486. metadata or discarded.
  1487. If the optional `lenient` argument evaluates to True,
  1488. checksum failures will raise warnings rather than exceptions.
  1489. """
  1490. self.validate_signature()
  1491. while True:
  1492. if not self.atchunk:
  1493. self.atchunk = self.chunklentype()
  1494. if self.atchunk is None:
  1495. raise FormatError(
  1496. 'This PNG file has no IDAT chunks.')
  1497. if self.atchunk[1] == 'IDAT':
  1498. return
  1499. self.process_chunk(lenient=lenient)
  1500. def chunklentype(self):
  1501. """Reads just enough of the input to determine the next
  1502. chunk's length and type, returned as a (*length*, *type*) pair
  1503. where *type* is a string. If there are no more chunks, ``None``
  1504. is returned.
  1505. """
  1506. x = self.file.read(8)
  1507. if not x:
  1508. return None
  1509. if len(x) != 8:
  1510. raise FormatError(
  1511. 'End of file whilst reading chunk length and type.')
  1512. length,type = struct.unpack('!I4s', x)
  1513. type = bytestostr(type)
  1514. if length > 2**31-1:
  1515. raise FormatError('Chunk %s is too large: %d.' % (type,length))
  1516. return length,type
  1517. def process_chunk(self, lenient=False):
  1518. """Process the next chunk and its data. This only processes the
  1519. following chunk types, all others are ignored: ``IHDR``,
  1520. ``PLTE``, ``bKGD``, ``tRNS``, ``gAMA``, ``sBIT``.
  1521. If the optional `lenient` argument evaluates to True,
  1522. checksum failures will raise warnings rather than exceptions.
  1523. """
  1524. type, data = self.chunk(lenient=lenient)
  1525. if type == 'IHDR':
  1526. # http://www.w3.org/TR/PNG/#11IHDR
  1527. if len(data) != 13:
  1528. raise FormatError('IHDR chunk has incorrect length.')
  1529. (self.width, self.height, self.bitdepth, self.color_type,
  1530. self.compression, self.filter,
  1531. self.interlace) = struct.unpack("!2I5B", data)
  1532. # Check that the header specifies only valid combinations.
  1533. if self.bitdepth not in (1,2,4,8,16):
  1534. raise Error("invalid bit depth %d" % self.bitdepth)
  1535. if self.color_type not in (0,2,3,4,6):
  1536. raise Error("invalid colour type %d" % self.color_type)
  1537. # Check indexed (palettized) images have 8 or fewer bits
  1538. # per pixel; check only indexed or greyscale images have
  1539. # fewer than 8 bits per pixel.
  1540. if ((self.color_type & 1 and self.bitdepth > 8) or
  1541. (self.bitdepth < 8 and self.color_type not in (0,3))):
  1542. raise FormatError("Illegal combination of bit depth (%d)"
  1543. " and colour type (%d)."
  1544. " See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
  1545. % (self.bitdepth, self.color_type))
  1546. if self.compression != 0:
  1547. raise Error("unknown compression method %d" % self.compression)
  1548. if self.filter != 0:
  1549. raise FormatError("Unknown filter method %d,"
  1550. " see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ."
  1551. % self.filter)
  1552. if self.interlace not in (0,1):
  1553. raise FormatError("Unknown interlace method %d,"
  1554. " see http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods ."
  1555. % self.interlace)
  1556. # Derived values
  1557. # http://www.w3.org/TR/PNG/#6Colour-values
  1558. colormap = bool(self.color_type & 1)
  1559. greyscale = not (self.color_type & 2)
  1560. alpha = bool(self.color_type & 4)
  1561. color_planes = (3,1)[greyscale or colormap]
  1562. planes = color_planes + alpha
  1563. self.colormap = colormap
  1564. self.greyscale = greyscale
  1565. self.alpha = alpha
  1566. self.color_planes = color_planes
  1567. self.planes = planes
  1568. self.psize = float(self.bitdepth)/float(8) * planes
  1569. if int(self.psize) == self.psize:
  1570. self.psize = int(self.psize)
  1571. self.row_bytes = int(math.ceil(self.width * self.psize))
  1572. # Stores PLTE chunk if present, and is used to check
  1573. # chunk ordering constraints.
  1574. self.plte = None
  1575. # Stores tRNS chunk if present, and is used to check chunk
  1576. # ordering constraints.
  1577. self.trns = None
  1578. # Stores sbit chunk if present.
  1579. self.sbit = None
  1580. elif type == 'PLTE':
  1581. # http://www.w3.org/TR/PNG/#11PLTE
  1582. if self.plte:
  1583. warnings.warn("Multiple PLTE chunks present.")
  1584. self.plte = data
  1585. if len(data) % 3 != 0:
  1586. raise FormatError(
  1587. "PLTE chunk's length should be a multiple of 3.")
  1588. if len(data) > (2**self.bitdepth)*3:
  1589. raise FormatError("PLTE chunk is too long.")
  1590. if len(data) == 0:
  1591. raise FormatError("Empty PLTE is not allowed.")
  1592. elif type == 'bKGD':
  1593. try:
  1594. if self.colormap:
  1595. if not self.plte:
  1596. warnings.warn(
  1597. "PLTE chunk is required before bKGD chunk.")
  1598. self.background = struct.unpack('B', data)
  1599. else:
  1600. self.background = struct.unpack("!%dH" % self.color_planes,
  1601. data)
  1602. except struct.error:
  1603. raise FormatError("bKGD chunk has incorrect length.")
  1604. elif type == 'tRNS':
  1605. # http://www.w3.org/TR/PNG/#11tRNS
  1606. self.trns = data
  1607. if self.colormap:
  1608. if not self.plte:
  1609. warnings.warn("PLTE chunk is required before tRNS chunk.")
  1610. else:
  1611. if len(data) > len(self.plte)/3:
  1612. # Was warning, but promoted to Error as it
  1613. # would otherwise cause pain later on.
  1614. raise FormatError("tRNS chunk is too long.")
  1615. else:
  1616. if self.alpha:
  1617. raise FormatError(
  1618. "tRNS chunk is not valid with colour type %d." %
  1619. self.color_type)
  1620. try:
  1621. self.transparent = \
  1622. struct.unpack("!%dH" % self.color_planes, data)
  1623. except struct.error:
  1624. raise FormatError("tRNS chunk has incorrect length.")
  1625. elif type == 'gAMA':
  1626. try:
  1627. self.gamma = struct.unpack("!L", data)[0] / 100000.0
  1628. except struct.error:
  1629. raise FormatError("gAMA chunk has incorrect length.")
  1630. elif type == 'sBIT':
  1631. self.sbit = data
  1632. if (self.colormap and len(data) != 3 or
  1633. not self.colormap and len(data) != self.planes):
  1634. raise FormatError("sBIT chunk has incorrect length.")
  1635. def read(self, lenient=False):
  1636. """
  1637. Read the PNG file and decode it. Returns (`width`, `height`,
  1638. `pixels`, `metadata`).
  1639. May use excessive memory.
  1640. `pixels` are returned in boxed row flat pixel format.
  1641. If the optional `lenient` argument evaluates to True,
  1642. checksum failures will raise warnings rather than exceptions.
  1643. """
  1644. def iteridat():
  1645. """Iterator that yields all the ``IDAT`` chunks as strings."""
  1646. while True:
  1647. try:
  1648. type, data = self.chunk(lenient=lenient)
  1649. except ValueError, e:
  1650. raise ChunkError(e.args[0])
  1651. if type == 'IEND':
  1652. # http://www.w3.org/TR/PNG/#11IEND
  1653. break
  1654. if type != 'IDAT':
  1655. continue
  1656. # type == 'IDAT'
  1657. # http://www.w3.org/TR/PNG/#11IDAT
  1658. if self.colormap and not self.plte:
  1659. warnings.warn("PLTE chunk is required before IDAT chunk")
  1660. yield data
  1661. def iterdecomp(idat):
  1662. """Iterator that yields decompressed strings. `idat` should
  1663. be an iterator that yields the ``IDAT`` chunk data.
  1664. """
  1665. # Currently, with no max_length paramter to decompress, this
  1666. # routine will do one yield per IDAT chunk. So not very
  1667. # incremental.
  1668. d = zlib.decompressobj()
  1669. # Each IDAT chunk is passed to the decompressor, then any
  1670. # remaining state is decompressed out.
  1671. for data in idat:
  1672. # :todo: add a max_length argument here to limit output
  1673. # size.
  1674. yield array('B', d.decompress(data))
  1675. yield array('B', d.flush())
  1676. self.preamble(lenient=lenient)
  1677. raw = iterdecomp(iteridat())
  1678. if self.interlace:
  1679. raw = array('B', itertools.chain(*raw))
  1680. arraycode = 'BH'[self.bitdepth>8]
  1681. # Like :meth:`group` but producing an array.array object for
  1682. # each row.
  1683. pixels = itertools.imap(lambda *row: array(arraycode, row),
  1684. *[iter(self.deinterlace(raw))]*self.width*self.planes)
  1685. else:
  1686. pixels = self.iterboxed(self.iterstraight(raw))
  1687. meta = dict()
  1688. for attr in 'greyscale alpha planes bitdepth interlace'.split():
  1689. meta[attr] = getattr(self, attr)
  1690. meta['size'] = (self.width, self.height)
  1691. for attr in 'gamma transparent background'.split():
  1692. a = getattr(self, attr, None)
  1693. if a is not None:
  1694. meta[attr] = a
  1695. if self.plte:
  1696. meta['palette'] = self.palette()
  1697. return self.width, self.height, pixels, meta
  1698. def read_flat(self):
  1699. """
  1700. Read a PNG file and decode it into flat row flat pixel format.
  1701. Returns (*width*, *height*, *pixels*, *metadata*).
  1702. May use excessive memory.
  1703. `pixels` are returned in flat row flat pixel format.
  1704. See also the :meth:`read` method which returns pixels in the
  1705. more stream-friendly boxed row flat pixel format.
  1706. """
  1707. x, y, pixel, meta = self.read()
  1708. arraycode = 'BH'[meta['bitdepth']>8]
  1709. pixel = array(arraycode, itertools.chain(*pixel))
  1710. return x, y, pixel, meta
  1711. def palette(self, alpha='natural'):
  1712. """Returns a palette that is a sequence of 3-tuples or 4-tuples,
  1713. synthesizing it from the ``PLTE`` and ``tRNS`` chunks. These
  1714. chunks should have already been processed (for example, by
  1715. calling the :meth:`preamble` method). All the tuples are the
  1716. same size: 3-tuples if there is no ``tRNS`` chunk, 4-tuples when
  1717. there is a ``tRNS`` chunk. Assumes that the image is colour type
  1718. 3 and therefore a ``PLTE`` chunk is required.
  1719. If the `alpha` argument is ``'force'`` then an alpha channel is
  1720. always added, forcing the result to be a sequence of 4-tuples.
  1721. """
  1722. if not self.plte:
  1723. raise FormatError(
  1724. "Required PLTE chunk is missing in colour type 3 image.")
  1725. plte = group(array('B', self.plte), 3)
  1726. if self.trns or alpha == 'force':
  1727. trns = array('B', self.trns or '')
  1728. trns.extend([255]*(len(plte)-len(trns)))
  1729. plte = map(operator.add, plte, group(trns, 1))
  1730. return plte
  1731. def asDirect(self):
  1732. """Returns the image data as a direct representation of an
  1733. ``x * y * planes`` array. This method is intended to remove the
  1734. need for callers to deal with palettes and transparency
  1735. themselves. Images with a palette (colour type 3)
  1736. are converted to RGB or RGBA; images with transparency (a
  1737. ``tRNS`` chunk) are converted to LA or RGBA as appropriate.
  1738. When returned in this format the pixel values represent the
  1739. colour value directly without needing to refer to palettes or
  1740. transparency information.
  1741. Like the :meth:`read` method this method returns a 4-tuple:
  1742. (*width*, *height*, *pixels*, *meta*)
  1743. This method normally returns pixel values with the bit depth
  1744. they have in the source image, but when the source PNG has an
  1745. ``sBIT`` chunk it is inspected and can reduce the bit depth of
  1746. the result pixels; pixel values will be reduced according to
  1747. the bit depth specified in the ``sBIT`` chunk (PNG nerds should
  1748. note a single result bit depth is used for all channels; the
  1749. maximum of the ones specified in the ``sBIT`` chunk. An RGB565
  1750. image will be rescaled to 6-bit RGB666).
  1751. The *meta* dictionary that is returned reflects the `direct`
  1752. format and not the original source image. For example, an RGB
  1753. source image with a ``tRNS`` chunk to represent a transparent
  1754. colour, will have ``planes=3`` and ``alpha=False`` for the
  1755. source image, but the *meta* dictionary returned by this method
  1756. will have ``planes=4`` and ``alpha=True`` because an alpha
  1757. channel is synthesized and added.
  1758. *pixels* is the pixel data in boxed row flat pixel format (just
  1759. like the :meth:`read` method).
  1760. All the other aspects of the image data are not changed.
  1761. """
  1762. self.preamble()
  1763. # Simple case, no conversion necessary.
  1764. if not self.colormap and not self.trns and not self.sbit:
  1765. return self.read()
  1766. x,y,pixels,meta = self.read()
  1767. if self.colormap:
  1768. meta['colormap'] = False
  1769. meta['alpha'] = bool(self.trns)
  1770. meta['bitdepth'] = 8
  1771. meta['planes'] = 3 + bool(self.trns)
  1772. plte = self.palette()
  1773. def iterpal(pixels):
  1774. for row in pixels:
  1775. row = map(plte.__getitem__, row)
  1776. yield array('B', itertools.chain(*row))
  1777. pixels = iterpal(pixels)
  1778. elif self.trns:
  1779. # It would be nice if there was some reasonable way of doing
  1780. # this without generating a whole load of intermediate tuples.
  1781. # But tuples does seem like the easiest way, with no other way
  1782. # clearly much simpler or much faster. (Actually, the L to LA
  1783. # conversion could perhaps go faster (all those 1-tuples!), but
  1784. # I still wonder whether the code proliferation is worth it)
  1785. it = self.transparent
  1786. maxval = 2**meta['bitdepth']-1
  1787. planes = meta['planes']
  1788. meta['alpha'] = True
  1789. meta['planes'] += 1
  1790. typecode = 'BH'[meta['bitdepth']>8]
  1791. def itertrns(pixels):
  1792. for row in pixels:
  1793. # For each row we group it into pixels, then form a
  1794. # characterisation vector that says whether each pixel
  1795. # is opaque or not. Then we convert True/False to
  1796. # 0/maxval (by multiplication), and add it as the extra
  1797. # channel.
  1798. row = group(row, planes)
  1799. opa = map(it.__ne__, row)
  1800. opa = map(maxval.__mul__, opa)
  1801. opa = zip(opa) # convert to 1-tuples
  1802. yield array(typecode,
  1803. itertools.chain(*map(operator.add, row, opa)))
  1804. pixels = itertrns(pixels)
  1805. targetbitdepth = None
  1806. if self.sbit:
  1807. sbit = struct.unpack('%dB' % len(self.sbit), self.sbit)
  1808. targetbitdepth = max(sbit)
  1809. if targetbitdepth > meta['bitdepth']:
  1810. raise Error('sBIT chunk %r exceeds bitdepth %d' %
  1811. (sbit,self.bitdepth))
  1812. if min(sbit) <= 0:
  1813. raise Error('sBIT chunk %r has a 0-entry' % sbit)
  1814. if targetbitdepth == meta['bitdepth']:
  1815. targetbitdepth = None
  1816. if targetbitdepth:
  1817. shift = meta['bitdepth'] - targetbitdepth
  1818. meta['bitdepth'] = targetbitdepth
  1819. def itershift(pixels):
  1820. for row in pixels:
  1821. yield map(shift.__rrshift__, row)
  1822. pixels = itershift(pixels)
  1823. return x,y,pixels,meta
  1824. def asFloat(self, maxval=1.0):
  1825. """Return image pixels as per :meth:`asDirect` method, but scale
  1826. all pixel values to be floating point values between 0.0 and
  1827. *maxval*.
  1828. """
  1829. x,y,pixels,info = self.asDirect()
  1830. sourcemaxval = 2**info['bitdepth']-1
  1831. del info['bitdepth']
  1832. info['maxval'] = float(maxval)
  1833. factor = float(maxval)/float(sourcemaxval)
  1834. def iterfloat():
  1835. for row in pixels:
  1836. yield map(factor.__mul__, row)
  1837. return x,y,iterfloat(),info
  1838. def _as_rescale(self, get, targetbitdepth):
  1839. """Helper used by :meth:`asRGB8` and :meth:`asRGBA8`."""
  1840. width,height,pixels,meta = get()
  1841. maxval = 2**meta['bitdepth'] - 1
  1842. targetmaxval = 2**targetbitdepth - 1
  1843. factor = float(targetmaxval) / float(maxval)
  1844. meta['bitdepth'] = targetbitdepth
  1845. def iterscale():
  1846. for row in pixels:
  1847. yield map(lambda x: int(round(x*factor)), row)
  1848. if maxval == targetmaxval:
  1849. return width, height, pixels, meta
  1850. else:
  1851. return width, height, iterscale(), meta
  1852. def asRGB8(self):
  1853. """Return the image data as an RGB pixels with 8-bits per
  1854. sample. This is like the :meth:`asRGB` method except that
  1855. this method additionally rescales the values so that they
  1856. are all between 0 and 255 (8-bit). In the case where the
  1857. source image has a bit depth < 8 the transformation preserves
  1858. all the information; where the source image has bit depth
  1859. > 8, then rescaling to 8-bit values loses precision. No
  1860. dithering is performed. Like :meth:`asRGB`, an alpha channel
  1861. in the source image will raise an exception.
  1862. This function returns a 4-tuple:
  1863. (*width*, *height*, *pixels*, *metadata*).
  1864. *width*, *height*, *metadata* are as per the :meth:`read` method.
  1865. *pixels* is the pixel data in boxed row flat pixel format.
  1866. """
  1867. return self._as_rescale(self.asRGB, 8)
  1868. def asRGBA8(self):
  1869. """Return the image data as RGBA pixels with 8-bits per
  1870. sample. This method is similar to :meth:`asRGB8` and
  1871. :meth:`asRGBA`: The result pixels have an alpha channel, *and*
  1872. values are rescaled to the range 0 to 255. The alpha channel is
  1873. synthesized if necessary (with a small speed penalty).
  1874. """
  1875. return self._as_rescale(self.asRGBA, 8)
  1876. def asRGB(self):
  1877. """Return image as RGB pixels. RGB colour images are passed
  1878. through unchanged; greyscales are expanded into RGB
  1879. triplets (there is a small speed overhead for doing this).
  1880. An alpha channel in the source image will raise an
  1881. exception.
  1882. The return values are as for the :meth:`read` method
  1883. except that the *metadata* reflect the returned pixels, not the
  1884. source image. In particular, for this method
  1885. ``metadata['greyscale']`` will be ``False``.
  1886. """
  1887. width,height,pixels,meta = self.asDirect()
  1888. if meta['alpha']:
  1889. raise Error("will not convert image with alpha channel to RGB")
  1890. if not meta['greyscale']:
  1891. return width,height,pixels,meta
  1892. meta['greyscale'] = False
  1893. typecode = 'BH'[meta['bitdepth'] > 8]
  1894. def iterrgb():
  1895. for row in pixels:
  1896. a = array(typecode, [0]) * 3 * width
  1897. for i in range(3):
  1898. a[i::3] = row
  1899. yield a
  1900. return width,height,iterrgb(),meta
  1901. def asRGBA(self):
  1902. """Return image as RGBA pixels. Greyscales are expanded into
  1903. RGB triplets; an alpha channel is synthesized if necessary.
  1904. The return values are as for the :meth:`read` method
  1905. except that the *metadata* reflect the returned pixels, not the
  1906. source image. In particular, for this method
  1907. ``metadata['greyscale']`` will be ``False``, and
  1908. ``metadata['alpha']`` will be ``True``.
  1909. """
  1910. width,height,pixels,meta = self.asDirect()
  1911. if meta['alpha'] and not meta['greyscale']:
  1912. return width,height,pixels,meta
  1913. typecode = 'BH'[meta['bitdepth'] > 8]
  1914. maxval = 2**meta['bitdepth'] - 1
  1915. maxbuffer = struct.pack('=' + typecode, maxval) * 4 * width
  1916. def newarray():
  1917. return array(typecode, maxbuffer)
  1918. if meta['alpha'] and meta['greyscale']:
  1919. # LA to RGBA
  1920. def convert():
  1921. for row in pixels:
  1922. # Create a fresh target row, then copy L channel
  1923. # into first three target channels, and A channel
  1924. # into fourth channel.
  1925. a = newarray()
  1926. pngfilters.convert_la_to_rgba(row, a)
  1927. yield a
  1928. elif meta['greyscale']:
  1929. # L to RGBA
  1930. def convert():
  1931. for row in pixels:
  1932. a = newarray()
  1933. pngfilters.convert_l_to_rgba(row, a)
  1934. yield a
  1935. else:
  1936. assert not meta['alpha'] and not meta['greyscale']
  1937. # RGB to RGBA
  1938. def convert():
  1939. for row in pixels:
  1940. a = newarray()
  1941. pngfilters.convert_rgb_to_rgba(row, a)
  1942. yield a
  1943. meta['alpha'] = True
  1944. meta['greyscale'] = False
  1945. return width,height,convert(),meta
  1946. # === Legacy Version Support ===
  1947. # :pyver:old: PyPNG works on Python versions 2.3 and 2.2, but not
  1948. # without some awkward problems. Really PyPNG works on Python 2.4 (and
  1949. # above); it works on Pythons 2.3 and 2.2 by virtue of fixing up
  1950. # problems here. It's a bit ugly (which is why it's hidden down here).
  1951. #
  1952. # Generally the strategy is one of pretending that we're running on
  1953. # Python 2.4 (or above), and patching up the library support on earlier
  1954. # versions so that it looks enough like Python 2.4. When it comes to
  1955. # Python 2.2 there is one thing we cannot patch: extended slices
  1956. # http://www.python.org/doc/2.3/whatsnew/section-slices.html.
  1957. # Instead we simply declare that features that are implemented using
  1958. # extended slices will not work on Python 2.2.
  1959. #
  1960. # In order to work on Python 2.3 we fix up a recurring annoyance involving
  1961. # the array type. In Python 2.3 an array cannot be initialised with an
  1962. # array, and it cannot be extended with a list (or other sequence).
  1963. # Both of those are repeated issues in the code. Whilst I would not
  1964. # normally tolerate this sort of behaviour, here we "shim" a replacement
  1965. # for array into place (and hope no-ones notices). You never read this.
  1966. #
  1967. # In an amusing case of warty hacks on top of warty hacks... the array
  1968. # shimming we try and do only works on Python 2.3 and above (you can't
  1969. # subclass array.array in Python 2.2). So to get it working on Python
  1970. # 2.2 we go for something much simpler and (probably) way slower.
  1971. try:
  1972. array('B').extend([])
  1973. array('B', array('B'))
  1974. except:
  1975. # Expect to get here on Python 2.3
  1976. try:
  1977. class _array_shim(array):
  1978. true_array = array
  1979. def __new__(cls, typecode, init=None):
  1980. super_new = super(_array_shim, cls).__new__
  1981. it = super_new(cls, typecode)
  1982. if init is None:
  1983. return it
  1984. it.extend(init)
  1985. return it
  1986. def extend(self, extension):
  1987. super_extend = super(_array_shim, self).extend
  1988. if isinstance(extension, self.true_array):
  1989. return super_extend(extension)
  1990. if not isinstance(extension, (list, str)):
  1991. # Convert to list. Allows iterators to work.
  1992. extension = list(extension)
  1993. return super_extend(self.true_array(self.typecode, extension))
  1994. array = _array_shim
  1995. except:
  1996. # Expect to get here on Python 2.2
  1997. def array(typecode, init=()):
  1998. if type(init) == str:
  1999. return map(ord, init)
  2000. return list(init)
  2001. # Further hacks to get it limping along on Python 2.2
  2002. try:
  2003. enumerate
  2004. except:
  2005. def enumerate(seq):
  2006. i=0
  2007. for x in seq:
  2008. yield i,x
  2009. i += 1
  2010. try:
  2011. reversed
  2012. except:
  2013. def reversed(l):
  2014. l = list(l)
  2015. l.reverse()
  2016. for x in l:
  2017. yield x
  2018. try:
  2019. itertools
  2020. except:
  2021. class _dummy_itertools:
  2022. pass
  2023. itertools = _dummy_itertools()
  2024. def _itertools_imap(f, seq):
  2025. for x in seq:
  2026. yield f(x)
  2027. itertools.imap = _itertools_imap
  2028. def _itertools_chain(*iterables):
  2029. for it in iterables:
  2030. for element in it:
  2031. yield element
  2032. itertools.chain = _itertools_chain
  2033. # === Support for users without Cython ===
  2034. try:
  2035. pngfilters
  2036. except:
  2037. class pngfilters(object):
  2038. def undo_filter_sub(filter_unit, scanline, previous, result):
  2039. """Undo sub filter."""
  2040. ai = 0
  2041. # Loops starts at index fu. Observe that the initial part
  2042. # of the result is already filled in correctly with
  2043. # scanline.
  2044. for i in range(filter_unit, len(result)):
  2045. x = scanline[i]
  2046. a = result[ai]
  2047. result[i] = (x + a) & 0xff
  2048. ai += 1
  2049. undo_filter_sub = staticmethod(undo_filter_sub)
  2050. def undo_filter_up(filter_unit, scanline, previous, result):
  2051. """Undo up filter."""
  2052. for i in range(len(result)):
  2053. x = scanline[i]
  2054. b = previous[i]
  2055. result[i] = (x + b) & 0xff
  2056. undo_filter_up = staticmethod(undo_filter_up)
  2057. def undo_filter_average(filter_unit, scanline, previous, result):
  2058. """Undo up filter."""
  2059. ai = -filter_unit
  2060. for i in range(len(result)):
  2061. x = scanline[i]
  2062. if ai < 0:
  2063. a = 0
  2064. else:
  2065. a = result[ai]
  2066. b = previous[i]
  2067. result[i] = (x + ((a + b) >> 1)) & 0xff
  2068. ai += 1
  2069. undo_filter_average = staticmethod(undo_filter_average)
  2070. def undo_filter_paeth(filter_unit, scanline, previous, result):
  2071. """Undo Paeth filter."""
  2072. # Also used for ci.
  2073. ai = -filter_unit
  2074. for i in range(len(result)):
  2075. x = scanline[i]
  2076. if ai < 0:
  2077. a = c = 0
  2078. else:
  2079. a = result[ai]
  2080. c = previous[ai]
  2081. b = previous[i]
  2082. p = a + b - c
  2083. pa = abs(p - a)
  2084. pb = abs(p - b)
  2085. pc = abs(p - c)
  2086. if pa <= pb and pa <= pc:
  2087. pr = a
  2088. elif pb <= pc:
  2089. pr = b
  2090. else:
  2091. pr = c
  2092. result[i] = (x + pr) & 0xff
  2093. ai += 1
  2094. undo_filter_paeth = staticmethod(undo_filter_paeth)
  2095. def convert_la_to_rgba(row, result):
  2096. for i in range(3):
  2097. result[i::4] = row[0::2]
  2098. result[3::4] = row[1::2]
  2099. convert_la_to_rgba = staticmethod(convert_la_to_rgba)
  2100. def convert_l_to_rgba(row, result):
  2101. """Convert a grayscale image to RGBA. This method assumes the alpha
  2102. channel in result is already correctly initialized."""
  2103. for i in range(3):
  2104. result[i::4] = row
  2105. convert_l_to_rgba = staticmethod(convert_l_to_rgba)
  2106. def convert_rgb_to_rgba(row, result):
  2107. """Convert an RGB image to RGBA. This method assumes the alpha
  2108. channel in result is already correctly initialized."""
  2109. for i in range(3):
  2110. result[i::4] = row[i::3]
  2111. convert_rgb_to_rgba = staticmethod(convert_rgb_to_rgba)
  2112. # === Internal Test Support ===
  2113. # This section comprises the tests that are internally validated (as
  2114. # opposed to tests which produce output files that are externally
  2115. # validated). Primarily they are unittests.
  2116. # Note that it is difficult to internally validate the results of
  2117. # writing a PNG file. The only thing we can do is read it back in
  2118. # again, which merely checks consistency, not that the PNG file we
  2119. # produce is valid.
  2120. # Run the tests from the command line:
  2121. # python -c 'import png;png.test()'
  2122. # (For an in-memory binary file IO object) We use BytesIO where
  2123. # available, otherwise we use StringIO, but name it BytesIO.
  2124. try:
  2125. from io import BytesIO
  2126. except:
  2127. from StringIO import StringIO as BytesIO
  2128. import tempfile
  2129. # http://www.python.org/doc/2.4.4/lib/module-unittest.html
  2130. import unittest
  2131. def test():
  2132. unittest.main(__name__)
  2133. def topngbytes(name, rows, x, y, **k):
  2134. """Convenience function for creating a PNG file "in memory" as a
  2135. string. Creates a :class:`Writer` instance using the keyword arguments,
  2136. then passes `rows` to its :meth:`Writer.write` method. The resulting
  2137. PNG file is returned as a string. `name` is used to identify the file for
  2138. debugging.
  2139. """
  2140. import os
  2141. print name
  2142. f = BytesIO()
  2143. w = Writer(x, y, **k)
  2144. w.write(f, rows)
  2145. if os.environ.get('PYPNG_TEST_TMP'):
  2146. w = open(name, 'wb')
  2147. w.write(f.getvalue())
  2148. w.close()
  2149. return f.getvalue()
  2150. def testWithIO(inp, out, f):
  2151. """Calls the function `f` with ``sys.stdin`` changed to `inp`
  2152. and ``sys.stdout`` changed to `out`. They are restored when `f`
  2153. returns. This function returns whatever `f` returns.
  2154. """
  2155. import os
  2156. try:
  2157. oldin,sys.stdin = sys.stdin,inp
  2158. oldout,sys.stdout = sys.stdout,out
  2159. x = f()
  2160. finally:
  2161. sys.stdin = oldin
  2162. sys.stdout = oldout
  2163. if os.environ.get('PYPNG_TEST_TMP') and hasattr(out,'getvalue'):
  2164. name = mycallersname()
  2165. if name:
  2166. w = open(name+'.png', 'wb')
  2167. w.write(out.getvalue())
  2168. w.close()
  2169. return x
  2170. def mycallersname():
  2171. """Returns the name of the caller of the caller of this function
  2172. (hence the name of the caller of the function in which
  2173. "mycallersname()" textually appears). Returns None if this cannot
  2174. be determined."""
  2175. # http://docs.python.org/library/inspect.html#the-interpreter-stack
  2176. import inspect
  2177. frame = inspect.currentframe()
  2178. if not frame:
  2179. return None
  2180. frame_,filename_,lineno_,funname,linelist_,listi_ = (
  2181. inspect.getouterframes(frame)[2])
  2182. return funname
  2183. def seqtobytes(s):
  2184. """Convert a sequence of integers to a *bytes* instance. Good for
  2185. plastering over Python 2 / Python 3 cracks.
  2186. """
  2187. return strtobytes(''.join(chr(x) for x in s))
  2188. class Test(unittest.TestCase):
  2189. # This member is used by the superclass. If we don't define a new
  2190. # class here then when we use self.assertRaises() and the PyPNG code
  2191. # raises an assertion then we get no proper traceback. I can't work
  2192. # out why, but defining a new class here means we get a proper
  2193. # traceback.
  2194. class failureException(Exception):
  2195. pass
  2196. def helperLN(self, n):
  2197. mask = (1 << n) - 1
  2198. # Use small chunk_limit so that multiple chunk writing is
  2199. # tested. Making it a test for Issue 20.
  2200. w = Writer(15, 17, greyscale=True, bitdepth=n, chunk_limit=99)
  2201. f = BytesIO()
  2202. w.write_array(f, array('B', map(mask.__and__, range(1, 256))))
  2203. r = Reader(bytes=f.getvalue())
  2204. x,y,pixels,meta = r.read()
  2205. self.assertEqual(x, 15)
  2206. self.assertEqual(y, 17)
  2207. self.assertEqual(list(itertools.chain(*pixels)),
  2208. map(mask.__and__, range(1,256)))
  2209. def testL8(self):
  2210. return self.helperLN(8)
  2211. def testL4(self):
  2212. return self.helperLN(4)
  2213. def testL2(self):
  2214. "Also tests asRGB8."
  2215. w = Writer(1, 4, greyscale=True, bitdepth=2)
  2216. f = BytesIO()
  2217. w.write_array(f, array('B', range(4)))
  2218. r = Reader(bytes=f.getvalue())
  2219. x,y,pixels,meta = r.asRGB8()
  2220. self.assertEqual(x, 1)
  2221. self.assertEqual(y, 4)
  2222. for i,row in enumerate(pixels):
  2223. self.assertEqual(len(row), 3)
  2224. self.assertEqual(list(row), [0x55*i]*3)
  2225. def testP2(self):
  2226. "2-bit palette."
  2227. a = (255,255,255)
  2228. b = (200,120,120)
  2229. c = (50,99,50)
  2230. w = Writer(1, 4, bitdepth=2, palette=[a,b,c])
  2231. f = BytesIO()
  2232. w.write_array(f, array('B', (0,1,1,2)))
  2233. r = Reader(bytes=f.getvalue())
  2234. x,y,pixels,meta = r.asRGB8()
  2235. self.assertEqual(x, 1)
  2236. self.assertEqual(y, 4)
  2237. self.assertEqual(map(list, pixels), map(list, [a, b, b, c]))
  2238. def testPtrns(self):
  2239. "Test colour type 3 and tRNS chunk (and 4-bit palette)."
  2240. a = (50,99,50,50)
  2241. b = (200,120,120,80)
  2242. c = (255,255,255)
  2243. d = (200,120,120)
  2244. e = (50,99,50)
  2245. w = Writer(3, 3, bitdepth=4, palette=[a,b,c,d,e])
  2246. f = BytesIO()
  2247. w.write_array(f, array('B', (4, 3, 2, 3, 2, 0, 2, 0, 1)))
  2248. r = Reader(bytes=f.getvalue())
  2249. x,y,pixels,meta = r.asRGBA8()
  2250. self.assertEqual(x, 3)
  2251. self.assertEqual(y, 3)
  2252. c = c+(255,)
  2253. d = d+(255,)
  2254. e = e+(255,)
  2255. boxed = [(e,d,c),(d,c,a),(c,a,b)]
  2256. flat = map(lambda row: itertools.chain(*row), boxed)
  2257. self.assertEqual(map(list, pixels), map(list, flat))
  2258. def testRGBtoRGBA(self):
  2259. "asRGBA8() on colour type 2 source."""
  2260. # Test for Issue 26
  2261. r = Reader(bytes=_pngsuite['basn2c08'])
  2262. x,y,pixels,meta = r.asRGBA8()
  2263. # Test the pixels at row 9 columns 0 and 1.
  2264. row9 = list(pixels)[9]
  2265. self.assertEqual(list(row9[0:8]),
  2266. [0xff, 0xdf, 0xff, 0xff, 0xff, 0xde, 0xff, 0xff])
  2267. def testLtoRGBA(self):
  2268. "asRGBA() on grey source."""
  2269. # Test for Issue 60
  2270. r = Reader(bytes=_pngsuite['basi0g08'])
  2271. x,y,pixels,meta = r.asRGBA()
  2272. row9 = list(list(pixels)[9])
  2273. self.assertEqual(row9[0:8],
  2274. [222, 222, 222, 255, 221, 221, 221, 255])
  2275. def testCtrns(self):
  2276. "Test colour type 2 and tRNS chunk."
  2277. # Test for Issue 25
  2278. r = Reader(bytes=_pngsuite['tbrn2c08'])
  2279. x,y,pixels,meta = r.asRGBA8()
  2280. # I just happen to know that the first pixel is transparent.
  2281. # In particular it should be #7f7f7f00
  2282. row0 = list(pixels)[0]
  2283. self.assertEqual(tuple(row0[0:4]), (0x7f, 0x7f, 0x7f, 0x00))
  2284. def testAdam7read(self):
  2285. """Adam7 interlace reading.
  2286. Specifically, test that for images in the PngSuite that
  2287. have both an interlaced and straightlaced pair that both
  2288. images from the pair produce the same array of pixels."""
  2289. for candidate in _pngsuite:
  2290. if not candidate.startswith('basn'):
  2291. continue
  2292. candi = candidate.replace('n', 'i')
  2293. if candi not in _pngsuite:
  2294. continue
  2295. print 'adam7 read', candidate
  2296. straight = Reader(bytes=_pngsuite[candidate])
  2297. adam7 = Reader(bytes=_pngsuite[candi])
  2298. # Just compare the pixels. Ignore x,y (because they're
  2299. # likely to be correct?); metadata is ignored because the
  2300. # "interlace" member differs. Lame.
  2301. straight = straight.read()[2]
  2302. adam7 = adam7.read()[2]
  2303. self.assertEqual(map(list, straight), map(list, adam7))
  2304. def testAdam7write(self):
  2305. """Adam7 interlace writing.
  2306. For each test image in the PngSuite, write an interlaced
  2307. and a straightlaced version. Decode both, and compare results.
  2308. """
  2309. # Not such a great test, because the only way we can check what
  2310. # we have written is to read it back again.
  2311. for name,bytes in _pngsuite.items():
  2312. # Only certain colour types supported for this test.
  2313. if name[3:5] not in ['n0', 'n2', 'n4', 'n6']:
  2314. continue
  2315. it = Reader(bytes=bytes)
  2316. x,y,pixels,meta = it.read()
  2317. pngi = topngbytes('adam7wn'+name+'.png', pixels,
  2318. x=x, y=y, bitdepth=it.bitdepth,
  2319. greyscale=it.greyscale, alpha=it.alpha,
  2320. transparent=it.transparent,
  2321. interlace=False)
  2322. x,y,ps,meta = Reader(bytes=pngi).read()
  2323. it = Reader(bytes=bytes)
  2324. x,y,pixels,meta = it.read()
  2325. pngs = topngbytes('adam7wi'+name+'.png', pixels,
  2326. x=x, y=y, bitdepth=it.bitdepth,
  2327. greyscale=it.greyscale, alpha=it.alpha,
  2328. transparent=it.transparent,
  2329. interlace=True)
  2330. x,y,pi,meta = Reader(bytes=pngs).read()
  2331. self.assertEqual(map(list, ps), map(list, pi))
  2332. def testPGMin(self):
  2333. """Test that the command line tool can read PGM files."""
  2334. def do():
  2335. return _main(['testPGMin'])
  2336. s = BytesIO()
  2337. s.write(strtobytes('P5 2 2 3\n'))
  2338. s.write(strtobytes('\x00\x01\x02\x03'))
  2339. s.flush()
  2340. s.seek(0)
  2341. o = BytesIO()
  2342. testWithIO(s, o, do)
  2343. r = Reader(bytes=o.getvalue())
  2344. x,y,pixels,meta = r.read()
  2345. self.assertTrue(r.greyscale)
  2346. self.assertEqual(r.bitdepth, 2)
  2347. def testPAMin(self):
  2348. """Test that the command line tool can read PAM file."""
  2349. def do():
  2350. return _main(['testPAMin'])
  2351. s = BytesIO()
  2352. s.write(strtobytes('P7\nWIDTH 3\nHEIGHT 1\nDEPTH 4\nMAXVAL 255\n'
  2353. 'TUPLTYPE RGB_ALPHA\nENDHDR\n'))
  2354. # The pixels in flat row flat pixel format
  2355. flat = [255,0,0,255, 0,255,0,120, 0,0,255,30]
  2356. asbytes = seqtobytes(flat)
  2357. s.write(asbytes)
  2358. s.flush()
  2359. s.seek(0)
  2360. o = BytesIO()
  2361. testWithIO(s, o, do)
  2362. r = Reader(bytes=o.getvalue())
  2363. x,y,pixels,meta = r.read()
  2364. self.assertTrue(r.alpha)
  2365. self.assertTrue(not r.greyscale)
  2366. self.assertEqual(list(itertools.chain(*pixels)), flat)
  2367. def testLA4(self):
  2368. """Create an LA image with bitdepth 4."""
  2369. bytes = topngbytes('la4.png', [[5, 12]], 1, 1,
  2370. greyscale=True, alpha=True, bitdepth=4)
  2371. sbit = Reader(bytes=bytes).chunk('sBIT')[1]
  2372. self.assertEqual(sbit, strtobytes('\x04\x04'))
  2373. def testPal(self):
  2374. """Test that a palette PNG returns the palette in info."""
  2375. r = Reader(bytes=_pngsuite['basn3p04'])
  2376. x,y,pixels,info = r.read()
  2377. self.assertEqual(x, 32)
  2378. self.assertEqual(y, 32)
  2379. self.assertTrue('palette' in info)
  2380. def testPalWrite(self):
  2381. """Test metadata for paletted PNG can be passed from one PNG
  2382. to another."""
  2383. r = Reader(bytes=_pngsuite['basn3p04'])
  2384. x,y,pixels,info = r.read()
  2385. w = Writer(**info)
  2386. o = BytesIO()
  2387. w.write(o, pixels)
  2388. o.flush()
  2389. o.seek(0)
  2390. r = Reader(file=o)
  2391. _,_,_,again_info = r.read()
  2392. # Same palette
  2393. self.assertEqual(again_info['palette'], info['palette'])
  2394. def testPalExpand(self):
  2395. """Test that bitdepth can be used to fiddle with pallete image."""
  2396. r = Reader(bytes=_pngsuite['basn3p04'])
  2397. x,y,pixels,info = r.read()
  2398. pixels = [list(row) for row in pixels]
  2399. info['bitdepth'] = 8
  2400. w = Writer(**info)
  2401. o = BytesIO()
  2402. w.write(o, pixels)
  2403. o.flush()
  2404. o.seek(0)
  2405. r = Reader(file=o)
  2406. _,_,again_pixels,again_info = r.read()
  2407. # Same pixels
  2408. again_pixels = [list(row) for row in again_pixels]
  2409. self.assertEqual(again_pixels, pixels)
  2410. def testPNMsbit(self):
  2411. """Test that PNM files can generates sBIT chunk."""
  2412. def do():
  2413. return _main(['testPNMsbit'])
  2414. s = BytesIO()
  2415. s.write(strtobytes('P6 8 1 1\n'))
  2416. for pixel in range(8):
  2417. s.write(struct.pack('<I', (0x4081*pixel)&0x10101)[:3])
  2418. s.flush()
  2419. s.seek(0)
  2420. o = BytesIO()
  2421. testWithIO(s, o, do)
  2422. r = Reader(bytes=o.getvalue())
  2423. sbit = r.chunk('sBIT')[1]
  2424. self.assertEqual(sbit, strtobytes('\x01\x01\x01'))
  2425. def testLtrns0(self):
  2426. """Create greyscale image with tRNS chunk."""
  2427. return self.helperLtrns(0)
  2428. def testLtrns1(self):
  2429. """Using 1-tuple for transparent arg."""
  2430. return self.helperLtrns((0,))
  2431. def helperLtrns(self, transparent):
  2432. """Helper used by :meth:`testLtrns*`."""
  2433. pixels = zip([0x00, 0x38, 0x4c, 0x54, 0x5c, 0x40, 0x38, 0x00])
  2434. o = BytesIO()
  2435. w = Writer(8, 8, greyscale=True, bitdepth=1, transparent=transparent)
  2436. w.write_packed(o, pixels)
  2437. r = Reader(bytes=o.getvalue())
  2438. x,y,pixels,meta = r.asDirect()
  2439. self.assertTrue(meta['alpha'])
  2440. self.assertTrue(meta['greyscale'])
  2441. self.assertEqual(meta['bitdepth'], 1)
  2442. def testWinfo(self):
  2443. """Test the dictionary returned by a `read` method can be used
  2444. as args for :meth:`Writer`.
  2445. """
  2446. r = Reader(bytes=_pngsuite['basn2c16'])
  2447. info = r.read()[3]
  2448. w = Writer(**info)
  2449. def testPackedIter(self):
  2450. """Test iterator for row when using write_packed.
  2451. Indicative for Issue 47.
  2452. """
  2453. w = Writer(16, 2, greyscale=True, alpha=False, bitdepth=1)
  2454. o = BytesIO()
  2455. w.write_packed(o, [itertools.chain([0x0a], [0xaa]),
  2456. itertools.chain([0x0f], [0xff])])
  2457. r = Reader(bytes=o.getvalue())
  2458. x,y,pixels,info = r.asDirect()
  2459. pixels = list(pixels)
  2460. self.assertEqual(len(pixels), 2)
  2461. self.assertEqual(len(pixels[0]), 16)
  2462. def testInterlacedArray(self):
  2463. """Test that reading an interlaced PNG yields each row as an
  2464. array."""
  2465. r = Reader(bytes=_pngsuite['basi0g08'])
  2466. list(r.read()[2])[0].tostring
  2467. def testTrnsArray(self):
  2468. """Test that reading a type 2 PNG with tRNS chunk yields each
  2469. row as an array (using asDirect)."""
  2470. r = Reader(bytes=_pngsuite['tbrn2c08'])
  2471. list(r.asDirect()[2])[0].tostring
  2472. # Invalid file format tests. These construct various badly
  2473. # formatted PNG files, then feed them into a Reader. When
  2474. # everything is working properly, we should get FormatError
  2475. # exceptions raised.
  2476. def testEmpty(self):
  2477. """Test empty file."""
  2478. r = Reader(bytes='')
  2479. self.assertRaises(FormatError, r.asDirect)
  2480. def testSigOnly(self):
  2481. """Test file containing just signature bytes."""
  2482. r = Reader(bytes=_signature)
  2483. self.assertRaises(FormatError, r.asDirect)
  2484. def testExtraPixels(self):
  2485. """Test file that contains too many pixels."""
  2486. def eachchunk(chunk):
  2487. if chunk[0] != 'IDAT':
  2488. return chunk
  2489. data = zlib.decompress(chunk[1])
  2490. data += strtobytes('\x00garbage')
  2491. data = zlib.compress(data)
  2492. chunk = (chunk[0], data)
  2493. return chunk
  2494. self.assertRaises(FormatError, self.helperFormat, eachchunk)
  2495. def testNotEnoughPixels(self):
  2496. def eachchunk(chunk):
  2497. if chunk[0] != 'IDAT':
  2498. return chunk
  2499. # Remove last byte.
  2500. data = zlib.decompress(chunk[1])
  2501. data = data[:-1]
  2502. data = zlib.compress(data)
  2503. return (chunk[0], data)
  2504. self.assertRaises(FormatError, self.helperFormat, eachchunk)
  2505. def helperFormat(self, f):
  2506. r = Reader(bytes=_pngsuite['basn0g01'])
  2507. o = BytesIO()
  2508. def newchunks():
  2509. for chunk in r.chunks():
  2510. yield f(chunk)
  2511. write_chunks(o, newchunks())
  2512. r = Reader(bytes=o.getvalue())
  2513. return list(r.asDirect()[2])
  2514. def testBadFilter(self):
  2515. def eachchunk(chunk):
  2516. if chunk[0] != 'IDAT':
  2517. return chunk
  2518. data = zlib.decompress(chunk[1])
  2519. # Corrupt the first filter byte
  2520. data = strtobytes('\x99') + data[1:]
  2521. data = zlib.compress(data)
  2522. return (chunk[0], data)
  2523. self.assertRaises(FormatError, self.helperFormat, eachchunk)
  2524. def testFlat(self):
  2525. """Test read_flat."""
  2526. import hashlib
  2527. r = Reader(bytes=_pngsuite['basn0g02'])
  2528. x,y,pixel,meta = r.read_flat()
  2529. d = hashlib.md5(seqtobytes(pixel)).digest()
  2530. self.assertEqual(_enhex(d), '255cd971ab8cd9e7275ff906e5041aa0')
  2531. def testfromarray(self):
  2532. img = from_array([[0, 0x33, 0x66], [0xff, 0xcc, 0x99]], 'L')
  2533. img.save('testfromarray.png')
  2534. def testfromarrayL16(self):
  2535. img = from_array(group(range(2**16), 256), 'L;16')
  2536. img.save('testL16.png')
  2537. def testfromarrayRGB(self):
  2538. img = from_array([[0,0,0, 0,0,1, 0,1,0, 0,1,1],
  2539. [1,0,0, 1,0,1, 1,1,0, 1,1,1]], 'RGB;1')
  2540. o = BytesIO()
  2541. img.save(o)
  2542. def testfromarrayIter(self):
  2543. import itertools
  2544. i = itertools.islice(itertools.count(10), 20)
  2545. i = itertools.imap(lambda x: [x, x, x], i)
  2546. img = from_array(i, 'RGB;5', dict(height=20))
  2547. f = open('testiter.png', 'wb')
  2548. img.save(f)
  2549. f.close()
  2550. # numpy dependent tests. These are skipped (with a message to
  2551. # sys.stderr) if numpy cannot be imported.
  2552. def testNumpyuint16(self):
  2553. """numpy uint16."""
  2554. try:
  2555. import numpy
  2556. except ImportError:
  2557. print >>sys.stderr, "skipping numpy test"
  2558. return
  2559. rows = [map(numpy.uint16, range(0,0x10000,0x5555))]
  2560. b = topngbytes('numpyuint16.png', rows, 4, 1,
  2561. greyscale=True, alpha=False, bitdepth=16)
  2562. def testNumpyuint8(self):
  2563. """numpy uint8."""
  2564. try:
  2565. import numpy
  2566. except ImportError:
  2567. print >>sys.stderr, "skipping numpy test"
  2568. return
  2569. rows = [map(numpy.uint8, range(0,0x100,0x55))]
  2570. b = topngbytes('numpyuint8.png', rows, 4, 1,
  2571. greyscale=True, alpha=False, bitdepth=8)
  2572. def testNumpybool(self):
  2573. """numpy bool."""
  2574. try:
  2575. import numpy
  2576. except ImportError:
  2577. print >>sys.stderr, "skipping numpy test"
  2578. return
  2579. rows = [map(numpy.bool, [0,1])]
  2580. b = topngbytes('numpybool.png', rows, 2, 1,
  2581. greyscale=True, alpha=False, bitdepth=1)
  2582. def testNumpyarray(self):
  2583. """numpy array."""
  2584. try:
  2585. import numpy
  2586. except ImportError:
  2587. print >>sys.stderr, "skipping numpy test"
  2588. return
  2589. pixels = numpy.array([[0,0x5555],[0x5555,0xaaaa]], numpy.uint16)
  2590. img = from_array(pixels, 'L')
  2591. img.save('testnumpyL16.png')
  2592. def paeth(self, x, a, b, c):
  2593. p = a + b - c
  2594. pa = abs(p - a)
  2595. pb = abs(p - b)
  2596. pc = abs(p - c)
  2597. if pa <= pb and pa <= pc:
  2598. pr = a
  2599. elif pb <= pc:
  2600. pr = b
  2601. else:
  2602. pr = c
  2603. return x - pr
  2604. # test filters and unfilters
  2605. def testFilterScanlineFirstLine(self):
  2606. fo = 3 # bytes per pixel
  2607. line = [30, 31, 32, 230, 231, 232]
  2608. out = filter_scanline(0, line, fo, None) # none
  2609. self.assertEqual(list(out), [0, 30, 31, 32, 230, 231, 232])
  2610. out = filter_scanline(1, line, fo, None) # sub
  2611. self.assertEqual(list(out), [1, 30, 31, 32, 200, 200, 200])
  2612. out = filter_scanline(2, line, fo, None) # up
  2613. # TODO: All filtered scanlines start with a byte indicating the filter
  2614. # algorithm, except "up". Is this a bug? Should the expected output
  2615. # start with 2 here?
  2616. self.assertEqual(list(out), [30, 31, 32, 230, 231, 232])
  2617. out = filter_scanline(3, line, fo, None) # average
  2618. self.assertEqual(list(out), [3, 30, 31, 32, 215, 216, 216])
  2619. out = filter_scanline(4, line, fo, None) # paeth
  2620. self.assertEqual(list(out), [
  2621. 4, self.paeth(30, 0, 0, 0), self.paeth(31, 0, 0, 0),
  2622. self.paeth(32, 0, 0, 0), self.paeth(230, 30, 0, 0),
  2623. self.paeth(231, 31, 0, 0), self.paeth(232, 32, 0, 0)
  2624. ])
  2625. def testFilterScanline(self):
  2626. prev = [20, 21, 22, 210, 211, 212]
  2627. line = [30, 32, 34, 230, 233, 236]
  2628. fo = 3
  2629. out = filter_scanline(0, line, fo, prev) # none
  2630. self.assertEqual(list(out), [0, 30, 32, 34, 230, 233, 236])
  2631. out = filter_scanline(1, line, fo, prev) # sub
  2632. self.assertEqual(list(out), [1, 30, 32, 34, 200, 201, 202])
  2633. out = filter_scanline(2, line, fo, prev) # up
  2634. self.assertEqual(list(out), [2, 10, 11, 12, 20, 22, 24])
  2635. out = filter_scanline(3, line, fo, prev) # average
  2636. self.assertEqual(list(out), [3, 20, 22, 23, 110, 112, 113])
  2637. out = filter_scanline(4, line, fo, prev) # paeth
  2638. self.assertEqual(list(out), [
  2639. 4, self.paeth(30, 0, 20, 0), self.paeth(32, 0, 21, 0),
  2640. self.paeth(34, 0, 22, 0), self.paeth(230, 30, 210, 20),
  2641. self.paeth(233, 32, 211, 21), self.paeth(236, 34, 212, 22)
  2642. ])
  2643. def testUnfilterScanline(self):
  2644. reader = Reader(bytes='')
  2645. reader.psize = 3
  2646. scanprev = array('B', [20, 21, 22, 210, 211, 212])
  2647. scanline = array('B', [30, 32, 34, 230, 233, 236])
  2648. def cp(a):
  2649. return array('B', a)
  2650. out = reader.undo_filter(0, cp(scanline), cp(scanprev))
  2651. self.assertEqual(list(out), list(scanline)) # none
  2652. out = reader.undo_filter(1, cp(scanline), cp(scanprev))
  2653. self.assertEqual(list(out), [30, 32, 34, 4, 9, 14]) # sub
  2654. out = reader.undo_filter(2, cp(scanline), cp(scanprev))
  2655. self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # up
  2656. out = reader.undo_filter(3, cp(scanline), cp(scanprev))
  2657. self.assertEqual(list(out), [40, 42, 45, 99, 103, 108]) # average
  2658. out = reader.undo_filter(4, cp(scanline), cp(scanprev))
  2659. self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # paeth
  2660. def testUnfilterScanlinePaeth(self):
  2661. # This tests more edge cases in the paeth unfilter
  2662. reader = Reader(bytes='')
  2663. reader.psize = 3
  2664. scanprev = array('B', [2, 0, 0, 0, 9, 11])
  2665. scanline = array('B', [6, 10, 9, 100, 101, 102])
  2666. out = reader.undo_filter(4, scanline, scanprev)
  2667. self.assertEqual(list(out), [8, 10, 9, 108, 111, 113]) # paeth
  2668. def testIterstraight(self):
  2669. def arraify(list_of_str):
  2670. return [array('B', s) for s in list_of_str]
  2671. reader = Reader(bytes='')
  2672. reader.row_bytes = 6
  2673. reader.psize = 3
  2674. rows = reader.iterstraight(arraify(['\x00abcdef', '\x00ghijkl']))
  2675. self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
  2676. rows = reader.iterstraight(arraify(['\x00abc', 'def\x00ghijkl']))
  2677. self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
  2678. rows = reader.iterstraight(arraify(['\x00abcdef\x00ghijkl']))
  2679. self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
  2680. rows = reader.iterstraight(arraify(['\x00abcdef\x00ghi', 'jkl']))
  2681. self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
  2682. # === Command Line Support ===
  2683. def _dehex(s):
  2684. """Liberally convert from hex string to binary string."""
  2685. import re
  2686. import binascii
  2687. # Remove all non-hexadecimal digits
  2688. s = re.sub(r'[^a-fA-F\d]', '', s)
  2689. # binscii.unhexlify works in Python 2 and Python 3 (unlike
  2690. # thing.decode('hex')).
  2691. return binascii.unhexlify(strtobytes(s))
  2692. def _enhex(s):
  2693. """Convert from binary string (bytes) to hex string (str)."""
  2694. import binascii
  2695. return bytestostr(binascii.hexlify(s))
  2696. # Copies of PngSuite test files taken
  2697. # from http://www.schaik.com/pngsuite/pngsuite_bas_png.html
  2698. # on 2009-02-19 by drj and converted to hex.
  2699. # Some of these are not actually in PngSuite (but maybe they should
  2700. # be?), they use the same naming scheme, but start with a capital
  2701. # letter.
  2702. _pngsuite = {
  2703. 'basi0g01': _dehex("""
  2704. 89504e470d0a1a0a0000000d49484452000000200000002001000000012c0677
  2705. cf0000000467414d41000186a031e8965f0000009049444154789c2d8d310ec2
  2706. 300c45dfc682c415187a00a42e197ab81e83b127e00c5639001363a580d8582c
  2707. 65c910357c4b78b0bfbfdf4f70168c19e7acb970a3f2d1ded9695ce5bf5963df
  2708. d92aaf4c9fd927ea449e6487df5b9c36e799b91bdf082b4d4bd4014fe4014b01
  2709. ab7a17aee694d28d328a2d63837a70451e1648702d9a9ff4a11d2f7a51aa21e5
  2710. a18c7ffd0094e3511d661822f20000000049454e44ae426082
  2711. """),
  2712. 'basi0g02': _dehex("""
  2713. 89504e470d0a1a0a0000000d49484452000000200000002002000000016ba60d
  2714. 1f0000000467414d41000186a031e8965f0000005149444154789c635062e860
  2715. 00e17286bb609c93c370ec189494960631366e4467b3ae675dcf10f521ea0303
  2716. 90c1ca006444e11643482064114a4852c710baea3f18c31918020c30410403a6
  2717. 0ac1a09239009c52804d85b6d97d0000000049454e44ae426082
  2718. """),
  2719. 'basi0g04': _dehex("""
  2720. 89504e470d0a1a0a0000000d4948445200000020000000200400000001e4e6f8
  2721. bf0000000467414d41000186a031e8965f000000ae49444154789c658e5111c2
  2722. 301044171c141c141c041c843a287510ea20d441c041c141c141c04191102454
  2723. 03994998cecd7edcecedbb9bdbc3b2c2b6457545fbc4bac1be437347f7c66a77
  2724. 3c23d60db15e88f5c5627338a5416c2e691a9b475a89cd27eda12895ae8dfdab
  2725. 43d61e590764f5c83a226b40d669bec307f93247701687723abf31ff83a2284b
  2726. a5b4ae6b63ac6520ad730ca4ed7b06d20e030369bd6720ed383290360406d24e
  2727. 13811f2781eba9d34d07160000000049454e44ae426082
  2728. """),
  2729. 'basi0g08': _dehex("""
  2730. 89504e470d0a1a0a0000000d4948445200000020000000200800000001211615
  2731. be0000000467414d41000186a031e8965f000000b549444154789cb5905d0ac2
  2732. 3010849dbac81c42c47bf843cf253e8878b0aa17110f214bdca6be240f5d21a5
  2733. 94ced3e49bcd322c1624115515154998aa424822a82a5624a1aa8a8b24c58f99
  2734. 999908130989a04a00d76c2c09e76cf21adcb209393a6553577da17140a2c59e
  2735. 70ecbfa388dff1f03b82fb82bd07f05f7cb13f80bb07ad2fd60c011c3c588eef
  2736. f1f4e03bbec7ce832dca927aea005e431b625796345307b019c845e6bfc3bb98
  2737. 769d84f9efb02ea6c00f9bb9ff45e81f9f280000000049454e44ae426082
  2738. """),
  2739. 'basi0g16': _dehex("""
  2740. 89504e470d0a1a0a0000000d49484452000000200000002010000000017186c9
  2741. fd0000000467414d41000186a031e8965f000000e249444154789cb5913b0ec2
  2742. 301044c7490aa8f85d81c3e4301c8f53a4ca0da8902c8144b3920b4043111282
  2743. 23bc4956681a6bf5fc3c5a3ba0448912d91a4de2c38dd8e380231eede4c4f7a1
  2744. 4677700bec7bd9b1d344689315a3418d1a6efbe5b8305ba01f8ff4808c063e26
  2745. c60d5c81edcf6c58c535e252839e93801b15c0a70d810ae0d306b205dc32b187
  2746. 272b64057e4720ff0502154034831520154034c3df81400510cdf0015c86e5cc
  2747. 5c79c639fddba9dcb5456b51d7980eb52d8e7d7fa620a75120d6064641a05120
  2748. b606771a05626b401a05f1f589827cf0fe44c1f0bae0055698ee8914fffffe00
  2749. 00000049454e44ae426082
  2750. """),
  2751. 'basi2c08': _dehex("""
  2752. 89504e470d0a1a0a0000000d49484452000000200000002008020000018b1fdd
  2753. 350000000467414d41000186a031e8965f000000f249444154789cd59341aa04
  2754. 210c44abc07b78133d59d37333bd89d76868b566d10cf4675af8596431a11662
  2755. 7c5688919280e312257dd6a0a4cf1a01008ee312a5f3c69c37e6fcc3f47e6776
  2756. a07f8bdaf5b40feed2d33e025e2ff4fe2d4a63e1a16d91180b736d8bc45854c5
  2757. 6d951863f4a7e0b66dcf09a900f3ffa2948d4091e53ca86c048a64390f662b50
  2758. 4a999660ced906182b9a01a8be00a56404a6ede182b1223b4025e32c4de34304
  2759. 63457680c93aada6c99b73865aab2fc094920d901a203f5ddfe1970d28456783
  2760. 26cffbafeffcd30654f46d119be4793f827387fc0d189d5bc4d69a3c23d45a7f
  2761. db803146578337df4d0a3121fc3d330000000049454e44ae426082
  2762. """),
  2763. 'basi2c16': _dehex("""
  2764. 89504e470d0a1a0a0000000d4948445200000020000000201002000001db8f01
  2765. 760000000467414d41000186a031e8965f0000020a49444154789cd5962173e3
  2766. 3010853fcf1838cc61a1818185a53e56787fa13fa130852e3b5878b4b0b03081
  2767. b97f7030070b53e6b057a0a8912bbb9163b9f109ececbc59bd7dcf2b45492409
  2768. d66f00eb1dd83cb5497d65456aeb8e1040913b3b2c04504c936dd5a9c7e2c6eb
  2769. b1b8f17a58e8d043da56f06f0f9f62e5217b6ba3a1b76f6c9e99e8696a2a72e2
  2770. c4fb1e4d452e92ec9652b807486d12b6669be00db38d9114b0c1961e375461a5
  2771. 5f76682a85c367ad6f682ff53a9c2a353191764b78bb07d8ddc3c97c1950f391
  2772. 6745c7b9852c73c2f212605a466a502705c8338069c8b9e84efab941eb393a97
  2773. d4c9fd63148314209f1c1d3434e847ead6380de291d6f26a25c1ebb5047f5f24
  2774. d85c49f0f22cc1d34282c72709cab90477bf25b89d49f0f351822297e0ea9704
  2775. f34c82bc94002448ede51866e5656aef5d7c6a385cb4d80e6a538ceba04e6df2
  2776. 480e9aa84ddedb413bb5c97b3838456df2d4fec2c7a706983e7474d085fae820
  2777. a841776a83073838973ac0413fea2f1dc4a06e71108fda73109bdae48954ad60
  2778. bf867aac3ce44c7c1589a711cf8a81df9b219679d96d1cec3d8bbbeaa2012626
  2779. df8c7802eda201b2d2e0239b409868171fc104ba8b76f10b4da09f6817ffc609
  2780. c413ede267fd1fbab46880c90f80eccf0013185eb48b47ba03df2bdaadef3181
  2781. cb8976f18e13188768170f98c0f844bb78cb04c62ddac59d09fc3fa25dfc1da4
  2782. 14deb3df1344f70000000049454e44ae426082
  2783. """),
  2784. 'basi3p08': _dehex("""
  2785. 89504e470d0a1a0a0000000d494844520000002000000020080300000133a3ba
  2786. 500000000467414d41000186a031e8965f00000300504c5445224400f5ffed77
  2787. ff77cbffff110a003a77002222ffff11ff110000222200ffac5566ff66ff6666
  2788. ff01ff221200dcffffccff994444ff005555220000cbcbff44440055ff55cbcb
  2789. 00331a00ffecdcedffffe4ffcbffdcdc44ff446666ff330000442200ededff66
  2790. 6600ffa444ffffaaeded0000cbcbfefffffdfffeffff0133ff33552a000101ff
  2791. 8888ff00aaaa010100440000888800ffe4cbba5b0022ff22663200ffff99aaaa
  2792. ff550000aaaa00cb630011ff11d4ffaa773a00ff4444dc6b0066000001ff0188
  2793. 4200ecffdc6bdc00ffdcba00333300ed00ed7300ffff88994a0011ffff770000
  2794. ff8301ffbabafe7b00fffeff00cb00ff999922ffff880000ffff77008888ffdc
  2795. ff1a33000000aa33ffff009900990000000001326600ffbaff44ffffffaaff00
  2796. 770000fefeaa00004a9900ffff66ff22220000998bff1155ffffff0101ff88ff
  2797. 005500001111fffffefffdfea4ff4466ffffff66ff003300ffff55ff77770000
  2798. 88ff44ff00110077ffff006666ffffed000100fff5ed1111ffffff44ff22ffff
  2799. eded11110088ffff00007793ff2200dcdc3333fffe00febabaff99ffff333300
  2800. 63cb00baba00acff55ffffdcffff337bfe00ed00ed5555ffaaffffdcdcff5555
  2801. 00000066dcdc00dc00dc83ff017777fffefeffffffcbff5555777700fefe00cb
  2802. 00cb0000fe010200010000122200ffff220044449bff33ffd4aa0000559999ff
  2803. 999900ba00ba2a5500ffcbcbb4ff66ff9b33ffffbaaa00aa42880053aa00ffaa
  2804. aa0000ed00babaffff1100fe00000044009999990099ffcc99ba000088008800
  2805. dc00ff93220000dcfefffeaa5300770077020100cb0000000033ffedff00ba00
  2806. ff3333edffedffc488bcff7700aa00660066002222dc0000ffcbffdcffdcff8b
  2807. 110000cb00010155005500880000002201ffffcbffcbed0000ff88884400445b
  2808. ba00ffbc77ff99ff006600baffba00777773ed00fe00003300330000baff77ff
  2809. 004400aaffaafffefe000011220022c4ff8800eded99ff99ff55ff002200ffb4
  2810. 661100110a1100ff1111dcffbabaffff88ff88010001ff33ffb98ed362000002
  2811. a249444154789c65d0695c0b001806f03711a9904a94d24dac63292949e5a810
  2812. d244588a14ca5161d1a1323973252242d62157d12ae498c8124d25ca3a11398a
  2813. 16e55a3cdffab0ffe7f77d7fcff3528645349b584c3187824d9d19d4ec2e3523
  2814. 9eb0ae975cf8de02f2486d502191841b42967a1ad49e5ddc4265f69a899e26b5
  2815. e9e468181baae3a71a41b95669da8df2ea3594c1b31046d7b17bfb86592e4cbe
  2816. d89b23e8db0af6304d756e60a8f4ad378bdc2552ae5948df1d35b52143141533
  2817. 33bbbbababebeb3b3bc9c9c9c6c6c0c0d7b7b535323225a5aa8a02024a4bedec
  2818. 0a0a2a2bcdcd7d7cf2f3a9a9c9cdcdd8b8adcdd5b5ababa828298982824a4ab2
  2819. b21212acadbdbc1414e2e24859b9a72730302f4f49292c4c57373c9c0a0b7372
  2820. 8c8c1c1c3a3a92936d6dfdfd293e3e26262a4a4eaea2424b4b5fbfbc9c323278
  2821. 3c0b0ba1303abaae8ecdeeed950d6669a9a7a7a141d4de9e9d5d5cdcd2229b94
  2822. c572716132f97cb1d8db9bc3110864a39795d9db6b6a26267a7a9a98d4d6a6a7
  2823. cb76090ef6f030354d4d75766e686030545464cb393a1a1ac6c68686eae8f8f9
  2824. a9aa4644c8b66d6e1689dcdd2512a994cb35330b0991ad9f9b6b659596a6addd
  2825. d8282fafae5e5323fb8f41d01f76c22fd8061be01bfc041a0323e1002c81cd30
  2826. 0b9ec027a0c930014ec035580fc3e112bc069a0b53e11c0c8095f00176c163a0
  2827. e5301baec06a580677600ddc05ba0f13e120bc81a770133ec355a017300d4ec2
  2828. 0c7800bbe1219c02fa08f3e13c1c85dbb00a2ec05ea0dff00a6ec15a98027360
  2829. 070c047a06d7e1085c84f1b014f6c03fa0b33018b6c0211801ebe018fc00da0a
  2830. 6f61113c877eb01d4ec317a085700f26c130f80efbe132bc039a0733e106fc81
  2831. f7f017f6c10aa0d1300a0ec374780943e1382c06fa0a9b60238c83473016cec0
  2832. 02f80f73fefe1072afc1e50000000049454e44ae426082
  2833. """),
  2834. 'basi6a08': _dehex("""
  2835. 89504e470d0a1a0a0000000d4948445200000020000000200806000001047d4a
  2836. 620000000467414d41000186a031e8965f0000012049444154789cc595414ec3
  2837. 3010459fa541b8bbb26641b8069b861e8b4d12c1c112c1452a710a2a65d840d5
  2838. 949041fc481ec98ae27c7f3f8d27e3e4648047600fec0d1f390fbbe2633a31e2
  2839. 9389e4e4ea7bfdbf3d9a6b800ab89f1bd6b553cfcbb0679e960563d72e0a9293
  2840. b7337b9f988cc67f5f0e186d20e808042f1c97054e1309da40d02d7e27f92e03
  2841. 6cbfc64df0fc3117a6210a1b6ad1a00df21c1abcf2a01944c7101b0cb568a001
  2842. 909c9cf9e399cf3d8d9d4660a875405d9a60d000b05e2de55e25780b7a5268e0
  2843. 622118e2399aab063a815808462f1ab86890fc2e03e48bb109ded7d26ce4bf59
  2844. 0db91bac0050747fec5015ce80da0e5700281be533f0ce6d5900b59bcb00ea6d
  2845. 200314cf801faab200ea752803a8d7a90c503a039f824a53f4694e7342000000
  2846. 0049454e44ae426082
  2847. """),
  2848. 'basn0g01': _dehex("""
  2849. 89504e470d0a1a0a0000000d49484452000000200000002001000000005b0147
  2850. 590000000467414d41000186a031e8965f0000005b49444154789c2dccb10903
  2851. 300c05d1ebd204b24a200b7a346f90153c82c18d0a61450751f1e08a2faaead2
  2852. a4846ccea9255306e753345712e211b221bf4b263d1b427325255e8bdab29e6f
  2853. 6aca30692e9d29616ee96f3065f0bf1f1087492fd02f14c90000000049454e44
  2854. ae426082
  2855. """),
  2856. 'basn0g02': _dehex("""
  2857. 89504e470d0a1a0a0000000d49484452000000200000002002000000001ca13d
  2858. 890000000467414d41000186a031e8965f0000001f49444154789c6360085df5
  2859. 1f8cf1308850c20053868f0133091f6390b90700bd497f818b0989a900000000
  2860. 49454e44ae426082
  2861. """),
  2862. # A version of basn0g04 dithered down to 3 bits.
  2863. 'Basn0g03': _dehex("""
  2864. 89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
  2865. 2900000001734249540371d88211000000fd49444154789c6d90d18906210c84
  2866. c356f22356b2889588604301b112112b11d94a96bb495cf7fe87f32d996f2689
  2867. 44741cc658e39c0b118f883e1f63cc89dafbc04c0f619d7d898396c54b875517
  2868. 83f3a2e7ac09a2074430e7f497f00f1138a5444f82839c5206b1f51053cca968
  2869. 63258821e7f2b5438aac16fbecc052b646e709de45cf18996b29648508728612
  2870. 952ca606a73566d44612b876845e9a347084ea4868d2907ff06be4436c4b41a3
  2871. a3e1774285614c5affb40dbd931a526619d9fa18e4c2be420858de1df0e69893
  2872. a0e3e5523461be448561001042b7d4a15309ce2c57aef2ba89d1c13794a109d7
  2873. b5880aa27744fc5c4aecb5e7bcef5fe528ec6293a930690000000049454e44ae
  2874. 426082
  2875. """),
  2876. 'basn0g04': _dehex("""
  2877. 89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
  2878. 290000000467414d41000186a031e8965f0000004849444154789c6360601014
  2879. 545232367671090d4d4b2b2f6720430095dbd1418e002a77e64c720450b9ab56
  2880. 912380caddbd9b1c0154ee9933e408a072efde25470095fbee1d1902001f14ee
  2881. 01eaff41fa0000000049454e44ae426082
  2882. """),
  2883. 'basn0g08': _dehex("""
  2884. 89504e470d0a1a0a0000000d4948445200000020000000200800000000561125
  2885. 280000000467414d41000186a031e8965f0000004149444154789c6364602400
  2886. 1408c8b30c05058c0f0829f8f71f3f6079301c1430ca11906764a2795c0c0605
  2887. 8c8ff0cafeffcff887e67131181430cae0956564040050e5fe7135e2d8590000
  2888. 000049454e44ae426082
  2889. """),
  2890. 'basn0g16': _dehex("""
  2891. 89504e470d0a1a0a0000000d49484452000000200000002010000000000681f9
  2892. 6b0000000467414d41000186a031e8965f0000005e49444154789cd5d2310ac0
  2893. 300c4351395bef7fc6dca093c0287b32d52a04a3d98f3f3880a7b857131363a0
  2894. 3a82601d089900dd82f640ca04e816dc06422640b7a03d903201ba05b7819009
  2895. d02d680fa44c603f6f07ec4ff41938cf7f0016d84bd85fae2b9fd70000000049
  2896. 454e44ae426082
  2897. """),
  2898. 'basn2c08': _dehex("""
  2899. 89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
  2900. a30000000467414d41000186a031e8965f0000004849444154789cedd5c10900
  2901. 300c024085ec91fdb772133b442bf4a1f8cee12bb40d043b800a14f81ca0ede4
  2902. 7d4c784081020f4a871fc284071428f0a0743823a94081bb7077a3c00182b1f9
  2903. 5e0f40cf4b0000000049454e44ae426082
  2904. """),
  2905. 'basn2c16': _dehex("""
  2906. 89504e470d0a1a0a0000000d4948445200000020000000201002000000ac8831
  2907. e00000000467414d41000186a031e8965f000000e549444154789cd596c10a83
  2908. 301044a7e0417fcb7eb7fdadf6961e06039286266693cc7a188645e43dd6a08f
  2909. 1042003e2fe09aef6472737e183d27335fcee2f35a77b702ebce742870a23397
  2910. f3edf2705dd10160f3b2815fe8ecf2027974a6b0c03f74a6e4192843e75c6c03
  2911. 35e8ec3202f5e84c0181bbe8cca967a00d9df3491bb040671f2e6087ce1c2860
  2912. 8d1e05f8c7ee0f1d00b667e70df44467ef26d01fbd9bc028f42860f71d188bce
  2913. fb8d3630039dbd59601e7ab3c06cf428507f0634d039afdc80123a7bb1801e7a
  2914. b1802a7a14c89f016d74ce331bf080ce9e08f8414f04bca133bfe642fe5e07bb
  2915. c4ec0000000049454e44ae426082
  2916. """),
  2917. 'basn3p04': _dehex("""
  2918. 89504e470d0a1a0a0000000d4948445200000020000000200403000000815467
  2919. c70000000467414d41000186a031e8965f000000037342495404040477f8b5a3
  2920. 0000002d504c54452200ff00ffff8800ff22ff000099ffff6600dd00ff77ff00
  2921. ff000000ff99ddff00ff00bbffbb000044ff00ff44d2b049bd00000047494441
  2922. 54789c63e8e8080d3d7366d5aaf27263e377ef66ce64204300952b28488e002a
  2923. d7c5851c0154eeddbbe408a07119c81140e52a29912380ca4d4b23470095bb7b
  2924. 37190200e0c4ead10f82057d0000000049454e44ae426082
  2925. """),
  2926. 'basn6a08': _dehex("""
  2927. 89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7a
  2928. f40000000467414d41000186a031e8965f0000006f49444154789cedd6310a80
  2929. 300c46e12764684fa1f73f55048f21c4ddc545781d52e85028fc1f4d28d98a01
  2930. 305e7b7e9cffba33831d75054703ca06a8f90d58a0074e351e227d805c8254e3
  2931. 1bb0420f5cdc2e0079208892ffe2a00136a07b4007943c1004d900195036407f
  2932. 011bf00052201a9c160fb84c0000000049454e44ae426082
  2933. """),
  2934. 'cs3n3p08': _dehex("""
  2935. 89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
  2936. c60000000467414d41000186a031e8965f0000000373424954030303a392a042
  2937. 00000054504c544592ff0000ff9200ffff00ff0000dbff00ff6dffb600006dff
  2938. b6ff00ff9200dbff000049ffff2400ff000024ff0049ff0000ffdb00ff4900ff
  2939. b6ffff0000ff2400b6ffffdb000092ffff6d000024ffff49006dff00df702b17
  2940. 0000004b49444154789c85cac70182000000b1b3625754b0edbfa72324ef7486
  2941. 184ed0177a437b680bcdd0031c0ed00ea21f74852ed00a1c9ed0086da0057487
  2942. 6ed0121cd6d004bda0013a421ff803224033e177f4ae260000000049454e44ae
  2943. 426082
  2944. """),
  2945. 's09n3p02': _dehex("""
  2946. 89504e470d0a1a0a0000000d49484452000000090000000902030000009dffee
  2947. 830000000467414d41000186a031e8965f000000037342495404040477f8b5a3
  2948. 0000000c504c544500ff000077ffff00ffff7700ff5600640000001f49444154
  2949. 789c63600002fbff0c0c56ab19182ca381581a4283f82071200000696505c36a
  2950. 437f230000000049454e44ae426082
  2951. """),
  2952. 'tbgn3p08': _dehex("""
  2953. 89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
  2954. c60000000467414d41000186a031e8965f00000207504c54457f7f7fafafafab
  2955. abab110000222200737300999999510d00444400959500959595e6e600919191
  2956. 8d8d8d620d00898989666600b7b700911600000000730d007373736f6f6faaaa
  2957. 006b6b6b676767c41a00cccc0000f30000ef00d51e0055555567670000dd0051
  2958. 515100d1004d4d4de61e0038380000b700160d0d00ab00560d00090900009500
  2959. 009100008d003333332f2f2f2f2b2f2b2b000077007c7c001a05002b27000073
  2960. 002b2b2b006f00bb1600272727780d002323230055004d4d00cc1e00004d00cc
  2961. 1a000d00003c09006f6f00002f003811271111110d0d0d55554d090909001100
  2962. 4d0900050505000d00e2e200000900000500626200a6a6a6a2a2a29e9e9e8484
  2963. 00fb00fbd5d500801100800d00ea00ea555500a6a600e600e6f7f700e200e233
  2964. 0500888888d900d9848484c01a007777003c3c05c8c8008080804409007c7c7c
  2965. bb00bbaa00aaa600a61e09056262629e009e9a009af322005e5e5e05050000ee
  2966. 005a5a5adddd00a616008d008d00e20016050027270088110078780000c40078
  2967. 00787300736f006f44444400aa00c81e004040406600663c3c3c090000550055
  2968. 1a1a00343434d91e000084004d004d007c004500453c3c00ea1e00222222113c
  2969. 113300331e1e1efb22001a1a1a004400afaf00270027003c001616161e001e0d
  2970. 160d2f2f00808000001e00d1d1001100110d000db7b7b7090009050005b3b3b3
  2971. 6d34c4230000000174524e530040e6d86600000001624b474402660b7c640000
  2972. 01f249444154789c6360c0048c8c58049100575f215ee92e6161ef109cd2a15e
  2973. 4b9645ce5d2c8f433aa4c24f3cbd4c98833b2314ab74a186f094b9c2c27571d2
  2974. 6a2a58e4253c5cda8559057a392363854db4d9d0641973660b0b0bb76bb16656
  2975. 06970997256877a07a95c75a1804b2fbcd128c80b482a0b0300f8a824276a9a8
  2976. ec6e61612b3e57ee06fbf0009619d5fac846ac5c60ed20e754921625a2daadc6
  2977. 1967e29e97d2239c8aec7e61fdeca9cecebef54eb36c848517164514af16169e
  2978. 866444b2b0b7b55534c815cc2ec22d89cd1353800a8473100a4485852d924a6a
  2979. 412adc74e7ad1016ceed043267238c901716f633a812022998a4072267c4af02
  2980. 92127005c0f811b62830054935ce017b38bf0948cc5c09955f030a24617d9d46
  2981. 63371fd940b0827931cbfdf4956076ac018b592f72d45594a9b1f307f3261b1a
  2982. 084bc2ad50018b1900719ba6ba4ca325d0427d3f6161449486f981144cf3100e
  2983. 2a5f2a1ce8683e4ddf1b64275240c8438d98af0c729bbe07982b8a1c94201dc2
  2984. b3174c9820bcc06201585ad81b25b64a2146384e3798290c05ad280a18c0a62e
  2985. e898260c07fca80a24c076cc864b777131a00190cdfa3069035eccbc038c30e1
  2986. 3e88b46d16b6acc5380d6ac202511c392f4b789aa7b0b08718765990111606c2
  2987. 9e854c38e5191878fbe471e749b0112bb18902008dc473b2b2e8e72700000000
  2988. 49454e44ae426082
  2989. """),
  2990. 'Tp2n3p08': _dehex("""
  2991. 89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
  2992. c60000000467414d41000186a031e8965f00000300504c544502ffff80ff05ff
  2993. 7f0703ff7f0180ff04ff00ffff06ff000880ff05ff7f07ffff06ff000804ff00
  2994. 0180ff02ffff03ff7f02ffff80ff0503ff7f0180ffff0008ff7f0704ff00ffff
  2995. 06ff000802ffffff7f0704ff0003ff7fffff0680ff050180ff04ff000180ffff
  2996. 0008ffff0603ff7f80ff05ff7f0702ffffff000880ff05ffff0603ff7f02ffff
  2997. ff7f070180ff04ff00ffff06ff000880ff050180ffff7f0702ffff04ff0003ff
  2998. 7fff7f0704ff0003ff7f0180ffffff06ff000880ff0502ffffffff0603ff7fff
  2999. 7f0702ffff04ff000180ff80ff05ff0008ff7f07ffff0680ff0504ff00ff0008
  3000. 0180ff03ff7f02ffff02ffffffff0604ff0003ff7f0180ffff000880ff05ff7f
  3001. 0780ff05ff00080180ff02ffffff7f0703ff7fffff0604ff00ff7f07ff0008ff
  3002. ff0680ff0504ff0002ffff0180ff03ff7fff0008ffff0680ff0504ff000180ff
  3003. 02ffff03ff7fff7f070180ff02ffff04ff00ffff06ff0008ff7f0780ff0503ff
  3004. 7fffff06ff0008ff7f0780ff0502ffff03ff7f0180ff04ff0002ffffff7f07ff
  3005. ff0604ff0003ff7fff00080180ff80ff05ffff0603ff7f0180ffff000804ff00
  3006. 80ff0502ffffff7f0780ff05ffff0604ff000180ffff000802ffffff7f0703ff
  3007. 7fff0008ff7f070180ff03ff7f02ffff80ff05ffff0604ff00ff0008ffff0602
  3008. ffff0180ff04ff0003ff7f80ff05ff7f070180ff04ff00ff7f0780ff0502ffff
  3009. ff000803ff7fffff0602ffffff7f07ffff0680ff05ff000804ff0003ff7f0180
  3010. ff02ffff0180ffff7f0703ff7fff000804ff0080ff05ffff0602ffff04ff00ff
  3011. ff0603ff7fff7f070180ff80ff05ff000803ff7f0180ffff7f0702ffffff0008
  3012. 04ff00ffff0680ff0503ff7f0180ff04ff0080ff05ffff06ff000802ffffff7f
  3013. 0780ff05ff0008ff7f070180ff03ff7f04ff0002ffffffff0604ff00ff7f07ff
  3014. 000880ff05ffff060180ff02ffff03ff7f80ff05ffff0602ffff0180ff03ff7f
  3015. 04ff00ff7f07ff00080180ffff000880ff0502ffff04ff00ff7f0703ff7fffff
  3016. 06ff0008ffff0604ff00ff7f0780ff0502ffff03ff7f0180ffdeb83387000000
  3017. f874524e53000000000000000008080808080808081010101010101010181818
  3018. 1818181818202020202020202029292929292929293131313131313131393939
  3019. 393939393941414141414141414a4a4a4a4a4a4a4a52525252525252525a5a5a
  3020. 5a5a5a5a5a62626262626262626a6a6a6a6a6a6a6a73737373737373737b7b7b
  3021. 7b7b7b7b7b83838383838383838b8b8b8b8b8b8b8b94949494949494949c9c9c
  3022. 9c9c9c9c9ca4a4a4a4a4a4a4a4acacacacacacacacb4b4b4b4b4b4b4b4bdbdbd
  3023. bdbdbdbdbdc5c5c5c5c5c5c5c5cdcdcdcdcdcdcdcdd5d5d5d5d5d5d5d5dedede
  3024. dededededee6e6e6e6e6e6e6e6eeeeeeeeeeeeeeeef6f6f6f6f6f6f6f6b98ac5
  3025. ca0000012c49444154789c6360e7169150d230b475f7098d4ccc28a96ced9e32
  3026. 63c1da2d7b8e9fb97af3d1fb8f3f18e8a0808953544a4dd7c4c2c9233c2621bf
  3027. b4aab17fdacce5ab36ee3a72eafaad87efbefea68702362e7159652d031b07cf
  3028. c0b8a4cce28aa68e89f316aedfb4ffd0b92bf79fbcfcfe931e0a183904e55435
  3029. 8decdcbcc22292b3caaadb7b27cc5db67af3be63e72fdf78fce2d31f7a2860e5
  3030. 119356d037b374f10e8a4fc92eaa6fee99347fc9caad7b0f9ebd74f7c1db2fbf
  3031. e8a180995f484645dbdccad12f38363dafbcb6a573faeca5ebb6ed3e7ce2c29d
  3032. e76fbefda38702063e0149751d537b67ff80e8d4dcc29a86bea97316add9b0e3
  3033. c0e96bf79ebdfafc971e0a587885e515f58cad5d7d43a2d2720aeadaba26cf5a
  3034. bc62fbcea3272fde7efafac37f3a28000087c0fe101bc2f85f0000000049454e
  3035. 44ae426082
  3036. """),
  3037. 'tbbn1g04': _dehex("""
  3038. 89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
  3039. 290000000467414d41000186a031e8965f0000000274524e530007e8f7589b00
  3040. 000002624b47440000aa8d23320000013e49444154789c55d1cd4b024118c7f1
  3041. efbe6419045b6a48a72d352808b435284f9187ae9b098627a1573a19945beba5
  3042. e8129e8222af11d81e3a4545742de8ef6af6d5762e0fbf0fc33c33f36085cb76
  3043. bc4204778771b867260683ee57e13f0c922df5c719c2b3b6c6c25b2382cea4b9
  3044. 9f7d4f244370746ac71f4ca88e0f173a6496749af47de8e44ba8f3bf9bdfa98a
  3045. 0faf857a7dd95c7dc8d7c67c782c99727997f41eb2e3c1e554152465bb00fe8e
  3046. b692d190b718d159f4c0a45c4435915a243c58a7a4312a7a57913f05747594c6
  3047. 46169866c57101e4d4ce4d511423119c419183a3530cc63db88559ae28e7342a
  3048. 1e9c8122b71139b8872d6e913153224bc1f35b60e4445bd4004e20ed6682c759
  3049. 1d9873b3da0fbf50137dc5c9bde84fdb2ec8bde1189e0448b63584735993c209
  3050. 7a601bd2710caceba6158797285b7f2084a2f82c57c01a0000000049454e44ae
  3051. 426082
  3052. """),
  3053. 'tbrn2c08': _dehex("""
  3054. 89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
  3055. a30000000467414d41000186a031e8965f0000000674524e53007f007f007f8a
  3056. 33334f00000006624b474400ff0000000033277cf3000004d649444154789cad
  3057. 965f68537714c73fd912d640235e692f34d0406fa0c1663481045ab060065514
  3058. 56660a295831607df0a1488715167060840a1614e6431e9cb34fd2c00a762c85
  3059. f6a10f816650c13b0cf40612e1822ddc4863bd628a8924d23d6464f9d3665dd9
  3060. f7e977ce3dbff3cd3939bfdfef6bb87dfb364782dbed065ebe7cd93acc78b4ec
  3061. a228debd7bb7bfbfbfbbbbfb7f261045311a8d261209405194274f9ea4d3e916
  3062. f15f1c3eb5dd6e4fa5fecce526239184a2b0b8486f6f617171b1f5ae4311381c
  3063. 8e57af5e5dbd7a351088150a78bd389d44222c2f93cdfe66b7db8f4ee07038b6
  3064. b6b6bebf766d7e7e7e60a06432313b4ba984c3c1c4049a46b95c5a58583822c1
  3065. dbb76f27272733d1b9df853c3030c0f232562b9108cf9eb1b888d7cbf030abab
  3066. 31abd5fa1f08dc6ef7e7cf9f1f3f7e1c8944745d4f1400c62c001313acad21cb
  3067. b8dd2c2c603271eb1640341aad4c6d331aa7e8c48913a150a861307ecc11e964
  3068. 74899919bc5e14e56fffc404f1388502f178dceff7ef4bf0a5cfe7abb533998c
  3069. e5f9ea2f1dd88c180d64cb94412df3dd57e83a6b3b3c7a84c98420100c72fd3a
  3070. 636348bae726379fe69e8e8d8dbd79f3a6558b0607079796965256479b918085
  3071. 7b02db12712b6181950233023f3f647494ee6e2e5ea45864cce5b8a7fe3acffc
  3072. 3aebb22c2bd5d20e22d0757d7b7bbbbdbd3d94a313bed1b0aa3cd069838b163a
  3073. 8d4c59585f677292d0b84d9a995bd337def3fe6bbe5e6001989b9b6bfe27ea08
  3074. 36373781542ab56573248b4c5bc843ac4048c7ab21aa24ca00534c25482828a3
  3075. 8c9ee67475bbaaaab22cb722c8e57240a150301a8d219de94e44534d7d90e885
  3076. 87acb0e2c4f9800731629b6c5ee14a35a6b9887d2a0032994cb9cf15dbe59650
  3077. ff7b46a04c9a749e7cc5112214266cc65c31354d5b5d5d3d90209bcd5616a552
  3078. a95c2e87f2a659bd9ee01c2cd73964e438f129a6aa9e582c363838b80f81d7eb
  3079. 5555b56a2a8ad2d9d7affd0409f8015c208013fea00177b873831b0282c964f2
  3080. 783c1e8fa7582cee5f81a669b5e6eeeeaee58e8559b0c233d8843c7c0b963a82
  3081. 34e94b5cb2396d7d7d7db22c8ba258fb0afd43f0e2c58b919191ba9de9b4d425
  3082. 118329b0c3323c8709d02041b52b4ea7f39de75d2a934a2693c0a953a76a93d4
  3083. 5d157ebf7f6565a5542a553df97c5e10045dd731c130b86113cc300cbd489224
  3084. 08422a952a140a95788fc763b1d41558d7a2d7af5f5fb870a1d6a3aaaacd6603
  3085. 18802da84c59015bd2e6897b745d9765b99a1df0f97c0daf74e36deaf7fbcd66
  3086. 73ad2797cb89a2c839880188a2e8743a8bc5a22ccbba5e376466b3b9bdbdbd21
  3087. 6123413a9d0e0402b51e4dd3bababa788eb022b85caeb6b6364551b6b7b76942
  3088. 43f7f727007a7a7a04a1ee8065b3595fde2768423299ac1ec6669c3973e65004
  3089. c0f8f878ad69341a33994ced2969c0d0d0502412f9f8f163f3a7fd654b474787
  3090. 288ad53e74757535df6215b85cae60302849d2410aecc037f9f2e5cbd5b5c160
  3091. 680eb0dbede170381c0e7ff8f0a185be3b906068684892a4ca7a6f6faff69328
  3092. 8ad3d3d3f7efdfdfdbdbfb57e96868a14d0d0643381c96242997cbe5f3794010
  3093. 84603078fcf8f1d6496bd14a3aba5c2ea7d369341a5555b5582c8140e0fcf9f3
  3094. 1b1b1b87cf4eeb0a8063c78e45a3d19e9e1ebfdfdf5a831e844655d18093274f
  3095. 9e3d7bf6d3a74f3b3b3b47c80efc05ff7af28fefb70d9b0000000049454e44ae
  3096. 426082
  3097. """),
  3098. 'basn6a16': _dehex("""
  3099. 89504e470d0a1a0a0000000d494844520000002000000020100600000023eaa6
  3100. b70000000467414d41000186a031e8965f00000d2249444154789cdd995f6c1c
  3101. d775c67ff38fb34b724d2ee55a8e4b04a0ac87049100cab4dbd8c6528902cb4d
  3102. 10881620592e52d4325ac0905bc98a94025e71fd622cb5065ac98a0c283050c0
  3103. 728a00b6e542a1d126885cd3298928891d9a0444037e904434951d4b90b84b2f
  3104. c9dde1fcebc33977a95555348f411e16dfce9d3b77ee77eebde77ce78c95a669
  3105. 0ad07c17009a13edd898b87dfb1fcb7d2b4d1bff217f33df80deb1e6267df0ff
  3106. c1e6e6dfafdf1f5a7fd30f9aef66b6d546dd355bf02c40662e3307f9725a96c6
  3107. 744c3031f83782f171c148dbc3bf1774f5dad1e79d6f095a3f54d4fbec5234ef
  3108. d9a2f8d73afe4f14f57ef4f42def7b44f19060f06b45bddf1c5534d77fd922be
  3109. 2973a15a82e648661c6e3240aa3612ead952b604bde57458894f29deaf133bac
  3110. 13d2766f5227a4a3b8cf08da7adfd6fbd6bd8a4fe9dbb43d35e3dfa3f844fbf8
  3111. 9119bf4f7144094fb56333abf8a86063ca106f94b3a3b512343765e60082097f
  3112. 1bb86ba72439a653519b09f5cee1ce61c897d37eedf5553580ae60f4af8af33a
  3113. b14fd400b6a0f34535c0434afc0b3a9f07147527a5fa7ca218ff56c74d74dc3f
  3114. 155cfd3325fc278acf2ae1cb4a539f5f9937c457263b0bd51234c732a300cdd1
  3115. cc1840f0aaff54db0e4874ed5a9b5d6d27d4bb36746d80de72baa877ff4b275a
  3116. d7895ed1897ea4139b5143fcbb1a62560da1ed9662aaed895ec78a91c18795b8
  3117. 5e07ab4af8ba128e95e682e0728bf8f2e5ae815a091a53d902ac1920d8e05f06
  3118. 589de8d8d66680789f4e454fb9d9ec66cd857af796ee2d902fa73fd5bba775a2
  3119. 153580ae44705ed0d37647d15697cb8f14bfa3e3e8fdf8031d47af571503357c
  3120. f30d25acedcbbf135c9a35c49766ba07ab255859e8ec03684e66860182dff8f7
  3121. 0304bff6ff1c20fc81b7afdd00a71475539a536e36bb5973a19e3b923b02bde5
  3122. e4efd4003ac170eb2d13fe274157afedbd82d6fb3a9a1e85e4551d47cf7078f8
  3123. 9671fe4289ebf5f2bf08d63f37c4eb4773c55a0996efeefa0ca011671d8060ca
  3124. 2f0004c7fcc300e166ef0240f825efe3361f106d57d423d0723f7acacd66376b
  3125. 2ed47b7a7a7a205f4ef4ac4691e0aad9aa0d41cf13741c3580a506487574ddca
  3126. 61a8c403c1863ebfbcac3475168b2de28b8b3d77544bb05ce92a02aceced3c0d
  3127. d0cc65ea371b201cf1c601c24dde1c4078cedbdeb60322f50126a019bf6edc9b
  3128. 39e566b39b3517eaf97c3e0fbde5e4491d45bd74537145d155b476aa0176e868
  3129. c6abebf30dbd5e525c54ac8e18e2d56abeb756827a3d970358a97416019a6f64
  3130. f60004fdfe1580d5c98e618070cc1b05887eee7e0d209a70db7d8063029889b4
  3131. c620ead78d7b33a7dc6c76b3e6427ddddbebde867c393aa7845e5403e8ca794a
  3132. d0d6fb897af5f03525fe5782f5e7046bdaef468bf88d1debc6ab25583cd17310
  3133. 6079b9ab0ba059c914018245bf076075b5a303200c3c1f209a733701444fbbaf
  3134. 00c4134ebb016c5d0b23614c243701cdf875e3decce9349bddacb9505fbf7dfd
  3135. 76e82d87736a00f5d2b5ffd4b7dce2719a4d25ae717ee153c1abef18e257cfad
  3136. 7fa45682da48ef38c052b53b0fd06864b300c151ff08c0ea431de701a287dd5f
  3137. 004497dc7b01a253ee3e80b8c7f91c20f967fb6fdb7c80ada7d8683723614c24
  3138. 3701cdf875e3decc29379bddacb950ef3fd47f08f2e5a61ea4aa2a3eb757cd55
  3139. 13345efcfa59c12b2f19e2578ef77fb75a82854ffbee01a83f977b11a031931d
  3140. 040802df07082b5e11207cc17b1e209a770700e2df0a83e409fb7580f827c230
  3141. 99b06fd901fb058d6835dacd481813c94d40337eddb83773cacd66376b2ed437
  3142. bebcf165e82d2f4e4beb7f3fa6e652c2d7ee10bc78c010bfb87fe3c95a09ae9f
  3143. bd732740bd2fb700d0f865f64180e059ff044018ca0ca28a5b04883f701e0088
  3144. bfec7c0c909cb71f0448c6ec518074b375012079d9dedf66004bcfbc51eb2dd1
  3145. aadacd481813c94d40337eddb83773cacd66376b2ed487868686205fbe7c49ef
  3146. 5605a73f34c4a7a787eeab96e0da81bb4e022c15ba27019a5b339300e16bf286
  3147. a8eae601e25866907cdf3e0890acb36f00245fb57f05904e59c300e92561946e
  3148. b2e600d209ab7d07f04d458dfb46ad1bd16ab49b913026929b8066fcba716fe6
  3149. 949bcd6ed65ca8ef7e7cf7e3d05b7e7c8f217ee6cdddbb6a25a856f37980e0c7
  3150. fe4e80a82623c48193014846ec7180f4acf518409aca0cd28a5504e03b32c374
  3151. de1a00608a0240faaa327a4b19fe946fb6f90054dbb5f2333d022db56eb4966a
  3152. 3723614c243701cdf8f556bea8a7dc6c76b3e66bd46584ddbbcebc0990cf4b0f
  3153. ff4070520c282338a7e26700ec725202b01e4bcf0258963c6f1d4d8f0030cb20
  3154. 805549c520930c03584fa522b676f11600ffc03fde3e1b3489a9c9054c9aa23b
  3155. c08856a3dd8c843191dc0434e3d78d7b33a75c36fb993761f7ae5a69f72ef97f
  3156. e6ad336fed7e1c60e8bee96980bbdebbb60da07b7069062033d9dc0ae03d296f
  3157. 70ab511ec071640676252902d833c916007b3e1900b0a6d2028035968e025861
  3158. ea01581369fb11488c34d18cbc95989afccca42baad65ba2d5683723614c24d7
  3159. 8066fcbab8b7e96918baaf5aaa56219f975fb50a43f7c9bde90fa73f1c1a02d8
  3160. 78f2e27e803b77ca08b90519315b6fe400fc1392097a9eccc0ad444500e70199
  3161. a1331f0f00d8934901c07e5d526ceb87c2d07e2579badd005a2b31a5089391b7
  3162. 1253358049535a6add8856dd0146c298482e01ede27ed878b256ba7600ee3a09
  3163. c18fc1df09fe01084ec25defc1b56db0f1a4f4bd78e0e2818d2f0334e7330300
  3164. 7df7c888b917e50dd9c1c60c80efcb0cbc63e1f700bce7c31700dccbd1060027
  3165. 8add9b0de06c8e2f00d84962b7d7030e2a61538331b98051f92631bd253f336a
  3166. dd8856a3dd44c25c390efddfad96ae9f853b77c25201ba27c533b8bdf28b6ad0
  3167. 3d084b33d2e7fa59099e9901b8f2d29597fa0f01848f78e70082117f1ca07b76
  3168. 6910209b9519f895a008d031bbba05c09d8f06005c5b18b8fba25300cea6780e
  3169. c03e911c6ccf06d507b48a4fa606634a114609de929f9934c5a87511ad57cfc1
  3170. fa476aa5854fa1ef1e3910b905686e85cc24c40138198915f133d2d6dc2a7dea
  3171. 7df2ccc2a752faf2cec1d577aebeb37e3b4034eeee0008dff3be0e6b923773b4
  3172. 7904c0ef9119767cb4fa1500ef1361e08e452500f71561e84cc4ed3e20fab6a2
  3173. c905f40cb76a3026bf3319b91ac2e46792a6dcd801ebc6aba5da08f48ecb81c8
  3174. bd088d5f42f6417191de93908c803d0e76199292b485af41b60e8d9c3c537f0e
  3175. 8211f0c7211a077707dc18b931b2ee6d80a4d7ae024491ebc24d4a708ff70680
  3176. 7f25e807e8785f1878e322d6ddaf453f0770ff2dfa769b01423dbbad72a391b6
  3177. 5a7c3235985629423372494cab55c8f7d64a8b27a0e7202c55a13b0f8d19c80e
  3178. 4ae9ca3f015115dc3ca467c17a4c7ee95970ab10e5a54ff0ac3cd39881ee5958
  3179. 1a84f03df0be0e492fd855a8d6aa35d10b4962dbb0a604a3d3ee5e80a8eee600
  3180. a24977f8660378bf0bbf00e01d0a8fb7f980f04b8aa6ce6aca8d5a7533c52753
  3181. 839152c4e222f4dc512dd5eb90cbc981e8ea12cf90cd8a8bf47d89159e2741d3
  3182. 7124f65b96fcd254dae258fa84a13c13043246a32129574787e49eae2b49b86d
  3183. c3e2e78b9ff7f4002415bb08907c66df0d103b4e0c104db90500ff70700c203a
  3184. ee1e82dba4c3e16e256c0acca6ceaae9afd1f612d7eb472157ac95962bd05594
  3185. 7dd1598466053245088e827f44628657942a825b84e4fb601f84b4025611aca3
  3186. 901e01bb024911dc0a4445f08e41f83df02b10142173149ab71baf027611ea95
  3187. 7a257704201d14cd9af4d90b00f194530088cb4e09c0df1c5c0088f7393f6833
  3188. c0aa3ac156655de3bca9b34ab9716906ba07aba5e5bba1eb3358d90b9da7c533
  3189. 64f6888bf47b60f521e8380fe10be03d2feac17900927560df40f4e48f805960
  3190. 50328d648bf4893f9067c217a0631656b7c898c122847bc07b03a2d3e0ee85e4
  3191. 33b0ef867450c4fad2ecd26cf7168074c0ba0c904cdac300c9cfec4701924df6
  3192. 1cdca61e10685c6f7d52d0caba1498972f43d740adb4b2009d7d7220b20e3473
  3193. 90a943d00ffe959bb6eac3e0fe42ea49ee00c45f06e76329b1dabf127d690d80
  3194. 5581b408f63c2403e0cc433c00ee658836803b0fd100747c04ab5f917704fd10
  3195. d5c1cd41ec801343d207f602a403605d86e5f9e5f9ae0d00e994556833806685
  3196. c931fb709b0f08b4e869bea5c827859549e82c544b8d29c816a0390999613920
  3197. 7e610d5727a16318c2003c1fa24be0de2b32caf92224e7c17e5004b6350c4c01
  3198. 05601218066b0ad28224e149019c086257ca315102de2712903bde97b8144d82
  3199. 3b2c6ac52d403c054e019249b087f53d0558995a99ea946c70cc927458b3c1ff
  3200. 550f30050df988d4284376b4566a8e416654cc921985e037e0df0fc131f00f4b
  3201. acf0c6211c036f14a239703741740adc7da227edd7e56b833d0ae92549b4d357
  3202. 25dfb49ed2ff63908e6adf27d6d0dda7638d4154d2778daca17f58e61297c129
  3203. 41f233b01f5dc3740cac51688c35c6b22580f48224fee9b83502569a66b629f1
  3204. 09f3713473413e2666e7fe6f6c6efefdfafda1f56f6e06f93496d9d67cb7366a
  3205. 9964b6f92e64b689196ec6c604646fd3fe4771ff1bf03f65d8ecc3addbb5f300
  3206. 00000049454e44ae426082
  3207. """),
  3208. }
  3209. def read_pam_header(infile):
  3210. """
  3211. Read (the rest of a) PAM header. `infile` should be positioned
  3212. immediately after the initial 'P7' line (at the beginning of the
  3213. second line). Returns are as for `read_pnm_header`.
  3214. """
  3215. # Unlike PBM, PGM, and PPM, we can read the header a line at a time.
  3216. header = dict()
  3217. while True:
  3218. l = infile.readline().strip()
  3219. if l == strtobytes('ENDHDR'):
  3220. break
  3221. if not l:
  3222. raise EOFError('PAM ended prematurely')
  3223. if l[0] == strtobytes('#'):
  3224. continue
  3225. l = l.split(None, 1)
  3226. if l[0] not in header:
  3227. header[l[0]] = l[1]
  3228. else:
  3229. header[l[0]] += strtobytes(' ') + l[1]
  3230. required = ['WIDTH', 'HEIGHT', 'DEPTH', 'MAXVAL']
  3231. required = [strtobytes(x) for x in required]
  3232. WIDTH,HEIGHT,DEPTH,MAXVAL = required
  3233. present = [x for x in required if x in header]
  3234. if len(present) != len(required):
  3235. raise Error('PAM file must specify WIDTH, HEIGHT, DEPTH, and MAXVAL')
  3236. width = int(header[WIDTH])
  3237. height = int(header[HEIGHT])
  3238. depth = int(header[DEPTH])
  3239. maxval = int(header[MAXVAL])
  3240. if (width <= 0 or
  3241. height <= 0 or
  3242. depth <= 0 or
  3243. maxval <= 0):
  3244. raise Error(
  3245. 'WIDTH, HEIGHT, DEPTH, MAXVAL must all be positive integers')
  3246. return 'P7', width, height, depth, maxval
  3247. def read_pnm_header(infile, supported=('P5','P6')):
  3248. """
  3249. Read a PNM header, returning (format,width,height,depth,maxval).
  3250. `width` and `height` are in pixels. `depth` is the number of
  3251. channels in the image; for PBM and PGM it is synthesized as 1, for
  3252. PPM as 3; for PAM images it is read from the header. `maxval` is
  3253. synthesized (as 1) for PBM images.
  3254. """
  3255. # Generally, see http://netpbm.sourceforge.net/doc/ppm.html
  3256. # and http://netpbm.sourceforge.net/doc/pam.html
  3257. supported = [strtobytes(x) for x in supported]
  3258. # Technically 'P7' must be followed by a newline, so by using
  3259. # rstrip() we are being liberal in what we accept. I think this
  3260. # is acceptable.
  3261. type = infile.read(3).rstrip()
  3262. if type not in supported:
  3263. raise NotImplementedError('file format %s not supported' % type)
  3264. if type == strtobytes('P7'):
  3265. # PAM header parsing is completely different.
  3266. return read_pam_header(infile)
  3267. # Expected number of tokens in header (3 for P4, 4 for P6)
  3268. expected = 4
  3269. pbm = ('P1', 'P4')
  3270. if type in pbm:
  3271. expected = 3
  3272. header = [type]
  3273. # We have to read the rest of the header byte by byte because the
  3274. # final whitespace character (immediately following the MAXVAL in
  3275. # the case of P6) may not be a newline. Of course all PNM files in
  3276. # the wild use a newline at this point, so it's tempting to use
  3277. # readline; but it would be wrong.
  3278. def getc():
  3279. c = infile.read(1)
  3280. if not c:
  3281. raise Error('premature EOF reading PNM header')
  3282. return c
  3283. c = getc()
  3284. while True:
  3285. # Skip whitespace that precedes a token.
  3286. while c.isspace():
  3287. c = getc()
  3288. # Skip comments.
  3289. while c == '#':
  3290. while c not in '\n\r':
  3291. c = getc()
  3292. if not c.isdigit():
  3293. raise Error('unexpected character %s found in header' % c)
  3294. # According to the specification it is legal to have comments
  3295. # that appear in the middle of a token.
  3296. # This is bonkers; I've never seen it; and it's a bit awkward to
  3297. # code good lexers in Python (no goto). So we break on such
  3298. # cases.
  3299. token = strtobytes('')
  3300. while c.isdigit():
  3301. token += c
  3302. c = getc()
  3303. # Slight hack. All "tokens" are decimal integers, so convert
  3304. # them here.
  3305. header.append(int(token))
  3306. if len(header) == expected:
  3307. break
  3308. # Skip comments (again)
  3309. while c == '#':
  3310. while c not in '\n\r':
  3311. c = getc()
  3312. if not c.isspace():
  3313. raise Error('expected header to end with whitespace, not %s' % c)
  3314. if type in pbm:
  3315. # synthesize a MAXVAL
  3316. header.append(1)
  3317. depth = (1,3)[type == strtobytes('P6')]
  3318. return header[0], header[1], header[2], depth, header[3]
  3319. def write_pnm(file, width, height, pixels, meta):
  3320. """Write a Netpbm PNM/PAM file."""
  3321. bitdepth = meta['bitdepth']
  3322. maxval = 2**bitdepth - 1
  3323. # Rudely, the number of image planes can be used to determine
  3324. # whether we are L (PGM), LA (PAM), RGB (PPM), or RGBA (PAM).
  3325. planes = meta['planes']
  3326. # Can be an assert as long as we assume that pixels and meta came
  3327. # from a PNG file.
  3328. assert planes in (1,2,3,4)
  3329. if planes in (1,3):
  3330. if 1 == planes:
  3331. # PGM
  3332. # Could generate PBM if maxval is 1, but we don't (for one
  3333. # thing, we'd have to convert the data, not just blat it
  3334. # out).
  3335. fmt = 'P5'
  3336. else:
  3337. # PPM
  3338. fmt = 'P6'
  3339. file.write('%s %d %d %d\n' % (fmt, width, height, maxval))
  3340. if planes in (2,4):
  3341. # PAM
  3342. # See http://netpbm.sourceforge.net/doc/pam.html
  3343. if 2 == planes:
  3344. tupltype = 'GRAYSCALE_ALPHA'
  3345. else:
  3346. tupltype = 'RGB_ALPHA'
  3347. file.write('P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n'
  3348. 'TUPLTYPE %s\nENDHDR\n' %
  3349. (width, height, planes, maxval, tupltype))
  3350. # Values per row
  3351. vpr = planes * width
  3352. # struct format
  3353. fmt = '>%d' % vpr
  3354. if maxval > 0xff:
  3355. fmt = fmt + 'H'
  3356. else:
  3357. fmt = fmt + 'B'
  3358. for row in pixels:
  3359. file.write(struct.pack(fmt, *row))
  3360. file.flush()
  3361. def color_triple(color):
  3362. """
  3363. Convert a command line colour value to a RGB triple of integers.
  3364. FIXME: Somewhere we need support for greyscale backgrounds etc.
  3365. """
  3366. if color.startswith('#') and len(color) == 4:
  3367. return (int(color[1], 16),
  3368. int(color[2], 16),
  3369. int(color[3], 16))
  3370. if color.startswith('#') and len(color) == 7:
  3371. return (int(color[1:3], 16),
  3372. int(color[3:5], 16),
  3373. int(color[5:7], 16))
  3374. elif color.startswith('#') and len(color) == 13:
  3375. return (int(color[1:5], 16),
  3376. int(color[5:9], 16),
  3377. int(color[9:13], 16))
  3378. def _add_common_options(parser):
  3379. """Call *parser.add_option* for each of the options that are
  3380. common between this PNG--PNM conversion tool and the gen
  3381. tool.
  3382. """
  3383. parser.add_option("-i", "--interlace",
  3384. default=False, action="store_true",
  3385. help="create an interlaced PNG file (Adam7)")
  3386. parser.add_option("-t", "--transparent",
  3387. action="store", type="string", metavar="#RRGGBB",
  3388. help="mark the specified colour as transparent")
  3389. parser.add_option("-b", "--background",
  3390. action="store", type="string", metavar="#RRGGBB",
  3391. help="save the specified background colour")
  3392. parser.add_option("-g", "--gamma",
  3393. action="store", type="float", metavar="value",
  3394. help="save the specified gamma value")
  3395. parser.add_option("-c", "--compression",
  3396. action="store", type="int", metavar="level",
  3397. help="zlib compression level (0-9)")
  3398. return parser
  3399. def _main(argv):
  3400. """
  3401. Run the PNG encoder with options from the command line.
  3402. """
  3403. # Parse command line arguments
  3404. from optparse import OptionParser
  3405. import re
  3406. version = '%prog ' + re.sub(r'( ?\$|URL: |Rev:)', '', __version__)
  3407. parser = OptionParser(version=version)
  3408. parser.set_usage("%prog [options] [imagefile]")
  3409. parser.add_option('-r', '--read-png', default=False,
  3410. action='store_true',
  3411. help='Read PNG, write PNM')
  3412. parser.add_option("-a", "--alpha",
  3413. action="store", type="string", metavar="pgmfile",
  3414. help="alpha channel transparency (RGBA)")
  3415. _add_common_options(parser)
  3416. (options, args) = parser.parse_args(args=argv[1:])
  3417. # Convert options
  3418. if options.transparent is not None:
  3419. options.transparent = color_triple(options.transparent)
  3420. if options.background is not None:
  3421. options.background = color_triple(options.background)
  3422. # Prepare input and output files
  3423. if len(args) == 0:
  3424. infilename = '-'
  3425. infile = sys.stdin
  3426. elif len(args) == 1:
  3427. infilename = args[0]
  3428. infile = open(infilename, 'rb')
  3429. else:
  3430. parser.error("more than one input file")
  3431. outfile = sys.stdout
  3432. if sys.platform == "win32":
  3433. import msvcrt, os
  3434. msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
  3435. if options.read_png:
  3436. # Encode PNG to PPM
  3437. png = Reader(file=infile)
  3438. width,height,pixels,meta = png.asDirect()
  3439. write_pnm(outfile, width, height, pixels, meta)
  3440. else:
  3441. # Encode PNM to PNG
  3442. format, width, height, depth, maxval = \
  3443. read_pnm_header(infile, ('P5','P6','P7'))
  3444. # When it comes to the variety of input formats, we do something
  3445. # rather rude. Observe that L, LA, RGB, RGBA are the 4 colour
  3446. # types supported by PNG and that they correspond to 1, 2, 3, 4
  3447. # channels respectively. So we use the number of channels in
  3448. # the source image to determine which one we have. We do not
  3449. # care about TUPLTYPE.
  3450. greyscale = depth <= 2
  3451. pamalpha = depth in (2,4)
  3452. supported = map(lambda x: 2**x-1, range(1,17))
  3453. try:
  3454. mi = supported.index(maxval)
  3455. except ValueError:
  3456. raise NotImplementedError(
  3457. 'your maxval (%s) not in supported list %s' %
  3458. (maxval, str(supported)))
  3459. bitdepth = mi+1
  3460. writer = Writer(width, height,
  3461. greyscale=greyscale,
  3462. bitdepth=bitdepth,
  3463. interlace=options.interlace,
  3464. transparent=options.transparent,
  3465. background=options.background,
  3466. alpha=bool(pamalpha or options.alpha),
  3467. gamma=options.gamma,
  3468. compression=options.compression)
  3469. if options.alpha:
  3470. pgmfile = open(options.alpha, 'rb')
  3471. format, awidth, aheight, adepth, amaxval = \
  3472. read_pnm_header(pgmfile, 'P5')
  3473. if amaxval != '255':
  3474. raise NotImplementedError(
  3475. 'maxval %s not supported for alpha channel' % amaxval)
  3476. if (awidth, aheight) != (width, height):
  3477. raise ValueError("alpha channel image size mismatch"
  3478. " (%s has %sx%s but %s has %sx%s)"
  3479. % (infilename, width, height,
  3480. options.alpha, awidth, aheight))
  3481. writer.convert_ppm_and_pgm(infile, pgmfile, outfile)
  3482. else:
  3483. writer.convert_pnm(infile, outfile)
  3484. if __name__ == '__main__':
  3485. try:
  3486. _main(sys.argv)
  3487. except Error, e:
  3488. print >>sys.stderr, e