{
    "file_diffs": [
        {
            "old_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# PNG support code\n#\n# See \"PNG (Portable Network Graphics) Specification, version 1.0;\n# W3C Recommendation\", 1996-10-01, Thomas Boutell (ed.).\n#\n# history:\n# 1996-05-06 fl   Created (couldn't resist it)\n# 1996-12-14 fl   Upgraded, added read and verify support (0.2)\n# 1996-12-15 fl   Separate PNG stream parser\n# 1996-12-29 fl   Added write support, added getchunks\n# 1996-12-30 fl   Eliminated circular references in decoder (0.3)\n# 1998-07-12 fl   Read/write 16-bit images as mode I (0.4)\n# 2001-02-08 fl   Added transparency support (from Zircon) (0.5)\n# 2001-04-16 fl   Don't close data source in \"open\" method (0.6)\n# 2004-02-24 fl   Don't even pretend to support interlaced files (0.7)\n# 2004-08-31 fl   Do basic sanity check on chunk identifiers (0.8)\n# 2004-09-20 fl   Added PngInfo chunk container\n# 2004-12-18 fl   Added DPI read support (based on code by Niki Spahiev)\n# 2008-08-13 fl   Added tRNS support for RGB images\n# 2009-03-06 fl   Support for preserving ICC profiles (by Florian Hoech)\n# 2009-03-08 fl   Added zTXT support (from Lowell Alleman)\n# 2009-03-29 fl   Read interlaced PNG files (from Conrado Porto Lopes Gouvua)\n#\n# Copyright (c) 1997-2009 by Secret Labs AB\n# Copyright (c) 1996 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom __future__ import print_function\n\nimport logging\nimport re\nimport zlib\nimport struct\n\nfrom PIL import Image, ImageFile, ImagePalette, _binary\n\n__version__ = \"0.9\"\n\nlogger = logging.getLogger(__name__)\n\ni8 = _binary.i8\ni16 = _binary.i16be\ni32 = _binary.i32be\n\nis_cid = re.compile(b\"\\w\\w\\w\\w\").match\n\n\n_MAGIC = b\"\\211PNG\\r\\n\\032\\n\"\n\n\n_MODES = {\n    # supported bits/color combinations, and corresponding modes/rawmodes\n    (1, 0):  (\"1\", \"1\"),\n    (2, 0):  (\"L\", \"L;2\"),\n    (4, 0):  (\"L\", \"L;4\"),\n    (8, 0):  (\"L\", \"L\"),\n    (16, 0): (\"I\", \"I;16B\"),\n    (8, 2):  (\"RGB\", \"RGB\"),\n    (16, 2): (\"RGB\", \"RGB;16B\"),\n    (1, 3):  (\"P\", \"P;1\"),\n    (2, 3):  (\"P\", \"P;2\"),\n    (4, 3):  (\"P\", \"P;4\"),\n    (8, 3):  (\"P\", \"P\"),\n    (8, 4):  (\"LA\", \"LA\"),\n    (16, 4): (\"RGBA\", \"LA;16B\"),  # LA;16B->LA not yet available\n    (8, 6):  (\"RGBA\", \"RGBA\"),\n    (16, 6): (\"RGBA\", \"RGBA;16B\"),\n}\n\n\n_simple_palette = re.compile(b'^\\xff*\\x00\\xff*$')\n\n# Maximum decompressed size for a iTXt or zTXt chunk.\n# Eliminates decompression bombs where compressed chunks can expand 1000x\nMAX_TEXT_CHUNK = ImageFile.SAFEBLOCK\n# Set the maximum total text chunk size.\nMAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK\n\n\ndef _safe_zlib_decompress(s):\n    dobj = zlib.decompressobj()\n    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)\n    if dobj.unconsumed_tail:\n        raise ValueError(\"Decompressed Data Too Large\")\n    return plaintext\n\n\n# --------------------------------------------------------------------\n# Support classes.  Suitable for PNG and related formats like MNG etc.\n\nclass ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids\n\n\nclass iTXt(str):\n    \"\"\"\n    Subclass of string to allow iTXt chunks to look like strings while\n    keeping their extra information\n\n    \"\"\"\n    @staticmethod\n    def __new__(cls, text, lang, tkey):\n        \"\"\"\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        \"\"\"\n\n        self = str.__new__(cls, text)\n        self.lang = lang\n        self.tkey = tkey\n        return self\n\n\nclass PngInfo(object):\n    \"\"\"\n    PNG chunk container (for use with save(pnginfo=))\n\n    \"\"\"\n\n    def __init__(self):\n        self.chunks = []\n\n    def add(self, cid, data):\n        \"\"\"Appends an arbitrary chunk. Use with caution.\n\n        :param cid: a byte string, 4 bytes long.\n        :param data: a byte string of the encoded data\n\n        \"\"\"\n\n        self.chunks.append((cid, data))\n\n    def add_itxt(self, key, value, lang=\"\", tkey=\"\", zip=False):\n        \"\"\"Appends an iTXt chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        :param zip: compression flag\n\n        \"\"\"\n\n        if not isinstance(key, bytes):\n            key = key.encode(\"latin-1\", \"strict\")\n        if not isinstance(value, bytes):\n            value = value.encode(\"utf-8\", \"strict\")\n        if not isinstance(lang, bytes):\n            lang = lang.encode(\"utf-8\", \"strict\")\n        if not isinstance(tkey, bytes):\n            tkey = tkey.encode(\"utf-8\", \"strict\")\n\n        if zip:\n            self.add(b\"iTXt\", key + b\"\\0\\x01\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     zlib.compress(value))\n        else:\n            self.add(b\"iTXt\", key + b\"\\0\\0\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     value)\n\n    def add_text(self, key, value, zip=0):\n        \"\"\"Appends a text chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key, text or an\n           :py:class:`PIL.PngImagePlugin.iTXt` instance\n        :param zip: compression flag\n\n        \"\"\"\n        if isinstance(value, iTXt):\n            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))\n\n        # The tEXt chunk stores latin-1 text\n        if not isinstance(value, bytes):\n            try:\n                value = value.encode('latin-1', 'strict')\n            except UnicodeError:\n                return self.add_itxt(key, value, zip=bool(zip))\n\n        if not isinstance(key, bytes):\n            key = key.encode('latin-1', 'strict')\n\n        if zip:\n            self.add(b\"zTXt\", key + b\"\\0\\0\" + zlib.compress(value))\n        else:\n            self.add(b\"tEXt\", key + b\"\\0\" + value)\n\n\n# --------------------------------------------------------------------\n# PNG image stream (IHDR/IEND)\n\nclass PngStream(ChunkStream):\n\n    def __init__(self, fp):\n\n        ChunkStream.__init__(self, fp)\n\n        # local copies of Image attributes\n        self.im_info = {}\n        self.im_text = {}\n        self.im_size = (0, 0)\n        self.im_mode = None\n        self.im_tile = None\n        self.im_palette = None\n\n        self.text_memory = 0\n\n    def check_text_memory(self, chunklen):\n        self.text_memory += chunklen\n        if self.text_memory > MAX_TEXT_MEMORY:\n            raise ValueError(\"Too much memory used in text chunks: %s>MAX_TEXT_MEMORY\" %\n                             self.text_memory)\n\n    def chunk_iCCP(self, pos, length):\n\n        # ICC profile\n        s = ImageFile._safe_read(self.fp, length)\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        i = s.find(b\"\\0\")\n        logger.debug(\"iCCP profile name %s\", s[:i])\n        logger.debug(\"Compression method %s\", i8(s[i]))\n        comp_method = i8(s[i])\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in iCCP chunk\" %\n                              comp_method)\n        try:\n            icc_profile = _safe_zlib_decompress(s[i+2:])\n        except zlib.error:\n            icc_profile = None  # FIXME\n        self.im_info[\"icc_profile\"] = icc_profile\n        return s\n\n    def chunk_IHDR(self, pos, length):\n\n        # image header\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_size = i32(s), i32(s[4:])\n        try:\n            self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))]\n        except:\n            pass\n        if i8(s[12]):\n            self.im_info[\"interlace\"] = 1\n        if i8(s[11]):\n            raise SyntaxError(\"unknown filter category\")\n        return s\n\n    def chunk_IDAT(self, pos, length):\n\n        # image data\n        self.im_tile = [(\"zip\", (0, 0)+self.im_size, pos, self.im_rawmode)]\n        self.im_idat = length\n        raise EOFError\n\n    def chunk_IEND(self, pos, length):\n\n        # end of PNG image\n        raise EOFError\n\n    def chunk_PLTE(self, pos, length):\n\n        # palette\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            self.im_palette = \"RGB\", s\n        return s\n\n    def chunk_tRNS(self, pos, length):\n\n        # transparency\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            if _simple_palette.match(s):\n                # tRNS contains only one full-transparent entry,\n                # other entries are full opaque\n                i = s.find(b\"\\0\")\n                if i >= 0:\n                    self.im_info[\"transparency\"] = i\n            else:\n                # otherwise, we have a byte string with one alpha value\n                # for each palette entry\n                self.im_info[\"transparency\"] = s\n        elif self.im_mode == \"L\":\n            self.im_info[\"transparency\"] = i16(s)\n        elif self.im_mode == \"RGB\":\n            self.im_info[\"transparency\"] = i16(s), i16(s[2:]), i16(s[4:])\n        return s\n\n    def chunk_gAMA(self, pos, length):\n\n        # gamma setting\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_info[\"gamma\"] = i32(s) / 100000.0\n        return s\n\n    def chunk_pHYs(self, pos, length):\n\n        # pixels per unit\n        s = ImageFile._safe_read(self.fp, length)\n        px, py = i32(s), i32(s[4:])\n        unit = i8(s[8])\n        if unit == 1:  # meter\n            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)\n            self.im_info[\"dpi\"] = dpi\n        elif unit == 0:\n            self.im_info[\"aspect\"] = px, py\n        return s\n\n    def chunk_tEXt(self, pos, length):\n\n        # text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            # fallback for broken tEXt tags\n            k = s\n            v = b\"\"\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_zTXt(self, pos, length):\n\n        # compressed text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            k = s\n            v = b\"\"\n        if v:\n            comp_method = i8(v[0])\n        else:\n            comp_method = 0\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in zTXt chunk\" %\n                              comp_method)\n        try:\n            v = _safe_zlib_decompress(v[1:])\n        except zlib.error:\n            v = b\"\"\n\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_iTXt(self, pos, length):\n\n        # international text\n        r = s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, r = r.split(b\"\\0\", 1)\n        except ValueError:\n            return s\n        if len(r) < 2:\n            return s\n        cf, cm, r = i8(r[0]), i8(r[1]), r[2:]\n        try:\n            lang, tk, v = r.split(b\"\\0\", 2)\n        except ValueError:\n            return s\n        if cf != 0:\n            if cm == 0:\n                try:\n                    v = _safe_zlib_decompress(v)\n                except zlib.error:\n                    return s\n            else:\n                return s\n        if bytes is not str:\n            try:\n                k = k.decode(\"latin-1\", \"strict\")\n                lang = lang.decode(\"utf-8\", \"strict\")\n                tk = tk.decode(\"utf-8\", \"strict\")\n                v = v.decode(\"utf-8\", \"strict\")\n            except UnicodeError:\n                return s\n\n        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)\n        self.check_text_memory(len(v))\n\n        return s\n\n\n# --------------------------------------------------------------------\n# PNG reader\n\ndef _accept(prefix):\n    return prefix[:8] == _MAGIC\n\n\n##\n# Image plugin for PNG images.\n\nclass PngImageFile(ImageFile.ImageFile):\n\n    format = \"PNG\"\n    format_description = \"Portable network graphics\"\n\n    def _open(self):\n\n        if self.fp.read(8) != _MAGIC:\n            raise SyntaxError(\"not a PNG file\")\n\n        #\n        # Parse headers up to the first IDAT chunk\n\n        self.png = PngStream(self.fp)\n\n        while True:\n\n            #\n            # get next chunk\n\n            cid, pos, length = self.png.read()\n\n            try:\n                s = self.png.call(cid, pos, length)\n            except EOFError:\n                break\n            except AttributeError:\n                logger.debug(\"%s %s %s (unknown)\", cid, pos, length)\n                s = ImageFile._safe_read(self.fp, length)\n\n            self.png.crc(cid, s)\n\n        #\n        # Copy relevant attributes from the PngStream.  An alternative\n        # would be to let the PngStream class modify these attributes\n        # directly, but that introduces circular references which are\n        # difficult to break if things go wrong in the decoder...\n        # (believe me, I've tried ;-)\n\n        self.mode = self.png.im_mode\n        self.size = self.png.im_size\n        self.info = self.png.im_info\n        self.text = self.png.im_text  # experimental\n        self.tile = self.png.im_tile\n\n        if self.png.im_palette:\n            rawmode, data = self.png.im_palette\n            self.palette = ImagePalette.raw(rawmode, data)\n\n        self.__idat = length  # used by load_read()\n\n    def verify(self):\n        \"Verify PNG file\"\n\n        if self.fp is None:\n            raise RuntimeError(\"verify must be called directly after open\")\n\n        # back up to beginning of IDAT block\n        self.fp.seek(self.tile[0][2] - 8)\n\n        self.png.verify()\n        self.png.close()\n\n        self.fp = None\n\n    def load_prepare(self):\n        \"internal: prepare to read PNG file\"\n\n        if self.info.get(\"interlace\"):\n            self.decoderconfig = self.decoderconfig + (1,)\n\n        ImageFile.ImageFile.load_prepare(self)\n\n    def load_read(self, read_bytes):\n        \"internal: read more image data\"\n\n        while self.__idat == 0:\n            # end of chunk, skip forward to next one\n\n            self.fp.read(4)  # CRC\n\n            cid, pos, length = self.png.read()\n\n            if cid not in [b\"IDAT\", b\"DDAT\"]:\n                self.png.push(cid, pos, length)\n                return b\"\"\n\n            self.__idat = length  # empty chunks are allowed\n\n        # read more data from this chunk\n        if read_bytes <= 0:\n            read_bytes = self.__idat\n        else:\n            read_bytes = min(read_bytes, self.__idat)\n\n        self.__idat = self.__idat - read_bytes\n\n        return self.fp.read(read_bytes)\n\n    def load_end(self):\n        \"internal: finished reading image data\"\n\n        self.png.close()\n        self.png = None\n\n\n# --------------------------------------------------------------------\n# PNG writer\n\no8 = _binary.o8\no16 = _binary.o16be\no32 = _binary.o32be\n\n_OUTMODES = {\n    # supported PIL modes, and corresponding rawmodes/bits/color combinations\n    \"1\":    (\"1\",       b'\\x01\\x00'),\n    \"L;1\":  (\"L;1\",     b'\\x01\\x00'),\n    \"L;2\":  (\"L;2\",     b'\\x02\\x00'),\n    \"L;4\":  (\"L;4\",     b'\\x04\\x00'),\n    \"L\":    (\"L\",       b'\\x08\\x00'),\n    \"LA\":   (\"LA\",      b'\\x08\\x04'),\n    \"I\":    (\"I;16B\",   b'\\x10\\x00'),\n    \"P;1\":  (\"P;1\",     b'\\x01\\x03'),\n    \"P;2\":  (\"P;2\",     b'\\x02\\x03'),\n    \"P;4\":  (\"P;4\",     b'\\x04\\x03'),\n    \"P\":    (\"P\",       b'\\x08\\x03'),\n    \"RGB\":  (\"RGB\",     b'\\x08\\x02'),\n    \"RGBA\": (\"RGBA\",    b'\\x08\\x06'),\n}\n\n\ndef putchunk(fp, cid, *data):\n    \"Write a PNG chunk (including CRC field)\"\n\n    data = b\"\".join(data)\n\n    fp.write(o32(len(data)) + cid)\n    fp.write(data)\n    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n    fp.write(o16(hi) + o16(lo))\n\n\nclass _idat(object):\n    # wrap output from the encoder in IDAT chunks\n\n    def __init__(self, fp, chunk):\n        self.fp = fp\n        self.chunk = chunk\n\n    def write(self, data):\n        self.chunk(self.fp, b\"IDAT\", data)\n\n\ndef _save(im, fp, filename, chunk=putchunk, check=0):\n    # save an image to disk (called by the save method)\n\n    mode = im.mode\n\n    if mode == \"P\":\n\n        #\n        # attempt to minimize storage requirements for palette images\n        if \"bits\" in im.encoderinfo:\n            # number of bits specified by user\n            colors = 1 << im.encoderinfo[\"bits\"]\n        else:\n            # check palette contents\n            if im.palette:\n                colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)\n            else:\n                colors = 256\n\n        if colors <= 2:\n            bits = 1\n        elif colors <= 4:\n            bits = 2\n        elif colors <= 16:\n            bits = 4\n        else:\n            bits = 8\n        if bits != 8:\n            mode = \"%s;%d\" % (mode, bits)\n\n    # encoder options\n    if \"dictionary\" in im.encoderinfo:\n        dictionary = im.encoderinfo[\"dictionary\"]\n    else:\n        dictionary = b\"\"\n\n    im.encoderconfig = (\"optimize\" in im.encoderinfo,\n                        im.encoderinfo.get(\"compress_level\", -1),\n                        im.encoderinfo.get(\"compress_type\", -1),\n                        dictionary)\n\n    # get the corresponding PNG mode\n    try:\n        rawmode, mode = _OUTMODES[mode]\n    except KeyError:\n        raise IOError(\"cannot write mode %s as PNG\" % mode)\n\n    if check:\n        return check\n\n    #\n    # write minimal PNG file\n\n    fp.write(_MAGIC)\n\n    chunk(fp, b\"IHDR\",\n          o32(im.size[0]), o32(im.size[1]),     # 0: size\n          mode,                                 # 8: depth/type\n          b'\\0',                                # 10: compression\n          b'\\0',                                # 11: filter category\n          b'\\0')                                # 12: interlace flag\n\n    if im.mode == \"P\":\n        palette_byte_number = (2 ** bits) * 3\n        palette_bytes = im.im.getpalette(\"RGB\")[:palette_byte_number]\n        while len(palette_bytes) < palette_byte_number:\n            palette_bytes += b'\\0'\n        chunk(fp, b\"PLTE\", palette_bytes)\n\n    transparency = im.encoderinfo.get('transparency',\n                                      im.info.get('transparency', None))\n\n    if transparency or transparency == 0:\n        if im.mode == \"P\":\n            # limit to actual palette size\n            alpha_bytes = 2**bits\n            if isinstance(transparency, bytes):\n                chunk(fp, b\"tRNS\", transparency[:alpha_bytes])\n            else:\n                transparency = max(0, min(255, transparency))\n                alpha = b'\\xFF' * transparency + b'\\0'\n                chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n        elif im.mode == \"L\":\n            transparency = max(0, min(65535, transparency))\n            chunk(fp, b\"tRNS\", o16(transparency))\n        elif im.mode == \"RGB\":\n            red, green, blue = transparency\n            chunk(fp, b\"tRNS\", o16(red) + o16(green) + o16(blue))\n        else:\n            if \"transparency\" in im.encoderinfo:\n                # don't bother with transparency if it's an RGBA\n                # and it's in the info dict. It's probably just stale.\n                raise IOError(\"cannot use transparency for this mode\")\n    else:\n        if im.mode == \"P\" and im.im.getpalettemode() == \"RGBA\":\n            alpha = im.im.getpalette(\"RGBA\", \"A\")\n            alpha_bytes = 2**bits\n            chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n\n    dpi = im.encoderinfo.get(\"dpi\")\n    if dpi:\n        chunk(fp, b\"pHYs\",\n              o32(int(dpi[0] / 0.0254 + 0.5)),\n              o32(int(dpi[1] / 0.0254 + 0.5)),\n              b'\\x01')\n\n    info = im.encoderinfo.get(\"pnginfo\")\n    if info:\n        for cid, data in info.chunks:\n            chunk(fp, cid, data)\n\n    # ICC profile writing support -- 2008-06-06 Florian Hoech\n    if im.info.get(\"icc_profile\"):\n        # ICC profile\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        name = b\"ICC Profile\"\n        data = name + b\"\\0\\0\" + zlib.compress(im.info[\"icc_profile\"])\n        chunk(fp, b\"iCCP\", data)\n\n    ImageFile._save(im, _idat(fp, chunk),\n                    [(\"zip\", (0, 0)+im.size, 0, rawmode)])\n\n    chunk(fp, b\"IEND\", b\"\")\n\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\n# --------------------------------------------------------------------\n# PNG chunk converter\n\ndef getchunks(im, **params):\n    \"\"\"Return a list of PNG chunks representing this image.\"\"\"\n\n    class collector(object):\n        data = []\n\n        def write(self, data):\n            pass\n\n        def append(self, chunk):\n            self.data.append(chunk)\n\n    def append(fp, cid, *data):\n        data = b\"\".join(data)\n        hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n        crc = o16(hi) + o16(lo)\n        fp.append((cid, data, crc))\n\n    fp = collector()\n\n    try:\n        im.encoderinfo = params\n        _save(im, fp, None, append)\n    finally:\n        del im.encoderinfo\n\n    return fp.data\n\n\n# --------------------------------------------------------------------\n# Registry\n\nImage.register_open(PngImageFile.format, PngImageFile, _accept)\nImage.register_save(PngImageFile.format, _save)\n\nImage.register_extension(PngImageFile.format, \".png\")\n\nImage.register_mime(PngImageFile.format, \"image/png\")\n",
            "new_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# PNG support code\n#\n# See \"PNG (Portable Network Graphics) Specification, version 1.0;\n# W3C Recommendation\", 1996-10-01, Thomas Boutell (ed.).\n#\n# history:\n# 1996-05-06 fl   Created (couldn't resist it)\n# 1996-12-14 fl   Upgraded, added read and verify support (0.2)\n# 1996-12-15 fl   Separate PNG stream parser\n# 1996-12-29 fl   Added write support, added getchunks\n# 1996-12-30 fl   Eliminated circular references in decoder (0.3)\n# 1998-07-12 fl   Read/write 16-bit images as mode I (0.4)\n# 2001-02-08 fl   Added transparency support (from Zircon) (0.5)\n# 2001-04-16 fl   Don't close data source in \"open\" method (0.6)\n# 2004-02-24 fl   Don't even pretend to support interlaced files (0.7)\n# 2004-08-31 fl   Do basic sanity check on chunk identifiers (0.8)\n# 2004-09-20 fl   Added PngInfo chunk container\n# 2004-12-18 fl   Added DPI read support (based on code by Niki Spahiev)\n# 2008-08-13 fl   Added tRNS support for RGB images\n# 2009-03-06 fl   Support for preserving ICC profiles (by Florian Hoech)\n# 2009-03-08 fl   Added zTXT support (from Lowell Alleman)\n# 2009-03-29 fl   Read interlaced PNG files (from Conrado Porto Lopes Gouvua)\n#\n# Copyright (c) 1997-2009 by Secret Labs AB\n# Copyright (c) 1996 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom __future__ import print_function\n\nimport logging\nimport re\nimport zlib\nimport struct\n\nfrom PIL import Image, ImageFile, ImagePalette, _binary\n\n__version__ = \"0.9\"\n\nlogger = logging.getLogger(__name__)\n\ni8 = _binary.i8\ni16 = _binary.i16be\ni32 = _binary.i32be\n\nis_cid = re.compile(b\"\\w\\w\\w\\w\").match\n\n\n_MAGIC = b\"\\211PNG\\r\\n\\032\\n\"\n\n\n_MODES = {\n    # supported bits/color combinations, and corresponding modes/rawmodes\n    (1, 0):  (\"1\", \"1\"),\n    (2, 0):  (\"L\", \"L;2\"),\n    (4, 0):  (\"L\", \"L;4\"),\n    (8, 0):  (\"L\", \"L\"),\n    (16, 0): (\"I\", \"I;16B\"),\n    (8, 2):  (\"RGB\", \"RGB\"),\n    (16, 2): (\"RGB\", \"RGB;16B\"),\n    (1, 3):  (\"P\", \"P;1\"),\n    (2, 3):  (\"P\", \"P;2\"),\n    (4, 3):  (\"P\", \"P;4\"),\n    (8, 3):  (\"P\", \"P\"),\n    (8, 4):  (\"LA\", \"LA\"),\n    (16, 4): (\"RGBA\", \"LA;16B\"),  # LA;16B->LA not yet available\n    (8, 6):  (\"RGBA\", \"RGBA\"),\n    (16, 6): (\"RGBA\", \"RGBA;16B\"),\n}\n\n\n_simple_palette = re.compile(b'^\\xff*\\x00\\xff*$')\n\n# Maximum decompressed size for a iTXt or zTXt chunk.\n# Eliminates decompression bombs where compressed chunks can expand 1000x\nMAX_TEXT_CHUNK = ImageFile.SAFEBLOCK\n# Set the maximum total text chunk size.\nMAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK\n\n\ndef _safe_zlib_decompress(s):\n    dobj = zlib.decompressobj()\n    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)\n    if dobj.unconsumed_tail:\n        raise ValueError(\"Decompressed Data Too Large\")\n    return plaintext\n\n\n# --------------------------------------------------------------------\n# Support classes.  Suitable for PNG and related formats like MNG etc.\n\nclass ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (i8(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids\n\n\nclass iTXt(str):\n    \"\"\"\n    Subclass of string to allow iTXt chunks to look like strings while\n    keeping their extra information\n\n    \"\"\"\n    @staticmethod\n    def __new__(cls, text, lang, tkey):\n        \"\"\"\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        \"\"\"\n\n        self = str.__new__(cls, text)\n        self.lang = lang\n        self.tkey = tkey\n        return self\n\n\nclass PngInfo(object):\n    \"\"\"\n    PNG chunk container (for use with save(pnginfo=))\n\n    \"\"\"\n\n    def __init__(self):\n        self.chunks = []\n\n    def add(self, cid, data):\n        \"\"\"Appends an arbitrary chunk. Use with caution.\n\n        :param cid: a byte string, 4 bytes long.\n        :param data: a byte string of the encoded data\n\n        \"\"\"\n\n        self.chunks.append((cid, data))\n\n    def add_itxt(self, key, value, lang=\"\", tkey=\"\", zip=False):\n        \"\"\"Appends an iTXt chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        :param zip: compression flag\n\n        \"\"\"\n\n        if not isinstance(key, bytes):\n            key = key.encode(\"latin-1\", \"strict\")\n        if not isinstance(value, bytes):\n            value = value.encode(\"utf-8\", \"strict\")\n        if not isinstance(lang, bytes):\n            lang = lang.encode(\"utf-8\", \"strict\")\n        if not isinstance(tkey, bytes):\n            tkey = tkey.encode(\"utf-8\", \"strict\")\n\n        if zip:\n            self.add(b\"iTXt\", key + b\"\\0\\x01\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     zlib.compress(value))\n        else:\n            self.add(b\"iTXt\", key + b\"\\0\\0\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     value)\n\n    def add_text(self, key, value, zip=0):\n        \"\"\"Appends a text chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key, text or an\n           :py:class:`PIL.PngImagePlugin.iTXt` instance\n        :param zip: compression flag\n\n        \"\"\"\n        if isinstance(value, iTXt):\n            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))\n\n        # The tEXt chunk stores latin-1 text\n        if not isinstance(value, bytes):\n            try:\n                value = value.encode('latin-1', 'strict')\n            except UnicodeError:\n                return self.add_itxt(key, value, zip=bool(zip))\n\n        if not isinstance(key, bytes):\n            key = key.encode('latin-1', 'strict')\n\n        if zip:\n            self.add(b\"zTXt\", key + b\"\\0\\0\" + zlib.compress(value))\n        else:\n            self.add(b\"tEXt\", key + b\"\\0\" + value)\n\n\n# --------------------------------------------------------------------\n# PNG image stream (IHDR/IEND)\n\nclass PngStream(ChunkStream):\n\n    def __init__(self, fp):\n\n        ChunkStream.__init__(self, fp)\n\n        # local copies of Image attributes\n        self.im_info = {}\n        self.im_text = {}\n        self.im_size = (0, 0)\n        self.im_mode = None\n        self.im_tile = None\n        self.im_palette = None\n\n        self.text_memory = 0\n\n    def check_text_memory(self, chunklen):\n        self.text_memory += chunklen\n        if self.text_memory > MAX_TEXT_MEMORY:\n            raise ValueError(\"Too much memory used in text chunks: %s>MAX_TEXT_MEMORY\" %\n                             self.text_memory)\n\n    def chunk_iCCP(self, pos, length):\n\n        # ICC profile\n        s = ImageFile._safe_read(self.fp, length)\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        i = s.find(b\"\\0\")\n        logger.debug(\"iCCP profile name %s\", s[:i])\n        logger.debug(\"Compression method %s\", i8(s[i]))\n        comp_method = i8(s[i])\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in iCCP chunk\" %\n                              comp_method)\n        try:\n            icc_profile = _safe_zlib_decompress(s[i+2:])\n        except zlib.error:\n            icc_profile = None  # FIXME\n        self.im_info[\"icc_profile\"] = icc_profile\n        return s\n\n    def chunk_IHDR(self, pos, length):\n\n        # image header\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_size = i32(s), i32(s[4:])\n        try:\n            self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))]\n        except:\n            pass\n        if i8(s[12]):\n            self.im_info[\"interlace\"] = 1\n        if i8(s[11]):\n            raise SyntaxError(\"unknown filter category\")\n        return s\n\n    def chunk_IDAT(self, pos, length):\n\n        # image data\n        self.im_tile = [(\"zip\", (0, 0)+self.im_size, pos, self.im_rawmode)]\n        self.im_idat = length\n        raise EOFError\n\n    def chunk_IEND(self, pos, length):\n\n        # end of PNG image\n        raise EOFError\n\n    def chunk_PLTE(self, pos, length):\n\n        # palette\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            self.im_palette = \"RGB\", s\n        return s\n\n    def chunk_tRNS(self, pos, length):\n\n        # transparency\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            if _simple_palette.match(s):\n                # tRNS contains only one full-transparent entry,\n                # other entries are full opaque\n                i = s.find(b\"\\0\")\n                if i >= 0:\n                    self.im_info[\"transparency\"] = i\n            else:\n                # otherwise, we have a byte string with one alpha value\n                # for each palette entry\n                self.im_info[\"transparency\"] = s\n        elif self.im_mode == \"L\":\n            self.im_info[\"transparency\"] = i16(s)\n        elif self.im_mode == \"RGB\":\n            self.im_info[\"transparency\"] = i16(s), i16(s[2:]), i16(s[4:])\n        return s\n\n    def chunk_gAMA(self, pos, length):\n\n        # gamma setting\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_info[\"gamma\"] = i32(s) / 100000.0\n        return s\n\n    def chunk_pHYs(self, pos, length):\n\n        # pixels per unit\n        s = ImageFile._safe_read(self.fp, length)\n        px, py = i32(s), i32(s[4:])\n        unit = i8(s[8])\n        if unit == 1:  # meter\n            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)\n            self.im_info[\"dpi\"] = dpi\n        elif unit == 0:\n            self.im_info[\"aspect\"] = px, py\n        return s\n\n    def chunk_tEXt(self, pos, length):\n\n        # text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            # fallback for broken tEXt tags\n            k = s\n            v = b\"\"\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_zTXt(self, pos, length):\n\n        # compressed text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            k = s\n            v = b\"\"\n        if v:\n            comp_method = i8(v[0])\n        else:\n            comp_method = 0\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in zTXt chunk\" %\n                              comp_method)\n        try:\n            v = _safe_zlib_decompress(v[1:])\n        except zlib.error:\n            v = b\"\"\n\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_iTXt(self, pos, length):\n\n        # international text\n        r = s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, r = r.split(b\"\\0\", 1)\n        except ValueError:\n            return s\n        if len(r) < 2:\n            return s\n        cf, cm, r = i8(r[0]), i8(r[1]), r[2:]\n        try:\n            lang, tk, v = r.split(b\"\\0\", 2)\n        except ValueError:\n            return s\n        if cf != 0:\n            if cm == 0:\n                try:\n                    v = _safe_zlib_decompress(v)\n                except zlib.error:\n                    return s\n            else:\n                return s\n        if bytes is not str:\n            try:\n                k = k.decode(\"latin-1\", \"strict\")\n                lang = lang.decode(\"utf-8\", \"strict\")\n                tk = tk.decode(\"utf-8\", \"strict\")\n                v = v.decode(\"utf-8\", \"strict\")\n            except UnicodeError:\n                return s\n\n        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)\n        self.check_text_memory(len(v))\n\n        return s\n\n\n# --------------------------------------------------------------------\n# PNG reader\n\ndef _accept(prefix):\n    return prefix[:8] == _MAGIC\n\n\n##\n# Image plugin for PNG images.\n\nclass PngImageFile(ImageFile.ImageFile):\n\n    format = \"PNG\"\n    format_description = \"Portable network graphics\"\n\n    def _open(self):\n\n        if self.fp.read(8) != _MAGIC:\n            raise SyntaxError(\"not a PNG file\")\n\n        #\n        # Parse headers up to the first IDAT chunk\n\n        self.png = PngStream(self.fp)\n\n        while True:\n\n            #\n            # get next chunk\n\n            cid, pos, length = self.png.read()\n\n            try:\n                s = self.png.call(cid, pos, length)\n            except EOFError:\n                break\n            except AttributeError:\n                logger.debug(\"%s %s %s (unknown)\", cid, pos, length)\n                s = ImageFile._safe_read(self.fp, length)\n\n            self.png.crc(cid, s)\n\n        #\n        # Copy relevant attributes from the PngStream.  An alternative\n        # would be to let the PngStream class modify these attributes\n        # directly, but that introduces circular references which are\n        # difficult to break if things go wrong in the decoder...\n        # (believe me, I've tried ;-)\n\n        self.mode = self.png.im_mode\n        self.size = self.png.im_size\n        self.info = self.png.im_info\n        self.text = self.png.im_text  # experimental\n        self.tile = self.png.im_tile\n\n        if self.png.im_palette:\n            rawmode, data = self.png.im_palette\n            self.palette = ImagePalette.raw(rawmode, data)\n\n        self.__idat = length  # used by load_read()\n\n    def verify(self):\n        \"Verify PNG file\"\n\n        if self.fp is None:\n            raise RuntimeError(\"verify must be called directly after open\")\n\n        # back up to beginning of IDAT block\n        self.fp.seek(self.tile[0][2] - 8)\n\n        self.png.verify()\n        self.png.close()\n\n        self.fp = None\n\n    def load_prepare(self):\n        \"internal: prepare to read PNG file\"\n\n        if self.info.get(\"interlace\"):\n            self.decoderconfig = self.decoderconfig + (1,)\n\n        ImageFile.ImageFile.load_prepare(self)\n\n    def load_read(self, read_bytes):\n        \"internal: read more image data\"\n\n        while self.__idat == 0:\n            # end of chunk, skip forward to next one\n\n            self.fp.read(4)  # CRC\n\n            cid, pos, length = self.png.read()\n\n            if cid not in [b\"IDAT\", b\"DDAT\"]:\n                self.png.push(cid, pos, length)\n                return b\"\"\n\n            self.__idat = length  # empty chunks are allowed\n\n        # read more data from this chunk\n        if read_bytes <= 0:\n            read_bytes = self.__idat\n        else:\n            read_bytes = min(read_bytes, self.__idat)\n\n        self.__idat = self.__idat - read_bytes\n\n        return self.fp.read(read_bytes)\n\n    def load_end(self):\n        \"internal: finished reading image data\"\n\n        self.png.close()\n        self.png = None\n\n\n# --------------------------------------------------------------------\n# PNG writer\n\no8 = _binary.o8\no16 = _binary.o16be\no32 = _binary.o32be\n\n_OUTMODES = {\n    # supported PIL modes, and corresponding rawmodes/bits/color combinations\n    \"1\":    (\"1\",       b'\\x01\\x00'),\n    \"L;1\":  (\"L;1\",     b'\\x01\\x00'),\n    \"L;2\":  (\"L;2\",     b'\\x02\\x00'),\n    \"L;4\":  (\"L;4\",     b'\\x04\\x00'),\n    \"L\":    (\"L\",       b'\\x08\\x00'),\n    \"LA\":   (\"LA\",      b'\\x08\\x04'),\n    \"I\":    (\"I;16B\",   b'\\x10\\x00'),\n    \"P;1\":  (\"P;1\",     b'\\x01\\x03'),\n    \"P;2\":  (\"P;2\",     b'\\x02\\x03'),\n    \"P;4\":  (\"P;4\",     b'\\x04\\x03'),\n    \"P\":    (\"P\",       b'\\x08\\x03'),\n    \"RGB\":  (\"RGB\",     b'\\x08\\x02'),\n    \"RGBA\": (\"RGBA\",    b'\\x08\\x06'),\n}\n\n\ndef putchunk(fp, cid, *data):\n    \"Write a PNG chunk (including CRC field)\"\n\n    data = b\"\".join(data)\n\n    fp.write(o32(len(data)) + cid)\n    fp.write(data)\n    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n    fp.write(o16(hi) + o16(lo))\n\n\nclass _idat(object):\n    # wrap output from the encoder in IDAT chunks\n\n    def __init__(self, fp, chunk):\n        self.fp = fp\n        self.chunk = chunk\n\n    def write(self, data):\n        self.chunk(self.fp, b\"IDAT\", data)\n\n\ndef _save(im, fp, filename, chunk=putchunk, check=0):\n    # save an image to disk (called by the save method)\n\n    mode = im.mode\n\n    if mode == \"P\":\n\n        #\n        # attempt to minimize storage requirements for palette images\n        if \"bits\" in im.encoderinfo:\n            # number of bits specified by user\n            colors = 1 << im.encoderinfo[\"bits\"]\n        else:\n            # check palette contents\n            if im.palette:\n                colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)\n            else:\n                colors = 256\n\n        if colors <= 2:\n            bits = 1\n        elif colors <= 4:\n            bits = 2\n        elif colors <= 16:\n            bits = 4\n        else:\n            bits = 8\n        if bits != 8:\n            mode = \"%s;%d\" % (mode, bits)\n\n    # encoder options\n    if \"dictionary\" in im.encoderinfo:\n        dictionary = im.encoderinfo[\"dictionary\"]\n    else:\n        dictionary = b\"\"\n\n    im.encoderconfig = (\"optimize\" in im.encoderinfo,\n                        im.encoderinfo.get(\"compress_level\", -1),\n                        im.encoderinfo.get(\"compress_type\", -1),\n                        dictionary)\n\n    # get the corresponding PNG mode\n    try:\n        rawmode, mode = _OUTMODES[mode]\n    except KeyError:\n        raise IOError(\"cannot write mode %s as PNG\" % mode)\n\n    if check:\n        return check\n\n    #\n    # write minimal PNG file\n\n    fp.write(_MAGIC)\n\n    chunk(fp, b\"IHDR\",\n          o32(im.size[0]), o32(im.size[1]),     # 0: size\n          mode,                                 # 8: depth/type\n          b'\\0',                                # 10: compression\n          b'\\0',                                # 11: filter category\n          b'\\0')                                # 12: interlace flag\n\n    if im.mode == \"P\":\n        palette_byte_number = (2 ** bits) * 3\n        palette_bytes = im.im.getpalette(\"RGB\")[:palette_byte_number]\n        while len(palette_bytes) < palette_byte_number:\n            palette_bytes += b'\\0'\n        chunk(fp, b\"PLTE\", palette_bytes)\n\n    transparency = im.encoderinfo.get('transparency',\n                                      im.info.get('transparency', None))\n\n    if transparency or transparency == 0:\n        if im.mode == \"P\":\n            # limit to actual palette size\n            alpha_bytes = 2**bits\n            if isinstance(transparency, bytes):\n                chunk(fp, b\"tRNS\", transparency[:alpha_bytes])\n            else:\n                transparency = max(0, min(255, transparency))\n                alpha = b'\\xFF' * transparency + b'\\0'\n                chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n        elif im.mode == \"L\":\n            transparency = max(0, min(65535, transparency))\n            chunk(fp, b\"tRNS\", o16(transparency))\n        elif im.mode == \"RGB\":\n            red, green, blue = transparency\n            chunk(fp, b\"tRNS\", o16(red) + o16(green) + o16(blue))\n        else:\n            if \"transparency\" in im.encoderinfo:\n                # don't bother with transparency if it's an RGBA\n                # and it's in the info dict. It's probably just stale.\n                raise IOError(\"cannot use transparency for this mode\")\n    else:\n        if im.mode == \"P\" and im.im.getpalettemode() == \"RGBA\":\n            alpha = im.im.getpalette(\"RGBA\", \"A\")\n            alpha_bytes = 2**bits\n            chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n\n    dpi = im.encoderinfo.get(\"dpi\")\n    if dpi:\n        chunk(fp, b\"pHYs\",\n              o32(int(dpi[0] / 0.0254 + 0.5)),\n              o32(int(dpi[1] / 0.0254 + 0.5)),\n              b'\\x01')\n\n    info = im.encoderinfo.get(\"pnginfo\")\n    if info:\n        for cid, data in info.chunks:\n            chunk(fp, cid, data)\n\n    # ICC profile writing support -- 2008-06-06 Florian Hoech\n    if im.info.get(\"icc_profile\"):\n        # ICC profile\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        name = b\"ICC Profile\"\n        data = name + b\"\\0\\0\" + zlib.compress(im.info[\"icc_profile\"])\n        chunk(fp, b\"iCCP\", data)\n\n    ImageFile._save(im, _idat(fp, chunk),\n                    [(\"zip\", (0, 0)+im.size, 0, rawmode)])\n\n    chunk(fp, b\"IEND\", b\"\")\n\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\n# --------------------------------------------------------------------\n# PNG chunk converter\n\ndef getchunks(im, **params):\n    \"\"\"Return a list of PNG chunks representing this image.\"\"\"\n\n    class collector(object):\n        data = []\n\n        def write(self, data):\n            pass\n\n        def append(self, chunk):\n            self.data.append(chunk)\n\n    def append(fp, cid, *data):\n        data = b\"\".join(data)\n        hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n        crc = o16(hi) + o16(lo)\n        fp.append((cid, data, crc))\n\n    fp = collector()\n\n    try:\n        im.encoderinfo = params\n        _save(im, fp, None, append)\n    finally:\n        del im.encoderinfo\n\n    return fp.data\n\n\n# --------------------------------------------------------------------\n# Registry\n\nImage.register_open(PngImageFile.format, PngImageFile, _accept)\nImage.register_save(PngImageFile.format, _save)\n\nImage.register_extension(PngImageFile.format, \".png\")\n\nImage.register_mime(PngImageFile.format, \"image/png\")\n",
            "header": {
                "file": {
                    "path": "PIL/PngImagePlugin.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "4d82c9a97",
                "new_commit_hash": "12a7ef17e",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/PIL/PngImagePlugin.py"
            },
            "plus_file": {
                "path": "b/PIL/PngImagePlugin.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 140,
                            "length": 7
                        },
                        "new_range": {
                            "start": 140,
                            "length": 7
                        },
                        "section": "class ChunkStream(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Skip CRC checks for ancillary chunks if allowed to load truncated images",
                                "type": "context"
                            },
                            {
                                "content": "        # 5th byte of first char is 1 [specs, section 5.4]",
                                "type": "context"
                            },
                            {
                                "content": "        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):",
                                "type": "deleted"
                            },
                            {
                                "content": "        if ImageFile.LOAD_TRUNCATED_IMAGES and (i8(cid[0]) >> 5 & 1):",
                                "type": "added"
                            },
                            {
                                "content": "            self.crc_skip(cid, data)",
                                "type": "context"
                            },
                            {
                                "content": "            return",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "PIL/PngImagePlugin.py",
                            "type": "method",
                            "name": "ChunkStream.crc",
                            "content": "class ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 138,
                            "end_lineno": 155,
                            "parent": {
                                "file_name": "PIL/PngImagePlugin.py",
                                "type": "class",
                                "name": "ChunkStream",
                                "content": "class ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 97,
                                "end_lineno": 180,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "PIL/PngImagePlugin.py",
                            "type": "class",
                            "name": "ChunkStream",
                            "content": "class ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 97,
                            "end_lineno": 180,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from helper import unittest, PillowTestCase, hopper\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import PngImagePlugin\nimport zlib\n\ncodecs = dir(Image.core)\n\n# sample png stream\n\nTEST_PNG_FILE = \"Tests/images/hopper.png\"\nTEST_DATA = open(TEST_PNG_FILE, \"rb\").read()\n\n# stuff to create inline PNG images\n\nMAGIC = PngImagePlugin._MAGIC\n\n\ndef chunk(cid, *data):\n    test_file = BytesIO()\n    PngImagePlugin.putchunk(*(test_file, cid) + data)\n    return test_file.getvalue()\n\no32 = PngImagePlugin.o32\n\nIHDR = chunk(b\"IHDR\", o32(1), o32(1), b'\\x08\\x02', b'\\0\\0\\0')\nIDAT = chunk(b\"IDAT\")\nIEND = chunk(b\"IEND\")\n\nHEAD = MAGIC + IHDR\nTAIL = IDAT + IEND\n\n\ndef load(data):\n    return Image.open(BytesIO(data))\n\n\ndef roundtrip(im, **options):\n    out = BytesIO()\n    im.save(out, \"PNG\", **options)\n    out.seek(0)\n    return Image.open(out)\n\n\nclass TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)\n\n\nif __name__ == '__main__':\n    unittest.main()\n\n# End of file\n",
            "new_file_content": "from helper import unittest, PillowTestCase, hopper\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import PngImagePlugin\nimport zlib\n\ncodecs = dir(Image.core)\n\n# sample png stream\n\nTEST_PNG_FILE = \"Tests/images/hopper.png\"\nTEST_DATA = open(TEST_PNG_FILE, \"rb\").read()\n\n# stuff to create inline PNG images\n\nMAGIC = PngImagePlugin._MAGIC\n\n\ndef chunk(cid, *data):\n    test_file = BytesIO()\n    PngImagePlugin.putchunk(*(test_file, cid) + data)\n    return test_file.getvalue()\n\no32 = PngImagePlugin.o32\n\nIHDR = chunk(b\"IHDR\", o32(1), o32(1), b'\\x08\\x02', b'\\0\\0\\0')\nIDAT = chunk(b\"IDAT\")\nIEND = chunk(b\"IEND\")\n\nHEAD = MAGIC + IHDR\nTAIL = IDAT + IEND\n\n\ndef load(data):\n    return Image.open(BytesIO(data))\n\n\ndef roundtrip(im, **options):\n    out = BytesIO()\n    im.save(out, \"PNG\", **options)\n    out.seek(0)\n    return Image.open(out)\n\n\nclass TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + b'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + b'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)\n\n\nif __name__ == '__main__':\n    unittest.main()\n\n# End of file\n",
            "header": {
                "file": {
                    "path": "Tests/test_file_png.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "d3ee54e54",
                "new_commit_hash": "e09abb172",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Tests/test_file_png.py"
            },
            "plus_file": {
                "path": "b/Tests/test_file_png.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 324,
                            "length": 7
                        },
                        "new_range": {
                            "start": 324,
                            "length": 7
                        },
                        "section": "class TestFilePng(PillowTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        # check ignores crc errors in ancillary chunks",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        chunk_data = chunk(b'tEXt', b'spam')",
                                "type": "context"
                            },
                            {
                                "content": "        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC",
                                "type": "deleted"
                            },
                            {
                                "content": "        broken_crc_chunk_data = chunk_data[:-1] + b'q'  # break CRC",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        image_data = HEAD + broken_crc_chunk_data + TAIL",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertRaises(SyntaxError,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_file_png.py",
                            "type": "class",
                            "name": "TestFilePng",
                            "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 48,
                            "end_lineno": 492,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_png.py",
                            "type": "method",
                            "name": "TestFilePng.test_verify_ignores_crc_error",
                            "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 323,
                            "end_lineno": 338,
                            "parent": {
                                "file_name": "Tests/test_file_png.py",
                                "type": "class",
                                "name": "TestFilePng",
                                "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 48,
                                "end_lineno": 492,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 340,
                            "length": 7
                        },
                        "new_range": {
                            "start": 340,
                            "length": 7
                        },
                        "section": "class TestFilePng(PillowTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    def test_verify_not_ignores_crc_error_in_required_chunk(self):",
                                "type": "context"
                            },
                            {
                                "content": "        # check does not ignore crc errors in required chunks",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL",
                                "type": "deleted"
                            },
                            {
                                "content": "        image_data = MAGIC + IHDR[:-1] + b'q' + TAIL",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        ImageFile.LOAD_TRUNCATED_IMAGES = True",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_file_png.py",
                            "type": "class",
                            "name": "TestFilePng",
                            "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 48,
                            "end_lineno": 492,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_png.py",
                            "type": "method",
                            "name": "TestFilePng.test_verify_not_ignores_crc_error_in_required_chunk",
                            "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 340,
                            "end_lineno": 350,
                            "parent": {
                                "file_name": "Tests/test_file_png.py",
                                "type": "class",
                                "name": "TestFilePng",
                                "content": "class TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + 'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + 'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 48,
                                "end_lineno": 492,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "885297d21f239af8d48f3d9a4ef5499b1db90033^",
    "new_commit_hash": "885297d21f239af8d48f3d9a4ef5499b1db90033",
    "commit_message": "Fix python 3 bytes to string concat error",
    "commit_date": "2016-06-29T14:44:29-07:00",
    "metadata": {}
}
{
    "repo_name": "pillow",
    "new_commit_hash": "885297d21f239af8d48f3d9a4ef5499b1db90033",
    "test_file_codes": [
        "from helper import unittest, PillowTestCase, hopper\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import PngImagePlugin\nimport zlib\n\ncodecs = dir(Image.core)\n\n# sample png stream\n\nTEST_PNG_FILE = \"Tests/images/hopper.png\"\nTEST_DATA = open(TEST_PNG_FILE, \"rb\").read()\n\n# stuff to create inline PNG images\n\nMAGIC = PngImagePlugin._MAGIC\n\n\ndef chunk(cid, *data):\n    test_file = BytesIO()\n    PngImagePlugin.putchunk(*(test_file, cid) + data)\n    return test_file.getvalue()\n\no32 = PngImagePlugin.o32\n\nIHDR = chunk(b\"IHDR\", o32(1), o32(1), b'\\x08\\x02', b'\\0\\0\\0')\nIDAT = chunk(b\"IDAT\")\nIEND = chunk(b\"IEND\")\n\nHEAD = MAGIC + IHDR\nTAIL = IDAT + IEND\n\n\ndef load(data):\n    return Image.open(BytesIO(data))\n\n\ndef roundtrip(im, **options):\n    out = BytesIO()\n    im.save(out, \"PNG\", **options)\n    out.seek(0)\n    return Image.open(out)\n\n\nclass TestFilePng(PillowTestCase):\n\n    def setUp(self):\n        if \"zip_encoder\" not in codecs or \"zip_decoder\" not in codecs:\n            self.skipTest(\"zip/deflate support not available\")\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegexpMatches(\n            Image.core.zlib_version, \"\\d+\\.\\d+\\.\\d+(\\.\\d+)?$\")\n\n        test_file = self.tempfile(\"temp.png\")\n\n        hopper(\"RGB\").save(test_file)\n\n        im = Image.open(test_file)\n        im.load()\n        self.assertEqual(im.mode, \"RGB\")\n        self.assertEqual(im.size, (128, 128))\n        self.assertEqual(im.format, \"PNG\")\n\n        hopper(\"1\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"L\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"P\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"RGB\").save(test_file)\n        im = Image.open(test_file)\n\n        hopper(\"I\").save(test_file)\n        im = Image.open(test_file)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(invalid_file))\n\n    def test_broken(self):\n        # Check reading of totally broken files.  In this case, the test\n        # file was checked into Subversion as a text file.\n\n        test_file = \"Tests/images/broken.png\"\n        self.assertRaises(IOError, lambda: Image.open(test_file))\n\n    def test_bad_text(self):\n        # Make sure PIL can read malformed tEXt chunks (@PIL152)\n\n        im = load(HEAD + chunk(b'tEXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {'spam': 'egg'})\n\n        im = load(HEAD + chunk(b'tEXt', b'spam\\0egg\\0') + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg\\x00'})\n\n    def test_bad_ztxt(self):\n        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)\n\n        im = load(HEAD + chunk(b'zTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'zTXt', b'spam\\0\\0') + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(\n            b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(\n            HEAD + chunk(b'zTXt', b'spam\\0\\0' + zlib.compress(b'egg')) + TAIL)\n        self.assertEqual(im.info,  {'spam': 'egg'})\n\n    def test_bad_itxt(self):\n\n        im = load(HEAD + chunk(b'iTXt') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\x02') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0foo\\0') + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\0\\0en\\0Spam\\0egg') + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")[:1]) + TAIL)\n        self.assertEqual(im.info, {'spam': ''})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\1en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {})\n\n        im = load(HEAD + chunk(b'iTXt', b'spam\\0\\1\\0en\\0Spam\\0' +\n                               zlib.compress(b\"egg\")) + TAIL)\n        self.assertEqual(im.info, {\"spam\": \"egg\"})\n        self.assertEqual(im.info[\"spam\"].lang, \"en\")\n        self.assertEqual(im.info[\"spam\"].tkey, \"Spam\")\n\n    def test_interlace(self):\n\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n        test_file = \"Tests/images/pil123rgba.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"RGBA\", (162, 150))\n        self.assertTrue(im.info.get(\"interlace\"))\n\n        im.load()\n\n    def test_load_transparent_p(self):\n        test_file = \"Tests/images/pil123p.png\"\n        im = Image.open(test_file)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 uniqe qlpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_load_transparent_rgb(self):\n        test_file = \"Tests/images/rgb_trns.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (0, 255, 52))\n\n        self.assert_image(im, \"RGB\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_palette(self):\n        in_file = \"Tests/images/pil123p.png\"\n        im = Image.open(in_file)\n\n        # 'transparency' contains a byte string with the opacity for\n        # each palette entry\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n\n        self.assert_image(im, \"P\", (162, 150))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (162, 150))\n\n        # image has 124 unique alpha values\n        self.assertEqual(len(im.split()[3].getcolors()), 124)\n\n    def test_save_p_single_transparency(self):\n        in_file = \"Tests/images/p_trns_single.png\"\n        im = Image.open(in_file)\n\n        # pixel value 164 is full transparent\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], 164)\n        self.assertEqual(im.getpixel((31, 31)), 164)\n        self.assert_image(im, \"P\", (64, 64))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (64, 64))\n\n        self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))\n\n        # image has 876 transparent pixels\n        self.assertEqual(im.split()[3].getcolors()[0][0], 876)\n\n    def test_save_p_transparent_black(self):\n        # check if solid black image with full transparency\n        # is supported (check for #1838)\n        im = Image.new(\"RGBA\", (10, 10), (0, 0, 0, 0))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n        im = im.convert(\"P\")\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # check if saved image contains same transparency\n        im = Image.open(test_file)\n        self.assertEqual(len(im.info[\"transparency\"]), 256)\n        self.assert_image(im, \"P\", (10, 10))\n        im = im.convert(\"RGBA\")\n        self.assert_image(im, \"RGBA\", (10, 10))\n        self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])\n\n    def test_save_l_transparency(self):\n        in_file = \"Tests/images/l_trns.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n        # There are 559 transparent pixels.\n        im = im.convert('RGBA')\n        self.assertEqual(im.split()[3].getcolors()[0][0], 559)\n\n    def test_save_rgb_single_transparency(self):\n        in_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(in_file)\n\n        test_file = self.tempfile(\"temp.png\")\n        im.save(test_file)\n\n    def test_load_verify(self):\n        # Check open/load/verify exception (@PIL150)\n\n        im = Image.open(TEST_PNG_FILE)\n        im.verify()\n\n        im = Image.open(TEST_PNG_FILE)\n        im.load()\n        self.assertRaises(RuntimeError, im.verify)\n\n    def test_verify_struct_error(self):\n        # Check open/load/verify exception (#1755)\n\n        # offsets to test, -10: breaks in i32() in read. (IOError)\n        #                  -13: breaks in crc, txt chunk.\n        #                  -14: malformed chunk\n\n        for offset in (-10, -13, -14):\n            with open(TEST_PNG_FILE,'rb') as f:\n                test_file = f.read()[:offset]\n\n            im = Image.open(BytesIO(test_file))\n            self.assertTrue(im.fp is not None)\n            self.assertRaises((IOError, SyntaxError), im.verify)\n\n    def test_verify_ignores_crc_error(self):\n        # check ignores crc errors in ancillary chunks\n\n        chunk_data = chunk(b'tEXt', b'spam')\n        broken_crc_chunk_data = chunk_data[:-1] + b'q'  # break CRC\n\n        image_data = HEAD + broken_crc_chunk_data + TAIL\n        self.assertRaises(SyntaxError,\n                          lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im = load(image_data)\n            self.assertTrue(im is not None)\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_verify_not_ignores_crc_error_in_required_chunk(self):\n        # check does not ignore crc errors in required chunks\n\n        image_data = MAGIC + IHDR[:-1] + b'q' + TAIL\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            self.assertRaises(SyntaxError,\n                              lambda: PngImagePlugin.PngImageFile(BytesIO(image_data)))\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\n    def test_roundtrip_dpi(self):\n        # Check dpi roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        im = roundtrip(im, dpi=(100, 100))\n        self.assertEqual(im.info[\"dpi\"], (100, 100))\n\n    def test_roundtrip_text(self):\n        # Check text roundtripping\n\n        im = Image.open(TEST_PNG_FILE)\n\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"TXT\", \"VALUE\")\n        info.add_text(\"ZIP\", \"VALUE\", 1)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n        self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})\n\n    def test_roundtrip_itxt(self):\n        # Check iTXt roundtripping\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_itxt(\"spam\", \"Eggs\", \"en\", \"Spam\")\n        info.add_text(\"eggs\", PngImagePlugin.iTXt(\"Spam\", \"en\", \"Eggs\"),\n                      zip=True)\n\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(im.info, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text, {\"spam\": \"Eggs\", \"eggs\": \"Spam\"})\n        self.assertEqual(im.text[\"spam\"].lang, \"en\")\n        self.assertEqual(im.text[\"spam\"].tkey, \"Spam\")\n        self.assertEqual(im.text[\"eggs\"].lang, \"en\")\n        self.assertEqual(im.text[\"eggs\"].tkey, \"Eggs\")\n\n    def test_nonunicode_text(self):\n        # Check so that non-Unicode text is saved as a tEXt rather than iTXt\n\n        im = Image.new(\"RGB\", (32, 32))\n        info = PngImagePlugin.PngInfo()\n        info.add_text(\"Text\", \"Ascii\")\n        im = roundtrip(im, pnginfo=info)\n        self.assertEqual(type(im.info[\"Text\"]), str)\n\n    def test_unicode_text(self):\n        # Check preservation of non-ASCII characters on Python3\n        # This cannot really be meaningfully tested on Python2,\n        # since it didn't preserve charsets to begin with.\n\n        def rt_text(value):\n            im = Image.new(\"RGB\", (32, 32))\n            info = PngImagePlugin.PngInfo()\n            info.add_text(\"Text\", value)\n            im = roundtrip(im, pnginfo=info)\n            self.assertEqual(im.info, {\"Text\": value})\n\n        if str is not bytes:\n            rt_text(\" Aa\" + chr(0xa0) + chr(0xc4) + chr(0xff))  # Latin1\n            rt_text(chr(0x400) + chr(0x472) + chr(0x4ff))       # Cyrillic\n            rt_text(chr(0x4e00) + chr(0x66f0) +                 # CJK\n                    chr(0x9fba) + chr(0x3042) + chr(0xac00))\n            rt_text(\"A\" + chr(0xc4) + chr(0x472) + chr(0x3042))  # Combined\n\n    def test_scary(self):\n        # Check reading of evil PNG file.  For information, see:\n        # http://scary.beasts.org/security/CESA-2004-001.txt\n        # The first byte is removed from pngtest_bad.png\n        # to avoid classification as malware.\n\n        with open(\"Tests/images/pngtest_bad.png.bin\", 'rb') as fd:\n            data = b'\\x89' + fd.read()\n\n        pngfile = BytesIO(data)\n        self.assertRaises(IOError, lambda: Image.open(pngfile))\n\n    def test_trns_rgb(self):\n        # Check writing and reading of tRNS chunks for RGB images.\n        # Independent file sample provided by Sebastian Spaeth.\n\n        test_file = \"Tests/images/caption_6_33_22.png\"\n        im = Image.open(test_file)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        # check saving transparency by default\n        im = roundtrip(im)\n        self.assertEqual(im.info[\"transparency\"], (248, 248, 248))\n\n        im = roundtrip(im, transparency=(0, 1, 2))\n        self.assertEqual(im.info[\"transparency\"], (0, 1, 2))\n\n    def test_trns_p(self):\n        # Check writing a transparency of 0, issue #528\n        im = hopper('P')\n        im.info['transparency'] = 0\n\n        f = self.tempfile(\"temp.png\")\n        im.save(f)\n\n        im2 = Image.open(f)\n        self.assertIn('transparency', im2.info)\n\n        self.assert_image_equal(im2.convert('RGBA'),\n                                im.convert('RGBA'))\n\n    def test_trns_null(self):\n        # Check reading images with null tRNS value, issue #1239\n        test_file = \"Tests/images/tRNS_null_1x1.png\"\n        im = Image.open(test_file)\n\n        self.assertEqual(im.info[\"transparency\"], 0)\n\n    def test_save_icc_profile_none(self):\n        # check saving files with an ICC profile set to None (omit profile)\n        in_file = \"Tests/images/icc_profile_none.png\"\n        im = Image.open(in_file)\n        self.assertEqual(im.info['icc_profile'], None)\n\n        im = roundtrip(im)\n        self.assertNotIn('icc_profile', im.info)\n\n    def test_roundtrip_icc_profile(self):\n        # check that we can roundtrip the icc profile\n        im = hopper('RGB')\n\n        jpeg_image = Image.open('Tests/images/flower2.jpg')\n        expected_icc = jpeg_image.info['icc_profile']\n\n        im.info['icc_profile'] = expected_icc\n        im = roundtrip(im)\n        self.assertEqual(im.info['icc_profile'], expected_icc)\n\n    def test_repr_png(self):\n        im = hopper()\n\n        repr_png = Image.open(BytesIO(im._repr_png_()))\n        self.assertEqual(repr_png.format, 'PNG')\n        self.assert_image_equal(im, repr_png)\n\n\nif __name__ == '__main__':\n    unittest.main()\n\n# End of file\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\"r2e_tests\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "unittest_custom_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Pillow installation attempts...\nVerifying Pillow installation...\n✅ Pillow installation successful!\nSuccessfully installed Pillow\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 12 packages in 16ms\nInstalled 12 packages in 167ms\n + coverage==7.6.10\n + exceptiongroup==1.2.2\n + iniconfig==2.0.0\n + packaging==24.2\n + pluggy==1.5.0\n + pyqt5==5.15.11\n + pyqt5-qt5==5.15.16\n + pyqt5-sip==12.16.1\n + pytest==8.3.4\n + pytest-cov==6.0.0\n + setuptools==75.8.0\n + tomli==2.2.1\nResolved 1 package in 557ms\nPrepared 1 package in 15.22s\nInstalled 1 package in 2ms\n + pillow==3.3.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033)\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033\n..............................\ncollected 30 items\n\n==================== short test summary info ====================\nPASSED test_1::TestFilePng::test_bad_itxt\nPASSED test_1::TestFilePng::test_bad_text\nPASSED test_1::TestFilePng::test_bad_ztxt\nPASSED test_1::TestFilePng::test_broken\nPASSED test_1::TestFilePng::test_interlace\nPASSED test_1::TestFilePng::test_invalid_file\nPASSED test_1::TestFilePng::test_load_transparent_p\nPASSED test_1::TestFilePng::test_load_transparent_rgb\nPASSED test_1::TestFilePng::test_load_verify\nPASSED test_1::TestFilePng::test_nonunicode_text\nPASSED test_1::TestFilePng::test_repr_png\nPASSED test_1::TestFilePng::test_roundtrip_dpi\nPASSED test_1::TestFilePng::test_roundtrip_icc_profile\nPASSED test_1::TestFilePng::test_roundtrip_itxt\nPASSED test_1::TestFilePng::test_roundtrip_text\nPASSED test_1::TestFilePng::test_sanity\nPASSED test_1::TestFilePng::test_save_icc_profile_none\nPASSED test_1::TestFilePng::test_save_l_transparency\nPASSED test_1::TestFilePng::test_save_p_single_transparency\nPASSED test_1::TestFilePng::test_save_p_transparent_black\nPASSED test_1::TestFilePng::test_save_p_transparent_palette\nPASSED test_1::TestFilePng::test_save_rgb_single_transparency\nPASSED test_1::TestFilePng::test_scary\nPASSED test_1::TestFilePng::test_trns_null\nPASSED test_1::TestFilePng::test_trns_p\nPASSED test_1::TestFilePng::test_trns_rgb\nPASSED test_1::TestFilePng::test_unicode_text\nPASSED test_1::TestFilePng::test_verify_ignores_crc_error\nPASSED test_1::TestFilePng::test_verify_not_ignores_crc_error_in_required_chunk\nPASSED test_1::TestFilePng::test_verify_struct_error\n=================== 30 passed in 0.24s ===================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033\n..............................\ncollected 30 items\n\n=================================== ERRORS =====================================\n__________ TestFilePng.test_verify_ignores_crc_error __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033/r2e_tests/test_1.py\", line 335, in test_verify_ignores_crc_error\n    im = load(image_data)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033/r2e_tests/test_1.py\", line 38, in load\n    return Image.open(BytesIO(data))\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_885297d21f239af8d48f3d9a4ef5499b1db90033/PIL/Image.py\", line 2312, in open\n    raise IOError(\"cannot identify image file %r\"\nOSError: cannot identify image file <_io.BytesIO object at 0x76c3faf01360>\n\n==================== short test summary info ====================\nPASSED test_1::TestFilePng::test_bad_itxt\nPASSED test_1::TestFilePng::test_bad_text\nPASSED test_1::TestFilePng::test_bad_ztxt\nPASSED test_1::TestFilePng::test_broken\nPASSED test_1::TestFilePng::test_interlace\nPASSED test_1::TestFilePng::test_invalid_file\nPASSED test_1::TestFilePng::test_load_transparent_p\nPASSED test_1::TestFilePng::test_load_transparent_rgb\nPASSED test_1::TestFilePng::test_load_verify\nPASSED test_1::TestFilePng::test_nonunicode_text\nPASSED test_1::TestFilePng::test_repr_png\nPASSED test_1::TestFilePng::test_roundtrip_dpi\nPASSED test_1::TestFilePng::test_roundtrip_icc_profile\nPASSED test_1::TestFilePng::test_roundtrip_itxt\nPASSED test_1::TestFilePng::test_roundtrip_text\nPASSED test_1::TestFilePng::test_sanity\nPASSED test_1::TestFilePng::test_save_icc_profile_none\nPASSED test_1::TestFilePng::test_save_l_transparency\nPASSED test_1::TestFilePng::test_save_p_single_transparency\nPASSED test_1::TestFilePng::test_save_p_transparent_black\nPASSED test_1::TestFilePng::test_save_p_transparent_palette\nPASSED test_1::TestFilePng::test_save_rgb_single_transparency\nPASSED test_1::TestFilePng::test_scary\nPASSED test_1::TestFilePng::test_trns_null\nPASSED test_1::TestFilePng::test_trns_p\nPASSED test_1::TestFilePng::test_trns_rgb\nPASSED test_1::TestFilePng::test_unicode_text\nERROR test_1::TestFilePng::test_verify_ignores_crc_error\nPASSED test_1::TestFilePng::test_verify_not_ignores_crc_error_in_required_chunk\nPASSED test_1::TestFilePng::test_verify_struct_error\n=================== 1 error, 29 passed in 0.14s ===================\n",
    "old_commit_res_stderr": ""
}
PIL/PngImagePlugin.py Tests/test_file_png.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Loading PNG with Corrupted Ancillary Chunk CRC Raises OSError Despite `LOAD_TRUNCATED_IMAGES` Enabled

**Description:**
When attempting to load a PNG image that contains a corrupted CRC in an ancillary chunk, setting `ImageFile.LOAD_TRUNCATED_IMAGES` to `True` should allow the image to load by ignoring the CRC error. However, an `OSError` is raised instead, preventing the image from being processed.

**Example Code:**
```python
from PIL import Image, ImageFile
from io import BytesIO

# Simulate corrupted ancillary chunk with broken CRC
broken_crc_chunk_data = b'tEXtspamq'  # 'q' alters the CRC
image_data = b'\x89PNG\r\n\x1a\n' + broken_crc_chunk_data + b'IEND\xaeB`\x82'

ImageFile.LOAD_TRUNCATED_IMAGES = True
image = Image.open(BytesIO(image_data))
image.load()
```

**Expected Behavior:**
The image should load successfully despite the corrupted CRC in the ancillary chunk because `LOAD_TRUNCATED_IMAGES` is enabled, which allows the loader to bypass certain types of errors.

**Actual Behavior:**
An `OSError` is raised with the message:
```
OSError: cannot identify image file <_io.BytesIO object at 0x...>
```
This prevents the image from being loaded even though truncated image loading is permitted.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### PIL/PngImagePlugin.py
#
# The Python Imaging Library.
# $Id$
#
# PNG support code
#
# See "PNG (Portable Network Graphics) Specification, version 1.0;
# W3C Recommendation", 1996-10-01, Thomas Boutell (ed.).
#
# history:
# 1996-05-06 fl   Created (couldn't resist it)
# 1996-12-14 fl   Upgraded, added read and verify support (0.2)
# 1996-12-15 fl   Separate PNG stream parser
# 1996-12-29 fl   Added write support, added getchunks
# 1996-12-30 fl   Eliminated circular references in decoder (0.3)
# 1998-07-12 fl   Read/write 16-bit images as mode I (0.4)
# 2001-02-08 fl   Added transparency support (from Zircon) (0.5)
# 2001-04-16 fl   Don't close data source in "open" method (0.6)
# 2004-02-24 fl   Don't even pretend to support interlaced files (0.7)
# 2004-08-31 fl   Do basic sanity check on chunk identifiers (0.8)
# 2004-09-20 fl   Added PngInfo chunk container
# 2004-12-18 fl   Added DPI read support (based on code by Niki Spahiev)
# 2008-08-13 fl   Added tRNS support for RGB images
# 2009-03-06 fl   Support for preserving ICC profiles (by Florian Hoech)
# 2009-03-08 fl   Added zTXT support (from Lowell Alleman)
# 2009-03-29 fl   Read interlaced PNG files (from Conrado Porto Lopes Gouvua)
#
# Copyright (c) 1997-2009 by Secret Labs AB
# Copyright (c) 1996 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

from __future__ import print_function

import logging
import re
import zlib
import struct

from PIL import Image, ImageFile, ImagePalette, _binary

__version__ = "0.9"

logger = logging.getLogger(__name__)

i8 = _binary.i8
i16 = _binary.i16be
i32 = _binary.i32be

is_cid = re.compile(b"\w\w\w\w").match


_MAGIC = b"\211PNG\r\n\032\n"


_MODES = {
    # supported bits/color combinations, and corresponding modes/rawmodes
    (1, 0):  ("1", "1"),
    (2, 0):  ("L", "L;2"),
    (4, 0):  ("L", "L;4"),
    (8, 0):  ("L", "L"),
    (16, 0): ("I", "I;16B"),
    (8, 2):  ("RGB", "RGB"),
    (16, 2): ("RGB", "RGB;16B"),
    (1, 3):  ("P", "P;1"),
    (2, 3):  ("P", "P;2"),
    (4, 3):  ("P", "P;4"),
    (8, 3):  ("P", "P"),
    (8, 4):  ("LA", "LA"),
    (16, 4): ("RGBA", "LA;16B"),  # LA;16B->LA not yet available
    (8, 6):  ("RGBA", "RGBA"),
    (16, 6): ("RGBA", "RGBA;16B"),
}


_simple_palette = re.compile(b'^\xff*\x00\xff*$')

# Maximum decompressed size for a iTXt or zTXt chunk.
# Eliminates decompression bombs where compressed chunks can expand 1000x
MAX_TEXT_CHUNK = ImageFile.SAFEBLOCK
# Set the maximum total text chunk size.
MAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK


def _safe_zlib_decompress(s):
    dobj = zlib.decompressobj()
    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
    if dobj.unconsumed_tail:
        raise ValueError("Decompressed Data Too Large")
    return plaintext


# --------------------------------------------------------------------
# Support classes.  Suitable for PNG and related formats like MNG etc.

class ChunkStream(object):

    def __init__(self, fp):

        self.fp = fp
        self.queue = []

        if not hasattr(Image.core, "crc32"):
            self.crc = self.crc_skip

    def read(self):
        "Fetch a new chunk. Returns header information."
        cid = None

        if self.queue:
            cid, pos, length = self.queue.pop()
            self.fp.seek(pos)
        else:
            s = self.fp.read(8)
            cid = s[4:]
            pos = self.fp.tell()
            length = i32(s)

        if not is_cid(cid):
            raise SyntaxError("broken PNG file (chunk %s)" % repr(cid))

        return cid, pos, length

    def close(self):
        self.queue = self.crc = self.fp = None

    def push(self, cid, pos, length):

        self.queue.append((cid, pos, length))

    def call(self, cid, pos, length):
        "Call the appropriate chunk handler"

        logger.debug("STREAM %s %s %s", cid, pos, length)
        return getattr(self, "chunk_" + cid.decode('ascii'))(pos, length)

    def crc(self, cid, data):
        "Read and verify checksum"

        # Skip CRC checks for ancillary chunks if allowed to load truncated images
        # 5th byte of first char is 1 [specs, section 5.4]
        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):
            self.crc_skip(cid, data)
            return

        try:
            crc1 = Image.core.crc32(data, Image.core.crc32(cid))
            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
            if crc1 != crc2:
                raise SyntaxError("broken PNG file (bad header checksum in %s)"
                                  % cid)
        except struct.error:
            raise SyntaxError("broken PNG file (incomplete checksum in %s)"
                              % cid)

    def crc_skip(self, cid, data):
        "Read checksum.  Used if the C module is not present"

        self.fp.read(4)

    def verify(self, endchunk=b"IEND"):

        # Simple approach; just calculate checksum for all remaining
        # blocks.  Must be called directly after open.

        cids = []

        while True:
            try:
                cid, pos, length = self.read()
            except struct.error:
                raise IOError("truncated PNG file")

            if cid == endchunk:
                break
            self.crc(cid, ImageFile._safe_read(self.fp, length))
            cids.append(cid)

        return cids


class iTXt(str):
    """
    Subclass of string to allow iTXt chunks to look like strings while
    keeping their extra information

    """
    @staticmethod
    def __new__(cls, text, lang, tkey):
        """
        :param value: value for this key
        :param lang: language code
        :param tkey: UTF-8 version of the key name
        """

        self = str.__new__(cls, text)
        self.lang = lang
        self.tkey = tkey
        return self


class PngInfo(object):
    """
    PNG chunk container (for use with save(pnginfo=))

    """

    def __init__(self):
        self.chunks = []

    def add(self, cid, data):
        """Appends an arbitrary chunk. Use with caution.

        :param cid: a byte string, 4 bytes long.
        :param data: a byte string of the encoded data

        """

        self.chunks.append((cid, data))

    def add_itxt(self, key, value, lang="", tkey="", zip=False):
        """Appends an iTXt chunk.

        :param key: latin-1 encodable text key name
        :param value: value for this key
        :param lang: language code
        :param tkey: UTF-8 version of the key name
        :param zip: compression flag

        """

        if not isinstance(key, bytes):
            key = key.encode("latin-1", "strict")
        if not isinstance(value, bytes):
            value = value.encode("utf-8", "strict")
        if not isinstance(lang, bytes):
            lang = lang.encode("utf-8", "strict")
        if not isinstance(tkey, bytes):
            tkey = tkey.encode("utf-8", "strict")

        if zip:
            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" +
                     zlib.compress(value))
        else:
            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" +
                     value)

    def add_text(self, key, value, zip=0):
        """Appends a text chunk.

        :param key: latin-1 encodable text key name
        :param value: value for this key, text or an
           :py:class:`PIL.PngImagePlugin.iTXt` instance
        :param zip: compression flag

        """
        if isinstance(value, iTXt):
            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))

        # The tEXt chunk stores latin-1 text
        if not isinstance(value, bytes):
            try:
                value = value.encode('latin-1', 'strict')
            except UnicodeError:
                return self.add_itxt(key, value, zip=bool(zip))

        if not isinstance(key, bytes):
            key = key.encode('latin-1', 'strict')

        if zip:
            self.add(b"zTXt", key + b"\0\0" + zlib.compress(value))
        else:
            self.add(b"tEXt", key + b"\0" + value)


# --------------------------------------------------------------------
# PNG image stream (IHDR/IEND)

class PngStream(ChunkStream):

    def __init__(self, fp):

        ChunkStream.__init__(self, fp)

        # local copies of Image attributes
        self.im_info = {}
        self.im_text = {}
        self.im_size = (0, 0)
        self.im_mode = None
        self.im_tile = None
        self.im_palette = None

        self.text_memory = 0

    def check_text_memory(self, chunklen):
        self.text_memory += chunklen
        if self.text_memory > MAX_TEXT_MEMORY:
            raise ValueError("Too much memory used in text chunks: %s>MAX_TEXT_MEMORY" %
                             self.text_memory)

    def chunk_iCCP(self, pos, length):

        # ICC profile
        s = ImageFile._safe_read(self.fp, length)
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator        1 byte (null character)
        # Compression method    1 byte (0)
        # Compressed profile    n bytes (zlib with deflate compression)
        i = s.find(b"\0")
        logger.debug("iCCP profile name %s", s[:i])
        logger.debug("Compression method %s", i8(s[i]))
        comp_method = i8(s[i])
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in iCCP chunk" %
                              comp_method)
        try:
            icc_profile = _safe_zlib_decompress(s[i+2:])
        except zlib.error:
            icc_profile = None  # FIXME
        self.im_info["icc_profile"] = icc_profile
        return s

    def chunk_IHDR(self, pos, length):

        # image header
        s = ImageFile._safe_read(self.fp, length)
        self.im_size = i32(s), i32(s[4:])
        try:
            self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))]
        except:
            pass
        if i8(s[12]):
            self.im_info["interlace"] = 1
        if i8(s[11]):
            raise SyntaxError("unknown filter category")
        return s

    def chunk_IDAT(self, pos, length):

        # image data
        self.im_tile = [("zip", (0, 0)+self.im_size, pos, self.im_rawmode)]
        self.im_idat = length
        raise EOFError

    def chunk_IEND(self, pos, length):

        # end of PNG image
        raise EOFError

    def chunk_PLTE(self, pos, length):

        # palette
        s = ImageFile._safe_read(self.fp, length)
        if self.im_mode == "P":
            self.im_palette = "RGB", s
        return s

    def chunk_tRNS(self, pos, length):

        # transparency
        s = ImageFile._safe_read(self.fp, length)
        if self.im_mode == "P":
            if _simple_palette.match(s):
                # tRNS contains only one full-transparent entry,
                # other entries are full opaque
                i = s.find(b"\0")
                if i >= 0:
                    self.im_info["transparency"] = i
            else:
                # otherwise, we have a byte string with one alpha value
                # for each palette entry
                self.im_info["transparency"] = s
        elif self.im_mode == "L":
            self.im_info["transparency"] = i16(s)
        elif self.im_mode == "RGB":
            self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
        return s

    def chunk_gAMA(self, pos, length):

        # gamma setting
        s = ImageFile._safe_read(self.fp, length)
        self.im_info["gamma"] = i32(s) / 100000.0
        return s

    def chunk_pHYs(self, pos, length):

        # pixels per unit
        s = ImageFile._safe_read(self.fp, length)
        px, py = i32(s), i32(s[4:])
        unit = i8(s[8])
        if unit == 1:  # meter
            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
            self.im_info["dpi"] = dpi
        elif unit == 0:
            self.im_info["aspect"] = px, py
        return s

    def chunk_tEXt(self, pos, length):

        # text
        s = ImageFile._safe_read(self.fp, length)
        try:
            k, v = s.split(b"\0", 1)
        except ValueError:
            # fallback for broken tEXt tags
            k = s
            v = b""
        if k:
            if bytes is not str:
                k = k.decode('latin-1', 'strict')
                v = v.decode('latin-1', 'replace')

            self.im_info[k] = self.im_text[k] = v
            self.check_text_memory(len(v))

        return s

    def chunk_zTXt(self, pos, length):

        # compressed text
        s = ImageFile._safe_read(self.fp, length)
        try:
            k, v = s.split(b"\0", 1)
        except ValueError:
            k = s
            v = b""
        if v:
            comp_method = i8(v[0])
        else:
            comp_method = 0
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in zTXt chunk" %
                              comp_method)
        try:
            v = _safe_zlib_decompress(v[1:])
        except zlib.error:
            v = b""

        if k:
            if bytes is not str:
                k = k.decode('latin-1', 'strict')
                v = v.decode('latin-1', 'replace')

            self.im_info[k] = self.im_text[k] = v
            self.check_text_memory(len(v))

        return s

    def chunk_iTXt(self, pos, length):

        # international text
        r = s = ImageFile._safe_read(self.fp, length)
        try:
            k, r = r.split(b"\0", 1)
        except ValueError:
            return s
        if len(r) < 2:
            return s
        cf, cm, r = i8(r[0]), i8(r[1]), r[2:]
        try:
            lang, tk, v = r.split(b"\0", 2)
        except ValueError:
            return s
        if cf != 0:
            if cm == 0:
                try:
                    v = _safe_zlib_decompress(v)
                except zlib.error:
                    return s
            else:
                return s
        if bytes is not str:
            try:
                k = k.decode("latin-1", "strict")
                lang = lang.decode("utf-8", "strict")
                tk = tk.decode("utf-8", "strict")
                v = v.decode("utf-8", "strict")
            except UnicodeError:
                return s

        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)
        self.check_text_memory(len(v))

        return s


# --------------------------------------------------------------------
# PNG reader

def _accept(prefix):
    return prefix[:8] == _MAGIC


##
# Image plugin for PNG images.

class PngImageFile(ImageFile.ImageFile):

    format = "PNG"
    format_description = "Portable network graphics"

    def _open(self):

        if self.fp.read(8) != _MAGIC:
            raise SyntaxError("not a PNG file")

        #
        # Parse headers up to the first IDAT chunk

        self.png = PngStream(self.fp)

        while True:

            #
            # get next chunk

            cid, pos, length = self.png.read()

            try:
                s = self.png.call(cid, pos, length)
            except EOFError:
                break
            except AttributeError:
                logger.debug("%s %s %s (unknown)", cid, pos, length)
                s = ImageFile._safe_read(self.fp, length)

            self.png.crc(cid, s)

        #
        # Copy relevant attributes from the PngStream.  An alternative
        # would be to let the PngStream class modify these attributes
        # directly, but that introduces circular references which are
        # difficult to break if things go wrong in the decoder...
        # (believe me, I've tried ;-)

        self.mode = self.png.im_mode
        self.size = self.png.im_size
        self.info = self.png.im_info
        self.text = self.png.im_text  # experimental
        self.tile = self.png.im_tile

        if self.png.im_palette:
            rawmode, data = self.png.im_palette
            self.palette = ImagePalette.raw(rawmode, data)

        self.__idat = length  # used by load_read()

    def verify(self):
        "Verify PNG file"

        if self.fp is None:
            raise RuntimeError("verify must be called directly after open")

        # back up to beginning of IDAT block
        self.fp.seek(self.tile[0][2] - 8)

        self.png.verify()
        self.png.close()

        self.fp = None

    def load_prepare(self):
        "internal: prepare to read PNG file"

        if self.info.get("interlace"):
            self.decoderconfig = self.decoderconfig + (1,)

        ImageFile.ImageFile.load_prepare(self)

    def load_read(self, read_bytes):
        "internal: read more image data"

        while self.__idat == 0:
            # end of chunk, skip forward to next one

            self.fp.read(4)  # CRC

            cid, pos, length = self.png.read()

            if cid not in [b"IDAT", b"DDAT"]:
                self.png.push(cid, pos, length)
                return b""

            self.__idat = length  # empty chunks are allowed

        # read more data from this chunk
        if read_bytes <= 0:
            read_bytes = self.__idat
        else:
            read_bytes = min(read_bytes, self.__idat)

        self.__idat = self.__idat - read_bytes

        return self.fp.read(read_bytes)

    def load_end(self):
        "internal: finished reading image data"

        self.png.close()
        self.png = None


# --------------------------------------------------------------------
# PNG writer

o8 = _binary.o8
o16 = _binary.o16be
o32 = _binary.o32be

_OUTMODES = {
    # supported PIL modes, and corresponding rawmodes/bits/color combinations
    "1":    ("1",       b'\x01\x00'),
    "L;1":  ("L;1",     b'\x01\x00'),
    "L;2":  ("L;2",     b'\x02\x00'),
    "L;4":  ("L;4",     b'\x04\x00'),
    "L":    ("L",       b'\x08\x00'),
    "LA":   ("LA",      b'\x08\x04'),
    "I":    ("I;16B",   b'\x10\x00'),
    "P;1":  ("P;1",     b'\x01\x03'),
    "P;2":  ("P;2",     b'\x02\x03'),
    "P;4":  ("P;4",     b'\x04\x03'),
    "P":    ("P",       b'\x08\x03'),
    "RGB":  ("RGB",     b'\x08\x02'),
    "RGBA": ("RGBA",    b'\x08\x06'),
}


def putchunk(fp, cid, *data):
    "Write a PNG chunk (including CRC field)"

    data = b"".join(data)

    fp.write(o32(len(data)) + cid)
    fp.write(data)
    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
    fp.write(o16(hi) + o16(lo))


class _idat(object):
    # wrap output from the encoder in IDAT chunks

    def __init__(self, fp, chunk):
        self.fp = fp
        self.chunk = chunk

    def write(self, data):
        self.chunk(self.fp, b"IDAT", data)


def _save(im, fp, filename, chunk=putchunk, check=0):
    # save an image to disk (called by the save method)

    mode = im.mode

    if mode == "P":

        #
        # attempt to minimize storage requirements for palette images
        if "bits" in im.encoderinfo:
            # number of bits specified by user
            colors = 1 << im.encoderinfo["bits"]
        else:
            # check palette contents
            if im.palette:
                colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)
            else:
                colors = 256

        if colors <= 2:
            bits = 1
        elif colors <= 4:
            bits = 2
        elif colors <= 16:
            bits = 4
        else:
            bits = 8
        if bits != 8:
            mode = "%s;%d" % (mode, bits)

    # encoder options
    if "dictionary" in im.encoderinfo:
        dictionary = im.encoderinfo["dictionary"]
    else:
        dictionary = b""

    im.encoderconfig = ("optimize" in im.encoderinfo,
                        im.encoderinfo.get("compress_level", -1),
                        im.encoderinfo.get("compress_type", -1),
                        dictionary)

    # get the corresponding PNG mode
    try:
        rawmode, mode = _OUTMODES[mode]
    except KeyError:
        raise IOError("cannot write mode %s as PNG" % mode)

    if check:
        return check

    #
    # write minimal PNG file

    fp.write(_MAGIC)

    chunk(fp, b"IHDR",
          o32(im.size[0]), o32(im.size[1]),     # 0: size
          mode,                                 # 8: depth/type
          b'\0',                                # 10: compression
          b'\0',                                # 11: filter category
          b'\0')                                # 12: interlace flag

    if im.mode == "P":
        palette_byte_number = (2 ** bits) * 3
        palette_bytes = im.im.getpalette("RGB")[:palette_byte_number]
        while len(palette_bytes) < palette_byte_number:
            palette_bytes += b'\0'
        chunk(fp, b"PLTE", palette_bytes)

    transparency = im.encoderinfo.get('transparency',
                                      im.info.get('transparency', None))

    if transparency or transparency == 0:
        if im.mode == "P":
            # limit to actual palette size
            alpha_bytes = 2**bits
            if isinstance(transparency, bytes):
                chunk(fp, b"tRNS", transparency[:alpha_bytes])
            else:
                transparency = max(0, min(255, transparency))
                alpha = b'\xFF' * transparency + b'\0'
                chunk(fp, b"tRNS", alpha[:alpha_bytes])
        elif im.mode == "L":
            transparency = max(0, min(65535, transparency))
            chunk(fp, b"tRNS", o16(transparency))
        elif im.mode == "RGB":
            red, green, blue = transparency
            chunk(fp, b"tRNS", o16(red) + o16(green) + o16(blue))
        else:
            if "transparency" in im.encoderinfo:
                # don't bother with transparency if it's an RGBA
                # and it's in the info dict. It's probably just stale.
                raise IOError("cannot use transparency for this mode")
    else:
        if im.mode == "P" and im.im.getpalettemode() == "RGBA":
            alpha = im.im.getpalette("RGBA", "A")
            alpha_bytes = 2**bits
            chunk(fp, b"tRNS", alpha[:alpha_bytes])

    dpi = im.encoderinfo.get("dpi")
    if dpi:
        chunk(fp, b"pHYs",
              o32(int(dpi[0] / 0.0254 + 0.5)),
              o32(int(dpi[1] / 0.0254 + 0.5)),
              b'\x01')

    info = im.encoderinfo.get("pnginfo")
    if info:
        for cid, data in info.chunks:
            chunk(fp, cid, data)

    # ICC profile writing support -- 2008-06-06 Florian Hoech
    if im.info.get("icc_profile"):
        # ICC profile
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator        1 byte (null character)
        # Compression method    1 byte (0)
        # Compressed profile    n bytes (zlib with deflate compression)
        name = b"ICC Profile"
        data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
        chunk(fp, b"iCCP", data)

    ImageFile._save(im, _idat(fp, chunk),
                    [("zip", (0, 0)+im.size, 0, rawmode)])

    chunk(fp, b"IEND", b"")

    if hasattr(fp, "flush"):
        fp.flush()


# --------------------------------------------------------------------
# PNG chunk converter

def getchunks(im, **params):
    """Return a list of PNG chunks representing this image."""

    class collector(object):
        data = []

        def write(self, data):
            pass

        def append(self, chunk):
            self.data.append(chunk)

    def append(fp, cid, *data):
        data = b"".join(data)
        hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
        crc = o16(hi) + o16(lo)
        fp.append((cid, data, crc))

    fp = collector()

    try:
        im.encoderinfo = params
        _save(im, fp, None, append)
    finally:
        del im.encoderinfo

    return fp.data


# --------------------------------------------------------------------
# Registry

Image.register_open(PngImageFile.format, PngImageFile, _accept)
Image.register_save(PngImageFile.format, _save)

Image.register_extension(PngImageFile.format, ".png")

Image.register_mime(PngImageFile.format, "image/png")

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** Loading PNG with Corrupted Ancillary Chunk CRC Raises OSError Despite `LOAD_TRUNCATED_IMAGES` Enabled

**Description:**
When attempting to load a PNG image that contains a corrupted CRC in an ancillary chunk, setting `ImageFile.LOAD_TRUNCATED_IMAGES` to `True` should allow the image to load by ignoring the CRC error. However, an `OSError` is raised instead, preventing the image from being processed.

**Example Code:**
```python
from PIL import Image, ImageFile
from io import BytesIO

# Simulate corrupted ancillary chunk with broken CRC
broken_crc_chunk_data = b'tEXtspamq'  # 'q' alters the CRC
image_data = b'\x89PNG\r\n\x1a\n' + broken_crc_chunk_data + b'IEND\xaeB`\x82'

ImageFile.LOAD_TRUNCATED_IMAGES = True
image = Image.open(BytesIO(image_data))
image.load()
```

**Expected Behavior:**
The image should load successfully despite the corrupted CRC in the ancillary chunk because `LOAD_TRUNCATED_IMAGES` is enabled, which allows the loader to bypass certain types of errors.

**Actual Behavior:**
An `OSError` is raised with the message:
```
OSError: cannot identify image file <_io.BytesIO object at 0x...>
```
This prevents the image from being loaded even though truncated image loading is permitted.

[/ISSUE]
{
    "TestFilePng.test_bad_itxt": "PASSED",
    "TestFilePng.test_bad_text": "PASSED",
    "TestFilePng.test_bad_ztxt": "PASSED",
    "TestFilePng.test_broken": "PASSED",
    "TestFilePng.test_interlace": "PASSED",
    "TestFilePng.test_invalid_file": "PASSED",
    "TestFilePng.test_load_transparent_p": "PASSED",
    "TestFilePng.test_load_transparent_rgb": "PASSED",
    "TestFilePng.test_load_verify": "PASSED",
    "TestFilePng.test_nonunicode_text": "PASSED",
    "TestFilePng.test_repr_png": "PASSED",
    "TestFilePng.test_roundtrip_dpi": "PASSED",
    "TestFilePng.test_roundtrip_icc_profile": "PASSED",
    "TestFilePng.test_roundtrip_itxt": "PASSED",
    "TestFilePng.test_roundtrip_text": "PASSED",
    "TestFilePng.test_sanity": "PASSED",
    "TestFilePng.test_save_icc_profile_none": "PASSED",
    "TestFilePng.test_save_l_transparency": "PASSED",
    "TestFilePng.test_save_p_single_transparency": "PASSED",
    "TestFilePng.test_save_p_transparent_black": "PASSED",
    "TestFilePng.test_save_p_transparent_palette": "PASSED",
    "TestFilePng.test_save_rgb_single_transparency": "PASSED",
    "TestFilePng.test_scary": "PASSED",
    "TestFilePng.test_trns_null": "PASSED",
    "TestFilePng.test_trns_p": "PASSED",
    "TestFilePng.test_trns_rgb": "PASSED",
    "TestFilePng.test_unicode_text": "PASSED",
    "TestFilePng.test_verify_ignores_crc_error": "PASSED",
    "TestFilePng.test_verify_not_ignores_crc_error_in_required_chunk": "PASSED",
    "TestFilePng.test_verify_struct_error": "PASSED"
}
diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py
index 4d82c9a97..12a7ef17e 100644
--- a/PIL/PngImagePlugin.py
+++ b/PIL/PngImagePlugin.py
@@ -140,7 +140,7 @@ class ChunkStream(object):
 
         # Skip CRC checks for ancillary chunks if allowed to load truncated images
         # 5th byte of first char is 1 [specs, section 5.4]
-        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):
+        if ImageFile.LOAD_TRUNCATED_IMAGES and (i8(cid[0]) >> 5 & 1):
             self.crc_skip(cid, data)
             return
 

{"PIL/PngImagePlugin.py": "#\n# The Python Imaging Library.\n# $Id$\n#\n# PNG support code\n#\n# See \"PNG (Portable Network Graphics) Specification, version 1.0;\n# W3C Recommendation\", 1996-10-01, Thomas Boutell (ed.).\n#\n# history:\n# 1996-05-06 fl   Created (couldn't resist it)\n# 1996-12-14 fl   Upgraded, added read and verify support (0.2)\n# 1996-12-15 fl   Separate PNG stream parser\n# 1996-12-29 fl   Added write support, added getchunks\n# 1996-12-30 fl   Eliminated circular references in decoder (0.3)\n# 1998-07-12 fl   Read/write 16-bit images as mode I (0.4)\n# 2001-02-08 fl   Added transparency support (from Zircon) (0.5)\n# 2001-04-16 fl   Don't close data source in \"open\" method (0.6)\n# 2004-02-24 fl   Don't even pretend to support interlaced files (0.7)\n# 2004-08-31 fl   Do basic sanity check on chunk identifiers (0.8)\n# 2004-09-20 fl   Added PngInfo chunk container\n# 2004-12-18 fl   Added DPI read support (based on code by Niki Spahiev)\n# 2008-08-13 fl   Added tRNS support for RGB images\n# 2009-03-06 fl   Support for preserving ICC profiles (by Florian Hoech)\n# 2009-03-08 fl   Added zTXT support (from Lowell Alleman)\n# 2009-03-29 fl   Read interlaced PNG files (from Conrado Porto Lopes Gouvua)\n#\n# Copyright (c) 1997-2009 by Secret Labs AB\n# Copyright (c) 1996 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom __future__ import print_function\n\nimport logging\nimport re\nimport zlib\nimport struct\n\nfrom PIL import Image, ImageFile, ImagePalette, _binary\n\n__version__ = \"0.9\"\n\nlogger = logging.getLogger(__name__)\n\ni8 = _binary.i8\ni16 = _binary.i16be\ni32 = _binary.i32be\n\nis_cid = re.compile(b\"\\w\\w\\w\\w\").match\n\n\n_MAGIC = b\"\\211PNG\\r\\n\\032\\n\"\n\n\n_MODES = {\n    # supported bits/color combinations, and corresponding modes/rawmodes\n    (1, 0):  (\"1\", \"1\"),\n    (2, 0):  (\"L\", \"L;2\"),\n    (4, 0):  (\"L\", \"L;4\"),\n    (8, 0):  (\"L\", \"L\"),\n    (16, 0): (\"I\", \"I;16B\"),\n    (8, 2):  (\"RGB\", \"RGB\"),\n    (16, 2): (\"RGB\", \"RGB;16B\"),\n    (1, 3):  (\"P\", \"P;1\"),\n    (2, 3):  (\"P\", \"P;2\"),\n    (4, 3):  (\"P\", \"P;4\"),\n    (8, 3):  (\"P\", \"P\"),\n    (8, 4):  (\"LA\", \"LA\"),\n    (16, 4): (\"RGBA\", \"LA;16B\"),  # LA;16B->LA not yet available\n    (8, 6):  (\"RGBA\", \"RGBA\"),\n    (16, 6): (\"RGBA\", \"RGBA;16B\"),\n}\n\n\n_simple_palette = re.compile(b'^\\xff*\\x00\\xff*$')\n\n# Maximum decompressed size for a iTXt or zTXt chunk.\n# Eliminates decompression bombs where compressed chunks can expand 1000x\nMAX_TEXT_CHUNK = ImageFile.SAFEBLOCK\n# Set the maximum total text chunk size.\nMAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK\n\n\ndef _safe_zlib_decompress(s):\n    dobj = zlib.decompressobj()\n    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)\n    if dobj.unconsumed_tail:\n        raise ValueError(\"Decompressed Data Too Large\")\n    return plaintext\n\n\n# --------------------------------------------------------------------\n# Support classes.  Suitable for PNG and related formats like MNG etc.\n\nclass ChunkStream(object):\n\n    def __init__(self, fp):\n\n        self.fp = fp\n        self.queue = []\n\n        if not hasattr(Image.core, \"crc32\"):\n            self.crc = self.crc_skip\n\n    def read(self):\n        \"Fetch a new chunk. Returns header information.\"\n        cid = None\n\n        if self.queue:\n            cid, pos, length = self.queue.pop()\n            self.fp.seek(pos)\n        else:\n            s = self.fp.read(8)\n            cid = s[4:]\n            pos = self.fp.tell()\n            length = i32(s)\n\n        if not is_cid(cid):\n            raise SyntaxError(\"broken PNG file (chunk %s)\" % repr(cid))\n\n        return cid, pos, length\n\n    def close(self):\n        self.queue = self.crc = self.fp = None\n\n    def push(self, cid, pos, length):\n\n        self.queue.append((cid, pos, length))\n\n    def call(self, cid, pos, length):\n        \"Call the appropriate chunk handler\"\n\n        logger.debug(\"STREAM %s %s %s\", cid, pos, length)\n        return getattr(self, \"chunk_\" + cid.decode('ascii'))(pos, length)\n\n    def crc(self, cid, data):\n        \"Read and verify checksum\"\n\n        # Skip CRC checks for ancillary chunks if allowed to load truncated images\n        # 5th byte of first char is 1 [specs, section 5.4]\n        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):\n            self.crc_skip(cid, data)\n            return\n\n        try:\n            crc1 = Image.core.crc32(data, Image.core.crc32(cid))\n            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))\n            if crc1 != crc2:\n                raise SyntaxError(\"broken PNG file (bad header checksum in %s)\"\n                                  % cid)\n        except struct.error:\n            raise SyntaxError(\"broken PNG file (incomplete checksum in %s)\"\n                              % cid)\n\n    def crc_skip(self, cid, data):\n        \"Read checksum.  Used if the C module is not present\"\n\n        self.fp.read(4)\n\n    def verify(self, endchunk=b\"IEND\"):\n\n        # Simple approach; just calculate checksum for all remaining\n        # blocks.  Must be called directly after open.\n\n        cids = []\n\n        while True:\n            try:\n                cid, pos, length = self.read()\n            except struct.error:\n                raise IOError(\"truncated PNG file\")\n\n            if cid == endchunk:\n                break\n            self.crc(cid, ImageFile._safe_read(self.fp, length))\n            cids.append(cid)\n\n        return cids\n\n\nclass iTXt(str):\n    \"\"\"\n    Subclass of string to allow iTXt chunks to look like strings while\n    keeping their extra information\n\n    \"\"\"\n    @staticmethod\n    def __new__(cls, text, lang, tkey):\n        \"\"\"\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        \"\"\"\n\n        self = str.__new__(cls, text)\n        self.lang = lang\n        self.tkey = tkey\n        return self\n\n\nclass PngInfo(object):\n    \"\"\"\n    PNG chunk container (for use with save(pnginfo=))\n\n    \"\"\"\n\n    def __init__(self):\n        self.chunks = []\n\n    def add(self, cid, data):\n        \"\"\"Appends an arbitrary chunk. Use with caution.\n\n        :param cid: a byte string, 4 bytes long.\n        :param data: a byte string of the encoded data\n\n        \"\"\"\n\n        self.chunks.append((cid, data))\n\n    def add_itxt(self, key, value, lang=\"\", tkey=\"\", zip=False):\n        \"\"\"Appends an iTXt chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key\n        :param lang: language code\n        :param tkey: UTF-8 version of the key name\n        :param zip: compression flag\n\n        \"\"\"\n\n        if not isinstance(key, bytes):\n            key = key.encode(\"latin-1\", \"strict\")\n        if not isinstance(value, bytes):\n            value = value.encode(\"utf-8\", \"strict\")\n        if not isinstance(lang, bytes):\n            lang = lang.encode(\"utf-8\", \"strict\")\n        if not isinstance(tkey, bytes):\n            tkey = tkey.encode(\"utf-8\", \"strict\")\n\n        if zip:\n            self.add(b\"iTXt\", key + b\"\\0\\x01\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     zlib.compress(value))\n        else:\n            self.add(b\"iTXt\", key + b\"\\0\\0\\0\" + lang + b\"\\0\" + tkey + b\"\\0\" +\n                     value)\n\n    def add_text(self, key, value, zip=0):\n        \"\"\"Appends a text chunk.\n\n        :param key: latin-1 encodable text key name\n        :param value: value for this key, text or an\n           :py:class:`PIL.PngImagePlugin.iTXt` instance\n        :param zip: compression flag\n\n        \"\"\"\n        if isinstance(value, iTXt):\n            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))\n\n        # The tEXt chunk stores latin-1 text\n        if not isinstance(value, bytes):\n            try:\n                value = value.encode('latin-1', 'strict')\n            except UnicodeError:\n                return self.add_itxt(key, value, zip=bool(zip))\n\n        if not isinstance(key, bytes):\n            key = key.encode('latin-1', 'strict')\n\n        if zip:\n            self.add(b\"zTXt\", key + b\"\\0\\0\" + zlib.compress(value))\n        else:\n            self.add(b\"tEXt\", key + b\"\\0\" + value)\n\n\n# --------------------------------------------------------------------\n# PNG image stream (IHDR/IEND)\n\nclass PngStream(ChunkStream):\n\n    def __init__(self, fp):\n\n        ChunkStream.__init__(self, fp)\n\n        # local copies of Image attributes\n        self.im_info = {}\n        self.im_text = {}\n        self.im_size = (0, 0)\n        self.im_mode = None\n        self.im_tile = None\n        self.im_palette = None\n\n        self.text_memory = 0\n\n    def check_text_memory(self, chunklen):\n        self.text_memory += chunklen\n        if self.text_memory > MAX_TEXT_MEMORY:\n            raise ValueError(\"Too much memory used in text chunks: %s>MAX_TEXT_MEMORY\" %\n                             self.text_memory)\n\n    def chunk_iCCP(self, pos, length):\n\n        # ICC profile\n        s = ImageFile._safe_read(self.fp, length)\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        i = s.find(b\"\\0\")\n        logger.debug(\"iCCP profile name %s\", s[:i])\n        logger.debug(\"Compression method %s\", i8(s[i]))\n        comp_method = i8(s[i])\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in iCCP chunk\" %\n                              comp_method)\n        try:\n            icc_profile = _safe_zlib_decompress(s[i+2:])\n        except zlib.error:\n            icc_profile = None  # FIXME\n        self.im_info[\"icc_profile\"] = icc_profile\n        return s\n\n    def chunk_IHDR(self, pos, length):\n\n        # image header\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_size = i32(s), i32(s[4:])\n        try:\n            self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))]\n        except:\n            pass\n        if i8(s[12]):\n            self.im_info[\"interlace\"] = 1\n        if i8(s[11]):\n            raise SyntaxError(\"unknown filter category\")\n        return s\n\n    def chunk_IDAT(self, pos, length):\n\n        # image data\n        self.im_tile = [(\"zip\", (0, 0)+self.im_size, pos, self.im_rawmode)]\n        self.im_idat = length\n        raise EOFError\n\n    def chunk_IEND(self, pos, length):\n\n        # end of PNG image\n        raise EOFError\n\n    def chunk_PLTE(self, pos, length):\n\n        # palette\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            self.im_palette = \"RGB\", s\n        return s\n\n    def chunk_tRNS(self, pos, length):\n\n        # transparency\n        s = ImageFile._safe_read(self.fp, length)\n        if self.im_mode == \"P\":\n            if _simple_palette.match(s):\n                # tRNS contains only one full-transparent entry,\n                # other entries are full opaque\n                i = s.find(b\"\\0\")\n                if i >= 0:\n                    self.im_info[\"transparency\"] = i\n            else:\n                # otherwise, we have a byte string with one alpha value\n                # for each palette entry\n                self.im_info[\"transparency\"] = s\n        elif self.im_mode == \"L\":\n            self.im_info[\"transparency\"] = i16(s)\n        elif self.im_mode == \"RGB\":\n            self.im_info[\"transparency\"] = i16(s), i16(s[2:]), i16(s[4:])\n        return s\n\n    def chunk_gAMA(self, pos, length):\n\n        # gamma setting\n        s = ImageFile._safe_read(self.fp, length)\n        self.im_info[\"gamma\"] = i32(s) / 100000.0\n        return s\n\n    def chunk_pHYs(self, pos, length):\n\n        # pixels per unit\n        s = ImageFile._safe_read(self.fp, length)\n        px, py = i32(s), i32(s[4:])\n        unit = i8(s[8])\n        if unit == 1:  # meter\n            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)\n            self.im_info[\"dpi\"] = dpi\n        elif unit == 0:\n            self.im_info[\"aspect\"] = px, py\n        return s\n\n    def chunk_tEXt(self, pos, length):\n\n        # text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            # fallback for broken tEXt tags\n            k = s\n            v = b\"\"\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_zTXt(self, pos, length):\n\n        # compressed text\n        s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, v = s.split(b\"\\0\", 1)\n        except ValueError:\n            k = s\n            v = b\"\"\n        if v:\n            comp_method = i8(v[0])\n        else:\n            comp_method = 0\n        if comp_method != 0:\n            raise SyntaxError(\"Unknown compression method %s in zTXt chunk\" %\n                              comp_method)\n        try:\n            v = _safe_zlib_decompress(v[1:])\n        except zlib.error:\n            v = b\"\"\n\n        if k:\n            if bytes is not str:\n                k = k.decode('latin-1', 'strict')\n                v = v.decode('latin-1', 'replace')\n\n            self.im_info[k] = self.im_text[k] = v\n            self.check_text_memory(len(v))\n\n        return s\n\n    def chunk_iTXt(self, pos, length):\n\n        # international text\n        r = s = ImageFile._safe_read(self.fp, length)\n        try:\n            k, r = r.split(b\"\\0\", 1)\n        except ValueError:\n            return s\n        if len(r) < 2:\n            return s\n        cf, cm, r = i8(r[0]), i8(r[1]), r[2:]\n        try:\n            lang, tk, v = r.split(b\"\\0\", 2)\n        except ValueError:\n            return s\n        if cf != 0:\n            if cm == 0:\n                try:\n                    v = _safe_zlib_decompress(v)\n                except zlib.error:\n                    return s\n            else:\n                return s\n        if bytes is not str:\n            try:\n                k = k.decode(\"latin-1\", \"strict\")\n                lang = lang.decode(\"utf-8\", \"strict\")\n                tk = tk.decode(\"utf-8\", \"strict\")\n                v = v.decode(\"utf-8\", \"strict\")\n            except UnicodeError:\n                return s\n\n        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)\n        self.check_text_memory(len(v))\n\n        return s\n\n\n# --------------------------------------------------------------------\n# PNG reader\n\ndef _accept(prefix):\n    return prefix[:8] == _MAGIC\n\n\n##\n# Image plugin for PNG images.\n\nclass PngImageFile(ImageFile.ImageFile):\n\n    format = \"PNG\"\n    format_description = \"Portable network graphics\"\n\n    def _open(self):\n\n        if self.fp.read(8) != _MAGIC:\n            raise SyntaxError(\"not a PNG file\")\n\n        #\n        # Parse headers up to the first IDAT chunk\n\n        self.png = PngStream(self.fp)\n\n        while True:\n\n            #\n            # get next chunk\n\n            cid, pos, length = self.png.read()\n\n            try:\n                s = self.png.call(cid, pos, length)\n            except EOFError:\n                break\n            except AttributeError:\n                logger.debug(\"%s %s %s (unknown)\", cid, pos, length)\n                s = ImageFile._safe_read(self.fp, length)\n\n            self.png.crc(cid, s)\n\n        #\n        # Copy relevant attributes from the PngStream.  An alternative\n        # would be to let the PngStream class modify these attributes\n        # directly, but that introduces circular references which are\n        # difficult to break if things go wrong in the decoder...\n        # (believe me, I've tried ;-)\n\n        self.mode = self.png.im_mode\n        self.size = self.png.im_size\n        self.info = self.png.im_info\n        self.text = self.png.im_text  # experimental\n        self.tile = self.png.im_tile\n\n        if self.png.im_palette:\n            rawmode, data = self.png.im_palette\n            self.palette = ImagePalette.raw(rawmode, data)\n\n        self.__idat = length  # used by load_read()\n\n    def verify(self):\n        \"Verify PNG file\"\n\n        if self.fp is None:\n            raise RuntimeError(\"verify must be called directly after open\")\n\n        # back up to beginning of IDAT block\n        self.fp.seek(self.tile[0][2] - 8)\n\n        self.png.verify()\n        self.png.close()\n\n        self.fp = None\n\n    def load_prepare(self):\n        \"internal: prepare to read PNG file\"\n\n        if self.info.get(\"interlace\"):\n            self.decoderconfig = self.decoderconfig + (1,)\n\n        ImageFile.ImageFile.load_prepare(self)\n\n    def load_read(self, read_bytes):\n        \"internal: read more image data\"\n\n        while self.__idat == 0:\n            # end of chunk, skip forward to next one\n\n            self.fp.read(4)  # CRC\n\n            cid, pos, length = self.png.read()\n\n            if cid not in [b\"IDAT\", b\"DDAT\"]:\n                self.png.push(cid, pos, length)\n                return b\"\"\n\n            self.__idat = length  # empty chunks are allowed\n\n        # read more data from this chunk\n        if read_bytes <= 0:\n            read_bytes = self.__idat\n        else:\n            read_bytes = min(read_bytes, self.__idat)\n\n        self.__idat = self.__idat - read_bytes\n\n        return self.fp.read(read_bytes)\n\n    def load_end(self):\n        \"internal: finished reading image data\"\n\n        self.png.close()\n        self.png = None\n\n\n# --------------------------------------------------------------------\n# PNG writer\n\no8 = _binary.o8\no16 = _binary.o16be\no32 = _binary.o32be\n\n_OUTMODES = {\n    # supported PIL modes, and corresponding rawmodes/bits/color combinations\n    \"1\":    (\"1\",       b'\\x01\\x00'),\n    \"L;1\":  (\"L;1\",     b'\\x01\\x00'),\n    \"L;2\":  (\"L;2\",     b'\\x02\\x00'),\n    \"L;4\":  (\"L;4\",     b'\\x04\\x00'),\n    \"L\":    (\"L\",       b'\\x08\\x00'),\n    \"LA\":   (\"LA\",      b'\\x08\\x04'),\n    \"I\":    (\"I;16B\",   b'\\x10\\x00'),\n    \"P;1\":  (\"P;1\",     b'\\x01\\x03'),\n    \"P;2\":  (\"P;2\",     b'\\x02\\x03'),\n    \"P;4\":  (\"P;4\",     b'\\x04\\x03'),\n    \"P\":    (\"P\",       b'\\x08\\x03'),\n    \"RGB\":  (\"RGB\",     b'\\x08\\x02'),\n    \"RGBA\": (\"RGBA\",    b'\\x08\\x06'),\n}\n\n\ndef putchunk(fp, cid, *data):\n    \"Write a PNG chunk (including CRC field)\"\n\n    data = b\"\".join(data)\n\n    fp.write(o32(len(data)) + cid)\n    fp.write(data)\n    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n    fp.write(o16(hi) + o16(lo))\n\n\nclass _idat(object):\n    # wrap output from the encoder in IDAT chunks\n\n    def __init__(self, fp, chunk):\n        self.fp = fp\n        self.chunk = chunk\n\n    def write(self, data):\n        self.chunk(self.fp, b\"IDAT\", data)\n\n\ndef _save(im, fp, filename, chunk=putchunk, check=0):\n    # save an image to disk (called by the save method)\n\n    mode = im.mode\n\n    if mode == \"P\":\n\n        #\n        # attempt to minimize storage requirements for palette images\n        if \"bits\" in im.encoderinfo:\n            # number of bits specified by user\n            colors = 1 << im.encoderinfo[\"bits\"]\n        else:\n            # check palette contents\n            if im.palette:\n                colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)\n            else:\n                colors = 256\n\n        if colors <= 2:\n            bits = 1\n        elif colors <= 4:\n            bits = 2\n        elif colors <= 16:\n            bits = 4\n        else:\n            bits = 8\n        if bits != 8:\n            mode = \"%s;%d\" % (mode, bits)\n\n    # encoder options\n    if \"dictionary\" in im.encoderinfo:\n        dictionary = im.encoderinfo[\"dictionary\"]\n    else:\n        dictionary = b\"\"\n\n    im.encoderconfig = (\"optimize\" in im.encoderinfo,\n                        im.encoderinfo.get(\"compress_level\", -1),\n                        im.encoderinfo.get(\"compress_type\", -1),\n                        dictionary)\n\n    # get the corresponding PNG mode\n    try:\n        rawmode, mode = _OUTMODES[mode]\n    except KeyError:\n        raise IOError(\"cannot write mode %s as PNG\" % mode)\n\n    if check:\n        return check\n\n    #\n    # write minimal PNG file\n\n    fp.write(_MAGIC)\n\n    chunk(fp, b\"IHDR\",\n          o32(im.size[0]), o32(im.size[1]),     # 0: size\n          mode,                                 # 8: depth/type\n          b'\\0',                                # 10: compression\n          b'\\0',                                # 11: filter category\n          b'\\0')                                # 12: interlace flag\n\n    if im.mode == \"P\":\n        palette_byte_number = (2 ** bits) * 3\n        palette_bytes = im.im.getpalette(\"RGB\")[:palette_byte_number]\n        while len(palette_bytes) < palette_byte_number:\n            palette_bytes += b'\\0'\n        chunk(fp, b\"PLTE\", palette_bytes)\n\n    transparency = im.encoderinfo.get('transparency',\n                                      im.info.get('transparency', None))\n\n    if transparency or transparency == 0:\n        if im.mode == \"P\":\n            # limit to actual palette size\n            alpha_bytes = 2**bits\n            if isinstance(transparency, bytes):\n                chunk(fp, b\"tRNS\", transparency[:alpha_bytes])\n            else:\n                transparency = max(0, min(255, transparency))\n                alpha = b'\\xFF' * transparency + b'\\0'\n                chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n        elif im.mode == \"L\":\n            transparency = max(0, min(65535, transparency))\n            chunk(fp, b\"tRNS\", o16(transparency))\n        elif im.mode == \"RGB\":\n            red, green, blue = transparency\n            chunk(fp, b\"tRNS\", o16(red) + o16(green) + o16(blue))\n        else:\n            if \"transparency\" in im.encoderinfo:\n                # don't bother with transparency if it's an RGBA\n                # and it's in the info dict. It's probably just stale.\n                raise IOError(\"cannot use transparency for this mode\")\n    else:\n        if im.mode == \"P\" and im.im.getpalettemode() == \"RGBA\":\n            alpha = im.im.getpalette(\"RGBA\", \"A\")\n            alpha_bytes = 2**bits\n            chunk(fp, b\"tRNS\", alpha[:alpha_bytes])\n\n    dpi = im.encoderinfo.get(\"dpi\")\n    if dpi:\n        chunk(fp, b\"pHYs\",\n              o32(int(dpi[0] / 0.0254 + 0.5)),\n              o32(int(dpi[1] / 0.0254 + 0.5)),\n              b'\\x01')\n\n    info = im.encoderinfo.get(\"pnginfo\")\n    if info:\n        for cid, data in info.chunks:\n            chunk(fp, cid, data)\n\n    # ICC profile writing support -- 2008-06-06 Florian Hoech\n    if im.info.get(\"icc_profile\"):\n        # ICC profile\n        # according to PNG spec, the iCCP chunk contains:\n        # Profile name  1-79 bytes (character string)\n        # Null separator        1 byte (null character)\n        # Compression method    1 byte (0)\n        # Compressed profile    n bytes (zlib with deflate compression)\n        name = b\"ICC Profile\"\n        data = name + b\"\\0\\0\" + zlib.compress(im.info[\"icc_profile\"])\n        chunk(fp, b\"iCCP\", data)\n\n    ImageFile._save(im, _idat(fp, chunk),\n                    [(\"zip\", (0, 0)+im.size, 0, rawmode)])\n\n    chunk(fp, b\"IEND\", b\"\")\n\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\n# --------------------------------------------------------------------\n# PNG chunk converter\n\ndef getchunks(im, **params):\n    \"\"\"Return a list of PNG chunks representing this image.\"\"\"\n\n    class collector(object):\n        data = []\n\n        def write(self, data):\n            pass\n\n        def append(self, chunk):\n            self.data.append(chunk)\n\n    def append(fp, cid, *data):\n        data = b\"\".join(data)\n        hi, lo = Image.core.crc32(data, Image.core.crc32(cid))\n        crc = o16(hi) + o16(lo)\n        fp.append((cid, data, crc))\n\n    fp = collector()\n\n    try:\n        im.encoderinfo = params\n        _save(im, fp, None, append)\n    finally:\n        del im.encoderinfo\n\n    return fp.data\n\n\n# --------------------------------------------------------------------\n# Registry\n\nImage.register_open(PngImageFile.format, PngImageFile, _accept)\nImage.register_save(PngImageFile.format, _save)\n\nImage.register_extension(PngImageFile.format, \".png\")\n\nImage.register_mime(PngImageFile.format, \"image/png\")\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Loading PNG with Corrupted Ancillary Chunk CRC Raises OSError Despite `LOAD_TRUNCATED_IMAGES` Enabled

**Description:**
When attempting to load a PNG image that contains a corrupted CRC in an ancillary chunk, setting `ImageFile.LOAD_TRUNCATED_IMAGES` to `True` should allow the image to load by ignoring the CRC error. However, an `OSError` is raised instead, preventing the image from being processed.

**Example Code:**
```python
from PIL import Image, ImageFile
from io import BytesIO

# Simulate corrupted ancillary chunk with broken CRC
broken_crc_chunk_data = b'tEXtspamq'  # 'q' alters the CRC
image_data = b'\x89PNG\r\n\x1a\n' + broken_crc_chunk_data + b'IEND\xaeB`\x82'

ImageFile.LOAD_TRUNCATED_IMAGES = True
image = Image.open(BytesIO(image_data))
image.load()
```

**Expected Behavior:**
The image should load successfully despite the corrupted CRC in the ancillary chunk because `LOAD_TRUNCATED_IMAGES` is enabled, which allows the loader to bypass certain types of errors.

**Actual Behavior:**
An `OSError` is raised with the message:
```
OSError: cannot identify image file <_io.BytesIO object at 0x...>
```
This prevents the image from being loaded even though truncated image loading is permitted.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### PIL/PngImagePlugin.py
#
# The Python Imaging Library.
# $Id$
#
# PNG support code
#
# See "PNG (Portable Network Graphics) Specification, version 1.0;
# W3C Recommendation", 1996-10-01, Thomas Boutell (ed.).
#
# history:
# 1996-05-06 fl   Created (couldn't resist it)
# 1996-12-14 fl   Upgraded, added read and verify support (0.2)
# 1996-12-15 fl   Separate PNG stream parser
# 1996-12-29 fl   Added write support, added getchunks
# 1996-12-30 fl   Eliminated circular references in decoder (0.3)
# 1998-07-12 fl   Read/write 16-bit images as mode I (0.4)
# 2001-02-08 fl   Added transparency support (from Zircon) (0.5)
# 2001-04-16 fl   Don't close data source in "open" method (0.6)
# 2004-02-24 fl   Don't even pretend to support interlaced files (0.7)
# 2004-08-31 fl   Do basic sanity check on chunk identifiers (0.8)
# 2004-09-20 fl   Added PngInfo chunk container
# 2004-12-18 fl   Added DPI read support (based on code by Niki Spahiev)
# 2008-08-13 fl   Added tRNS support for RGB images
# 2009-03-06 fl   Support for preserving ICC profiles (by Florian Hoech)
# 2009-03-08 fl   Added zTXT support (from Lowell Alleman)
# 2009-03-29 fl   Read interlaced PNG files (from Conrado Porto Lopes Gouvua)
#
# Copyright (c) 1997-2009 by Secret Labs AB
# Copyright (c) 1996 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

from __future__ import print_function

import logging
import re
import zlib
import struct

from PIL import Image, ImageFile, ImagePalette, _binary

__version__ = "0.9"

logger = logging.getLogger(__name__)

i8 = _binary.i8
i16 = _binary.i16be
i32 = _binary.i32be

is_cid = re.compile(b"\w\w\w\w").match


_MAGIC = b"\211PNG\r\n\032\n"


_MODES = {
    # supported bits/color combinations, and corresponding modes/rawmodes
    (1, 0):  ("1", "1"),
    (2, 0):  ("L", "L;2"),
    (4, 0):  ("L", "L;4"),
    (8, 0):  ("L", "L"),
    (16, 0): ("I", "I;16B"),
    (8, 2):  ("RGB", "RGB"),
    (16, 2): ("RGB", "RGB;16B"),
    (1, 3):  ("P", "P;1"),
    (2, 3):  ("P", "P;2"),
    (4, 3):  ("P", "P;4"),
    (8, 3):  ("P", "P"),
    (8, 4):  ("LA", "LA"),
    (16, 4): ("RGBA", "LA;16B"),  # LA;16B->LA not yet available
    (8, 6):  ("RGBA", "RGBA"),
    (16, 6): ("RGBA", "RGBA;16B"),
}


_simple_palette = re.compile(b'^\xff*\x00\xff*$')

# Maximum decompressed size for a iTXt or zTXt chunk.
# Eliminates decompression bombs where compressed chunks can expand 1000x
MAX_TEXT_CHUNK = ImageFile.SAFEBLOCK
# Set the maximum total text chunk size.
MAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK


def _safe_zlib_decompress(s):
    dobj = zlib.decompressobj()
    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
    if dobj.unconsumed_tail:
        raise ValueError("Decompressed Data Too Large")
    return plaintext


# --------------------------------------------------------------------
# Support classes.  Suitable for PNG and related formats like MNG etc.

class ChunkStream(object):

    def __init__(self, fp):

        self.fp = fp
        self.queue = []

        if not hasattr(Image.core, "crc32"):
            self.crc = self.crc_skip

    def read(self):
        "Fetch a new chunk. Returns header information."
        cid = None

        if self.queue:
            cid, pos, length = self.queue.pop()
            self.fp.seek(pos)
        else:
            s = self.fp.read(8)
            cid = s[4:]
            pos = self.fp.tell()
            length = i32(s)

        if not is_cid(cid):
            raise SyntaxError("broken PNG file (chunk %s)" % repr(cid))

        return cid, pos, length

    def close(self):
        self.queue = self.crc = self.fp = None

    def push(self, cid, pos, length):

        self.queue.append((cid, pos, length))

    def call(self, cid, pos, length):
        "Call the appropriate chunk handler"

        logger.debug("STREAM %s %s %s", cid, pos, length)
        return getattr(self, "chunk_" + cid.decode('ascii'))(pos, length)

    def crc(self, cid, data):
        "Read and verify checksum"

        # Skip CRC checks for ancillary chunks if allowed to load truncated images
        # 5th byte of first char is 1 [specs, section 5.4]
        if ImageFile.LOAD_TRUNCATED_IMAGES and (ord(cid[0]) >> 5 & 1):
            self.crc_skip(cid, data)
            return

        try:
            crc1 = Image.core.crc32(data, Image.core.crc32(cid))
            crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
            if crc1 != crc2:
                raise SyntaxError("broken PNG file (bad header checksum in %s)"
                                  % cid)
        except struct.error:
            raise SyntaxError("broken PNG file (incomplete checksum in %s)"
                              % cid)

    def crc_skip(self, cid, data):
        "Read checksum.  Used if the C module is not present"

        self.fp.read(4)

    def verify(self, endchunk=b"IEND"):

        # Simple approach; just calculate checksum for all remaining
        # blocks.  Must be called directly after open.

        cids = []

        while True:
            try:
                cid, pos, length = self.read()
            except struct.error:
                raise IOError("truncated PNG file")

            if cid == endchunk:
                break
            self.crc(cid, ImageFile._safe_read(self.fp, length))
            cids.append(cid)

        return cids


class iTXt(str):
    """
    Subclass of string to allow iTXt chunks to look like strings while
    keeping their extra information

    """
    @staticmethod
    def __new__(cls, text, lang, tkey):
        """
        :param value: value for this key
        :param lang: language code
        :param tkey: UTF-8 version of the key name
        """

        self = str.__new__(cls, text)
        self.lang = lang
        self.tkey = tkey
        return self


class PngInfo(object):
    """
    PNG chunk container (for use with save(pnginfo=))

    """

    def __init__(self):
        self.chunks = []

    def add(self, cid, data):
        """Appends an arbitrary chunk. Use with caution.

        :param cid: a byte string, 4 bytes long.
        :param data: a byte string of the encoded data

        """

        self.chunks.append((cid, data))

    def add_itxt(self, key, value, lang="", tkey="", zip=False):
        """Appends an iTXt chunk.

        :param key: latin-1 encodable text key name
        :param value: value for this key
        :param lang: language code
        :param tkey: UTF-8 version of the key name
        :param zip: compression flag

        """

        if not isinstance(key, bytes):
            key = key.encode("latin-1", "strict")
        if not isinstance(value, bytes):
            value = value.encode("utf-8", "strict")
        if not isinstance(lang, bytes):
            lang = lang.encode("utf-8", "strict")
        if not isinstance(tkey, bytes):
            tkey = tkey.encode("utf-8", "strict")

        if zip:
            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" +
                     zlib.compress(value))
        else:
            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" +
                     value)

    def add_text(self, key, value, zip=0):
        """Appends a text chunk.

        :param key: latin-1 encodable text key name
        :param value: value for this key, text or an
           :py:class:`PIL.PngImagePlugin.iTXt` instance
        :param zip: compression flag

        """
        if isinstance(value, iTXt):
            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))

        # The tEXt chunk stores latin-1 text
        if not isinstance(value, bytes):
            try:
                value = value.encode('latin-1', 'strict')
            except UnicodeError:
                return self.add_itxt(key, value, zip=bool(zip))

        if not isinstance(key, bytes):
            key = key.encode('latin-1', 'strict')

        if zip:
            self.add(b"zTXt", key + b"\0\0" + zlib.compress(value))
        else:
            self.add(b"tEXt", key + b"\0" + value)


# --------------------------------------------------------------------
# PNG image stream (IHDR/IEND)

class PngStream(ChunkStream):

    def __init__(self, fp):

        ChunkStream.__init__(self, fp)

        # local copies of Image attributes
        self.im_info = {}
        self.im_text = {}
        self.im_size = (0, 0)
        self.im_mode = None
        self.im_tile = None
        self.im_palette = None

        self.text_memory = 0

    def check_text_memory(self, chunklen):
        self.text_memory += chunklen
        if self.text_memory > MAX_TEXT_MEMORY:
            raise ValueError("Too much memory used in text chunks: %s>MAX_TEXT_MEMORY" %
                             self.text_memory)

    def chunk_iCCP(self, pos, length):

        # ICC profile
        s = ImageFile._safe_read(self.fp, length)
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator        1 byte (null character)
        # Compression method    1 byte (0)
        # Compressed profile    n bytes (zlib with deflate compression)
        i = s.find(b"\0")
        logger.debug("iCCP profile name %s", s[:i])
        logger.debug("Compression method %s", i8(s[i]))
        comp_method = i8(s[i])
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in iCCP chunk" %
                              comp_method)
        try:
            icc_profile = _safe_zlib_decompress(s[i+2:])
        except zlib.error:
            icc_profile = None  # FIXME
        self.im_info["icc_profile"] = icc_profile
        return s

    def chunk_IHDR(self, pos, length):

        # image header
        s = ImageFile._safe_read(self.fp, length)
        self.im_size = i32(s), i32(s[4:])
        try:
            self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))]
        except:
            pass
        if i8(s[12]):
            self.im_info["interlace"] = 1
        if i8(s[11]):
            raise SyntaxError("unknown filter category")
        return s

    def chunk_IDAT(self, pos, length):

        # image data
        self.im_tile = [("zip", (0, 0)+self.im_size, pos, self.im_rawmode)]
        self.im_idat = length
        raise EOFError

    def chunk_IEND(self, pos, length):

        # end of PNG image
        raise EOFError

    def chunk_PLTE(self, pos, length):

        # palette
        s = ImageFile._safe_read(self.fp, length)
        if self.im_mode == "P":
            self.im_palette = "RGB", s
        return s

    def chunk_tRNS(self, pos, length):

        # transparency
        s = ImageFile._safe_read(self.fp, length)
        if self.im_mode == "P":
            if _simple_palette.match(s):
                # tRNS contains only one full-transparent entry,
                # other entries are full opaque
                i = s.find(b"\0")
                if i >= 0:
                    self.im_info["transparency"] = i
            else:
                # otherwise, we have a byte string with one alpha value
                # for each palette entry
                self.im_info["transparency"] = s
        elif self.im_mode == "L":
            self.im_info["transparency"] = i16(s)
        elif self.im_mode == "RGB":
            self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
        return s

    def chunk_gAMA(self, pos, length):

        # gamma setting
        s = ImageFile._safe_read(self.fp, length)
        self.im_info["gamma"] = i32(s) / 100000.0
        return s

    def chunk_pHYs(self, pos, length):

        # pixels per unit
        s = ImageFile._safe_read(self.fp, length)
        px, py = i32(s), i32(s[4:])
        unit = i8(s[8])
        if unit == 1:  # meter
            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
            self.im_info["dpi"] = dpi
        elif unit == 0:
            self.im_info["aspect"] = px, py
        return s

    def chunk_tEXt(self, pos, length):

        # text
        s = ImageFile._safe_read(self.fp, length)
        try:
            k, v = s.split(b"\0", 1)
        except ValueError:
            # fallback for broken tEXt tags
            k = s
            v = b""
        if k:
            if bytes is not str:
                k = k.decode('latin-1', 'strict')
                v = v.decode('latin-1', 'replace')

            self.im_info[k] = self.im_text[k] = v
            self.check_text_memory(len(v))

        return s

    def chunk_zTXt(self, pos, length):

        # compressed text
        s = ImageFile._safe_read(self.fp, length)
        try:
            k, v = s.split(b"\0", 1)
        except ValueError:
            k = s
            v = b""
        if v:
            comp_method = i8(v[0])
        else:
            comp_method = 0
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in zTXt chunk" %
                              comp_method)
        try:
            v = _safe_zlib_decompress(v[1:])
        except zlib.error:
            v = b""

        if k:
            if bytes is not str:
                k = k.decode('latin-1', 'strict')
                v = v.decode('latin-1', 'replace')

            self.im_info[k] = self.im_text[k] = v
            self.check_text_memory(len(v))

        return s

    def chunk_iTXt(self, pos, length):

        # international text
        r = s = ImageFile._safe_read(self.fp, length)
        try:
            k, r = r.split(b"\0", 1)
        except ValueError:
            return s
        if len(r) < 2:
            return s
        cf, cm, r = i8(r[0]), i8(r[1]), r[2:]
        try:
            lang, tk, v = r.split(b"\0", 2)
        except ValueError:
            return s
        if cf != 0:
            if cm == 0:
                try:
                    v = _safe_zlib_decompress(v)
                except zlib.error:
                    return s
            else:
                return s
        if bytes is not str:
            try:
                k = k.decode("latin-1", "strict")
                lang = lang.decode("utf-8", "strict")
                tk = tk.decode("utf-8", "strict")
                v = v.decode("utf-8", "strict")
            except UnicodeError:
                return s

        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)
        self.check_text_memory(len(v))

        return s


# --------------------------------------------------------------------
# PNG reader

def _accept(prefix):
    return prefix[:8] == _MAGIC


##
# Image plugin for PNG images.

class PngImageFile(ImageFile.ImageFile):

    format = "PNG"
    format_description = "Portable network graphics"

    def _open(self):

        if self.fp.read(8) != _MAGIC:
            raise SyntaxError("not a PNG file")

        #
        # Parse headers up to the first IDAT chunk

        self.png = PngStream(self.fp)

        while True:

            #
            # get next chunk

            cid, pos, length = self.png.read()

            try:
                s = self.png.call(cid, pos, length)
            except EOFError:
                break
            except AttributeError:
                logger.debug("%s %s %s (unknown)", cid, pos, length)
                s = ImageFile._safe_read(self.fp, length)

            self.png.crc(cid, s)

        #
        # Copy relevant attributes from the PngStream.  An alternative
        # would be to let the PngStream class modify these attributes
        # directly, but that introduces circular references which are
        # difficult to break if things go wrong in the decoder...
        # (believe me, I've tried ;-)

        self.mode = self.png.im_mode
        self.size = self.png.im_size
        self.info = self.png.im_info
        self.text = self.png.im_text  # experimental
        self.tile = self.png.im_tile

        if self.png.im_palette:
            rawmode, data = self.png.im_palette
            self.palette = ImagePalette.raw(rawmode, data)

        self.__idat = length  # used by load_read()

    def verify(self):
        "Verify PNG file"

        if self.fp is None:
            raise RuntimeError("verify must be called directly after open")

        # back up to beginning of IDAT block
        self.fp.seek(self.tile[0][2] - 8)

        self.png.verify()
        self.png.close()

        self.fp = None

    def load_prepare(self):
        "internal: prepare to read PNG file"

        if self.info.get("interlace"):
            self.decoderconfig = self.decoderconfig + (1,)

        ImageFile.ImageFile.load_prepare(self)

    def load_read(self, read_bytes):
        "internal: read more image data"

        while self.__idat == 0:
            # end of chunk, skip forward to next one

            self.fp.read(4)  # CRC

            cid, pos, length = self.png.read()

            if cid not in [b"IDAT", b"DDAT"]:
                self.png.push(cid, pos, length)
                return b""

            self.__idat = length  # empty chunks are allowed

        # read more data from this chunk
        if read_bytes <= 0:
            read_bytes = self.__idat
        else:
            read_bytes = min(read_bytes, self.__idat)

        self.__idat = self.__idat - read_bytes

        return self.fp.read(read_bytes)

    def load_end(self):
        "internal: finished reading image data"

        self.png.close()
        self.png = None


# --------------------------------------------------------------------
# PNG writer

o8 = _binary.o8
o16 = _binary.o16be
o32 = _binary.o32be

_OUTMODES = {
    # supported PIL modes, and corresponding rawmodes/bits/color combinations
    "1":    ("1",       b'\x01\x00'),
    "L;1":  ("L;1",     b'\x01\x00'),
    "L;2":  ("L;2",     b'\x02\x00'),
    "L;4":  ("L;4",     b'\x04\x00'),
    "L":    ("L",       b'\x08\x00'),
    "LA":   ("LA",      b'\x08\x04'),
    "I":    ("I;16B",   b'\x10\x00'),
    "P;1":  ("P;1",     b'\x01\x03'),
    "P;2":  ("P;2",     b'\x02\x03'),
    "P;4":  ("P;4",     b'\x04\x03'),
    "P":    ("P",       b'\x08\x03'),
    "RGB":  ("RGB",     b'\x08\x02'),
    "RGBA": ("RGBA",    b'\x08\x06'),
}


def putchunk(fp, cid, *data):
    "Write a PNG chunk (including CRC field)"

    data = b"".join(data)

    fp.write(o32(len(data)) + cid)
    fp.write(data)
    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
    fp.write(o16(hi) + o16(lo))


class _idat(object):
    # wrap output from the encoder in IDAT chunks

    def __init__(self, fp, chunk):
        self.fp = fp
        self.chunk = chunk

    def write(self, data):
        self.chunk(self.fp, b"IDAT", data)


def _save(im, fp, filename, chunk=putchunk, check=0):
    # save an image to disk (called by the save method)

    mode = im.mode

    if mode == "P":

        #
        # attempt to minimize storage requirements for palette images
        if "bits" in im.encoderinfo:
            # number of bits specified by user
            colors = 1 << im.encoderinfo["bits"]
        else:
            # check palette contents
            if im.palette:
                colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)
            else:
                colors = 256

        if colors <= 2:
            bits = 1
        elif colors <= 4:
            bits = 2
        elif colors <= 16:
            bits = 4
        else:
            bits = 8
        if bits != 8:
            mode = "%s;%d" % (mode, bits)

    # encoder options
    if "dictionary" in im.encoderinfo:
        dictionary = im.encoderinfo["dictionary"]
    else:
        dictionary = b""

    im.encoderconfig = ("optimize" in im.encoderinfo,
                        im.encoderinfo.get("compress_level", -1),
                        im.encoderinfo.get("compress_type", -1),
                        dictionary)

    # get the corresponding PNG mode
    try:
        rawmode, mode = _OUTMODES[mode]
    except KeyError:
        raise IOError("cannot write mode %s as PNG" % mode)

    if check:
        return check

    #
    # write minimal PNG file

    fp.write(_MAGIC)

    chunk(fp, b"IHDR",
          o32(im.size[0]), o32(im.size[1]),     # 0: size
          mode,                                 # 8: depth/type
          b'\0',                                # 10: compression
          b'\0',                                # 11: filter category
          b'\0')                                # 12: interlace flag

    if im.mode == "P":
        palette_byte_number = (2 ** bits) * 3
        palette_bytes = im.im.getpalette("RGB")[:palette_byte_number]
        while len(palette_bytes) < palette_byte_number:
            palette_bytes += b'\0'
        chunk(fp, b"PLTE", palette_bytes)

    transparency = im.encoderinfo.get('transparency',
                                      im.info.get('transparency', None))

    if transparency or transparency == 0:
        if im.mode == "P":
            # limit to actual palette size
            alpha_bytes = 2**bits
            if isinstance(transparency, bytes):
                chunk(fp, b"tRNS", transparency[:alpha_bytes])
            else:
                transparency = max(0, min(255, transparency))
                alpha = b'\xFF' * transparency + b'\0'
                chunk(fp, b"tRNS", alpha[:alpha_bytes])
        elif im.mode == "L":
            transparency = max(0, min(65535, transparency))
            chunk(fp, b"tRNS", o16(transparency))
        elif im.mode == "RGB":
            red, green, blue = transparency
            chunk(fp, b"tRNS", o16(red) + o16(green) + o16(blue))
        else:
            if "transparency" in im.encoderinfo:
                # don't bother with transparency if it's an RGBA
                # and it's in the info dict. It's probably just stale.
                raise IOError("cannot use transparency for this mode")
    else:
        if im.mode == "P" and im.im.getpalettemode() == "RGBA":
            alpha = im.im.getpalette("RGBA", "A")
            alpha_bytes = 2**bits
            chunk(fp, b"tRNS", alpha[:alpha_bytes])

    dpi = im.encoderinfo.get("dpi")
    if dpi:
        chunk(fp, b"pHYs",
              o32(int(dpi[0] / 0.0254 + 0.5)),
              o32(int(dpi[1] / 0.0254 + 0.5)),
              b'\x01')

    info = im.encoderinfo.get("pnginfo")
    if info:
        for cid, data in info.chunks:
            chunk(fp, cid, data)

    # ICC profile writing support -- 2008-06-06 Florian Hoech
    if im.info.get("icc_profile"):
        # ICC profile
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator        1 byte (null character)
        # Compression method    1 byte (0)
        # Compressed profile    n bytes (zlib with deflate compression)
        name = b"ICC Profile"
        data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
        chunk(fp, b"iCCP", data)

    ImageFile._save(im, _idat(fp, chunk),
                    [("zip", (0, 0)+im.size, 0, rawmode)])

    chunk(fp, b"IEND", b"")

    if hasattr(fp, "flush"):
        fp.flush()


# --------------------------------------------------------------------
# PNG chunk converter

def getchunks(im, **params):
    """Return a list of PNG chunks representing this image."""

    class collector(object):
        data = []

        def write(self, data):
            pass

        def append(self, chunk):
            self.data.append(chunk)

    def append(fp, cid, *data):
        data = b"".join(data)
        hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
        crc = o16(hi) + o16(lo)
        fp.append((cid, data, crc))

    fp = collector()

    try:
        im.encoderinfo = params
        _save(im, fp, None, append)
    finally:
        del im.encoderinfo

    return fp.data


# --------------------------------------------------------------------
# Registry

Image.register_open(PngImageFile.format, PngImageFile, _accept)
Image.register_save(PngImageFile.format, _save)

Image.register_extension(PngImageFile.format, ".png")

Image.register_mime(PngImageFile.format, "image/png")

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user