<s> from __future__ import absolute_import , division , print_function <EOL> from . constants import MIME_TYPE , PNG_CHUNK_TYPE <EOL> from . exceptions import InvalidImageStreamError <EOL> from . helpers import BIG_ENDIAN , StreamReader <EOL> from . image import BaseImageHeader <EOL> class Png ( BaseImageHeader ) : <EOL> """<STR_LIT>""" <EOL> @ property <EOL> def content_type ( self ) : <EOL> """<STR_LIT>""" <EOL> return MIME_TYPE . PNG <EOL> @ property <EOL> def default_ext ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' <EOL> @ classmethod <EOL> def from_stream ( cls , stream ) : <EOL> """<STR_LIT>""" <EOL> parser = _PngParser . parse ( stream ) <EOL> px_width = parser . px_width <EOL> px_height = parser . px_height <EOL> horz_dpi = parser . horz_dpi <EOL> vert_dpi = parser . vert_dpi <EOL> return cls ( px_width , px_height , horz_dpi , vert_dpi ) <EOL> class _PngParser ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chunks ) : <EOL> super ( _PngParser , self ) . __init__ ( ) <EOL> self . _chunks = chunks <EOL> @ classmethod <EOL> def parse ( cls , stream ) : <EOL> """<STR_LIT>""" <EOL> chunks = _Chunks . from_stream ( stream ) <EOL> return cls ( chunks ) <EOL> @ property <EOL> def px_width ( self ) : <EOL> """<STR_LIT>""" <EOL> IHDR = self . _chunks . IHDR <EOL> return IHDR . px_width <EOL> @ property <EOL> def px_height ( self ) : <EOL> """<STR_LIT>""" <EOL> IHDR = self . _chunks . IHDR <EOL> return IHDR . px_height <EOL> @ property <EOL> def horz_dpi ( self ) : <EOL> """<STR_LIT>""" <EOL> pHYs = self . _chunks . pHYs <EOL> if pHYs is None : <EOL> return <NUM_LIT> <EOL> return self . _dpi ( pHYs . units_specifier , pHYs . horz_px_per_unit ) <EOL> @ property <EOL> def vert_dpi ( self ) : <EOL> """<STR_LIT>""" <EOL> pHYs = self . _chunks . pHYs <EOL> if pHYs is None : <EOL> return <NUM_LIT> <EOL> return self . _dpi ( pHYs . units_specifier , pHYs . vert_px_per_unit ) <EOL> @ staticmethod <EOL> def _dpi ( units_specifier , px_per_unit ) : <EOL> """<STR_LIT>""" <EOL> if units_specifier == <NUM_LIT:1> and px_per_unit : <EOL> return int ( round ( px_per_unit * <NUM_LIT> ) ) <EOL> return <NUM_LIT> <EOL> class _Chunks ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chunk_iterable ) : <EOL> super ( _Chunks , self ) . __init__ ( ) <EOL> self . _chunks = list ( chunk_iterable ) <EOL> @ classmethod <EOL> def from_stream ( cls , stream ) : <EOL> """<STR_LIT>""" <EOL> chunk_parser = _ChunkParser . from_stream ( stream ) <EOL> chunks = [ chunk for chunk in chunk_parser . iter_chunks ( ) ] <EOL> return cls ( chunks ) <EOL> @ property <EOL> def IHDR ( self ) : <EOL> """<STR_LIT>""" <EOL> match = lambda chunk : chunk . type_name == PNG_CHUNK_TYPE . IHDR <EOL> IHDR = self . _find_first ( match ) <EOL> if IHDR is None : <EOL> raise InvalidImageStreamError ( '<STR_LIT>' ) <EOL> return IHDR <EOL> @ property <EOL> def pHYs ( self ) : <EOL> """<STR_LIT>""" <EOL> match = lambda chunk : chunk . type_name == PNG_CHUNK_TYPE . pHYs <EOL> return self . _find_first ( match ) <EOL> def _find_first ( self , match ) : <EOL> """<STR_LIT>""" <EOL> for chunk in self . _chunks : <EOL> if match ( chunk ) : <EOL> return chunk <EOL> return None <EOL> class _ChunkParser ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , stream_rdr ) : <EOL> super ( _ChunkParser , self ) . __init__ ( ) <EOL> self . _stream_rdr = stream_rdr <EOL> @ classmethod <EOL> def from_stream ( cls , stream ) : <EOL> """<STR_LIT>""" <EOL> stream_rdr = StreamReader ( stream , BIG_ENDIAN ) <EOL> return cls ( stream_rdr ) <EOL> def iter_chunks ( self ) : <EOL> """<STR_LIT>""" <EOL> for chunk_type , offset in self . _iter_chunk_offsets ( ) : <EOL> chunk = _ChunkFactory ( chunk_type , self . _stream_rdr , offset ) <EOL> yield chunk <EOL> def _iter_chunk_offsets ( self ) : <EOL> """<STR_LIT>""" <EOL> chunk_offset = <NUM_LIT:8> <EOL> while True : <EOL> chunk_data_len = self . _stream_rdr . read_long ( chunk_offset ) <EOL> chunk_type = self . _stream_rdr . read_str ( <NUM_LIT:4> , chunk_offset , <NUM_LIT:4> ) <EOL> data_offset = chunk_offset + <NUM_LIT:8> <EOL> yield chunk_type , data_offset <EOL> if chunk_type == '<STR_LIT>' : <EOL> break <EOL> chunk_offset += ( <NUM_LIT:4> + <NUM_LIT:4> + chunk_data_len + <NUM_LIT:4> ) <EOL> def _ChunkFactory ( chunk_type , stream_rdr , offset ) : <EOL> """<STR_LIT>""" <EOL> chunk_cls_map = { <EOL> PNG_CHUNK_TYPE . IHDR : _IHDRChunk , <EOL> PNG_CHUNK_TYPE . pHYs : _pHYsChunk , <EOL> } <EOL> chunk_cls = chunk_cls_map . get ( chunk_type , _Chunk ) <EOL> return chunk_cls . from_offset ( chunk_type , stream_rdr , offset ) <EOL> class _Chunk ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chunk_type ) : <EOL> super ( _Chunk , self ) . __init__ ( ) <EOL> self . _chunk_type = chunk_type <EOL> @ classmethod <EOL> def from_offset ( cls , chunk_type , stream_rdr , offset ) : <EOL> """<STR_LIT>""" <EOL> return cls ( chunk_type ) <EOL> @ property <EOL> def type_name ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _chunk_type <EOL> class _IHDRChunk ( _Chunk ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chunk_type , px_width , px_height ) : <EOL> super ( _IHDRChunk , self ) . __init__ ( chunk_type ) <EOL> self . _px_width = px_width <EOL> self . _px_height = px_height <EOL> @ classmethod <EOL> def from_offset ( cls , chunk_type , stream_rdr , offset ) : <EOL> """<STR_LIT>""" <EOL> px_width = stream_rdr . read_long ( offset ) <EOL> px_height = stream_rdr . read_long ( offset , <NUM_LIT:4> ) <EOL> return cls ( chunk_type , px_width , px_height ) <EOL> @ property <EOL> def px_width ( self ) : <EOL> return self . _px_width <EOL> @ property <EOL> def px_height ( self ) : <EOL> return self . _px_height <EOL> class _pHYsChunk ( _Chunk ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , chunk_type , horz_px_per_unit , vert_px_per_unit , <EOL> units_specifier ) : <EOL> super ( _pHYsChunk , self ) . __init__ ( chunk_type ) <EOL> self . _horz_px_per_unit = horz_px_per_unit <EOL> self . _vert_px_per_unit = vert_px_per_unit <EOL> self . _units_specifier = units_specifier <EOL> @ classmethod <EOL> def from_offset ( cls , chunk_type , stream_rdr , offset ) : <EOL> """<STR_LIT>""" <EOL> horz_px_per_unit = stream_rdr . read_long ( offset ) <EOL> vert_px_per_unit = stream_rdr . read_long ( offset , <NUM_LIT:4> ) <EOL> units_specifier = stream_rdr . read_byte ( offset , <NUM_LIT:8> ) <EOL> return cls ( <EOL> chunk_type , horz_px_per_unit , vert_px_per_unit , units_specifier <EOL> ) <EOL> @ property <EOL> def horz_px_per_unit ( self ) : <EOL> return self . _horz_px_per_unit <EOL> @ property <EOL> def vert_px_per_unit ( self ) : <EOL> return self . _vert_px_per_unit <EOL> @ property <EOL> def units_specifier ( self ) : <EOL> return self . _units_specifier </s>
