Movatterモバイル変換


[0]ホーム

URL:


ContentsMenuExpandLight modeDark modeAuto light/dark, in light modeAuto light/dark, in dark modeSkip to content
Pillow (PIL Fork) 12.0.0 documentation
Light LogoDark Logo
Pillow (PIL Fork) 12.0.0 documentation
Back to top

Source code for PIL.PpmImagePlugin

## The Python Imaging Library.# $Id$## PPM support for PIL## History:#       96-03-24 fl     Created#       98-03-06 fl     Write RGBA images (as RGB, that is)## Copyright (c) Secret Labs AB 1997-98.# Copyright (c) Fredrik Lundh 1996.## See the README file for information on usage and redistribution.#from__future__importannotationsimportmathfromtypingimportIOfrom.importImage,ImageFilefrom._binaryimporti16beasi16from._binaryimporto8from._binaryimporto32leaso32## --------------------------------------------------------------------b_whitespace=b"\x20\x09\x0a\x0b\x0c\x0d"MODES={# standardb"P1":"1",b"P2":"L",b"P3":"RGB",b"P4":"1",b"P5":"L",b"P6":"RGB",# extensionsb"P0CMYK":"CMYK",b"Pf":"F",# PIL extensions (for test purposes only)b"PyP":"P",b"PyRGBA":"RGBA",b"PyCMYK":"CMYK",}def_accept(prefix:bytes)->bool:returnlen(prefix)>=2andprefix.startswith(b"P")andprefix[1]inb"0123456fy"### Image plugin for PBM, PGM, and PPM images.
[docs]classPpmImageFile(ImageFile.ImageFile):format="PPM"format_description="Pbmplus image"def_read_magic(self)->bytes:assertself.fpisnotNonemagic=b""# read until whitespace or longest available magic numberfor_inrange(6):c=self.fp.read(1)ifnotcorcinb_whitespace:breakmagic+=creturnmagicdef_read_token(self)->bytes:assertself.fpisnotNonetoken=b""whilelen(token)<=10:# read until next whitespace or limit of 10 charactersc=self.fp.read(1)ifnotc:breakelifcinb_whitespace:# token endedifnottoken:# skip whitespace at startcontinuebreakelifc==b"#":# ignores rest of the line; stops at CR, LF or EOFwhileself.fp.read(1)notinb"\r\n":passcontinuetoken+=cifnottoken:# Token was not even 1 bytemsg="Reached EOF while reading header"raiseValueError(msg)eliflen(token)>10:msg_too_long=b"Token too long in file header:%s"%tokenraiseValueError(msg_too_long)returntokendef_open(self)->None:assertself.fpisnotNonemagic_number=self._read_magic()try:mode=MODES[magic_number]exceptKeyError:msg="not a PPM file"raiseSyntaxError(msg)self._mode=modeifmagic_numberin(b"P1",b"P4"):self.custom_mimetype="image/x-portable-bitmap"elifmagic_numberin(b"P2",b"P5"):self.custom_mimetype="image/x-portable-graymap"elifmagic_numberin(b"P3",b"P6"):self.custom_mimetype="image/x-portable-pixmap"self._size=int(self._read_token()),int(self._read_token())decoder_name="raw"ifmagic_numberin(b"P1",b"P2",b"P3"):decoder_name="ppm_plain"args:str|tuple[str|int,...]ifmode=="1":args="1;I"elifmode=="F":scale=float(self._read_token())ifscale==0.0ornotmath.isfinite(scale):msg="scale must be finite and non-zero"raiseValueError(msg)self.info["scale"]=abs(scale)rawmode="F;32F"ifscale<0else"F;32BF"args=(rawmode,0,-1)else:maxval=int(self._read_token())ifnot0<maxval<65536:msg="maxval must be greater than 0 and less than 65536"raiseValueError(msg)ifmaxval>255andmode=="L":self._mode="I"rawmode=modeifdecoder_name!="ppm_plain":# If maxval matches a bit depth, use the raw decoder directlyifmaxval==65535andmode=="L":rawmode="I;16B"elifmaxval!=255:decoder_name="ppm"args=rawmodeifdecoder_name=="raw"else(rawmode,maxval)self.tile=[ImageFile._Tile(decoder_name,(0,0)+self.size,self.fp.tell(),args)]
## --------------------------------------------------------------------
[docs]classPpmPlainDecoder(ImageFile.PyDecoder):_pulls_fd=True_comment_spans:booldef_read_block(self)->bytes:assertself.fdisnotNonereturnself.fd.read(ImageFile.SAFEBLOCK)def_find_comment_end(self,block:bytes,start:int=0)->int:a=block.find(b"\n",start)b=block.find(b"\r",start)returnmin(a,b)ifa*b>0elsemax(a,b)# lowest nonnegative index (or -1)def_ignore_comments(self,block:bytes)->bytes:ifself._comment_spans:# Finish current commentwhileblock:comment_end=self._find_comment_end(block)ifcomment_end!=-1:# Comment ends in this block# Delete tail of commentblock=block[comment_end+1:]breakelse:# Comment spans whole block# So read the next block, looking for the endblock=self._read_block()# Search for any further commentsself._comment_spans=FalsewhileTrue:comment_start=block.find(b"#")ifcomment_start==-1:# No comment foundbreakcomment_end=self._find_comment_end(block,comment_start)ifcomment_end!=-1:# Comment ends in this block# Delete commentblock=block[:comment_start]+block[comment_end+1:]else:# Comment continues to next block(s)block=block[:comment_start]self._comment_spans=Truebreakreturnblockdef_decode_bitonal(self)->bytearray:""" This is a separate method because in the plain PBM format, all data tokens are exactly one byte, so the inter-token whitespace is optional. """data=bytearray()total_bytes=self.state.xsize*self.state.ysizewhilelen(data)!=total_bytes:block=self._read_block()# read next blockifnotblock:# eofbreakblock=self._ignore_comments(block)tokens=b"".join(block.split())fortokenintokens:iftokennotin(48,49):msg=b"Invalid token for this mode:%s"%bytes([token])raiseValueError(msg)data=(data+tokens)[:total_bytes]invert=bytes.maketrans(b"01",b"\xff\x00")returndata.translate(invert)def_decode_blocks(self,maxval:int)->bytearray:data=bytearray()max_len=10out_byte_count=4ifself.mode=="I"else1out_max=65535ifself.mode=="I"else255bands=Image.getmodebands(self.mode)total_bytes=self.state.xsize*self.state.ysize*bands*out_byte_counthalf_token=b""whilelen(data)!=total_bytes:block=self._read_block()# read next blockifnotblock:ifhalf_token:block=bytearray(b" ")# flush half_tokenelse:# eofbreakblock=self._ignore_comments(block)ifhalf_token:block=half_token+block# stitch half_token to new blockhalf_token=b""tokens=block.split()ifblockandnotblock[-1:].isspace():# block might split tokenhalf_token=tokens.pop()# save half token for lateriflen(half_token)>max_len:# prevent buildup of half_tokenmsg=(b"Token too long found in data:%s"%half_token[:max_len+1])raiseValueError(msg)fortokenintokens:iflen(token)>max_len:msg=b"Token too long found in data:%s"%token[:max_len+1]raiseValueError(msg)value=int(token)ifvalue<0:msg_str=f"Channel value is negative:{value}"raiseValueError(msg_str)ifvalue>maxval:msg_str=f"Channel value too large for this mode:{value}"raiseValueError(msg_str)value=round(value/maxval*out_max)data+=o32(value)ifself.mode=="I"elseo8(value)iflen(data)==total_bytes:# finished!breakreturndata
[docs]defdecode(self,buffer:bytes|Image.SupportsArrayInterface)->tuple[int,int]:self._comment_spans=Falseifself.mode=="1":data=self._decode_bitonal()rawmode="1;8"else:maxval=self.args[-1]data=self._decode_blocks(maxval)rawmode="I;32"ifself.mode=="I"elseself.modeself.set_as_raw(bytes(data),rawmode)return-1,0
[docs]classPpmDecoder(ImageFile.PyDecoder):_pulls_fd=True
[docs]defdecode(self,buffer:bytes|Image.SupportsArrayInterface)->tuple[int,int]:assertself.fdisnotNonedata=bytearray()maxval=self.args[-1]in_byte_count=1ifmaxval<256else2out_byte_count=4ifself.mode=="I"else1out_max=65535ifself.mode=="I"else255bands=Image.getmodebands(self.mode)dest_length=self.state.xsize*self.state.ysize*bands*out_byte_countwhilelen(data)<dest_length:pixels=self.fd.read(in_byte_count*bands)iflen(pixels)<in_byte_count*bands:# eofbreakforbinrange(bands):value=(pixels[b]ifin_byte_count==1elsei16(pixels,b*in_byte_count))value=min(out_max,round(value/maxval*out_max))data+=o32(value)ifself.mode=="I"elseo8(value)rawmode="I;32"ifself.mode=="I"elseself.modeself.set_as_raw(bytes(data),rawmode)return-1,0
## --------------------------------------------------------------------def_save(im:Image.Image,fp:IO[bytes],filename:str|bytes)->None:ifim.mode=="1":rawmode,head="1;I",b"P4"elifim.mode=="L":rawmode,head="L",b"P5"elifim.modein("I","I;16"):rawmode,head="I;16B",b"P5"elifim.modein("RGB","RGBA"):rawmode,head="RGB",b"P6"elifim.mode=="F":rawmode,head="F;32F",b"Pf"else:msg=f"cannot write mode{im.mode} as PPM"raiseOSError(msg)fp.write(head+b"\n%d%d\n"%im.size)ifhead==b"P6":fp.write(b"255\n")elifhead==b"P5":ifrawmode=="L":fp.write(b"255\n")else:fp.write(b"65535\n")elifhead==b"Pf":fp.write(b"-1.0\n")row_order=-1ifim.mode=="F"else1ImageFile._save(im,fp,[ImageFile._Tile("raw",(0,0)+im.size,0,(rawmode,0,row_order))])## --------------------------------------------------------------------Image.register_open(PpmImageFile.format,PpmImageFile,_accept)Image.register_save(PpmImageFile.format,_save)Image.register_decoder("ppm",PpmDecoder)Image.register_decoder("ppm_plain",PpmPlainDecoder)Image.register_extensions(PpmImageFile.format,[".pbm",".pgm",".ppm",".pnm",".pfm"])Image.register_mime(PpmImageFile.format,"image/x-portable-anymap")
Copyright © 1995-2011 Fredrik Lundh and contributors, 2010 Jeffrey A. Clark and contributors.
Made withSphinx and@pradyunsg'sFuro

[8]
ページ先頭

©2009-2025 Movatter.jp