## The Python Imaging Library# $Id$## FITS file handling## Copyright (c) 1998-2003 by Fredrik Lundh## See the README file for information on usage and redistribution.#from__future__importannotationsimportgzipimportmathfrom.importImage,ImageFiledef_accept(prefix:bytes)->bool:returnprefix.startswith(b"SIMPLE")
[docs]classFitsImageFile(ImageFile.ImageFile):format="FITS"format_description="FITS"def_open(self)->None:assertself.fpisnotNoneheaders:dict[bytes,bytes]={}header_in_progress=Falsedecoder_name=""whileTrue:header=self.fp.read(80)ifnotheader:msg="Truncated FITS file"raiseOSError(msg)keyword=header[:8].strip()ifkeywordin(b"SIMPLE",b"XTENSION"):header_in_progress=Trueelifheadersandnotheader_in_progress:# This is now a data unitbreakelifkeyword==b"END":# Seek to the end of the header unitself.fp.seek(math.ceil(self.fp.tell()/2880)*2880)ifnotdecoder_name:decoder_name,offset,args=self._parse_headers(headers)header_in_progress=Falsecontinueifdecoder_name:# Keep going to read past the headerscontinuevalue=header[8:].split(b"/")[0].strip()ifvalue.startswith(b"="):value=value[1:].strip()ifnotheadersand(not_accept(keyword)orvalue!=b"T"):msg="Not a FITS file"raiseSyntaxError(msg)headers[keyword]=valueifnotdecoder_name:msg="No image data"raiseValueError(msg)offset+=self.fp.tell()-80self.tile=[ImageFile._Tile(decoder_name,(0,0)+self.size,offset,args)]def_get_size(self,headers:dict[bytes,bytes],prefix:bytes)->tuple[int,int]|None:naxis=int(headers[prefix+b"NAXIS"])ifnaxis==0:returnNoneifnaxis==1:return1,int(headers[prefix+b"NAXIS1"])else:returnint(headers[prefix+b"NAXIS1"]),int(headers[prefix+b"NAXIS2"])def_parse_headers(self,headers:dict[bytes,bytes])->tuple[str,int,tuple[str|int,...]]:prefix=b""decoder_name="raw"offset=0if(headers.get(b"XTENSION")==b"'BINTABLE'"andheaders.get(b"ZIMAGE")==b"T"andheaders[b"ZCMPTYPE"]==b"'GZIP_1 '"):no_prefix_size=self._get_size(headers,prefix)or(0,0)number_of_bits=int(headers[b"BITPIX"])offset=no_prefix_size[0]*no_prefix_size[1]*(number_of_bits//8)prefix=b"Z"decoder_name="fits_gzip"size=self._get_size(headers,prefix)ifnotsize:return"",0,()self._size=sizenumber_of_bits=int(headers[prefix+b"BITPIX"])ifnumber_of_bits==8:self._mode="L"elifnumber_of_bits==16:self._mode="I;16"elifnumber_of_bits==32:self._mode="I"elifnumber_of_bitsin(-32,-64):self._mode="F"args:tuple[str|int,...]ifdecoder_name=="raw":args=(self.mode,0,-1)else:args=(number_of_bits,)returndecoder_name,offset,args