{
    "file_diffs": [
        {
            "old_file_content": "from helper import unittest, PillowTestCase, hopper\nfrom helper import djpeg_available, cjpeg_available\n\nfrom io import BytesIO\nimport os\nimport sys\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import JpegImagePlugin\n\ncodecs = dir(Image.core)\n\nTEST_FILE = \"Tests/images/hopper.jpg\"\n\n\nclass TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n\n@unittest.skipUnless(sys.platform.startswith('win32'), \"Windows only\")\nclass TestFileCloseW32(PillowTestCase):\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def test_fd_leak(self):\n        tmpfile = self.tempfile(\"temp.jpg\")\n\n        with Image.open(\"Tests/images/hopper.jpg\") as im:\n            im.save(tmpfile)\n\n        im = Image.open(tmpfile)\n        fp = im.fp\n        self.assertFalse(fp.closed)\n        self.assertRaises(WindowsError, os.remove, tmpfile)\n        im.load()\n        self.assertTrue(fp.closed)\n        # this should not fail, as load should have closed the file.\n        os.remove(tmpfile)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "new_file_content": "from helper import unittest, PillowTestCase, hopper\nfrom helper import djpeg_available, cjpeg_available\n\nfrom io import BytesIO\nimport os\nimport sys\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import JpegImagePlugin\n\ncodecs = dir(Image.core)\n\nTEST_FILE = \"Tests/images/hopper.jpg\"\n\n\nclass TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n\n@unittest.skipUnless(sys.platform.startswith('win32'), \"Windows only\")\nclass TestFileCloseW32(PillowTestCase):\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def test_fd_leak(self):\n        tmpfile = self.tempfile(\"temp.jpg\")\n\n        with Image.open(\"Tests/images/hopper.jpg\") as im:\n            im.save(tmpfile)\n\n        im = Image.open(tmpfile)\n        fp = im.fp\n        self.assertFalse(fp.closed)\n        self.assertRaises(WindowsError, os.remove, tmpfile)\n        im.load()\n        self.assertTrue(fp.closed)\n        # this should not fail, as load should have closed the file.\n        os.remove(tmpfile)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "header": {
                "file": {
                    "path": "Tests/test_file_jpeg.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "9804c2676",
                "new_commit_hash": "2d9a9a091",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Tests/test_file_jpeg.py"
            },
            "plus_file": {
                "path": "b/Tests/test_file_jpeg.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 48,
                            "length": 6
                        },
                        "new_range": {
                            "start": 48,
                            "length": 7
                        },
                        "section": "class TestFileJpeg(PillowTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual(im.mode, \"RGB\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(im.size, (128, 128))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(im.format, \"JPEG\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_app(self):",
                                "type": "context"
                            },
                            {
                                "content": "        # Test APP/COM reader (@PIL135)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_file_jpeg.py",
                            "type": "class",
                            "name": "TestFileJpeg",
                            "content": "class TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 17,
                            "end_lineno": 585,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_jpeg.py",
                            "type": "method",
                            "name": "TestFileJpeg.test_sanity",
                            "content": "class TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 41,
                            "end_lineno": 51,
                            "parent": {
                                "file_name": "Tests/test_file_jpeg.py",
                                "type": "class",
                                "name": "TestFileJpeg",
                                "content": "class TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 17,
                                "end_lineno": 585,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from helper import hopper, unittest, PillowTestCase\n\nfrom PIL import Image, PixarImagePlugin\n\nTEST_FILE = \"Tests/images/hopper.pxr\"\n\n\nclass TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "new_file_content": "from helper import hopper, unittest, PillowTestCase\n\nfrom PIL import Image, PixarImagePlugin\n\nTEST_FILE = \"Tests/images/hopper.pxr\"\n\n\nclass TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n        self.assertIsNone(im.get_format_mimetype())\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "header": {
                "file": {
                    "path": "Tests/test_file_pixar.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "ae8c7d5f5",
                "new_commit_hash": "3b00c710e",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Tests/test_file_pixar.py"
            },
            "plus_file": {
                "path": "b/Tests/test_file_pixar.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 13,
                            "length": 6
                        },
                        "new_range": {
                            "start": 13,
                            "length": 7
                        },
                        "section": "class TestFilePixar(PillowTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual(im.mode, \"RGB\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(im.size, (128, 128))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(im.format, \"PIXAR\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertIsNone(im.get_format_mimetype())",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        im2 = hopper()",
                                "type": "context"
                            },
                            {
                                "content": "        self.assert_image_similar(im, im2, 4.8)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_file_pixar.py",
                            "type": "class",
                            "name": "TestFilePixar",
                            "content": "class TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n        self.assertIsNone(im.get_format_mimetype())\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 8,
                            "end_lineno": 26,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_pixar.py",
                            "type": "method",
                            "name": "TestFilePixar.test_sanity",
                            "content": "class TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n        self.assertIsNone(im.get_format_mimetype())\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 10,
                            "end_lineno": 19,
                            "parent": {
                                "file_name": "Tests/test_file_pixar.py",
                                "type": "class",
                                "name": "TestFilePixar",
                                "content": "class TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n        self.assertIsNone(im.get_format_mimetype())\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 8,
                                "end_lineno": 26,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from helper import unittest, PillowTestCase, hopper, fromstring, tostring\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import EpsImagePlugin\n\n\ncodecs = dir(Image.core)\n\n# save original block sizes\nMAXBLOCK = ImageFile.MAXBLOCK\nSAFEBLOCK = ImageFile.SAFEBLOCK\n\n\nclass TestImageFile(PillowTestCase):\n\n    def test_parser(self):\n\n        def roundtrip(format):\n\n            im = hopper(\"L\").resize((1000, 1000))\n            if format in (\"MSP\", \"XBM\"):\n                im = im.convert(\"1\")\n\n            test_file = BytesIO()\n\n            im.copy().save(test_file, format)\n\n            data = test_file.getvalue()\n\n            parser = ImageFile.Parser()\n            parser.feed(data)\n            imOut = parser.close()\n\n            return im, imOut\n\n        self.assert_image_equal(*roundtrip(\"BMP\"))\n        im1, im2 = roundtrip(\"GIF\")\n        self.assert_image_similar(im1.convert('P'), im2, 1)\n        self.assert_image_equal(*roundtrip(\"IM\"))\n        self.assert_image_equal(*roundtrip(\"MSP\"))\n        if \"zip_encoder\" in codecs:\n            try:\n                # force multiple blocks in PNG driver\n                ImageFile.MAXBLOCK = 8192\n                self.assert_image_equal(*roundtrip(\"PNG\"))\n            finally:\n                ImageFile.MAXBLOCK = MAXBLOCK\n        self.assert_image_equal(*roundtrip(\"PPM\"))\n        self.assert_image_equal(*roundtrip(\"TIFF\"))\n        self.assert_image_equal(*roundtrip(\"XBM\"))\n        self.assert_image_equal(*roundtrip(\"TGA\"))\n        self.assert_image_equal(*roundtrip(\"PCX\"))\n\n        if EpsImagePlugin.has_ghostscript():\n            im1, im2 = roundtrip(\"EPS\")\n            # This test fails on Ubuntu 12.04, PPC (Bigendian) It\n            # appears to be a ghostscript 9.05 bug, since the\n            # ghostscript rendering is wonky and the file is identical\n            # to that written on ubuntu 12.04 x64\n            # md5sum: ba974835ff2d6f3f2fd0053a23521d4a\n\n            # EPS comes back in RGB:\n            self.assert_image_similar(im1, im2.convert('L'), 20)\n\n        if \"jpeg_encoder\" in codecs:\n            im1, im2 = roundtrip(\"JPEG\")  # lossy compression\n            self.assert_image(im1, im2.mode, im2.size)\n\n        self.assertRaises(IOError, roundtrip, \"PDF\")\n\n    def test_ico(self):\n        with open('Tests/images/python.ico', 'rb') as f:\n            data = f.read()\n        with ImageFile.Parser() as p:\n            p.feed(data)\n            self.assertEqual((48, 48), p.image.size)\n\n    def test_safeblock(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im1 = hopper()\n\n        try:\n            ImageFile.SAFEBLOCK = 1\n            im2 = fromstring(tostring(im1, \"PNG\"))\n        finally:\n            ImageFile.SAFEBLOCK = SAFEBLOCK\n\n        self.assert_image_equal(im1, im2)\n\n    def test_raise_ioerror(self):\n        self.assertRaises(IOError, ImageFile.raise_ioerror, 1)\n\n    def test_raise_typeerror(self):\n        with self.assertRaises(TypeError):\n            parser = ImageFile.Parser()\n            parser.feed(1)\n\n    def test_truncated_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_truncated_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_broken_datastream_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_broken_datastream_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\nclass MockPyDecoder(ImageFile.PyDecoder):\n    def decode(self, buffer):\n        # eof\n        return (-1, 0)\n\n\nxoff, yoff, xsize, ysize = 10, 20, 100, 100\n\n\nclass MockImageFile(ImageFile.ImageFile):\n    def _open(self):\n        self.rawmode = 'RGBA'\n        self.mode = 'RGBA'\n        self.size = (200, 200)\n        self.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize), 32, None)]\n\n\nclass TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "new_file_content": "from helper import unittest, PillowTestCase, hopper, fromstring, tostring\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import EpsImagePlugin\n\n\ncodecs = dir(Image.core)\n\n# save original block sizes\nMAXBLOCK = ImageFile.MAXBLOCK\nSAFEBLOCK = ImageFile.SAFEBLOCK\n\n\nclass TestImageFile(PillowTestCase):\n\n    def test_parser(self):\n\n        def roundtrip(format):\n\n            im = hopper(\"L\").resize((1000, 1000))\n            if format in (\"MSP\", \"XBM\"):\n                im = im.convert(\"1\")\n\n            test_file = BytesIO()\n\n            im.copy().save(test_file, format)\n\n            data = test_file.getvalue()\n\n            parser = ImageFile.Parser()\n            parser.feed(data)\n            imOut = parser.close()\n\n            return im, imOut\n\n        self.assert_image_equal(*roundtrip(\"BMP\"))\n        im1, im2 = roundtrip(\"GIF\")\n        self.assert_image_similar(im1.convert('P'), im2, 1)\n        self.assert_image_equal(*roundtrip(\"IM\"))\n        self.assert_image_equal(*roundtrip(\"MSP\"))\n        if \"zip_encoder\" in codecs:\n            try:\n                # force multiple blocks in PNG driver\n                ImageFile.MAXBLOCK = 8192\n                self.assert_image_equal(*roundtrip(\"PNG\"))\n            finally:\n                ImageFile.MAXBLOCK = MAXBLOCK\n        self.assert_image_equal(*roundtrip(\"PPM\"))\n        self.assert_image_equal(*roundtrip(\"TIFF\"))\n        self.assert_image_equal(*roundtrip(\"XBM\"))\n        self.assert_image_equal(*roundtrip(\"TGA\"))\n        self.assert_image_equal(*roundtrip(\"PCX\"))\n\n        if EpsImagePlugin.has_ghostscript():\n            im1, im2 = roundtrip(\"EPS\")\n            # This test fails on Ubuntu 12.04, PPC (Bigendian) It\n            # appears to be a ghostscript 9.05 bug, since the\n            # ghostscript rendering is wonky and the file is identical\n            # to that written on ubuntu 12.04 x64\n            # md5sum: ba974835ff2d6f3f2fd0053a23521d4a\n\n            # EPS comes back in RGB:\n            self.assert_image_similar(im1, im2.convert('L'), 20)\n\n        if \"jpeg_encoder\" in codecs:\n            im1, im2 = roundtrip(\"JPEG\")  # lossy compression\n            self.assert_image(im1, im2.mode, im2.size)\n\n        self.assertRaises(IOError, roundtrip, \"PDF\")\n\n    def test_ico(self):\n        with open('Tests/images/python.ico', 'rb') as f:\n            data = f.read()\n        with ImageFile.Parser() as p:\n            p.feed(data)\n            self.assertEqual((48, 48), p.image.size)\n\n    def test_safeblock(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im1 = hopper()\n\n        try:\n            ImageFile.SAFEBLOCK = 1\n            im2 = fromstring(tostring(im1, \"PNG\"))\n        finally:\n            ImageFile.SAFEBLOCK = SAFEBLOCK\n\n        self.assert_image_equal(im1, im2)\n\n    def test_raise_ioerror(self):\n        self.assertRaises(IOError, ImageFile.raise_ioerror, 1)\n\n    def test_raise_typeerror(self):\n        with self.assertRaises(TypeError):\n            parser = ImageFile.Parser()\n            parser.feed(1)\n\n    def test_truncated_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_truncated_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_broken_datastream_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_broken_datastream_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\nclass MockPyDecoder(ImageFile.PyDecoder):\n    def decode(self, buffer):\n        # eof\n        return (-1, 0)\n\n\nxoff, yoff, xsize, ysize = 10, 20, 100, 100\n\n\nclass MockImageFile(ImageFile.ImageFile):\n    def _open(self):\n        self.rawmode = 'RGBA'\n        self.mode = 'RGBA'\n        self.size = (200, 200)\n        self.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize), 32, None)]\n\n\nclass TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_no_format(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        self.assertIsNone(im.format)\n        self.assertIsNone(im.get_format_mimetype())\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
            "header": {
                "file": {
                    "path": "Tests/test_imagefile.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "32e44a0e1",
                "new_commit_hash": "4b750af0d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Tests/test_imagefile.py"
            },
            "plus_file": {
                "path": "b/Tests/test_imagefile.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 223,
                            "length": 6
                        },
                        "new_range": {
                            "start": 223,
                            "length": 13
                        },
                        "section": "class TestPyDecoder(PillowTestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertRaises(ValueError, im.load)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_no_format(self):",
                                "type": "added"
                            },
                            {
                                "content": "        buf = BytesIO(b'\\x00'*255)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        im = MockImageFile(buf)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertIsNone(im.format)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertIsNone(im.get_format_mimetype())",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "if __name__ == '__main__':",
                                "type": "context"
                            },
                            {
                                "content": "    unittest.main()",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_imagefile.py",
                            "type": "class",
                            "name": "TestPyDecoder",
                            "content": "class TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_no_format(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        self.assertIsNone(im.format)\n        self.assertIsNone(im.get_format_mimetype())",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 161,
                            "end_lineno": 231,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "Tests/test_imagefile.py",
                            "type": "method",
                            "name": "TestPyDecoder.test_no_format",
                            "content": "class TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_no_format(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        self.assertIsNone(im.format)\n        self.assertIsNone(im.get_format_mimetype())",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 226,
                            "end_lineno": 231,
                            "parent": {
                                "file_name": "Tests/test_imagefile.py",
                                "type": "class",
                                "name": "TestPyDecoder",
                                "content": "class TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_no_format(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        self.assertIsNone(im.format)\n        self.assertIsNone(im.get_format_mimetype())",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 161,
                                "end_lineno": 231,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# base class for image file handlers\n#\n# history:\n# 1995-09-09 fl   Created\n# 1996-03-11 fl   Fixed load mechanism.\n# 1996-04-15 fl   Added pcx/xbm decoders.\n# 1996-04-30 fl   Added encoders.\n# 1996-12-14 fl   Added load helpers\n# 1997-01-11 fl   Use encode_to_file where possible\n# 1997-08-27 fl   Flush output in _save\n# 1998-03-05 fl   Use memory mapping for some modes\n# 1999-02-04 fl   Use memory mapping also for \"I;16\" and \"I;16B\"\n# 1999-05-31 fl   Added image parser\n# 2000-10-12 fl   Set readonly flag on memory-mapped images\n# 2002-03-20 fl   Use better messages for common decoder errors\n# 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available\n# 2003-10-30 fl   Added StubImageFile class\n# 2004-02-25 fl   Made incremental parser more robust\n#\n# Copyright (c) 1997-2004 by Secret Labs AB\n# Copyright (c) 1995-2004 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom . import Image\nfrom ._util import isPath\nimport io\nimport os\nimport sys\nimport struct\n\nMAXBLOCK = 65536\n\nSAFEBLOCK = 1024*1024\n\nLOAD_TRUNCATED_IMAGES = False\n\nERRORS = {\n    -1: \"image buffer overrun error\",\n    -2: \"decoding error\",\n    -3: \"unknown error\",\n    -8: \"bad configuration\",\n    -9: \"out of memory error\"\n}\n\n\ndef raise_ioerror(error):\n    try:\n        message = Image.core.getcodecstatus(error)\n    except AttributeError:\n        message = ERRORS.get(error)\n    if not message:\n        message = \"decoder error %d\" % error\n    raise IOError(message + \" when reading image file\")\n\n\n#\n# --------------------------------------------------------------------\n# Helpers\n\ndef _tilesort(t):\n    # sort on offset\n    return t[2]\n\n\n#\n# --------------------------------------------------------------------\n# ImageFile base class\n\nclass ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame\n\n\nclass StubImageFile(ImageFile):\n    \"\"\"\n    Base class for stub image loaders.\n\n    A stub loader is an image loader that can identify files of a\n    certain format, but relies on external code to load the file.\n    \"\"\"\n\n    def _open(self):\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _open\"\n            )\n\n    def load(self):\n        loader = self._load()\n        if loader is None:\n            raise IOError(\"cannot find loader for this %s file\" % self.format)\n        image = loader.load(self)\n        assert image is not None\n        # become the other object (!)\n        self.__class__ = image.__class__\n        self.__dict__ = image.__dict__\n\n    def _load(self):\n        \"(Hook) Find actual image loader.\"\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _load\"\n            )\n\n\nclass Parser(object):\n    \"\"\"\n    Incremental image parser.  This class implements the standard\n    feed/close consumer interface.\n    \"\"\"\n    incremental = None\n    image = None\n    data = None\n    decoder = None\n    offset = 0\n    finished = 0\n\n    def reset(self):\n        \"\"\"\n        (Consumer) Reset the parser.  Note that you can only call this\n        method immediately after you've created a parser; parser\n        instances cannot be reused.\n        \"\"\"\n        assert self.data is None, \"cannot reuse parsers\"\n\n    def feed(self, data):\n        \"\"\"\n        (Consumer) Feed data to the parser.\n\n        :param data: A string buffer.\n        :exception IOError: If the parser failed to parse the image file.\n        \"\"\"\n        # collect data\n\n        if self.finished:\n            return\n\n        if self.data is None:\n            self.data = data\n        else:\n            self.data = self.data + data\n\n        # parse what we have\n        if self.decoder:\n\n            if self.offset > 0:\n                # skip header\n                skip = min(len(self.data), self.offset)\n                self.data = self.data[skip:]\n                self.offset = self.offset - skip\n                if self.offset > 0 or not self.data:\n                    return\n\n            n, e = self.decoder.decode(self.data)\n\n            if n < 0:\n                # end of stream\n                self.data = None\n                self.finished = 1\n                if e < 0:\n                    # decoding error\n                    self.image = None\n                    raise_ioerror(e)\n                else:\n                    # end of image\n                    return\n            self.data = self.data[n:]\n\n        elif self.image:\n\n            # if we end up here with no decoder, this file cannot\n            # be incrementally parsed.  wait until we've gotten all\n            # available data\n            pass\n\n        else:\n\n            # attempt to open this file\n            try:\n                with io.BytesIO(self.data) as fp:\n                    im = Image.open(fp)\n            except IOError:\n                # traceback.print_exc()\n                pass  # not enough data\n            else:\n                flag = hasattr(im, \"load_seek\") or hasattr(im, \"load_read\")\n                if flag or len(im.tile) != 1:\n                    # custom load code, or multiple tiles\n                    self.decode = None\n                else:\n                    # initialize decoder\n                    im.load_prepare()\n                    d, e, o, a = im.tile[0]\n                    im.tile = []\n                    self.decoder = Image._getdecoder(\n                        im.mode, d, a, im.decoderconfig\n                        )\n                    self.decoder.setimage(im.im, e)\n\n                    # calculate decoder offset\n                    self.offset = o\n                    if self.offset <= len(self.data):\n                        self.data = self.data[self.offset:]\n                        self.offset = 0\n\n                self.image = im\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n\n    def close(self):\n        \"\"\"\n        (Consumer) Close the stream.\n\n        :returns: An image object.\n        :exception IOError: If the parser failed to parse the image file either\n                            because it cannot be identified or cannot be\n                            decoded.\n        \"\"\"\n        # finish decoding\n        if self.decoder:\n            # get rid of what's left in the buffers\n            self.feed(b\"\")\n            self.data = self.decoder = None\n            if not self.finished:\n                raise IOError(\"image was incomplete\")\n        if not self.image:\n            raise IOError(\"cannot parse this image\")\n        if self.data:\n            # incremental parsing not possible; reopen the file\n            # not that we have all data\n            with io.BytesIO(self.data) as fp:\n                try:\n                    self.image = Image.open(fp)\n                finally:\n                    self.image.load()\n        return self.image\n\n\n# --------------------------------------------------------------------\n\ndef _save(im, fp, tile, bufsize=0):\n    \"\"\"Helper to save image based on tile list\n\n    :param im: Image object.\n    :param fp: File object.\n    :param tile: Tile list.\n    :param bufsize: Optional buffer size\n    \"\"\"\n\n    im.load()\n    if not hasattr(im, \"encoderconfig\"):\n        im.encoderconfig = ()\n    tile.sort(key=_tilesort)\n    # FIXME: make MAXBLOCK a configuration parameter\n    # It would be great if we could have the encoder specify what it needs\n    # But, it would need at least the image size in most cases. RawEncode is\n    # a tricky case.\n    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c\n    if fp == sys.stdout:\n        fp.flush()\n        return\n    try:\n        fh = fp.fileno()\n        fp.flush()\n    except (AttributeError, io.UnsupportedOperation):\n        # compress to Python file-compatible object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                while True:\n                    l, s, d = e.encode(bufsize)\n                    fp.write(d)\n                    if s:\n                        break\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    else:\n        # slight speedup: compress to real file object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                s = e.encode_to_file(fh, bufsize)\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\ndef _safe_read(fp, size):\n    \"\"\"\n    Reads large blocks in a safe way.  Unlike fp.read(n), this function\n    doesn't trust the user.  If the requested size is larger than\n    SAFEBLOCK, the file is read block by block.\n\n    :param fp: File handle.  Must implement a <b>read</b> method.\n    :param size: Number of bytes to read.\n    :returns: A string containing up to <i>size</i> bytes of data.\n    \"\"\"\n    if size <= 0:\n        return b\"\"\n    if size <= SAFEBLOCK:\n        return fp.read(size)\n    data = []\n    while size > 0:\n        block = fp.read(min(size, SAFEBLOCK))\n        if not block:\n            break\n        data.append(block)\n        size -= len(block)\n    return b\"\".join(data)\n\n\nclass PyCodecState(object):\n    def __init__(self):\n        self.xsize = 0\n        self.ysize = 0\n        self.xoff = 0\n        self.yoff = 0\n\n    def extents(self):\n        return (self.xoff, self.yoff,\n                self.xoff+self.xsize, self.yoff+self.ysize)\n\n\nclass PyDecoder(object):\n    \"\"\"\n    Python implementation of a format decoder. Override this class and\n    add the decoding logic in the `decode` method.\n\n    See :ref:`Writing Your Own File Decoder in Python<file-decoders-py>`\n    \"\"\"\n\n    _pulls_fd = False\n\n    def __init__(self, mode, *args):\n        self.im = None\n        self.state = PyCodecState()\n        self.fd = None\n        self.mode = mode\n        self.init(args)\n\n    def init(self, args):\n        \"\"\"\n        Override to perform decoder specific initialization\n\n        :param args: Array of args items from the tile entry\n        :returns: None\n        \"\"\"\n        self.args = args\n\n    @property\n    def pulls_fd(self):\n        return self._pulls_fd\n\n    def decode(self, buffer):\n        \"\"\"\n        Override to perform the decoding process.\n\n        :param buffer: A bytes object with the data to be decoded.  If `handles_eof`\n             is set, then `buffer` will be empty and `self.fd` will be set.\n        :returns: A tuple of (bytes consumed, errcode). If finished with decoding\n             return <0 for the bytes consumed. Err codes are from `ERRORS`\n        \"\"\"\n        raise NotImplementedError()\n\n    def cleanup(self):\n        \"\"\"\n        Override to perform decoder specific cleanup\n\n        :returns: None\n        \"\"\"\n        pass\n\n    def setfd(self, fd):\n        \"\"\"\n        Called from ImageFile to set the python file-like object\n\n        :param fd: A python file-like object\n        :returns: None\n        \"\"\"\n        self.fd = fd\n\n    def setimage(self, im, extents=None):\n        \"\"\"\n        Called from ImageFile to set the core output image for the decoder\n\n        :param im: A core image object\n        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle\n            for this tile\n        :returns: None\n        \"\"\"\n\n        # following c code\n        self.im = im\n\n        if extents:\n            (x0, y0, x1, y1) = extents\n        else:\n            (x0, y0, x1, y1) = (0, 0, 0, 0)\n\n        if x0 == 0 and x1 == 0:\n            self.state.xsize, self.state.ysize = self.im.size\n        else:\n            self.state.xoff = x0\n            self.state.yoff = y0\n            self.state.xsize = x1 - x0\n            self.state.ysize = y1 - y0\n\n        if self.state.xsize <= 0 or self.state.ysize <= 0:\n            raise ValueError(\"Size cannot be negative\")\n\n        if (self.state.xsize + self.state.xoff > self.im.size[0] or\n           self.state.ysize + self.state.yoff > self.im.size[1]):\n            raise ValueError(\"Tile cannot extend outside image\")\n\n    def set_as_raw(self, data, rawmode=None):\n        \"\"\"\n        Convenience method to set the internal image from a stream of raw data\n\n        :param data: Bytes to be set\n        :param rawmode: The rawmode to be used for the decoder. If not specified,\n             it will default to the mode of the image\n        :returns: None\n        \"\"\"\n\n        if not rawmode:\n            rawmode = self.mode\n        d = Image._getdecoder(self.mode, 'raw', (rawmode))\n        d.setimage(self.im, self.state.extents())\n        s = d.decode(data)\n\n        if s[0] >= 0:\n            raise ValueError(\"not enough image data\")\n        if s[1] != 0:\n            raise ValueError(\"cannot decode image data\")\n",
            "new_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# base class for image file handlers\n#\n# history:\n# 1995-09-09 fl   Created\n# 1996-03-11 fl   Fixed load mechanism.\n# 1996-04-15 fl   Added pcx/xbm decoders.\n# 1996-04-30 fl   Added encoders.\n# 1996-12-14 fl   Added load helpers\n# 1997-01-11 fl   Use encode_to_file where possible\n# 1997-08-27 fl   Flush output in _save\n# 1998-03-05 fl   Use memory mapping for some modes\n# 1999-02-04 fl   Use memory mapping also for \"I;16\" and \"I;16B\"\n# 1999-05-31 fl   Added image parser\n# 2000-10-12 fl   Set readonly flag on memory-mapped images\n# 2002-03-20 fl   Use better messages for common decoder errors\n# 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available\n# 2003-10-30 fl   Added StubImageFile class\n# 2004-02-25 fl   Made incremental parser more robust\n#\n# Copyright (c) 1997-2004 by Secret Labs AB\n# Copyright (c) 1995-2004 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom . import Image\nfrom ._util import isPath\nimport io\nimport os\nimport sys\nimport struct\n\nMAXBLOCK = 65536\n\nSAFEBLOCK = 1024*1024\n\nLOAD_TRUNCATED_IMAGES = False\n\nERRORS = {\n    -1: \"image buffer overrun error\",\n    -2: \"decoding error\",\n    -3: \"unknown error\",\n    -8: \"bad configuration\",\n    -9: \"out of memory error\"\n}\n\n\ndef raise_ioerror(error):\n    try:\n        message = Image.core.getcodecstatus(error)\n    except AttributeError:\n        message = ERRORS.get(error)\n    if not message:\n        message = \"decoder error %d\" % error\n    raise IOError(message + \" when reading image file\")\n\n\n#\n# --------------------------------------------------------------------\n# Helpers\n\ndef _tilesort(t):\n    # sort on offset\n    return t[2]\n\n\n#\n# --------------------------------------------------------------------\n# ImageFile base class\n\nclass ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def get_format_mimetype(self):\n        if self.format is None:\n            return\n        return Image.MIME.get(self.format.upper())\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame\n\n\nclass StubImageFile(ImageFile):\n    \"\"\"\n    Base class for stub image loaders.\n\n    A stub loader is an image loader that can identify files of a\n    certain format, but relies on external code to load the file.\n    \"\"\"\n\n    def _open(self):\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _open\"\n            )\n\n    def load(self):\n        loader = self._load()\n        if loader is None:\n            raise IOError(\"cannot find loader for this %s file\" % self.format)\n        image = loader.load(self)\n        assert image is not None\n        # become the other object (!)\n        self.__class__ = image.__class__\n        self.__dict__ = image.__dict__\n\n    def _load(self):\n        \"(Hook) Find actual image loader.\"\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _load\"\n            )\n\n\nclass Parser(object):\n    \"\"\"\n    Incremental image parser.  This class implements the standard\n    feed/close consumer interface.\n    \"\"\"\n    incremental = None\n    image = None\n    data = None\n    decoder = None\n    offset = 0\n    finished = 0\n\n    def reset(self):\n        \"\"\"\n        (Consumer) Reset the parser.  Note that you can only call this\n        method immediately after you've created a parser; parser\n        instances cannot be reused.\n        \"\"\"\n        assert self.data is None, \"cannot reuse parsers\"\n\n    def feed(self, data):\n        \"\"\"\n        (Consumer) Feed data to the parser.\n\n        :param data: A string buffer.\n        :exception IOError: If the parser failed to parse the image file.\n        \"\"\"\n        # collect data\n\n        if self.finished:\n            return\n\n        if self.data is None:\n            self.data = data\n        else:\n            self.data = self.data + data\n\n        # parse what we have\n        if self.decoder:\n\n            if self.offset > 0:\n                # skip header\n                skip = min(len(self.data), self.offset)\n                self.data = self.data[skip:]\n                self.offset = self.offset - skip\n                if self.offset > 0 or not self.data:\n                    return\n\n            n, e = self.decoder.decode(self.data)\n\n            if n < 0:\n                # end of stream\n                self.data = None\n                self.finished = 1\n                if e < 0:\n                    # decoding error\n                    self.image = None\n                    raise_ioerror(e)\n                else:\n                    # end of image\n                    return\n            self.data = self.data[n:]\n\n        elif self.image:\n\n            # if we end up here with no decoder, this file cannot\n            # be incrementally parsed.  wait until we've gotten all\n            # available data\n            pass\n\n        else:\n\n            # attempt to open this file\n            try:\n                with io.BytesIO(self.data) as fp:\n                    im = Image.open(fp)\n            except IOError:\n                # traceback.print_exc()\n                pass  # not enough data\n            else:\n                flag = hasattr(im, \"load_seek\") or hasattr(im, \"load_read\")\n                if flag or len(im.tile) != 1:\n                    # custom load code, or multiple tiles\n                    self.decode = None\n                else:\n                    # initialize decoder\n                    im.load_prepare()\n                    d, e, o, a = im.tile[0]\n                    im.tile = []\n                    self.decoder = Image._getdecoder(\n                        im.mode, d, a, im.decoderconfig\n                        )\n                    self.decoder.setimage(im.im, e)\n\n                    # calculate decoder offset\n                    self.offset = o\n                    if self.offset <= len(self.data):\n                        self.data = self.data[self.offset:]\n                        self.offset = 0\n\n                self.image = im\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n\n    def close(self):\n        \"\"\"\n        (Consumer) Close the stream.\n\n        :returns: An image object.\n        :exception IOError: If the parser failed to parse the image file either\n                            because it cannot be identified or cannot be\n                            decoded.\n        \"\"\"\n        # finish decoding\n        if self.decoder:\n            # get rid of what's left in the buffers\n            self.feed(b\"\")\n            self.data = self.decoder = None\n            if not self.finished:\n                raise IOError(\"image was incomplete\")\n        if not self.image:\n            raise IOError(\"cannot parse this image\")\n        if self.data:\n            # incremental parsing not possible; reopen the file\n            # not that we have all data\n            with io.BytesIO(self.data) as fp:\n                try:\n                    self.image = Image.open(fp)\n                finally:\n                    self.image.load()\n        return self.image\n\n\n# --------------------------------------------------------------------\n\ndef _save(im, fp, tile, bufsize=0):\n    \"\"\"Helper to save image based on tile list\n\n    :param im: Image object.\n    :param fp: File object.\n    :param tile: Tile list.\n    :param bufsize: Optional buffer size\n    \"\"\"\n\n    im.load()\n    if not hasattr(im, \"encoderconfig\"):\n        im.encoderconfig = ()\n    tile.sort(key=_tilesort)\n    # FIXME: make MAXBLOCK a configuration parameter\n    # It would be great if we could have the encoder specify what it needs\n    # But, it would need at least the image size in most cases. RawEncode is\n    # a tricky case.\n    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c\n    if fp == sys.stdout:\n        fp.flush()\n        return\n    try:\n        fh = fp.fileno()\n        fp.flush()\n    except (AttributeError, io.UnsupportedOperation):\n        # compress to Python file-compatible object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                while True:\n                    l, s, d = e.encode(bufsize)\n                    fp.write(d)\n                    if s:\n                        break\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    else:\n        # slight speedup: compress to real file object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                s = e.encode_to_file(fh, bufsize)\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\ndef _safe_read(fp, size):\n    \"\"\"\n    Reads large blocks in a safe way.  Unlike fp.read(n), this function\n    doesn't trust the user.  If the requested size is larger than\n    SAFEBLOCK, the file is read block by block.\n\n    :param fp: File handle.  Must implement a <b>read</b> method.\n    :param size: Number of bytes to read.\n    :returns: A string containing up to <i>size</i> bytes of data.\n    \"\"\"\n    if size <= 0:\n        return b\"\"\n    if size <= SAFEBLOCK:\n        return fp.read(size)\n    data = []\n    while size > 0:\n        block = fp.read(min(size, SAFEBLOCK))\n        if not block:\n            break\n        data.append(block)\n        size -= len(block)\n    return b\"\".join(data)\n\n\nclass PyCodecState(object):\n    def __init__(self):\n        self.xsize = 0\n        self.ysize = 0\n        self.xoff = 0\n        self.yoff = 0\n\n    def extents(self):\n        return (self.xoff, self.yoff,\n                self.xoff+self.xsize, self.yoff+self.ysize)\n\n\nclass PyDecoder(object):\n    \"\"\"\n    Python implementation of a format decoder. Override this class and\n    add the decoding logic in the `decode` method.\n\n    See :ref:`Writing Your Own File Decoder in Python<file-decoders-py>`\n    \"\"\"\n\n    _pulls_fd = False\n\n    def __init__(self, mode, *args):\n        self.im = None\n        self.state = PyCodecState()\n        self.fd = None\n        self.mode = mode\n        self.init(args)\n\n    def init(self, args):\n        \"\"\"\n        Override to perform decoder specific initialization\n\n        :param args: Array of args items from the tile entry\n        :returns: None\n        \"\"\"\n        self.args = args\n\n    @property\n    def pulls_fd(self):\n        return self._pulls_fd\n\n    def decode(self, buffer):\n        \"\"\"\n        Override to perform the decoding process.\n\n        :param buffer: A bytes object with the data to be decoded.  If `handles_eof`\n             is set, then `buffer` will be empty and `self.fd` will be set.\n        :returns: A tuple of (bytes consumed, errcode). If finished with decoding\n             return <0 for the bytes consumed. Err codes are from `ERRORS`\n        \"\"\"\n        raise NotImplementedError()\n\n    def cleanup(self):\n        \"\"\"\n        Override to perform decoder specific cleanup\n\n        :returns: None\n        \"\"\"\n        pass\n\n    def setfd(self, fd):\n        \"\"\"\n        Called from ImageFile to set the python file-like object\n\n        :param fd: A python file-like object\n        :returns: None\n        \"\"\"\n        self.fd = fd\n\n    def setimage(self, im, extents=None):\n        \"\"\"\n        Called from ImageFile to set the core output image for the decoder\n\n        :param im: A core image object\n        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle\n            for this tile\n        :returns: None\n        \"\"\"\n\n        # following c code\n        self.im = im\n\n        if extents:\n            (x0, y0, x1, y1) = extents\n        else:\n            (x0, y0, x1, y1) = (0, 0, 0, 0)\n\n        if x0 == 0 and x1 == 0:\n            self.state.xsize, self.state.ysize = self.im.size\n        else:\n            self.state.xoff = x0\n            self.state.yoff = y0\n            self.state.xsize = x1 - x0\n            self.state.ysize = y1 - y0\n\n        if self.state.xsize <= 0 or self.state.ysize <= 0:\n            raise ValueError(\"Size cannot be negative\")\n\n        if (self.state.xsize + self.state.xoff > self.im.size[0] or\n           self.state.ysize + self.state.yoff > self.im.size[1]):\n            raise ValueError(\"Tile cannot extend outside image\")\n\n    def set_as_raw(self, data, rawmode=None):\n        \"\"\"\n        Convenience method to set the internal image from a stream of raw data\n\n        :param data: Bytes to be set\n        :param rawmode: The rawmode to be used for the decoder. If not specified,\n             it will default to the mode of the image\n        :returns: None\n        \"\"\"\n\n        if not rawmode:\n            rawmode = self.mode\n        d = Image._getdecoder(self.mode, 'raw', (rawmode))\n        d.setimage(self.im, self.state.extents())\n        s = d.decode(data)\n\n        if s[0] >= 0:\n            raise ValueError(\"not enough image data\")\n        if s[1] != 0:\n            raise ValueError(\"cannot decode image data\")\n",
            "header": {
                "file": {
                    "path": "src/PIL/ImageFile.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "63a9d4ca2",
                "new_commit_hash": "681dee524",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/src/PIL/ImageFile.py"
            },
            "plus_file": {
                "path": "b/src/PIL/ImageFile.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 118,
                            "length": 6
                        },
                        "new_range": {
                            "start": 118,
                            "length": 11
                        },
                        "section": "class ImageFile(Image.Image):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        pass",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def get_format_mimetype(self):",
                                "type": "added"
                            },
                            {
                                "content": "        if self.format is None:",
                                "type": "added"
                            },
                            {
                                "content": "            return",
                                "type": "added"
                            },
                            {
                                "content": "        return Image.MIME.get(self.format.upper())",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def verify(self):",
                                "type": "context"
                            },
                            {
                                "content": "        \"Check file integrity\"",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "src/PIL/ImageFile.py",
                            "type": "class",
                            "name": "ImageFile",
                            "content": "class ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def get_format_mimetype(self):\n        if self.format is None:\n            return\n        return Image.MIME.get(self.format.upper())\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 75,
                            "end_lineno": 287,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "src/PIL/ImageFile.py",
                            "type": "method",
                            "name": "ImageFile.get_format_mimetype",
                            "content": "class ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def get_format_mimetype(self):\n        if self.format is None:\n            return\n        return Image.MIME.get(self.format.upper())\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 121,
                            "end_lineno": 124,
                            "parent": {
                                "file_name": "src/PIL/ImageFile.py",
                                "type": "class",
                                "name": "ImageFile",
                                "content": "class ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def get_format_mimetype(self):\n        if self.format is None:\n            return\n        return Image.MIME.get(self.format.upper())\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 75,
                                "end_lineno": 287,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "d97e16c9039618e72f4b58db82dafadc74694a81^",
    "new_commit_hash": "d97e16c9039618e72f4b58db82dafadc74694a81",
    "commit_message": "Merge pull request #3190 from radarhere/mimetype\n\nAdded ImageFile get_format_mimetype method",
    "commit_date": "2018-07-01T21:19:57+03:00",
    "metadata": {}
}
{
    "repo_name": "pillow",
    "new_commit_hash": "d97e16c9039618e72f4b58db82dafadc74694a81",
    "test_file_codes": [
        "from helper import hopper, unittest, PillowTestCase\n\nfrom PIL import Image, PixarImagePlugin\n\nTEST_FILE = \"Tests/images/hopper.pxr\"\n\n\nclass TestFilePixar(PillowTestCase):\n\n    def test_sanity(self):\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, \"PIXAR\")\n        self.assertIsNone(im.get_format_mimetype())\n\n        im2 = hopper()\n        self.assert_image_similar(im, im2, 4.8)\n\n    def test_invalid_file(self):\n        invalid_file = \"Tests/images/flower.jpg\"\n\n        self.assertRaises(\n            SyntaxError,\n            PixarImagePlugin.PixarImageFile, invalid_file)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
        "from helper import unittest, PillowTestCase, hopper\nfrom helper import djpeg_available, cjpeg_available\n\nfrom io import BytesIO\nimport os\nimport sys\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import JpegImagePlugin\n\ncodecs = dir(Image.core)\n\nTEST_FILE = \"Tests/images/hopper.jpg\"\n\n\nclass TestFileJpeg(PillowTestCase):\n\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def roundtrip(self, im, **options):\n        out = BytesIO()\n        im.save(out, \"JPEG\", **options)\n        test_bytes = out.tell()\n        out.seek(0)\n        im = Image.open(out)\n        im.bytes = test_bytes  # for testing only\n        return im\n\n    def gen_random_image(self, size, mode='RGB'):\n        \"\"\" Generates a very hard to compress file\n        :param size: tuple\n        :param mode: optional image mode\n\n        \"\"\"\n        return Image.frombytes(mode, size,\n                               os.urandom(size[0]*size[1]*len(mode)))\n\n    def test_sanity(self):\n\n        # internal version number\n        self.assertRegex(Image.core.jpeglib_version, r\"\\d+\\.\\d+$\")\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, \"JPEG\")\n        self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\n\n    def test_app(self):\n        # Test APP/COM reader (@PIL135)\n        im = Image.open(TEST_FILE)\n        self.assertEqual(\n            im.applist[0],\n            (\"APP0\", b\"JFIF\\x00\\x01\\x01\\x01\\x00`\\x00`\\x00\\x00\"))\n        self.assertEqual(im.applist[1], (\n            \"COM\", b\"File written by Adobe Photoshop\\xa8 4.0\\x00\"))\n        self.assertEqual(len(im.applist), 2)\n\n    def test_cmyk(self):\n        # Test CMYK handling.  Thanks to Tim and Charlie for test data,\n        # Michael for getting me to look one more time.\n        f = \"Tests/images/pil_sample_cmyk.jpg\"\n        im = Image.open(f)\n        # the source image has red pixels in the upper left corner.\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        # the opposite corner is black\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n        # roundtrip, and check again\n        im = self.roundtrip(im)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]\n        self.assertEqual(c, 0.0)\n        self.assertGreater(m, 0.8)\n        self.assertGreater(y, 0.8)\n        self.assertEqual(k, 0.0)\n        c, m, y, k = [x / 255.0 for x in im.getpixel((\n            im.size[0]-1, im.size[1]-1))]\n        self.assertGreater(k, 0.9)\n\n    def test_dpi(self):\n        def test(xdpi, ydpi=None):\n            im = Image.open(TEST_FILE)\n            im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))\n            return im.info.get(\"dpi\")\n        self.assertEqual(test(72), (72, 72))\n        self.assertEqual(test(300), (300, 300))\n        self.assertEqual(test(100, 200), (100, 200))\n        self.assertIsNone(test(0))  # square pixels\n\n    def test_icc(self):\n        # Test ICC support\n        im1 = Image.open(\"Tests/images/rgb.jpg\")\n        icc_profile = im1.info[\"icc_profile\"]\n        self.assertEqual(len(icc_profile), 3144)\n        # Roundtrip via physical file.\n        f = self.tempfile(\"temp.jpg\")\n        im1.save(f, icc_profile=icc_profile)\n        im2 = Image.open(f)\n        self.assertEqual(im2.info.get(\"icc_profile\"), icc_profile)\n        # Roundtrip via memory buffer.\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), icc_profile=icc_profile)\n        self.assert_image_equal(im1, im2)\n        self.assertFalse(im1.info.get(\"icc_profile\"))\n        self.assertTrue(im2.info.get(\"icc_profile\"))\n\n    def test_icc_big(self):\n        # Make sure that the \"extra\" support handles large blocks\n        def test(n):\n            # The ICC APP marker can store 65519 bytes per marker, so\n            # using a 4-byte test code should allow us to detect out of\n            # order issues.\n            icc_profile = (b\"Test\"*int(n/4+1))[:n]\n            self.assertEqual(len(icc_profile), n)  # sanity\n            im1 = self.roundtrip(hopper(), icc_profile=icc_profile)\n            self.assertEqual(im1.info.get(\"icc_profile\"), icc_profile or None)\n        test(0)\n        test(1)\n        test(3)\n        test(4)\n        test(5)\n        test(65533-14)  # full JPEG marker block\n        test(65533-14+1)  # full block plus one byte\n        test(ImageFile.MAXBLOCK)  # full buffer block\n        test(ImageFile.MAXBLOCK+1)  # full buffer block plus one byte\n        test(ImageFile.MAXBLOCK*4+3)  # large block\n\n    def test_large_icc_meta(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        # Sometimes the meta data on the icc_profile block is bigger than\n        # Image.MAXBLOCK or the image size.\n        im = Image.open('Tests/images/icc_profile_big.jpg')\n        f = self.tempfile(\"temp.jpg\")\n        icc_profile = im.info[\"icc_profile\"]\n        try:\n            im.save(f, format='JPEG', progressive=True, quality=95,\n                    icc_profile=icc_profile, optimize=True)\n        except IOError:\n            self.fail(\"Failed saving image with icc larger than image size\")\n\n    def test_optimize(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), optimize=0)\n        im3 = self.roundtrip(hopper(), optimize=1)\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_optimize_large_buffer(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", optimize=True)\n\n    def test_progressive(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), progressive=False)\n        im3 = self.roundtrip(hopper(), progressive=True)\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n\n        self.assert_image_equal(im1, im3)\n        self.assertGreaterEqual(im1.bytes, im3.bytes)\n\n    def test_progressive_large_buffer(self):\n        f = self.tempfile('temp.jpg')\n        # this requires ~ 1.5x Image.MAXBLOCK\n        im = Image.new(\"RGB\", (4096, 4096), 0xff3333)\n        im.save(f, format=\"JPEG\", progressive=True)\n\n    def test_progressive_large_buffer_highest_quality(self):\n        f = self.tempfile('temp.jpg')\n        im = self.gen_random_image((255, 255))\n        # this requires more bytes than pixels in the image\n        im.save(f, format=\"JPEG\", progressive=True, quality=100)\n\n    def test_progressive_cmyk_buffer(self):\n        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.\n        f = BytesIO()\n        im = self.gen_random_image((256, 256), 'CMYK')\n        im.save(f, format='JPEG', progressive=True, quality=94)\n\n    def test_large_exif(self):\n        # https://github.com/python-pillow/Pillow/issues/148\n        f = self.tempfile('temp.jpg')\n        im = hopper()\n        im.save(f, 'JPEG', quality=90, exif=b\"1\"*65532)\n\n    def test_exif_typeerror(self):\n        im = Image.open('Tests/images/exif_typeerror.jpg')\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_exif_gps(self):\n        # Arrange\n        im = Image.open('Tests/images/exif_gps.jpg')\n        gps_index = 34853\n        expected_exif_gps = {\n            0: b'\\x00\\x00\\x00\\x01',\n            2: (4294967295, 1),\n            5: b'\\x01',\n            30: 65535,\n            29: '1999:99:99 99:99:99'}\n\n        # Act\n        exif = im._getexif()\n\n        # Assert\n        self.assertEqual(exif[gps_index], expected_exif_gps)\n\n    def test_exif_rollback(self):\n        # rolling back exif support in 3.1 to pre-3.0 formatting.\n        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility\n        # this test passes on 2.9 and 3.1, but not 3.0\n        expected_exif = {34867: 4294967295,\n                         258: (24, 24, 24),\n                         36867: '2099:09:29 10:10:10',\n                         34853: {0: b'\\x00\\x00\\x00\\x01',\n                                 2: (4294967295, 1),\n                                 5: b'\\x01',\n                                 30: 65535,\n                                 29: '1999:99:99 99:99:99'},\n                         296: 65535,\n                         34665: 185,\n                         41994: 65535,\n                         514: 4294967295,\n                         271: 'Make',\n                         272: 'XXX-XXX',\n                         305: 'PIL',\n                         42034: ((1, 1), (1, 1), (1, 1), (1, 1)),\n                         42035: 'LensMake',\n                         34856: b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa',\n                         282: (4294967295, 1),\n                         33434: (4294967295, 1)}\n\n        im = Image.open('Tests/images/exif_gps.jpg')\n        exif = im._getexif()\n\n        for tag, value in expected_exif.items():\n            self.assertEqual(value, exif[tag])\n\n    def test_exif_gps_typeerror(self):\n        im = Image.open('Tests/images/exif_gps_typeerror.jpg')\n\n        # Should not raise a TypeError\n        im._getexif()\n\n    def test_progressive_compat(self):\n        im1 = self.roundtrip(hopper())\n        self.assertFalse(im1.info.get(\"progressive\"))\n        self.assertFalse(im1.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=0)\n        im3 = self.roundtrip(hopper(), progression=0)  # compatibility\n        self.assertFalse(im2.info.get(\"progressive\"))\n        self.assertFalse(im2.info.get(\"progression\"))\n        self.assertFalse(im3.info.get(\"progressive\"))\n        self.assertFalse(im3.info.get(\"progression\"))\n\n        im2 = self.roundtrip(hopper(), progressive=1)\n        im3 = self.roundtrip(hopper(), progression=1)  # compatibility\n        self.assert_image_equal(im1, im2)\n        self.assert_image_equal(im1, im3)\n        self.assertTrue(im2.info.get(\"progressive\"))\n        self.assertTrue(im2.info.get(\"progression\"))\n        self.assertTrue(im3.info.get(\"progressive\"))\n        self.assertTrue(im3.info.get(\"progression\"))\n\n    def test_quality(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), quality=50)\n        self.assert_image(im1, im2.mode, im2.size)\n        self.assertGreaterEqual(im1.bytes, im2.bytes)\n\n    def test_smooth(self):\n        im1 = self.roundtrip(hopper())\n        im2 = self.roundtrip(hopper(), smooth=100)\n        self.assert_image(im1, im2.mode, im2.size)\n\n    def test_subsampling(self):\n        def getsampling(im):\n            layer = im.layer\n            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]\n        # experimental API\n        im = self.roundtrip(hopper(), subsampling=-1)  # default\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=0)  # 4:4:4\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=1)  # 4:2:2\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=2)  # 4:2:0\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=3)  # default (undefined)\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        im = self.roundtrip(hopper(), subsampling=\"4:4:4\")\n        self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:2\")\n        self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:2:0\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n        im = self.roundtrip(hopper(), subsampling=\"4:1:1\")\n        self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))\n\n        self.assertRaises(\n            TypeError, self.roundtrip, hopper(), subsampling=\"1:1:1\")\n\n    def test_exif(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        info = im._getexif()\n        self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')\n\n    def test_mp(self):\n        im = Image.open(\"Tests/images/pil_sample_rgb.jpg\")\n        self.assertIsNone(im._getmp())\n\n    def test_quality_keep(self):\n        # RGB\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # Grayscale\n        im = Image.open(\"Tests/images/hopper_gray.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n        # CMYK\n        im = Image.open(\"Tests/images/pil_sample_cmyk.jpg\")\n        f = self.tempfile('temp.jpg')\n        im.save(f, quality='keep')\n\n    def test_junk_jpeg_header(self):\n        # https://github.com/python-pillow/Pillow/issues/630\n        filename = \"Tests/images/junk_jpeg_header.jpg\"\n        Image.open(filename)\n\n    def test_ff00_jpeg_header(self):\n        filename = \"Tests/images/jpeg_ff00_header.jpg\"\n        Image.open(filename)\n\n    def test_truncated_jpeg_should_read_all_the_data(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        im = Image.open(filename)\n        im.load()\n        ImageFile.LOAD_TRUNCATED_IMAGES = False\n        self.assertIsNotNone(im.getbbox())\n\n    def test_truncated_jpeg_throws_IOError(self):\n        filename = \"Tests/images/truncated_jpeg.jpg\"\n        im = Image.open(filename)\n\n        with self.assertRaises(IOError):\n            im.load()\n\n\n    def _n_qtables_helper(self, n, test_file):\n        im = Image.open(test_file)\n        f = self.tempfile('temp.jpg')\n        im.save(f, qtables=[[n]*64]*n)\n        im = Image.open(f)\n        self.assertEqual(len(im.quantization), n)\n        reloaded = self.roundtrip(im, qtables=\"keep\")\n        self.assertEqual(im.quantization, reloaded.quantization)\n\n    def test_qtables(self):\n        im = Image.open(\"Tests/images/hopper.jpg\")\n        qtables = im.quantization\n        reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)\n        self.assertEqual(im.quantization, reloaded.quantization)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'),\n                                  30)\n        self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)\n\n        # valid bounds for baseline qtable\n        bounds_qtable = [int(s) for s in (\"255 1 \" * 32).split(None)]\n        self.roundtrip(im, qtables=[bounds_qtable])\n\n        # values from wizard.txt in jpeg9-a src package.\n        standard_l_qtable = [int(s) for s in \"\"\"\n            16  11  10  16  24  40  51  61\n            12  12  14  19  26  58  60  55\n            14  13  16  24  40  57  69  56\n            14  17  22  29  51  87  80  62\n            18  22  37  56  68 109 103  77\n            24  35  55  64  81 104 113  92\n            49  64  78  87 103 121 120 101\n            72  92  95  98 112 100 103  99\n            \"\"\".split(None)]\n\n        standard_chrominance_qtable = [int(s) for s in \"\"\"\n            17  18  24  47  99  99  99  99\n            18  21  26  66  99  99  99  99\n            24  26  56  99  99  99  99  99\n            47  66  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            99  99  99  99  99  99  99  99\n            \"\"\".split(None)]\n        # list of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=[standard_l_qtable, standard_chrominance_qtable]),\n            30)\n\n        # tuple of qtable lists\n        self.assert_image_similar(\n            im, self.roundtrip(\n                im, qtables=(standard_l_qtable, standard_chrominance_qtable)),\n            30)\n\n        # dict of qtable lists\n        self.assert_image_similar(im,\n                                  self.roundtrip(im, qtables={\n                                      0: standard_l_qtable,\n                                      1: standard_chrominance_qtable\n                                  }), 30)\n\n        self._n_qtables_helper(1, \"Tests/images/hopper_gray.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_rgb.jpg\")\n        self._n_qtables_helper(1, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(2, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(3, \"Tests/images/pil_sample_cmyk.jpg\")\n        self._n_qtables_helper(4, \"Tests/images/pil_sample_cmyk.jpg\")\n\n        # not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables='a')\n        # sequence wrong length\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[])\n        # sequence wrong length\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[1, 2, 3, 4, 5])\n\n        # qtable entry not a sequence\n        self.assertRaises(ValueError, self.roundtrip, im, qtables=[1])\n        # qtable entry has wrong number of items\n        self.assertRaises(ValueError,\n                          self.roundtrip, im, qtables=[[1, 2, 3, 4]])\n\n    @unittest.skipUnless(djpeg_available(), \"djpeg not available\")\n    def test_load_djpeg(self):\n        img = Image.open(TEST_FILE)\n        img.load_djpeg()\n        self.assert_image_similar(img, Image.open(TEST_FILE), 0)\n\n    @unittest.skipUnless(cjpeg_available(), \"cjpeg not available\")\n    def test_save_cjpeg(self):\n        img = Image.open(TEST_FILE)\n\n        tempfile = self.tempfile(\"temp.jpg\")\n        JpegImagePlugin._save_cjpeg(img, 0, tempfile)\n        # Default save quality is 75%, so a tiny bit of difference is alright\n        self.assert_image_similar(img, Image.open(tempfile), 17)\n\n    def test_no_duplicate_0x1001_tag(self):\n        # Arrange\n        from PIL import ExifTags\n        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}\n\n        # Assert\n        self.assertEqual(tag_ids['RelatedImageWidth'], 0x1001)\n        self.assertEqual(tag_ids['RelatedImageLength'], 0x1002)\n\n    def test_MAXBLOCK_scaling(self):\n        im = self.gen_random_image((512, 512))\n        f = self.tempfile(\"temp.jpeg\")\n        im.save(f, quality=100, optimize=True)\n\n        reloaded = Image.open(f)\n\n        # none of these should crash\n        reloaded.save(f, quality='keep')\n        reloaded.save(f, quality='keep', progressive=True)\n        reloaded.save(f, quality='keep', optimize=True)\n\n    def test_bad_mpo_header(self):\n        \"\"\" Treat unknown MPO as JPEG \"\"\"\n        # Arrange\n\n        # Act\n        # Shouldn't raise error\n        fn = \"Tests/images/sugarshack_bad_mpo_header.jpg\"\n        im = self.assert_warning(UserWarning, Image.open, fn)\n\n        # Assert\n        self.assertEqual(im.format, \"JPEG\")\n\n    def test_save_correct_modes(self):\n        out = BytesIO()\n        for mode in ['1', 'L', 'RGB', 'RGBX', 'CMYK', 'YCbCr']:\n            img = Image.new(mode, (20, 20))\n            img.save(out, \"JPEG\")\n\n    def test_save_wrong_modes(self):\n        # ref https://github.com/python-pillow/Pillow/issues/2005\n        out = BytesIO()\n        for mode in ['LA', 'La', 'RGBA', 'RGBa', 'P']:\n            img = Image.new(mode, (20, 20))\n            self.assertRaises(IOError, img.save, out, \"JPEG\")\n\n    def test_save_tiff_with_dpi(self):\n        # Arrange\n        outfile = self.tempfile(\"temp.tif\")\n        im = Image.open(\"Tests/images/hopper.tif\")\n\n        # Act\n        im.save(outfile, 'JPEG', dpi=im.info['dpi'])\n\n        # Assert\n        reloaded = Image.open(outfile)\n        reloaded.load()\n        self.assertEqual(im.info['dpi'], reloaded.info['dpi'])\n\n    def test_dpi_tuple_from_exif(self):\n        # Arrange\n        # This Photoshop CC 2017 image has DPI in EXIF not metadata\n        # EXIF XResolution is (2000000, 10000)\n        im = Image.open(\"Tests/images/photoshop-200dpi.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (200, 200))\n\n    def test_dpi_int_from_exif(self):\n        # Arrange\n        # This image has DPI in EXIF not metadata\n        # EXIF XResolution is 72\n        im = Image.open(\"Tests/images/exif-72dpi-int.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_dpi_from_dpcm_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:\n        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-200dpcm.jpg\")\n\n        # Act / Assert\n        self.assertEqual(im.info.get(\"dpi\"), (508, 508))\n\n    def test_dpi_exif_zero_division(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:\n        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/exif-dpi-zerodivision.jpg\")\n\n        # Act / Assert\n        # This should return the default, and not raise a ZeroDivisionError\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_no_dpi_in_exif(self):\n        # Arrange\n        # This is photoshop-200dpi.jpg with resolution removed from EXIF:\n        # exiftool \"-*resolution*\"= photoshop-200dpi.jpg\n        im = Image.open(\"Tests/images/no-dpi-in-exif.jpg\")\n\n        # Act / Assert\n        # \"When the image resolution is unknown, 72 [dpi] is designated.\"\n        # http://www.exiv2.org/tags.html\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n    def test_invalid_exif(self):\n        # This is no-dpi-in-exif with the tiff header of the exif block\n        # hexedited from MM * to FF FF FF FF\n        im = Image.open(\"Tests/images/invalid-exif.jpg\")\n\n        # This should return the default, and not a SyntaxError or\n        # OSError for unidentified image.\n        self.assertEqual(im.info.get(\"dpi\"), (72, 72))\n\n\n@unittest.skipUnless(sys.platform.startswith('win32'), \"Windows only\")\nclass TestFileCloseW32(PillowTestCase):\n    def setUp(self):\n        if \"jpeg_encoder\" not in codecs or \"jpeg_decoder\" not in codecs:\n            self.skipTest(\"jpeg support not available\")\n\n    def test_fd_leak(self):\n        tmpfile = self.tempfile(\"temp.jpg\")\n\n        with Image.open(\"Tests/images/hopper.jpg\") as im:\n            im.save(tmpfile)\n\n        im = Image.open(tmpfile)\n        fp = im.fp\n        self.assertFalse(fp.closed)\n        self.assertRaises(WindowsError, os.remove, tmpfile)\n        im.load()\n        self.assertTrue(fp.closed)\n        # this should not fail, as load should have closed the file.\n        os.remove(tmpfile)\n\n\nif __name__ == '__main__':\n    unittest.main()\n",
        "from helper import unittest, PillowTestCase, hopper, fromstring, tostring\n\nfrom io import BytesIO\n\nfrom PIL import Image\nfrom PIL import ImageFile\nfrom PIL import EpsImagePlugin\n\n\ncodecs = dir(Image.core)\n\n# save original block sizes\nMAXBLOCK = ImageFile.MAXBLOCK\nSAFEBLOCK = ImageFile.SAFEBLOCK\n\n\nclass TestImageFile(PillowTestCase):\n\n    def test_parser(self):\n\n        def roundtrip(format):\n\n            im = hopper(\"L\").resize((1000, 1000))\n            if format in (\"MSP\", \"XBM\"):\n                im = im.convert(\"1\")\n\n            test_file = BytesIO()\n\n            im.copy().save(test_file, format)\n\n            data = test_file.getvalue()\n\n            parser = ImageFile.Parser()\n            parser.feed(data)\n            imOut = parser.close()\n\n            return im, imOut\n\n        self.assert_image_equal(*roundtrip(\"BMP\"))\n        im1, im2 = roundtrip(\"GIF\")\n        self.assert_image_similar(im1.convert('P'), im2, 1)\n        self.assert_image_equal(*roundtrip(\"IM\"))\n        self.assert_image_equal(*roundtrip(\"MSP\"))\n        if \"zip_encoder\" in codecs:\n            try:\n                # force multiple blocks in PNG driver\n                ImageFile.MAXBLOCK = 8192\n                self.assert_image_equal(*roundtrip(\"PNG\"))\n            finally:\n                ImageFile.MAXBLOCK = MAXBLOCK\n        self.assert_image_equal(*roundtrip(\"PPM\"))\n        self.assert_image_equal(*roundtrip(\"TIFF\"))\n        self.assert_image_equal(*roundtrip(\"XBM\"))\n        self.assert_image_equal(*roundtrip(\"TGA\"))\n        self.assert_image_equal(*roundtrip(\"PCX\"))\n\n        if EpsImagePlugin.has_ghostscript():\n            im1, im2 = roundtrip(\"EPS\")\n            # This test fails on Ubuntu 12.04, PPC (Bigendian) It\n            # appears to be a ghostscript 9.05 bug, since the\n            # ghostscript rendering is wonky and the file is identical\n            # to that written on ubuntu 12.04 x64\n            # md5sum: ba974835ff2d6f3f2fd0053a23521d4a\n\n            # EPS comes back in RGB:\n            self.assert_image_similar(im1, im2.convert('L'), 20)\n\n        if \"jpeg_encoder\" in codecs:\n            im1, im2 = roundtrip(\"JPEG\")  # lossy compression\n            self.assert_image(im1, im2.mode, im2.size)\n\n        self.assertRaises(IOError, roundtrip, \"PDF\")\n\n    def test_ico(self):\n        with open('Tests/images/python.ico', 'rb') as f:\n            data = f.read()\n        with ImageFile.Parser() as p:\n            p.feed(data)\n            self.assertEqual((48, 48), p.image.size)\n\n    def test_safeblock(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im1 = hopper()\n\n        try:\n            ImageFile.SAFEBLOCK = 1\n            im2 = fromstring(tostring(im1, \"PNG\"))\n        finally:\n            ImageFile.SAFEBLOCK = SAFEBLOCK\n\n        self.assert_image_equal(im1, im2)\n\n    def test_raise_ioerror(self):\n        self.assertRaises(IOError, ImageFile.raise_ioerror, 1)\n\n    def test_raise_typeerror(self):\n        with self.assertRaises(TypeError):\n            parser = ImageFile.Parser()\n            parser.feed(1)\n\n    def test_truncated_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_truncated_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/truncated_image.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n    def test_broken_datastream_with_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n        with self.assertRaises(IOError):\n            im.load()\n\n    def test_broken_datastream_without_errors(self):\n        if \"zip_encoder\" not in codecs:\n            self.skipTest(\"PNG (zlib) encoder not available\")\n\n        im = Image.open(\"Tests/images/broken_data_stream.png\")\n\n        ImageFile.LOAD_TRUNCATED_IMAGES = True\n        try:\n            im.load()\n        finally:\n            ImageFile.LOAD_TRUNCATED_IMAGES = False\n\n\nclass MockPyDecoder(ImageFile.PyDecoder):\n    def decode(self, buffer):\n        # eof\n        return (-1, 0)\n\n\nxoff, yoff, xsize, ysize = 10, 20, 100, 100\n\n\nclass MockImageFile(ImageFile.ImageFile):\n    def _open(self):\n        self.rawmode = 'RGBA'\n        self.mode = 'RGBA'\n        self.size = (200, 200)\n        self.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize), 32, None)]\n\n\nclass TestPyDecoder(PillowTestCase):\n\n    def get_decoder(self):\n        decoder = MockPyDecoder(None)\n\n        def closure(mode, *args):\n            decoder.__init__(mode, *args)\n            return decoder\n\n        Image.register_decoder('MOCK', closure)\n        return decoder\n\n    def test_setimage(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, xoff)\n        self.assertEqual(d.state.yoff, yoff)\n        self.assertEqual(d.state.xsize, xsize)\n        self.assertEqual(d.state.ysize, ysize)\n\n        self.assertRaises(ValueError, d.set_as_raw, b'\\x00')\n\n    def test_extents_none(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", None, 32, None)]\n        d = self.get_decoder()\n\n        im.load()\n\n        self.assertEqual(d.state.xoff, 0)\n        self.assertEqual(d.state.yoff, 0)\n        self.assertEqual(d.state.xsize, 200)\n        self.assertEqual(d.state.ysize, 200)\n\n    def test_negsize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, -10, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, -10), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_oversize(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize + 100, yoff+ysize), 32, None)]\n        d = self.get_decoder()\n\n        self.assertRaises(ValueError, im.load)\n\n        im.tile = [(\"MOCK\", (xoff, yoff, xoff+xsize, yoff+ysize + 100), 32, None)]\n        self.assertRaises(ValueError, im.load)\n\n    def test_no_format(self):\n        buf = BytesIO(b'\\x00'*255)\n\n        im = MockImageFile(buf)\n        self.assertIsNone(im.format)\n        self.assertIsNone(im.get_format_mimetype())\n\n\nif __name__ == '__main__':\n    unittest.main()\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",
        "test_2.py",
        "test_3.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 14ms\nInstalled 12 packages in 184ms\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 896ms\nPrepared 1 package in 14.85s\nInstalled 1 package in 1ms\n + pillow==5.2.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_d97e16c9039618e72f4b58db82dafadc74694a81)\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_d97e16c9039618e72f4b58db82dafadc74694a81\n.............................................................\ncollected 61 items\n\n==================== short test summary info ====================\nPASSED test_1::TestFilePixar::test_invalid_file\nPASSED test_1::TestFilePixar::test_sanity\nSKIPPED test_2::TestFileCloseW32::test_fd_leak\nPASSED test_2::TestFileJpeg::test_MAXBLOCK_scaling\nPASSED test_2::TestFileJpeg::test_app\nPASSED test_2::TestFileJpeg::test_bad_mpo_header\nPASSED test_2::TestFileJpeg::test_cmyk\nPASSED test_2::TestFileJpeg::test_dpi\nPASSED test_2::TestFileJpeg::test_dpi_exif_zero_division\nPASSED test_2::TestFileJpeg::test_dpi_from_dpcm_exif\nPASSED test_2::TestFileJpeg::test_dpi_int_from_exif\nPASSED test_2::TestFileJpeg::test_dpi_tuple_from_exif\nPASSED test_2::TestFileJpeg::test_exif\nPASSED test_2::TestFileJpeg::test_exif_gps\nPASSED test_2::TestFileJpeg::test_exif_gps_typeerror\nPASSED test_2::TestFileJpeg::test_exif_rollback\nPASSED test_2::TestFileJpeg::test_exif_typeerror\nPASSED test_2::TestFileJpeg::test_ff00_jpeg_header\nPASSED test_2::TestFileJpeg::test_icc\nPASSED test_2::TestFileJpeg::test_icc_big\nPASSED test_2::TestFileJpeg::test_invalid_exif\nPASSED test_2::TestFileJpeg::test_junk_jpeg_header\nPASSED test_2::TestFileJpeg::test_large_exif\nPASSED test_2::TestFileJpeg::test_large_icc_meta\nSKIPPED test_2::TestFileJpeg::test_load_djpeg\nPASSED test_2::TestFileJpeg::test_mp\nPASSED test_2::TestFileJpeg::test_no_dpi_in_exif\nPASSED test_2::TestFileJpeg::test_no_duplicate_0x1001_tag\nPASSED test_2::TestFileJpeg::test_optimize\nPASSED test_2::TestFileJpeg::test_optimize_large_buffer\nPASSED test_2::TestFileJpeg::test_progressive\nPASSED test_2::TestFileJpeg::test_progressive_cmyk_buffer\nPASSED test_2::TestFileJpeg::test_progressive_compat\nPASSED test_2::TestFileJpeg::test_progressive_large_buffer\nPASSED test_2::TestFileJpeg::test_progressive_large_buffer_highest_quality\nPASSED test_2::TestFileJpeg::test_qtables\nPASSED test_2::TestFileJpeg::test_quality\nPASSED test_2::TestFileJpeg::test_quality_keep\nPASSED test_2::TestFileJpeg::test_sanity\nSKIPPED test_2::TestFileJpeg::test_save_cjpeg\nPASSED test_2::TestFileJpeg::test_save_correct_modes\nPASSED test_2::TestFileJpeg::test_save_tiff_with_dpi\nPASSED test_2::TestFileJpeg::test_save_wrong_modes\nPASSED test_2::TestFileJpeg::test_smooth\nPASSED test_2::TestFileJpeg::test_subsampling\nPASSED test_2::TestFileJpeg::test_truncated_jpeg_should_read_all_the_data\nPASSED test_2::TestFileJpeg::test_truncated_jpeg_throws_IOError\nPASSED test_3::TestImageFile::test_broken_datastream_with_errors\nPASSED test_3::TestImageFile::test_broken_datastream_without_errors\nPASSED test_3::TestImageFile::test_ico\nPASSED test_3::TestImageFile::test_parser\nPASSED test_3::TestImageFile::test_raise_ioerror\nPASSED test_3::TestImageFile::test_raise_typeerror\nPASSED test_3::TestImageFile::test_safeblock\nPASSED test_3::TestImageFile::test_truncated_with_errors\nPASSED test_3::TestImageFile::test_truncated_without_errors\nPASSED test_3::TestPyDecoder::test_extents_none\nPASSED test_3::TestPyDecoder::test_negsize\nPASSED test_3::TestPyDecoder::test_no_format\nPASSED test_3::TestPyDecoder::test_oversize\nPASSED test_3::TestPyDecoder::test_setimage\n=================== 58 passed, 3 skipped in 1.34s ===================\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_d97e16c9039618e72f4b58db82dafadc74694a81\n....=== orphaned temp file: /tmp/temp_rqvt92m.jpeg\n...............=== orphaned temp file: /tmp/tempnkwovsv7.jpg\n....=== orphaned temp file: /tmp/tempje4divl1.jpg\n.=== orphaned temp file: /tmp/temp1b8nix_o.jpg\n......=== orphaned temp file: /tmp/temp0h2a6s2g.jpg\n....=== orphaned temp file: /tmp/tempw0sm7bmt.jpg\n.=== orphaned temp file: /tmp/tempz06ntrkd.jpg\n.=== orphaned temp file: /tmp/temp962_1ur2.jpg\n=== orphaned temp file: /tmp/tempgszvxbf4.jpg\n=== orphaned temp file: /tmp/temp4m3dbez8.jpg\n=== orphaned temp file: /tmp/tempvlz0mqpl.jpg\n=== orphaned temp file: /tmp/tempew5lpzqj.jpg\n=== orphaned temp file: /tmp/tempdixx04cy.jpg\n=== orphaned temp file: /tmp/tempxwoy693w.jpg\n=== orphaned temp file: /tmp/templ_xk_jnl.jpg\n..=== orphaned temp file: /tmp/temptxcdg3m3.jpg\n=== orphaned temp file: /tmp/tempfuec6u16.jpg\n=== orphaned temp file: /tmp/temp42tfiynl.jpg\n....=== orphaned temp file: /tmp/tempzg2o486z.tif\n...................\ncollected 61 items\n\n=================================== ERRORS =====================================\n__________ TestFilePixar.test_sanity __________\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_d97e16c9039618e72f4b58db82dafadc74694a81/r2e_tests/test_1.py\", line 16, in test_sanity\n    self.assertIsNone(im.get_format_mimetype())\nAttributeError: 'PixarImageFile' object has no attribute 'get_format_mimetype'\n__________ TestFileJpeg.test_sanity __________\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_d97e16c9039618e72f4b58db82dafadc74694a81/r2e_tests/test_2.py\", line 51, in test_sanity\n    self.assertEqual(im.get_format_mimetype(), \"image/jpeg\")\nAttributeError: 'JpegImageFile' object has no attribute 'get_format_mimetype'\n__________ TestPyDecoder.test_no_format __________\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_d97e16c9039618e72f4b58db82dafadc74694a81/r2e_tests/test_3.py\", line 231, in test_no_format\n    self.assertIsNone(im.get_format_mimetype())\nAttributeError: 'MockImageFile' object has no attribute 'get_format_mimetype'\n\n==================== short test summary info ====================\nPASSED test_1::TestFilePixar::test_invalid_file\nERROR test_1::TestFilePixar::test_sanity\nSKIPPED test_2::TestFileCloseW32::test_fd_leak\nPASSED test_2::TestFileJpeg::test_MAXBLOCK_scaling\nPASSED test_2::TestFileJpeg::test_app\nPASSED test_2::TestFileJpeg::test_bad_mpo_header\nPASSED test_2::TestFileJpeg::test_cmyk\nPASSED test_2::TestFileJpeg::test_dpi\nPASSED test_2::TestFileJpeg::test_dpi_exif_zero_division\nPASSED test_2::TestFileJpeg::test_dpi_from_dpcm_exif\nPASSED test_2::TestFileJpeg::test_dpi_int_from_exif\nPASSED test_2::TestFileJpeg::test_dpi_tuple_from_exif\nPASSED test_2::TestFileJpeg::test_exif\nPASSED test_2::TestFileJpeg::test_exif_gps\nPASSED test_2::TestFileJpeg::test_exif_gps_typeerror\nPASSED test_2::TestFileJpeg::test_exif_rollback\nPASSED test_2::TestFileJpeg::test_exif_typeerror\nPASSED test_2::TestFileJpeg::test_ff00_jpeg_header\nPASSED test_2::TestFileJpeg::test_icc\nPASSED test_2::TestFileJpeg::test_icc_big\nPASSED test_2::TestFileJpeg::test_invalid_exif\nPASSED test_2::TestFileJpeg::test_junk_jpeg_header\nPASSED test_2::TestFileJpeg::test_large_exif\nPASSED test_2::TestFileJpeg::test_large_icc_meta\nSKIPPED test_2::TestFileJpeg::test_load_djpeg\nPASSED test_2::TestFileJpeg::test_mp\nPASSED test_2::TestFileJpeg::test_no_dpi_in_exif\nPASSED test_2::TestFileJpeg::test_no_duplicate_0x1001_tag\nPASSED test_2::TestFileJpeg::test_optimize\nPASSED test_2::TestFileJpeg::test_optimize_large_buffer\nPASSED test_2::TestFileJpeg::test_progressive\nPASSED test_2::TestFileJpeg::test_progressive_cmyk_buffer\nPASSED test_2::TestFileJpeg::test_progressive_compat\nPASSED test_2::TestFileJpeg::test_progressive_large_buffer\nPASSED test_2::TestFileJpeg::test_progressive_large_buffer_highest_quality\nPASSED test_2::TestFileJpeg::test_qtables\nPASSED test_2::TestFileJpeg::test_quality\nPASSED test_2::TestFileJpeg::test_quality_keep\nERROR test_2::TestFileJpeg::test_sanity\nSKIPPED test_2::TestFileJpeg::test_save_cjpeg\nPASSED test_2::TestFileJpeg::test_save_correct_modes\nPASSED test_2::TestFileJpeg::test_save_tiff_with_dpi\nPASSED test_2::TestFileJpeg::test_save_wrong_modes\nPASSED test_2::TestFileJpeg::test_smooth\nPASSED test_2::TestFileJpeg::test_subsampling\nPASSED test_2::TestFileJpeg::test_truncated_jpeg_should_read_all_the_data\nPASSED test_2::TestFileJpeg::test_truncated_jpeg_throws_IOError\nPASSED test_3::TestImageFile::test_broken_datastream_with_errors\nPASSED test_3::TestImageFile::test_broken_datastream_without_errors\nPASSED test_3::TestImageFile::test_ico\nPASSED test_3::TestImageFile::test_parser\nPASSED test_3::TestImageFile::test_raise_ioerror\nPASSED test_3::TestImageFile::test_raise_typeerror\nPASSED test_3::TestImageFile::test_safeblock\nPASSED test_3::TestImageFile::test_truncated_with_errors\nPASSED test_3::TestImageFile::test_truncated_without_errors\nPASSED test_3::TestPyDecoder::test_extents_none\nPASSED test_3::TestPyDecoder::test_negsize\nERROR test_3::TestPyDecoder::test_no_format\nPASSED test_3::TestPyDecoder::test_oversize\nPASSED test_3::TestPyDecoder::test_setimage\n=================== 3 errors, 55 passed, 3 skipped in 0.94s ===================\n",
    "old_commit_res_stderr": ""
}
Tests/test_file_jpeg.py Tests/test_file_pixar.py Tests/test_imagefile.py src/PIL/ImageFile.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Missing `get_format_mimetype` Method Causes AttributeError in ImageFile Subclasses

**Description:**
When working with certain image file types, attempting to retrieve the MIME type using the `get_format_mimetype` method results in an `AttributeError`. This issue affects subclasses of `ImageFile`, such as `JpegImageFile` and `PixarImageFile`, preventing proper handling of MIME types.

**Example Code:**
```python
from PIL import Image

# Attempting to get MIME type for a JPEG image
im = Image.open('example.jpg')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'JpegImageFile' object has no attribute 'get_format_mimetype'

# Attempting to get MIME type for a Pixar image
im = Image.open('example.pixar')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'PixarImageFile' object has no attribute 'get_format_mimetype'

# Using a mock image file without a format
class MockImageFile(Image.Image):
    pass

mock_im = MockImageFile()
mime_type = mock_im.get_format_mimetype()
print(mime_type)  # AttributeError: 'MockImageFile' object has no attribute 'get_format_mimetype'
```

**Expected Behavior:**
The `get_format_mimetype` method should be available in all subclasses of `ImageFile`. Calling this method on any image instance should return the correct MIME type based on the image format. For image files without a defined format, the method should return `None`.

**Actual Behavior:**
Calling `get_format_mimetype` on instances of `JpegImageFile`, `PixarImageFile`, or a mock image file without a format raises an `AttributeError`, indicating that the method does not exist. This prevents developers from reliably obtaining MIME types for different image formats and handling images without formats appropriately.

</ISSUE>
--- END ISSUE ---

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

--- BEGIN FILE ---
```
### src/PIL/ImageFile.py
#
# The Python Imaging Library.
# $Id$
#
# base class for image file handlers
#
# history:
# 1995-09-09 fl   Created
# 1996-03-11 fl   Fixed load mechanism.
# 1996-04-15 fl   Added pcx/xbm decoders.
# 1996-04-30 fl   Added encoders.
# 1996-12-14 fl   Added load helpers
# 1997-01-11 fl   Use encode_to_file where possible
# 1997-08-27 fl   Flush output in _save
# 1998-03-05 fl   Use memory mapping for some modes
# 1999-02-04 fl   Use memory mapping also for "I;16" and "I;16B"
# 1999-05-31 fl   Added image parser
# 2000-10-12 fl   Set readonly flag on memory-mapped images
# 2002-03-20 fl   Use better messages for common decoder errors
# 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available
# 2003-10-30 fl   Added StubImageFile class
# 2004-02-25 fl   Made incremental parser more robust
#
# Copyright (c) 1997-2004 by Secret Labs AB
# Copyright (c) 1995-2004 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

from . import Image
from ._util import isPath
import io
import os
import sys
import struct

MAXBLOCK = 65536

SAFEBLOCK = 1024*1024

LOAD_TRUNCATED_IMAGES = False

ERRORS = {
    -1: "image buffer overrun error",
    -2: "decoding error",
    -3: "unknown error",
    -8: "bad configuration",
    -9: "out of memory error"
}


def raise_ioerror(error):
    try:
        message = Image.core.getcodecstatus(error)
    except AttributeError:
        message = ERRORS.get(error)
    if not message:
        message = "decoder error %d" % error
    raise IOError(message + " when reading image file")


#
# --------------------------------------------------------------------
# Helpers

def _tilesort(t):
    # sort on offset
    return t[2]


#
# --------------------------------------------------------------------
# ImageFile base class

class ImageFile(Image.Image):
    "Base class for image file format handlers."

    def __init__(self, fp=None, filename=None):
        Image.Image.__init__(self)

        self._min_frame = 0

        self.tile = None
        self.readonly = 1  # until we know better

        self.decoderconfig = ()
        self.decodermaxblock = MAXBLOCK

        if isPath(fp):
            # filename
            self.fp = open(fp, "rb")
            self.filename = fp
            self._exclusive_fp = True
        else:
            # stream
            self.fp = fp
            self.filename = filename
            # can be overridden
            self._exclusive_fp = None

        try:
            self._open()
        except (IndexError,  # end of data
                TypeError,  # end of data (ord)
                KeyError,  # unsupported mode
                EOFError,  # got header but not the first frame
                struct.error) as v:
            # close the file only if we have opened it this constructor
            if self._exclusive_fp:
                self.fp.close()
            raise SyntaxError(v)

        if not self.mode or self.size[0] <= 0:
            raise SyntaxError("not identified by this driver")

    def draft(self, mode, size):
        "Set draft mode"

        pass

    def verify(self):
        "Check file integrity"

        # raise exception if something's wrong.  must be called
        # directly after open, and closes file when finished.
        if self._exclusive_fp:
            self.fp.close()
        self.fp = None

    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            decoder_name, extents, offset, args = self.tile[0]
            if decoder_name == "raw" and len(args) >= 3 and args[0] == self.mode \
               and args[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper  WIN32 only
                        self.map = Image.core.map(self.filename)
                        self.map.seek(offset)
                        self.im = self.map.readimage(
                            self.mode, self.size, args[1], args[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        with open(self.filename, "r") as fp:
                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, decoder_name, extents, offset, args
                            )
                    readonly = 1
                    # After trashing self.im, we might need to reload the palette data.
                    if self.palette:
                        self.palette.dirty = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()
        err_code = -3  # initialize to unknown error
        if not self.map:
            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for decoder_name, extents, offset, args in self.tile:
                decoder = Image._getdecoder(self.mode, decoder_name,
                                            args, self.decoderconfig)
                try:
                    seek(offset)
                    decoder.setimage(self.im, extents)
                    if decoder.pulls_fd:
                        decoder.setfd(self.fp)
                        status, err_code = decoder.decode(b"")
                    else:
                        b = prefix
                        while True:
                            try:
                                s = read(self.decodermaxblock)
                            except (IndexError, struct.error):  # truncated png/gif
                                if LOAD_TRUNCATED_IMAGES:
                                    break
                                else:
                                    raise IOError("image file is truncated")

                            if not s:  # truncated jpeg
                                if LOAD_TRUNCATED_IMAGES:
                                    break
                                else:
                                    self.tile = []
                                    raise IOError("image file is truncated "
                                                  "(%d bytes not processed)" % len(b))

                            b = b + s
                            n, err_code = decoder.decode(b)
                            if n < 0:
                                break
                            b = b[n:]
                finally:
                    # Need to cleanup here to prevent leaks
                    decoder.cleanup()

        self.tile = []
        self.readonly = readonly

        self.load_end()

        if self._exclusive_fp and self._close_exclusive_fp_after_loading:
            self.fp.close()
        self.fp = None

        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(err_code)

        return Image.Image.load(self)

    def load_prepare(self):
        # create image memory if necessary
        if not self.im or\
           self.im.mode != self.mode or self.im.size != self.size:
            self.im = Image.core.new(self.mode, self.size)
        # create palette (optional)
        if self.mode == "P":
            Image.Image.load(self)

    def load_end(self):
        # may be overridden
        pass

    # may be defined for contained formats
    # def load_seek(self, pos):
    #     pass

    # may be defined for blocked formats (e.g. PNG)
    # def load_read(self, bytes):
    #     pass

    def _seek_check(self, frame):
        if (frame < self._min_frame or
            # Only check upper limit on frames if additional seek operations
            # are not required to do so
            (not (hasattr(self, "_n_frames") and self._n_frames is None) and
             frame >= self.n_frames+self._min_frame)):
            raise EOFError("attempt to seek outside sequence")

        return self.tell() != frame


class StubImageFile(ImageFile):
    """
    Base class for stub image loaders.

    A stub loader is an image loader that can identify files of a
    certain format, but relies on external code to load the file.
    """

    def _open(self):
        raise NotImplementedError(
            "StubImageFile subclass must implement _open"
            )

    def load(self):
        loader = self._load()
        if loader is None:
            raise IOError("cannot find loader for this %s file" % self.format)
        image = loader.load(self)
        assert image is not None
        # become the other object (!)
        self.__class__ = image.__class__
        self.__dict__ = image.__dict__

    def _load(self):
        "(Hook) Find actual image loader."
        raise NotImplementedError(
            "StubImageFile subclass must implement _load"
            )


class Parser(object):
    """
    Incremental image parser.  This class implements the standard
    feed/close consumer interface.
    """
    incremental = None
    image = None
    data = None
    decoder = None
    offset = 0
    finished = 0

    def reset(self):
        """
        (Consumer) Reset the parser.  Note that you can only call this
        method immediately after you've created a parser; parser
        instances cannot be reused.
        """
        assert self.data is None, "cannot reuse parsers"

    def feed(self, data):
        """
        (Consumer) Feed data to the parser.

        :param data: A string buffer.
        :exception IOError: If the parser failed to parse the image file.
        """
        # collect data

        if self.finished:
            return

        if self.data is None:
            self.data = data
        else:
            self.data = self.data + data

        # parse what we have
        if self.decoder:

            if self.offset > 0:
                # skip header
                skip = min(len(self.data), self.offset)
                self.data = self.data[skip:]
                self.offset = self.offset - skip
                if self.offset > 0 or not self.data:
                    return

            n, e = self.decoder.decode(self.data)

            if n < 0:
                # end of stream
                self.data = None
                self.finished = 1
                if e < 0:
                    # decoding error
                    self.image = None
                    raise_ioerror(e)
                else:
                    # end of image
                    return
            self.data = self.data[n:]

        elif self.image:

            # if we end up here with no decoder, this file cannot
            # be incrementally parsed.  wait until we've gotten all
            # available data
            pass

        else:

            # attempt to open this file
            try:
                with io.BytesIO(self.data) as fp:
                    im = Image.open(fp)
            except IOError:
                # traceback.print_exc()
                pass  # not enough data
            else:
                flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
                if flag or len(im.tile) != 1:
                    # custom load code, or multiple tiles
                    self.decode = None
                else:
                    # initialize decoder
                    im.load_prepare()
                    d, e, o, a = im.tile[0]
                    im.tile = []
                    self.decoder = Image._getdecoder(
                        im.mode, d, a, im.decoderconfig
                        )
                    self.decoder.setimage(im.im, e)

                    # calculate decoder offset
                    self.offset = o
                    if self.offset <= len(self.data):
                        self.data = self.data[self.offset:]
                        self.offset = 0

                self.image = im

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def close(self):
        """
        (Consumer) Close the stream.

        :returns: An image object.
        :exception IOError: If the parser failed to parse the image file either
                            because it cannot be identified or cannot be
                            decoded.
        """
        # finish decoding
        if self.decoder:
            # get rid of what's left in the buffers
            self.feed(b"")
            self.data = self.decoder = None
            if not self.finished:
                raise IOError("image was incomplete")
        if not self.image:
            raise IOError("cannot parse this image")
        if self.data:
            # incremental parsing not possible; reopen the file
            # not that we have all data
            with io.BytesIO(self.data) as fp:
                try:
                    self.image = Image.open(fp)
                finally:
                    self.image.load()
        return self.image


# --------------------------------------------------------------------

def _save(im, fp, tile, bufsize=0):
    """Helper to save image based on tile list

    :param im: Image object.
    :param fp: File object.
    :param tile: Tile list.
    :param bufsize: Optional buffer size
    """

    im.load()
    if not hasattr(im, "encoderconfig"):
        im.encoderconfig = ()
    tile.sort(key=_tilesort)
    # FIXME: make MAXBLOCK a configuration parameter
    # It would be great if we could have the encoder specify what it needs
    # But, it would need at least the image size in most cases. RawEncode is
    # a tricky case.
    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c
    if fp == sys.stdout:
        fp.flush()
        return
    try:
        fh = fp.fileno()
        fp.flush()
    except (AttributeError, io.UnsupportedOperation):
        # compress to Python file-compatible object
        for e, b, o, a in tile:
            e = Image._getencoder(im.mode, e, a, im.encoderconfig)
            if o > 0:
                fp.seek(o, 0)
            e.setimage(im.im, b)
            if e.pushes_fd:
                e.setfd(fp)
                l, s = e.encode_to_pyfd()
            else:
                while True:
                    l, s, d = e.encode(bufsize)
                    fp.write(d)
                    if s:
                        break
            if s < 0:
                raise IOError("encoder error %d when writing image file" % s)
            e.cleanup()
    else:
        # slight speedup: compress to real file object
        for e, b, o, a in tile:
            e = Image._getencoder(im.mode, e, a, im.encoderconfig)
            if o > 0:
                fp.seek(o, 0)
            e.setimage(im.im, b)
            if e.pushes_fd:
                e.setfd(fp)
                l, s = e.encode_to_pyfd()
            else:
                s = e.encode_to_file(fh, bufsize)
            if s < 0:
                raise IOError("encoder error %d when writing image file" % s)
            e.cleanup()
    if hasattr(fp, "flush"):
        fp.flush()


def _safe_read(fp, size):
    """
    Reads large blocks in a safe way.  Unlike fp.read(n), this function
    doesn't trust the user.  If the requested size is larger than
    SAFEBLOCK, the file is read block by block.

    :param fp: File handle.  Must implement a <b>read</b> method.
    :param size: Number of bytes to read.
    :returns: A string containing up to <i>size</i> bytes of data.
    """
    if size <= 0:
        return b""
    if size <= SAFEBLOCK:
        return fp.read(size)
    data = []
    while size > 0:
        block = fp.read(min(size, SAFEBLOCK))
        if not block:
            break
        data.append(block)
        size -= len(block)
    return b"".join(data)


class PyCodecState(object):
    def __init__(self):
        self.xsize = 0
        self.ysize = 0
        self.xoff = 0
        self.yoff = 0

    def extents(self):
        return (self.xoff, self.yoff,
                self.xoff+self.xsize, self.yoff+self.ysize)


class PyDecoder(object):
    """
    Python implementation of a format decoder. Override this class and
    add the decoding logic in the `decode` method.

    See :ref:`Writing Your Own File Decoder in Python<file-decoders-py>`
    """

    _pulls_fd = False

    def __init__(self, mode, *args):
        self.im = None
        self.state = PyCodecState()
        self.fd = None
        self.mode = mode
        self.init(args)

    def init(self, args):
        """
        Override to perform decoder specific initialization

        :param args: Array of args items from the tile entry
        :returns: None
        """
        self.args = args

    @property
    def pulls_fd(self):
        return self._pulls_fd

    def decode(self, buffer):
        """
        Override to perform the decoding process.

        :param buffer: A bytes object with the data to be decoded.  If `handles_eof`
             is set, then `buffer` will be empty and `self.fd` will be set.
        :returns: A tuple of (bytes consumed, errcode). If finished with decoding
             return <0 for the bytes consumed. Err codes are from `ERRORS`
        """
        raise NotImplementedError()

    def cleanup(self):
        """
        Override to perform decoder specific cleanup

        :returns: None
        """
        pass

    def setfd(self, fd):
        """
        Called from ImageFile to set the python file-like object

        :param fd: A python file-like object
        :returns: None
        """
        self.fd = fd

    def setimage(self, im, extents=None):
        """
        Called from ImageFile to set the core output image for the decoder

        :param im: A core image object
        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle
            for this tile
        :returns: None
        """

        # following c code
        self.im = im

        if extents:
            (x0, y0, x1, y1) = extents
        else:
            (x0, y0, x1, y1) = (0, 0, 0, 0)

        if x0 == 0 and x1 == 0:
            self.state.xsize, self.state.ysize = self.im.size
        else:
            self.state.xoff = x0
            self.state.yoff = y0
            self.state.xsize = x1 - x0
            self.state.ysize = y1 - y0

        if self.state.xsize <= 0 or self.state.ysize <= 0:
            raise ValueError("Size cannot be negative")

        if (self.state.xsize + self.state.xoff > self.im.size[0] or
           self.state.ysize + self.state.yoff > self.im.size[1]):
            raise ValueError("Tile cannot extend outside image")

    def set_as_raw(self, data, rawmode=None):
        """
        Convenience method to set the internal image from a stream of raw data

        :param data: Bytes to be set
        :param rawmode: The rawmode to be used for the decoder. If not specified,
             it will default to the mode of the image
        :returns: None
        """

        if not rawmode:
            rawmode = self.mode
        d = Image._getdecoder(self.mode, 'raw', (rawmode))
        d.setimage(self.im, self.state.extents())
        s = d.decode(data)

        if s[0] >= 0:
            raise ValueError("not enough image data")
        if s[1] != 0:
            raise ValueError("cannot decode image data")

```
--- 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:** Missing `get_format_mimetype` Method Causes AttributeError in ImageFile Subclasses

**Description:**
When working with certain image file types, attempting to retrieve the MIME type using the `get_format_mimetype` method results in an `AttributeError`. This issue affects subclasses of `ImageFile`, such as `JpegImageFile` and `PixarImageFile`, preventing proper handling of MIME types.

**Example Code:**
```python
from PIL import Image

# Attempting to get MIME type for a JPEG image
im = Image.open('example.jpg')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'JpegImageFile' object has no attribute 'get_format_mimetype'

# Attempting to get MIME type for a Pixar image
im = Image.open('example.pixar')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'PixarImageFile' object has no attribute 'get_format_mimetype'

# Using a mock image file without a format
class MockImageFile(Image.Image):
    pass

mock_im = MockImageFile()
mime_type = mock_im.get_format_mimetype()
print(mime_type)  # AttributeError: 'MockImageFile' object has no attribute 'get_format_mimetype'
```

**Expected Behavior:**
The `get_format_mimetype` method should be available in all subclasses of `ImageFile`. Calling this method on any image instance should return the correct MIME type based on the image format. For image files without a defined format, the method should return `None`.

**Actual Behavior:**
Calling `get_format_mimetype` on instances of `JpegImageFile`, `PixarImageFile`, or a mock image file without a format raises an `AttributeError`, indicating that the method does not exist. This prevents developers from reliably obtaining MIME types for different image formats and handling images without formats appropriately.

</ISSUE>
{
    "TestFilePixar.test_invalid_file": "PASSED",
    "TestFilePixar.test_sanity": "PASSED",
    "TestFileJpeg.test_MAXBLOCK_scaling": "PASSED",
    "TestFileJpeg.test_app": "PASSED",
    "TestFileJpeg.test_bad_mpo_header": "PASSED",
    "TestFileJpeg.test_cmyk": "PASSED",
    "TestFileJpeg.test_dpi": "PASSED",
    "TestFileJpeg.test_dpi_exif_zero_division": "PASSED",
    "TestFileJpeg.test_dpi_from_dpcm_exif": "PASSED",
    "TestFileJpeg.test_dpi_int_from_exif": "PASSED",
    "TestFileJpeg.test_dpi_tuple_from_exif": "PASSED",
    "TestFileJpeg.test_exif": "PASSED",
    "TestFileJpeg.test_exif_gps": "PASSED",
    "TestFileJpeg.test_exif_gps_typeerror": "PASSED",
    "TestFileJpeg.test_exif_rollback": "PASSED",
    "TestFileJpeg.test_exif_typeerror": "PASSED",
    "TestFileJpeg.test_ff00_jpeg_header": "PASSED",
    "TestFileJpeg.test_icc": "PASSED",
    "TestFileJpeg.test_icc_big": "PASSED",
    "TestFileJpeg.test_invalid_exif": "PASSED",
    "TestFileJpeg.test_junk_jpeg_header": "PASSED",
    "TestFileJpeg.test_large_exif": "PASSED",
    "TestFileJpeg.test_large_icc_meta": "PASSED",
    "TestFileJpeg.test_mp": "PASSED",
    "TestFileJpeg.test_no_dpi_in_exif": "PASSED",
    "TestFileJpeg.test_no_duplicate_0x1001_tag": "PASSED",
    "TestFileJpeg.test_optimize": "PASSED",
    "TestFileJpeg.test_optimize_large_buffer": "PASSED",
    "TestFileJpeg.test_progressive": "PASSED",
    "TestFileJpeg.test_progressive_cmyk_buffer": "PASSED",
    "TestFileJpeg.test_progressive_compat": "PASSED",
    "TestFileJpeg.test_progressive_large_buffer": "PASSED",
    "TestFileJpeg.test_progressive_large_buffer_highest_quality": "PASSED",
    "TestFileJpeg.test_qtables": "PASSED",
    "TestFileJpeg.test_quality": "PASSED",
    "TestFileJpeg.test_quality_keep": "PASSED",
    "TestFileJpeg.test_sanity": "PASSED",
    "TestFileJpeg.test_save_correct_modes": "PASSED",
    "TestFileJpeg.test_save_tiff_with_dpi": "PASSED",
    "TestFileJpeg.test_save_wrong_modes": "PASSED",
    "TestFileJpeg.test_smooth": "PASSED",
    "TestFileJpeg.test_subsampling": "PASSED",
    "TestFileJpeg.test_truncated_jpeg_should_read_all_the_data": "PASSED",
    "TestFileJpeg.test_truncated_jpeg_throws_IOError": "PASSED",
    "TestImageFile.test_broken_datastream_with_errors": "PASSED",
    "TestImageFile.test_broken_datastream_without_errors": "PASSED",
    "TestImageFile.test_ico": "PASSED",
    "TestImageFile.test_parser": "PASSED",
    "TestImageFile.test_raise_ioerror": "PASSED",
    "TestImageFile.test_raise_typeerror": "PASSED",
    "TestImageFile.test_safeblock": "PASSED",
    "TestImageFile.test_truncated_with_errors": "PASSED",
    "TestImageFile.test_truncated_without_errors": "PASSED",
    "TestPyDecoder.test_extents_none": "PASSED",
    "TestPyDecoder.test_negsize": "PASSED",
    "TestPyDecoder.test_no_format": "PASSED",
    "TestPyDecoder.test_oversize": "PASSED",
    "TestPyDecoder.test_setimage": "PASSED"
}
diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py
index 63a9d4ca2..681dee524 100644
--- a/src/PIL/ImageFile.py
+++ b/src/PIL/ImageFile.py
@@ -118,6 +118,11 @@ class ImageFile(Image.Image):
 
         pass
 
+    def get_format_mimetype(self):
+        if self.format is None:
+            return
+        return Image.MIME.get(self.format.upper())
+
     def verify(self):
         "Check file integrity"
 
 

{"src/PIL/ImageFile.py": "#\n# The Python Imaging Library.\n# $Id$\n#\n# base class for image file handlers\n#\n# history:\n# 1995-09-09 fl   Created\n# 1996-03-11 fl   Fixed load mechanism.\n# 1996-04-15 fl   Added pcx/xbm decoders.\n# 1996-04-30 fl   Added encoders.\n# 1996-12-14 fl   Added load helpers\n# 1997-01-11 fl   Use encode_to_file where possible\n# 1997-08-27 fl   Flush output in _save\n# 1998-03-05 fl   Use memory mapping for some modes\n# 1999-02-04 fl   Use memory mapping also for \"I;16\" and \"I;16B\"\n# 1999-05-31 fl   Added image parser\n# 2000-10-12 fl   Set readonly flag on memory-mapped images\n# 2002-03-20 fl   Use better messages for common decoder errors\n# 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available\n# 2003-10-30 fl   Added StubImageFile class\n# 2004-02-25 fl   Made incremental parser more robust\n#\n# Copyright (c) 1997-2004 by Secret Labs AB\n# Copyright (c) 1995-2004 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nfrom . import Image\nfrom ._util import isPath\nimport io\nimport os\nimport sys\nimport struct\n\nMAXBLOCK = 65536\n\nSAFEBLOCK = 1024*1024\n\nLOAD_TRUNCATED_IMAGES = False\n\nERRORS = {\n    -1: \"image buffer overrun error\",\n    -2: \"decoding error\",\n    -3: \"unknown error\",\n    -8: \"bad configuration\",\n    -9: \"out of memory error\"\n}\n\n\ndef raise_ioerror(error):\n    try:\n        message = Image.core.getcodecstatus(error)\n    except AttributeError:\n        message = ERRORS.get(error)\n    if not message:\n        message = \"decoder error %d\" % error\n    raise IOError(message + \" when reading image file\")\n\n\n#\n# --------------------------------------------------------------------\n# Helpers\n\ndef _tilesort(t):\n    # sort on offset\n    return t[2]\n\n\n#\n# --------------------------------------------------------------------\n# ImageFile base class\n\nclass ImageFile(Image.Image):\n    \"Base class for image file format handlers.\"\n\n    def __init__(self, fp=None, filename=None):\n        Image.Image.__init__(self)\n\n        self._min_frame = 0\n\n        self.tile = None\n        self.readonly = 1  # until we know better\n\n        self.decoderconfig = ()\n        self.decodermaxblock = MAXBLOCK\n\n        if isPath(fp):\n            # filename\n            self.fp = open(fp, \"rb\")\n            self.filename = fp\n            self._exclusive_fp = True\n        else:\n            # stream\n            self.fp = fp\n            self.filename = filename\n            # can be overridden\n            self._exclusive_fp = None\n\n        try:\n            self._open()\n        except (IndexError,  # end of data\n                TypeError,  # end of data (ord)\n                KeyError,  # unsupported mode\n                EOFError,  # got header but not the first frame\n                struct.error) as v:\n            # close the file only if we have opened it this constructor\n            if self._exclusive_fp:\n                self.fp.close()\n            raise SyntaxError(v)\n\n        if not self.mode or self.size[0] <= 0:\n            raise SyntaxError(\"not identified by this driver\")\n\n    def draft(self, mode, size):\n        \"Set draft mode\"\n\n        pass\n\n    def verify(self):\n        \"Check file integrity\"\n\n        # raise exception if something's wrong.  must be called\n        # directly after open, and closes file when finished.\n        if self._exclusive_fp:\n            self.fp.close()\n        self.fp = None\n\n    def load(self):\n        \"Load image data based on tile list\"\n\n        pixel = Image.Image.load(self)\n\n        if self.tile is None:\n            raise IOError(\"cannot load this image\")\n        if not self.tile:\n            return pixel\n\n        self.map = None\n        use_mmap = self.filename and len(self.tile) == 1\n        # As of pypy 2.1.0, memory mapping was failing here.\n        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')\n\n        readonly = 0\n\n        # look for read/seek overrides\n        try:\n            read = self.load_read\n            # don't use mmap if there are custom read/seek functions\n            use_mmap = False\n        except AttributeError:\n            read = self.fp.read\n\n        try:\n            seek = self.load_seek\n            use_mmap = False\n        except AttributeError:\n            seek = self.fp.seek\n\n        if use_mmap:\n            # try memory mapping\n            decoder_name, extents, offset, args = self.tile[0]\n            if decoder_name == \"raw\" and len(args) >= 3 and args[0] == self.mode \\\n               and args[0] in Image._MAPMODES:\n                try:\n                    if hasattr(Image.core, \"map\"):\n                        # use built-in mapper  WIN32 only\n                        self.map = Image.core.map(self.filename)\n                        self.map.seek(offset)\n                        self.im = self.map.readimage(\n                            self.mode, self.size, args[1], args[2]\n                            )\n                    else:\n                        # use mmap, if possible\n                        import mmap\n                        with open(self.filename, \"r\") as fp:\n                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)\n                        self.im = Image.core.map_buffer(\n                            self.map, self.size, decoder_name, extents, offset, args\n                            )\n                    readonly = 1\n                    # After trashing self.im, we might need to reload the palette data.\n                    if self.palette:\n                        self.palette.dirty = 1\n                except (AttributeError, EnvironmentError, ImportError):\n                    self.map = None\n\n        self.load_prepare()\n        err_code = -3  # initialize to unknown error\n        if not self.map:\n            # sort tiles in file order\n            self.tile.sort(key=_tilesort)\n\n            try:\n                # FIXME: This is a hack to handle TIFF's JpegTables tag.\n                prefix = self.tile_prefix\n            except AttributeError:\n                prefix = b\"\"\n\n            for decoder_name, extents, offset, args in self.tile:\n                decoder = Image._getdecoder(self.mode, decoder_name,\n                                            args, self.decoderconfig)\n                try:\n                    seek(offset)\n                    decoder.setimage(self.im, extents)\n                    if decoder.pulls_fd:\n                        decoder.setfd(self.fp)\n                        status, err_code = decoder.decode(b\"\")\n                    else:\n                        b = prefix\n                        while True:\n                            try:\n                                s = read(self.decodermaxblock)\n                            except (IndexError, struct.error):  # truncated png/gif\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    raise IOError(\"image file is truncated\")\n\n                            if not s:  # truncated jpeg\n                                if LOAD_TRUNCATED_IMAGES:\n                                    break\n                                else:\n                                    self.tile = []\n                                    raise IOError(\"image file is truncated \"\n                                                  \"(%d bytes not processed)\" % len(b))\n\n                            b = b + s\n                            n, err_code = decoder.decode(b)\n                            if n < 0:\n                                break\n                            b = b[n:]\n                finally:\n                    # Need to cleanup here to prevent leaks\n                    decoder.cleanup()\n\n        self.tile = []\n        self.readonly = readonly\n\n        self.load_end()\n\n        if self._exclusive_fp and self._close_exclusive_fp_after_loading:\n            self.fp.close()\n        self.fp = None\n\n        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:\n            # still raised if decoder fails to return anything\n            raise_ioerror(err_code)\n\n        return Image.Image.load(self)\n\n    def load_prepare(self):\n        # create image memory if necessary\n        if not self.im or\\\n           self.im.mode != self.mode or self.im.size != self.size:\n            self.im = Image.core.new(self.mode, self.size)\n        # create palette (optional)\n        if self.mode == \"P\":\n            Image.Image.load(self)\n\n    def load_end(self):\n        # may be overridden\n        pass\n\n    # may be defined for contained formats\n    # def load_seek(self, pos):\n    #     pass\n\n    # may be defined for blocked formats (e.g. PNG)\n    # def load_read(self, bytes):\n    #     pass\n\n    def _seek_check(self, frame):\n        if (frame < self._min_frame or\n            # Only check upper limit on frames if additional seek operations\n            # are not required to do so\n            (not (hasattr(self, \"_n_frames\") and self._n_frames is None) and\n             frame >= self.n_frames+self._min_frame)):\n            raise EOFError(\"attempt to seek outside sequence\")\n\n        return self.tell() != frame\n\n\nclass StubImageFile(ImageFile):\n    \"\"\"\n    Base class for stub image loaders.\n\n    A stub loader is an image loader that can identify files of a\n    certain format, but relies on external code to load the file.\n    \"\"\"\n\n    def _open(self):\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _open\"\n            )\n\n    def load(self):\n        loader = self._load()\n        if loader is None:\n            raise IOError(\"cannot find loader for this %s file\" % self.format)\n        image = loader.load(self)\n        assert image is not None\n        # become the other object (!)\n        self.__class__ = image.__class__\n        self.__dict__ = image.__dict__\n\n    def _load(self):\n        \"(Hook) Find actual image loader.\"\n        raise NotImplementedError(\n            \"StubImageFile subclass must implement _load\"\n            )\n\n\nclass Parser(object):\n    \"\"\"\n    Incremental image parser.  This class implements the standard\n    feed/close consumer interface.\n    \"\"\"\n    incremental = None\n    image = None\n    data = None\n    decoder = None\n    offset = 0\n    finished = 0\n\n    def reset(self):\n        \"\"\"\n        (Consumer) Reset the parser.  Note that you can only call this\n        method immediately after you've created a parser; parser\n        instances cannot be reused.\n        \"\"\"\n        assert self.data is None, \"cannot reuse parsers\"\n\n    def feed(self, data):\n        \"\"\"\n        (Consumer) Feed data to the parser.\n\n        :param data: A string buffer.\n        :exception IOError: If the parser failed to parse the image file.\n        \"\"\"\n        # collect data\n\n        if self.finished:\n            return\n\n        if self.data is None:\n            self.data = data\n        else:\n            self.data = self.data + data\n\n        # parse what we have\n        if self.decoder:\n\n            if self.offset > 0:\n                # skip header\n                skip = min(len(self.data), self.offset)\n                self.data = self.data[skip:]\n                self.offset = self.offset - skip\n                if self.offset > 0 or not self.data:\n                    return\n\n            n, e = self.decoder.decode(self.data)\n\n            if n < 0:\n                # end of stream\n                self.data = None\n                self.finished = 1\n                if e < 0:\n                    # decoding error\n                    self.image = None\n                    raise_ioerror(e)\n                else:\n                    # end of image\n                    return\n            self.data = self.data[n:]\n\n        elif self.image:\n\n            # if we end up here with no decoder, this file cannot\n            # be incrementally parsed.  wait until we've gotten all\n            # available data\n            pass\n\n        else:\n\n            # attempt to open this file\n            try:\n                with io.BytesIO(self.data) as fp:\n                    im = Image.open(fp)\n            except IOError:\n                # traceback.print_exc()\n                pass  # not enough data\n            else:\n                flag = hasattr(im, \"load_seek\") or hasattr(im, \"load_read\")\n                if flag or len(im.tile) != 1:\n                    # custom load code, or multiple tiles\n                    self.decode = None\n                else:\n                    # initialize decoder\n                    im.load_prepare()\n                    d, e, o, a = im.tile[0]\n                    im.tile = []\n                    self.decoder = Image._getdecoder(\n                        im.mode, d, a, im.decoderconfig\n                        )\n                    self.decoder.setimage(im.im, e)\n\n                    # calculate decoder offset\n                    self.offset = o\n                    if self.offset <= len(self.data):\n                        self.data = self.data[self.offset:]\n                        self.offset = 0\n\n                self.image = im\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n\n    def close(self):\n        \"\"\"\n        (Consumer) Close the stream.\n\n        :returns: An image object.\n        :exception IOError: If the parser failed to parse the image file either\n                            because it cannot be identified or cannot be\n                            decoded.\n        \"\"\"\n        # finish decoding\n        if self.decoder:\n            # get rid of what's left in the buffers\n            self.feed(b\"\")\n            self.data = self.decoder = None\n            if not self.finished:\n                raise IOError(\"image was incomplete\")\n        if not self.image:\n            raise IOError(\"cannot parse this image\")\n        if self.data:\n            # incremental parsing not possible; reopen the file\n            # not that we have all data\n            with io.BytesIO(self.data) as fp:\n                try:\n                    self.image = Image.open(fp)\n                finally:\n                    self.image.load()\n        return self.image\n\n\n# --------------------------------------------------------------------\n\ndef _save(im, fp, tile, bufsize=0):\n    \"\"\"Helper to save image based on tile list\n\n    :param im: Image object.\n    :param fp: File object.\n    :param tile: Tile list.\n    :param bufsize: Optional buffer size\n    \"\"\"\n\n    im.load()\n    if not hasattr(im, \"encoderconfig\"):\n        im.encoderconfig = ()\n    tile.sort(key=_tilesort)\n    # FIXME: make MAXBLOCK a configuration parameter\n    # It would be great if we could have the encoder specify what it needs\n    # But, it would need at least the image size in most cases. RawEncode is\n    # a tricky case.\n    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c\n    if fp == sys.stdout:\n        fp.flush()\n        return\n    try:\n        fh = fp.fileno()\n        fp.flush()\n    except (AttributeError, io.UnsupportedOperation):\n        # compress to Python file-compatible object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                while True:\n                    l, s, d = e.encode(bufsize)\n                    fp.write(d)\n                    if s:\n                        break\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    else:\n        # slight speedup: compress to real file object\n        for e, b, o, a in tile:\n            e = Image._getencoder(im.mode, e, a, im.encoderconfig)\n            if o > 0:\n                fp.seek(o, 0)\n            e.setimage(im.im, b)\n            if e.pushes_fd:\n                e.setfd(fp)\n                l, s = e.encode_to_pyfd()\n            else:\n                s = e.encode_to_file(fh, bufsize)\n            if s < 0:\n                raise IOError(\"encoder error %d when writing image file\" % s)\n            e.cleanup()\n    if hasattr(fp, \"flush\"):\n        fp.flush()\n\n\ndef _safe_read(fp, size):\n    \"\"\"\n    Reads large blocks in a safe way.  Unlike fp.read(n), this function\n    doesn't trust the user.  If the requested size is larger than\n    SAFEBLOCK, the file is read block by block.\n\n    :param fp: File handle.  Must implement a <b>read</b> method.\n    :param size: Number of bytes to read.\n    :returns: A string containing up to <i>size</i> bytes of data.\n    \"\"\"\n    if size <= 0:\n        return b\"\"\n    if size <= SAFEBLOCK:\n        return fp.read(size)\n    data = []\n    while size > 0:\n        block = fp.read(min(size, SAFEBLOCK))\n        if not block:\n            break\n        data.append(block)\n        size -= len(block)\n    return b\"\".join(data)\n\n\nclass PyCodecState(object):\n    def __init__(self):\n        self.xsize = 0\n        self.ysize = 0\n        self.xoff = 0\n        self.yoff = 0\n\n    def extents(self):\n        return (self.xoff, self.yoff,\n                self.xoff+self.xsize, self.yoff+self.ysize)\n\n\nclass PyDecoder(object):\n    \"\"\"\n    Python implementation of a format decoder. Override this class and\n    add the decoding logic in the `decode` method.\n\n    See :ref:`Writing Your Own File Decoder in Python<file-decoders-py>`\n    \"\"\"\n\n    _pulls_fd = False\n\n    def __init__(self, mode, *args):\n        self.im = None\n        self.state = PyCodecState()\n        self.fd = None\n        self.mode = mode\n        self.init(args)\n\n    def init(self, args):\n        \"\"\"\n        Override to perform decoder specific initialization\n\n        :param args: Array of args items from the tile entry\n        :returns: None\n        \"\"\"\n        self.args = args\n\n    @property\n    def pulls_fd(self):\n        return self._pulls_fd\n\n    def decode(self, buffer):\n        \"\"\"\n        Override to perform the decoding process.\n\n        :param buffer: A bytes object with the data to be decoded.  If `handles_eof`\n             is set, then `buffer` will be empty and `self.fd` will be set.\n        :returns: A tuple of (bytes consumed, errcode). If finished with decoding\n             return <0 for the bytes consumed. Err codes are from `ERRORS`\n        \"\"\"\n        raise NotImplementedError()\n\n    def cleanup(self):\n        \"\"\"\n        Override to perform decoder specific cleanup\n\n        :returns: None\n        \"\"\"\n        pass\n\n    def setfd(self, fd):\n        \"\"\"\n        Called from ImageFile to set the python file-like object\n\n        :param fd: A python file-like object\n        :returns: None\n        \"\"\"\n        self.fd = fd\n\n    def setimage(self, im, extents=None):\n        \"\"\"\n        Called from ImageFile to set the core output image for the decoder\n\n        :param im: A core image object\n        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle\n            for this tile\n        :returns: None\n        \"\"\"\n\n        # following c code\n        self.im = im\n\n        if extents:\n            (x0, y0, x1, y1) = extents\n        else:\n            (x0, y0, x1, y1) = (0, 0, 0, 0)\n\n        if x0 == 0 and x1 == 0:\n            self.state.xsize, self.state.ysize = self.im.size\n        else:\n            self.state.xoff = x0\n            self.state.yoff = y0\n            self.state.xsize = x1 - x0\n            self.state.ysize = y1 - y0\n\n        if self.state.xsize <= 0 or self.state.ysize <= 0:\n            raise ValueError(\"Size cannot be negative\")\n\n        if (self.state.xsize + self.state.xoff > self.im.size[0] or\n           self.state.ysize + self.state.yoff > self.im.size[1]):\n            raise ValueError(\"Tile cannot extend outside image\")\n\n    def set_as_raw(self, data, rawmode=None):\n        \"\"\"\n        Convenience method to set the internal image from a stream of raw data\n\n        :param data: Bytes to be set\n        :param rawmode: The rawmode to be used for the decoder. If not specified,\n             it will default to the mode of the image\n        :returns: None\n        \"\"\"\n\n        if not rawmode:\n            rawmode = self.mode\n        d = Image._getdecoder(self.mode, 'raw', (rawmode))\n        d.setimage(self.im, self.state.extents())\n        s = d.decode(data)\n\n        if s[0] >= 0:\n            raise ValueError(\"not enough image data\")\n        if s[1] != 0:\n            raise ValueError(\"cannot decode image data\")\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:** Missing `get_format_mimetype` Method Causes AttributeError in ImageFile Subclasses

**Description:**
When working with certain image file types, attempting to retrieve the MIME type using the `get_format_mimetype` method results in an `AttributeError`. This issue affects subclasses of `ImageFile`, such as `JpegImageFile` and `PixarImageFile`, preventing proper handling of MIME types.

**Example Code:**
```python
from PIL import Image

# Attempting to get MIME type for a JPEG image
im = Image.open('example.jpg')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'JpegImageFile' object has no attribute 'get_format_mimetype'

# Attempting to get MIME type for a Pixar image
im = Image.open('example.pixar')
mime_type = im.get_format_mimetype()
print(mime_type)  # AttributeError: 'PixarImageFile' object has no attribute 'get_format_mimetype'

# Using a mock image file without a format
class MockImageFile(Image.Image):
    pass

mock_im = MockImageFile()
mime_type = mock_im.get_format_mimetype()
print(mime_type)  # AttributeError: 'MockImageFile' object has no attribute 'get_format_mimetype'
```

**Expected Behavior:**
The `get_format_mimetype` method should be available in all subclasses of `ImageFile`. Calling this method on any image instance should return the correct MIME type based on the image format. For image files without a defined format, the method should return `None`.

**Actual Behavior:**
Calling `get_format_mimetype` on instances of `JpegImageFile`, `PixarImageFile`, or a mock image file without a format raises an `AttributeError`, indicating that the method does not exist. This prevents developers from reliably obtaining MIME types for different image formats and handling images without formats appropriately.

</ISSUE>
--- END ISSUE ---

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

--- BEGIN FILE ---
```
### src/PIL/ImageFile.py
#
# The Python Imaging Library.
# $Id$
#
# base class for image file handlers
#
# history:
# 1995-09-09 fl   Created
# 1996-03-11 fl   Fixed load mechanism.
# 1996-04-15 fl   Added pcx/xbm decoders.
# 1996-04-30 fl   Added encoders.
# 1996-12-14 fl   Added load helpers
# 1997-01-11 fl   Use encode_to_file where possible
# 1997-08-27 fl   Flush output in _save
# 1998-03-05 fl   Use memory mapping for some modes
# 1999-02-04 fl   Use memory mapping also for "I;16" and "I;16B"
# 1999-05-31 fl   Added image parser
# 2000-10-12 fl   Set readonly flag on memory-mapped images
# 2002-03-20 fl   Use better messages for common decoder errors
# 2003-04-21 fl   Fall back on mmap/map_buffer if map is not available
# 2003-10-30 fl   Added StubImageFile class
# 2004-02-25 fl   Made incremental parser more robust
#
# Copyright (c) 1997-2004 by Secret Labs AB
# Copyright (c) 1995-2004 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

from . import Image
from ._util import isPath
import io
import os
import sys
import struct

MAXBLOCK = 65536

SAFEBLOCK = 1024*1024

LOAD_TRUNCATED_IMAGES = False

ERRORS = {
    -1: "image buffer overrun error",
    -2: "decoding error",
    -3: "unknown error",
    -8: "bad configuration",
    -9: "out of memory error"
}


def raise_ioerror(error):
    try:
        message = Image.core.getcodecstatus(error)
    except AttributeError:
        message = ERRORS.get(error)
    if not message:
        message = "decoder error %d" % error
    raise IOError(message + " when reading image file")


#
# --------------------------------------------------------------------
# Helpers

def _tilesort(t):
    # sort on offset
    return t[2]


#
# --------------------------------------------------------------------
# ImageFile base class

class ImageFile(Image.Image):
    "Base class for image file format handlers."

    def __init__(self, fp=None, filename=None):
        Image.Image.__init__(self)

        self._min_frame = 0

        self.tile = None
        self.readonly = 1  # until we know better

        self.decoderconfig = ()
        self.decodermaxblock = MAXBLOCK

        if isPath(fp):
            # filename
            self.fp = open(fp, "rb")
            self.filename = fp
            self._exclusive_fp = True
        else:
            # stream
            self.fp = fp
            self.filename = filename
            # can be overridden
            self._exclusive_fp = None

        try:
            self._open()
        except (IndexError,  # end of data
                TypeError,  # end of data (ord)
                KeyError,  # unsupported mode
                EOFError,  # got header but not the first frame
                struct.error) as v:
            # close the file only if we have opened it this constructor
            if self._exclusive_fp:
                self.fp.close()
            raise SyntaxError(v)

        if not self.mode or self.size[0] <= 0:
            raise SyntaxError("not identified by this driver")

    def draft(self, mode, size):
        "Set draft mode"

        pass

    def verify(self):
        "Check file integrity"

        # raise exception if something's wrong.  must be called
        # directly after open, and closes file when finished.
        if self._exclusive_fp:
            self.fp.close()
        self.fp = None

    def load(self):
        "Load image data based on tile list"

        pixel = Image.Image.load(self)

        if self.tile is None:
            raise IOError("cannot load this image")
        if not self.tile:
            return pixel

        self.map = None
        use_mmap = self.filename and len(self.tile) == 1
        # As of pypy 2.1.0, memory mapping was failing here.
        use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')

        readonly = 0

        # look for read/seek overrides
        try:
            read = self.load_read
            # don't use mmap if there are custom read/seek functions
            use_mmap = False
        except AttributeError:
            read = self.fp.read

        try:
            seek = self.load_seek
            use_mmap = False
        except AttributeError:
            seek = self.fp.seek

        if use_mmap:
            # try memory mapping
            decoder_name, extents, offset, args = self.tile[0]
            if decoder_name == "raw" and len(args) >= 3 and args[0] == self.mode \
               and args[0] in Image._MAPMODES:
                try:
                    if hasattr(Image.core, "map"):
                        # use built-in mapper  WIN32 only
                        self.map = Image.core.map(self.filename)
                        self.map.seek(offset)
                        self.im = self.map.readimage(
                            self.mode, self.size, args[1], args[2]
                            )
                    else:
                        # use mmap, if possible
                        import mmap
                        with open(self.filename, "r") as fp:
                            self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)
                        self.im = Image.core.map_buffer(
                            self.map, self.size, decoder_name, extents, offset, args
                            )
                    readonly = 1
                    # After trashing self.im, we might need to reload the palette data.
                    if self.palette:
                        self.palette.dirty = 1
                except (AttributeError, EnvironmentError, ImportError):
                    self.map = None

        self.load_prepare()
        err_code = -3  # initialize to unknown error
        if not self.map:
            # sort tiles in file order
            self.tile.sort(key=_tilesort)

            try:
                # FIXME: This is a hack to handle TIFF's JpegTables tag.
                prefix = self.tile_prefix
            except AttributeError:
                prefix = b""

            for decoder_name, extents, offset, args in self.tile:
                decoder = Image._getdecoder(self.mode, decoder_name,
                                            args, self.decoderconfig)
                try:
                    seek(offset)
                    decoder.setimage(self.im, extents)
                    if decoder.pulls_fd:
                        decoder.setfd(self.fp)
                        status, err_code = decoder.decode(b"")
                    else:
                        b = prefix
                        while True:
                            try:
                                s = read(self.decodermaxblock)
                            except (IndexError, struct.error):  # truncated png/gif
                                if LOAD_TRUNCATED_IMAGES:
                                    break
                                else:
                                    raise IOError("image file is truncated")

                            if not s:  # truncated jpeg
                                if LOAD_TRUNCATED_IMAGES:
                                    break
                                else:
                                    self.tile = []
                                    raise IOError("image file is truncated "
                                                  "(%d bytes not processed)" % len(b))

                            b = b + s
                            n, err_code = decoder.decode(b)
                            if n < 0:
                                break
                            b = b[n:]
                finally:
                    # Need to cleanup here to prevent leaks
                    decoder.cleanup()

        self.tile = []
        self.readonly = readonly

        self.load_end()

        if self._exclusive_fp and self._close_exclusive_fp_after_loading:
            self.fp.close()
        self.fp = None

        if not self.map and not LOAD_TRUNCATED_IMAGES and err_code < 0:
            # still raised if decoder fails to return anything
            raise_ioerror(err_code)

        return Image.Image.load(self)

    def load_prepare(self):
        # create image memory if necessary
        if not self.im or\
           self.im.mode != self.mode or self.im.size != self.size:
            self.im = Image.core.new(self.mode, self.size)
        # create palette (optional)
        if self.mode == "P":
            Image.Image.load(self)

    def load_end(self):
        # may be overridden
        pass

    # may be defined for contained formats
    # def load_seek(self, pos):
    #     pass

    # may be defined for blocked formats (e.g. PNG)
    # def load_read(self, bytes):
    #     pass

    def _seek_check(self, frame):
        if (frame < self._min_frame or
            # Only check upper limit on frames if additional seek operations
            # are not required to do so
            (not (hasattr(self, "_n_frames") and self._n_frames is None) and
             frame >= self.n_frames+self._min_frame)):
            raise EOFError("attempt to seek outside sequence")

        return self.tell() != frame


class StubImageFile(ImageFile):
    """
    Base class for stub image loaders.

    A stub loader is an image loader that can identify files of a
    certain format, but relies on external code to load the file.
    """

    def _open(self):
        raise NotImplementedError(
            "StubImageFile subclass must implement _open"
            )

    def load(self):
        loader = self._load()
        if loader is None:
            raise IOError("cannot find loader for this %s file" % self.format)
        image = loader.load(self)
        assert image is not None
        # become the other object (!)
        self.__class__ = image.__class__
        self.__dict__ = image.__dict__

    def _load(self):
        "(Hook) Find actual image loader."
        raise NotImplementedError(
            "StubImageFile subclass must implement _load"
            )


class Parser(object):
    """
    Incremental image parser.  This class implements the standard
    feed/close consumer interface.
    """
    incremental = None
    image = None
    data = None
    decoder = None
    offset = 0
    finished = 0

    def reset(self):
        """
        (Consumer) Reset the parser.  Note that you can only call this
        method immediately after you've created a parser; parser
        instances cannot be reused.
        """
        assert self.data is None, "cannot reuse parsers"

    def feed(self, data):
        """
        (Consumer) Feed data to the parser.

        :param data: A string buffer.
        :exception IOError: If the parser failed to parse the image file.
        """
        # collect data

        if self.finished:
            return

        if self.data is None:
            self.data = data
        else:
            self.data = self.data + data

        # parse what we have
        if self.decoder:

            if self.offset > 0:
                # skip header
                skip = min(len(self.data), self.offset)
                self.data = self.data[skip:]
                self.offset = self.offset - skip
                if self.offset > 0 or not self.data:
                    return

            n, e = self.decoder.decode(self.data)

            if n < 0:
                # end of stream
                self.data = None
                self.finished = 1
                if e < 0:
                    # decoding error
                    self.image = None
                    raise_ioerror(e)
                else:
                    # end of image
                    return
            self.data = self.data[n:]

        elif self.image:

            # if we end up here with no decoder, this file cannot
            # be incrementally parsed.  wait until we've gotten all
            # available data
            pass

        else:

            # attempt to open this file
            try:
                with io.BytesIO(self.data) as fp:
                    im = Image.open(fp)
            except IOError:
                # traceback.print_exc()
                pass  # not enough data
            else:
                flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
                if flag or len(im.tile) != 1:
                    # custom load code, or multiple tiles
                    self.decode = None
                else:
                    # initialize decoder
                    im.load_prepare()
                    d, e, o, a = im.tile[0]
                    im.tile = []
                    self.decoder = Image._getdecoder(
                        im.mode, d, a, im.decoderconfig
                        )
                    self.decoder.setimage(im.im, e)

                    # calculate decoder offset
                    self.offset = o
                    if self.offset <= len(self.data):
                        self.data = self.data[self.offset:]
                        self.offset = 0

                self.image = im

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def close(self):
        """
        (Consumer) Close the stream.

        :returns: An image object.
        :exception IOError: If the parser failed to parse the image file either
                            because it cannot be identified or cannot be
                            decoded.
        """
        # finish decoding
        if self.decoder:
            # get rid of what's left in the buffers
            self.feed(b"")
            self.data = self.decoder = None
            if not self.finished:
                raise IOError("image was incomplete")
        if not self.image:
            raise IOError("cannot parse this image")
        if self.data:
            # incremental parsing not possible; reopen the file
            # not that we have all data
            with io.BytesIO(self.data) as fp:
                try:
                    self.image = Image.open(fp)
                finally:
                    self.image.load()
        return self.image


# --------------------------------------------------------------------

def _save(im, fp, tile, bufsize=0):
    """Helper to save image based on tile list

    :param im: Image object.
    :param fp: File object.
    :param tile: Tile list.
    :param bufsize: Optional buffer size
    """

    im.load()
    if not hasattr(im, "encoderconfig"):
        im.encoderconfig = ()
    tile.sort(key=_tilesort)
    # FIXME: make MAXBLOCK a configuration parameter
    # It would be great if we could have the encoder specify what it needs
    # But, it would need at least the image size in most cases. RawEncode is
    # a tricky case.
    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c
    if fp == sys.stdout:
        fp.flush()
        return
    try:
        fh = fp.fileno()
        fp.flush()
    except (AttributeError, io.UnsupportedOperation):
        # compress to Python file-compatible object
        for e, b, o, a in tile:
            e = Image._getencoder(im.mode, e, a, im.encoderconfig)
            if o > 0:
                fp.seek(o, 0)
            e.setimage(im.im, b)
            if e.pushes_fd:
                e.setfd(fp)
                l, s = e.encode_to_pyfd()
            else:
                while True:
                    l, s, d = e.encode(bufsize)
                    fp.write(d)
                    if s:
                        break
            if s < 0:
                raise IOError("encoder error %d when writing image file" % s)
            e.cleanup()
    else:
        # slight speedup: compress to real file object
        for e, b, o, a in tile:
            e = Image._getencoder(im.mode, e, a, im.encoderconfig)
            if o > 0:
                fp.seek(o, 0)
            e.setimage(im.im, b)
            if e.pushes_fd:
                e.setfd(fp)
                l, s = e.encode_to_pyfd()
            else:
                s = e.encode_to_file(fh, bufsize)
            if s < 0:
                raise IOError("encoder error %d when writing image file" % s)
            e.cleanup()
    if hasattr(fp, "flush"):
        fp.flush()


def _safe_read(fp, size):
    """
    Reads large blocks in a safe way.  Unlike fp.read(n), this function
    doesn't trust the user.  If the requested size is larger than
    SAFEBLOCK, the file is read block by block.

    :param fp: File handle.  Must implement a <b>read</b> method.
    :param size: Number of bytes to read.
    :returns: A string containing up to <i>size</i> bytes of data.
    """
    if size <= 0:
        return b""
    if size <= SAFEBLOCK:
        return fp.read(size)
    data = []
    while size > 0:
        block = fp.read(min(size, SAFEBLOCK))
        if not block:
            break
        data.append(block)
        size -= len(block)
    return b"".join(data)


class PyCodecState(object):
    def __init__(self):
        self.xsize = 0
        self.ysize = 0
        self.xoff = 0
        self.yoff = 0

    def extents(self):
        return (self.xoff, self.yoff,
                self.xoff+self.xsize, self.yoff+self.ysize)


class PyDecoder(object):
    """
    Python implementation of a format decoder. Override this class and
    add the decoding logic in the `decode` method.

    See :ref:`Writing Your Own File Decoder in Python<file-decoders-py>`
    """

    _pulls_fd = False

    def __init__(self, mode, *args):
        self.im = None
        self.state = PyCodecState()
        self.fd = None
        self.mode = mode
        self.init(args)

    def init(self, args):
        """
        Override to perform decoder specific initialization

        :param args: Array of args items from the tile entry
        :returns: None
        """
        self.args = args

    @property
    def pulls_fd(self):
        return self._pulls_fd

    def decode(self, buffer):
        """
        Override to perform the decoding process.

        :param buffer: A bytes object with the data to be decoded.  If `handles_eof`
             is set, then `buffer` will be empty and `self.fd` will be set.
        :returns: A tuple of (bytes consumed, errcode). If finished with decoding
             return <0 for the bytes consumed. Err codes are from `ERRORS`
        """
        raise NotImplementedError()

    def cleanup(self):
        """
        Override to perform decoder specific cleanup

        :returns: None
        """
        pass

    def setfd(self, fd):
        """
        Called from ImageFile to set the python file-like object

        :param fd: A python file-like object
        :returns: None
        """
        self.fd = fd

    def setimage(self, im, extents=None):
        """
        Called from ImageFile to set the core output image for the decoder

        :param im: A core image object
        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle
            for this tile
        :returns: None
        """

        # following c code
        self.im = im

        if extents:
            (x0, y0, x1, y1) = extents
        else:
            (x0, y0, x1, y1) = (0, 0, 0, 0)

        if x0 == 0 and x1 == 0:
            self.state.xsize, self.state.ysize = self.im.size
        else:
            self.state.xoff = x0
            self.state.yoff = y0
            self.state.xsize = x1 - x0
            self.state.ysize = y1 - y0

        if self.state.xsize <= 0 or self.state.ysize <= 0:
            raise ValueError("Size cannot be negative")

        if (self.state.xsize + self.state.xoff > self.im.size[0] or
           self.state.ysize + self.state.yoff > self.im.size[1]):
            raise ValueError("Tile cannot extend outside image")

    def set_as_raw(self, data, rawmode=None):
        """
        Convenience method to set the internal image from a stream of raw data

        :param data: Bytes to be set
        :param rawmode: The rawmode to be used for the decoder. If not specified,
             it will default to the mode of the image
        :returns: None
        """

        if not rawmode:
            rawmode = self.mode
        d = Image._getdecoder(self.mode, 'raw', (rawmode))
        d.setimage(self.im, self.state.extents())
        s = d.decode(data)

        if s[0] >= 0:
            raise ValueError("not enough image data")
        if s[1] != 0:
            raise ValueError("cannot decode image data")

```
--- 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