From f1045107d9daff0fa24480fe21eeb856abe85384 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 9 Sep 2026 05:57:20 +1000 Subject: [PATCH] Show JPEGs the way up their Exif Orientation tag says A photo off a phone is nearly always stored the way the sensor read it, with an Exif Orientation tag saying which way round that is. Browsers have honoured that tag by default since image-orientation: from-image became the initial value, so an image that sits the right way up on the page it was copied from arrives in a PDF on its side, or mirrored. Turn useImageExifOrientation on and processJpg() reads the tag, and when it says anything other than "as stored", rotates and mirrors the samples through GD before the rest of the pipeline sees them. Doing it there rather than at the drawing sites means the intrinsic width and height come back off the corrected image, so layout, background sizing, and every place that scales an image get the right numbers without knowing anything about Exif. The setting is off by default. Correcting an image costs a decode and a re-encode of it, and a document laid out around the samples as stored should not move under an upgrade. The quality of that re-encode is imageJpegQuality, which the WebP and AVIF conversions now read as well - they were already re-encoding at GD's implicit default, and 75 is that default, so their output is unchanged to the pixel. Raising it is the obvious temptation and it is a real change: at 85 those two conversions grow about a quarter, which moves the four snapshots that carry a WebP. 85 is the knee on a real photo, worth about 7 dB for 6% more bytes, and the setting is there for anyone who wants it. The snapshot asks for 95 because its fixtures are four saturated flat colours meeting at hard edges, which is the one thing chroma subsampling handles badly at any quality below 90. It is there to show which way up the samples are, not what JPEG does to a colour boundary. The Exif is read out of the marker segments jpgSegments() indexes, and the TIFF IFD behind them is parsed directly, in both byte orders, rather than through ext-exif, which is not a dependency and cannot read from a string. Anything malformed reads as orientation 1 and the image is passed through untouched. Only images that carry an orientation to correct are re-encoded; everything else, including every JPEG that has no Exif at all, comes through byte for byte as before. CMYK images are left alone because GD reads their samples without their colour space. An ICC profile is copied across to the re-encoded file, since the samples are still in the space it describes. The snapshot renders all eight orientations at a fixed width and no height, so a sample that was not corrected is drawn twice as tall as its neighbours rather than half as tall. A half turn is both flips. imagerotate() allocates a second image the size of the first and copies every pixel into it; imageflip() works in place. Orientation 3 is the common one - a photo taken upside down - and it costs no allocation at all, leaving only the quarter turns of 5 to 8 needing a copy. The transforms table still says 180 degrees, because that is what CIPA DC-008 Figure 11 says orientation 3 means and the table is checked against the figure; which GD call gets there is the executor's business. On a 4000x3000 JPEG this takes peak RSS from 139 MB to 92 MB, and the encoded bytes are identical. GD writes a JFIF segment of its own in place of the one it read, so the density is read off the original before the re-encode and handed back through imageresolution(), and the re-encoded segment carries it too; without that a corrected image came out at GD's 96 dpi whatever the original said, and drew three times too large at 300. The decode goes through imageFromString(), budgeted at a second image for a quarter turn and none for a flip, so a header claiming more than memory_limit leaves the image as stored, and an orientation that could not be applied for any reason is logged. imageJpegQuality is clamped to the -1..100 imagejpeg() accepts, because PHP 8 refuses anything else with a ValueError the @ does not suppress, which would leave the output buffer open; the buffer is closed in a finally as well. A greyscale JPEG comes back RGB, since GD cannot write one component. Documented on the setting and locked in by a test. Co-authored-by: Claude Opus 5 (1M context) Co-Authored-By: Claude Fable 5.1 --- src/Config/ConfigVariables.php | 8 + src/Image/ImageProcessor.php | 270 ++++++++++++++++- src/Mpdf.php | 2 + tests/Mpdf/Image/ExifOrientationTest.php | 277 ++++++++++++++++++ .../Snapshots/ExifOrientationSnapshotTest.php | 84 ++++++ tests/data/img/exif-orientation-1.jpg | Bin 0 -> 1173 bytes tests/data/img/exif-orientation-2.jpg | Bin 0 -> 1171 bytes tests/data/img/exif-orientation-3.jpg | Bin 0 -> 1182 bytes tests/data/img/exif-orientation-4.jpg | Bin 0 -> 1181 bytes tests/data/img/exif-orientation-5.jpg | Bin 0 -> 1192 bytes tests/data/img/exif-orientation-6-gray.jpg | Bin 0 -> 337 bytes tests/data/img/exif-orientation-6-icc.jpg | Bin 0 -> 1345 bytes tests/data/img/exif-orientation-6.jpg | Bin 0 -> 1195 bytes tests/data/img/exif-orientation-7.jpg | Bin 0 -> 1193 bytes tests/data/img/exif-orientation-8.jpg | Bin 0 -> 1194 bytes tests/data/img/exif-orientation-none.jpg | Bin 0 -> 1137 bytes tests/data/snapshots/exif-orientation.pdf | Bin 0 -> 59176 bytes 17 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 tests/Mpdf/Image/ExifOrientationTest.php create mode 100644 tests/Snapshots/ExifOrientationSnapshotTest.php create mode 100644 tests/data/img/exif-orientation-1.jpg create mode 100644 tests/data/img/exif-orientation-2.jpg create mode 100644 tests/data/img/exif-orientation-3.jpg create mode 100644 tests/data/img/exif-orientation-4.jpg create mode 100644 tests/data/img/exif-orientation-5.jpg create mode 100644 tests/data/img/exif-orientation-6-gray.jpg create mode 100644 tests/data/img/exif-orientation-6-icc.jpg create mode 100644 tests/data/img/exif-orientation-6.jpg create mode 100644 tests/data/img/exif-orientation-7.jpg create mode 100644 tests/data/img/exif-orientation-8.jpg create mode 100644 tests/data/img/exif-orientation-none.jpg create mode 100644 tests/data/snapshots/exif-orientation.pdf diff --git a/src/Config/ConfigVariables.php b/src/Config/ConfigVariables.php index 0113ee996..b7d2ce514 100644 --- a/src/Config/ConfigVariables.php +++ b/src/Config/ConfigVariables.php @@ -295,6 +295,14 @@ public function __construct() // Default dpi to output images if size not defined // See also above "dpi" 'img_dpi' => 96, + // Rotate and mirror JPEGs to match their Exif Orientation tag, the way browsers do + // Off by default: it costs a GD re-encode of each image that carries an orientation to correct, + // and GD writes RGB, so a greyscale JPEG that needed correcting is embedded with three channels + 'useImageExifOrientation' => false, + // Quality GD writes a JPEG at when it has to re-encode one: correcting an Exif orientation, + // or converting a WebP or AVIF. 75 is GD's own default, so raising it grows every existing + // document that carries one of those; 85 is the knee if you would rather have the quality + 'imageJpegQuality' => 75, // Specify whitelisted PHP streams to be used for images // Useful to add custom streams like `s3` // Note: for security reasons the `phar` stream cannot be used @see https://github.com/mpdf/mpdf/issues/949 diff --git a/src/Image/ImageProcessor.php b/src/Image/ImageProcessor.php index 6c92f265d..c27d12b88 100644 --- a/src/Image/ImageProcessor.php +++ b/src/Image/ImageProcessor.php @@ -527,6 +527,16 @@ private function jpgDensity($data) return 0; } + /** + * The quality to hand imagejpeg(), clamped to the -1 to 100 PHP 8 insists on with an exception @ does not catch + * + * @return int + */ + private function jpegQuality() + { + return max(-1, min(100, (int) $this->mpdf->imageJpegQuality)); + } + /** * Decode an image with GD, unless its header says the result would not fit memory_limit * @@ -633,6 +643,239 @@ private function jpgSegments($data) } } + /** + * Read the Orientation tag out of a JPEG's Exif APP1 segment + * + * The segment is CIPA DC-008 (Exif 2.32) 4.7.2: the APP1 marker and size, the "Exif\0\0" identifier, + * then a TIFF header every offset inside is relative to. + * + * @param string $data + * + * @return int 1 to 8, 1 being the identity that images without an orientation are shown at + */ + private function jpgExifOrientation($data) + { + foreach ($this->jpgSegments($data) as $segment) { + + // A segment shorter than its own header cannot hold a TIFF structure, whatever it starts with + if ($segment['marker'] !== 0xE1 || $segment['size'] < 8 || substr($data, $segment['payload'], 6) !== "Exif\0\0") { // APP1 + continue; + } + + return $this->exifOrientationFromTiff(substr($data, $segment['payload'] + 6, $segment['size'] - 8)); + } + + return 1; + } + + /** + * Read the Orientation tag out of the TIFF structure an Exif segment wraps + * + * Orientation is tag 274 (0x0112) of type SHORT, CIPA DC-008 4.6.4 Table 4. The IFD around it is + * TIFF Rev. 6.0: a byte order mark, the number 42, an offset to IFD0, then a count of 12-byte entries. + * + * @param string $tiff Starting at the byte order mark, which every offset inside is relative to + * + * @return int + */ + private function exifOrientationFromTiff($tiff) + { + $length = strlen($tiff); + + if ($length < 8) { + return 1; + } + + $byteOrder = substr($tiff, 0, 2); + + if ($byteOrder !== 'II' && $byteOrder !== 'MM') { + return 1; + } + + $bigEndian = $byteOrder === 'MM'; + + if ($this->tiffValue(substr($tiff, 2, 2), $bigEndian) !== 42) { + return 1; + } + + $ifd = $this->tiffValue(substr($tiff, 4, 4), $bigEndian); + + if ($ifd < 8 || $ifd + 2 > $length) { + return 1; + } + + $entries = $this->tiffValue(substr($tiff, $ifd, 2), $bigEndian); + + for ($i = 0; $i < $entries; $i++) { + + $entry = $ifd + 2 + ($i * 12); + + if ($entry + 12 > $length) { + break; + } + + if ($this->tiffValue(substr($tiff, $entry, 2), $bigEndian) !== 0x0112) { // Orientation + continue; + } + + if ($this->tiffValue(substr($tiff, $entry + 2, 2), $bigEndian) !== 3) { // SHORT, TIFF Rev. 6.0 type 3 + break; + } + + // A SHORT is left-justified in the four bytes the entry gives its value, either byte order + $orientation = $this->tiffValue(substr($tiff, $entry + 8, 2), $bigEndian); + + return $orientation >= 1 && $orientation <= 8 ? $orientation : 1; + } + + return 1; + } + + /** + * Read a 2- or 4-byte TIFF integer of either byte order + * + * The bounds checks in exifOrientationFromTiff() are what guarantee a whole 2 or 4 bytes to read + * + * @param string $bytes + * @param bool $bigEndian + * + * @return int + */ + private function tiffValue($bytes, $bigEndian) + { + if (!$bigEndian) { + $bytes = strrev($bytes); + } + + return strlen($bytes) === 4 ? $this->fourBytesToInt($bytes) : $this->twoBytesToInt($bytes); + } + + /** + * Re-encode a JPEG so its samples sit the way its Exif Orientation tag says they should be shown + * + * Orientation records where row 0 and column 0 of the stored samples belong on screen, which comes to + * a rotation, a mirror, or one of each. The eight cases are drawn in CIPA DC-008 Figure 11. + * + * GD writes a JFIF segment of its own in place of the one it read, so the density has to be handed back + * to it, or the re-encoded image would come out at GD's default of 96 whatever the original said. + * + * @param string $data + * @param int $orientation + * @param int $dpi 0 where the image has none + * + * @return string|null Null when the image is already the right way up, or GD cannot read or rewrite it, + * leaving the caller its original data + */ + private function applyJpgExifOrientation($data, $orientation, $dpi) + { + // The rotation and mirror each orientation needs; one missing from the table is already the right way up + $transforms = [ + 2 => [0, IMG_FLIP_HORIZONTAL], + 3 => [180, 0], + 4 => [0, IMG_FLIP_VERTICAL], + 5 => [270, IMG_FLIP_HORIZONTAL], + 6 => [270, 0], + 7 => [90, IMG_FLIP_HORIZONTAL], + 8 => [90, 0], + ]; + + if (!isset($transforms[$orientation])) { + return null; + } + + list($rotation, $mirror) = $transforms[$orientation]; + + // A quarter turn is a second image the size of the first; a flip is done in place + $image = $this->imageFromString($data, $rotation === 90 || $rotation === 270 ? 2 : 1); + + if (!$image) { + return null; + } + + if ($rotation === 180) { + + // A half turn is both flips, which imageflip() does in place where imagerotate() would copy the image + if (!@imageflip($image, IMG_FLIP_BOTH)) { + $this->destroyImage($image); + return null; + } + + } elseif ($rotation) { + + $rotated = @imagerotate($image, $rotation, 0); + $this->destroyImage($image); + + if (!$rotated) { + return null; + } + + $image = $rotated; + } + + if ($mirror && !@imageflip($image, $mirror)) { + $this->destroyImage($image); + return null; + } + + if ($dpi > 0 && function_exists('imageresolution')) { // PHP 7.2 + @imageresolution($image, $dpi, $dpi); + } + + ob_start(); + + try { + $written = @imagejpeg($image, null, $this->jpegQuality()); + } finally { + $rotatedData = ob_get_clean(); + $this->destroyImage($image); + $image = null; // destroyImage() does nothing on PHP 8+, and the pixels are dead from here + } + + if (!$written || !$rotatedData) { + return null; + } + + return $this->copyJpgIccProfile($data, $rotatedData); + } + + /** + * Carry an ICC profile over to a re-encoded JPEG + * + * GD keeps the samples but drops every application segment, and the samples are still in whatever + * space the profile describes, so the profile has to travel with them. The APP2 chunks the profile is + * split into are ICC Technical Note 10-21. + * + * @param string $source + * @param string $target + * + * @return string + */ + private function copyJpgIccProfile($source, $target) + { + $profile = ''; + + foreach ($this->jpgSegments($source) as $segment) { + if ($segment['marker'] === 0xE2 && substr($source, $segment['payload'], 12) === "ICC_PROFILE\0") { // APP2 + $profile .= substr($source, $segment['offset'], 2 + $segment['size']); + } + } + + if ($profile === '') { + return $target; + } + + // An APP2 segment is legal anywhere before the frame, but JFIF wants its own APP0 to come + // first, and that is what GD writes + $p = 2; + + foreach ($this->jpgSegments($target) as $first) { + $p = $first['marker'] === 0xE0 ? $first['offset'] + 2 + $first['size'] : 2; + break; + } + + return substr_replace($target, $profile, $p, 0); + } + /** * Corrects 2-byte integer to 8-bit depth value * If original image is bpc != 8, tRNS will be in this bpc @@ -723,7 +966,30 @@ public function processJpg($data, $file, $firstTime, $interpolation) } $a = $this->jpgDataFromHeader($hdr); - $ppUx = $this->jpgDensity($data); + $ppUx = $this->jpgDensity($data); // Read before any re-encode, which replaces the segment it lives in + + // GD reads the samples but not the colour space, so a CMYK image would come back inverted. It also + // decodes everything else to RGB, so a greyscale image comes back with three channels + if ($this->mpdf->useImageExifOrientation && $a[2] !== 'DeviceCMYK') { + + $orientation = $this->jpgExifOrientation($data); + $rotated = $this->applyJpgExifOrientation($data, $orientation, $ppUx); + + if ($rotated !== null) { + + $data = $rotated; + $hdr = $this->jpgHeaderFromString($data); + + if (!$hdr) { + return $this->imageError($file, $firstTime, 'Error parsing JPG header after applying Exif orientation'); + } + + $a = $this->jpgDataFromHeader($hdr); + + } elseif ($orientation !== 1) { + $this->logger->warning(sprintf('Exif orientation %d not applied, image embedded as stored (%s)', $orientation, $file), ['context' => LogContext::IMAGES]); + } + } $channels = (int) $a[4]; @@ -1447,7 +1713,7 @@ private function jpgViaGd($data, $file, $firstTime, $writer, $format) return $this->imageError($file, $firstTime, sprintf('Error creating temporary file "%s" when using GD library to parse %s image', $checkfile, $format)); } - @imagejpeg($im, $tempfile); + @imagejpeg($im, $tempfile, $this->jpegQuality()); $data = file_get_contents($tempfile); $this->destroyImage($im); unlink($tempfile); diff --git a/src/Mpdf.php b/src/Mpdf.php index 4cd9b55e1..21bfa3fcf 100644 --- a/src/Mpdf.php +++ b/src/Mpdf.php @@ -190,6 +190,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface var $allow_html_optional_endtags; var $img_dpi; + var $useImageExifOrientation; + var $imageJpegQuality; var $whitelistStreamWrappers; var $defaultheaderfontsize; diff --git a/tests/Mpdf/Image/ExifOrientationTest.php b/tests/Mpdf/Image/ExifOrientationTest.php new file mode 100644 index 000000000..a24dd4af9 --- /dev/null +++ b/tests/Mpdf/Image/ExifOrientationTest.php @@ -0,0 +1,277 @@ + true]; + + private $mpdf; + + protected function tear_down() + { + parent::tear_down(); + + if ($this->mpdf) { + $this->mpdf->cleanup(); + $this->mpdf = null; + } + } + + public function orientationProvider() + { + return [[1], [2], [3], [4], [5], [6], [7], [8]]; + } + + /** + * Each fixture holds the same picture stored a different way up, tagged with the orientation that + * says so. Half are little-endian Exif and half big-endian, so the set proves both are read. + * + * @dataProvider orientationProvider + */ + public function testEveryOrientationIsShownTheSameWayUp($orientation) + { + $image = $this->render($this->fixture('exif-orientation-' . $orientation . '.jpg'), self::$on); + + $this->assertSame(40, $image['w'], 'Corrected width'); + $this->assertSame(20, $image['h'], 'Corrected height'); + $this->assertCorners(self::$canonical, $image['data']); + } + + public function testAnImageWithNoExifAtAllIsPassedThroughUntouched() + { + $file = $this->fixture('exif-orientation-none.jpg'); + $image = $this->render($file, self::$on); + + $this->assertSame(file_get_contents($file), $image['data']); + } + + public function testAnImageAlreadyTheRightWayUpIsNotReEncoded() + { + $file = $this->fixture('exif-orientation-1.jpg'); + $image = $this->render($file, self::$on); + + $this->assertSame(file_get_contents($file), $image['data']); + } + + public function testAnImageIsUsedAsStoredUntilTheSettingIsTurnedOn() + { + $file = $this->fixture('exif-orientation-6.jpg'); + $image = $this->render($file); + + $this->assertSame(20, $image['w']); + $this->assertSame(40, $image['h']); + $this->assertSame(file_get_contents($file), $image['data']); + } + + public function testAColourProfileSurvivesTheRotation() + { + $image = $this->render($this->fixture('exif-orientation-6-icc.jpg'), self::$on); + + $this->assertSame(40, $image['w']); + $this->assertNotFalse($image['icc']); + $this->assertSame('acsp', substr($image['icc'], 36, 4)); + $this->assertSame(132, strlen($image['icc'])); + } + + public function testTheReEncodeHonoursTheConfiguredJpegQuality() + { + $file = $this->fixture('exif-orientation-6.jpg'); + + $low = $this->render($file, self::$on + ['imageJpegQuality' => 20]); + $high = $this->render($file, self::$on + ['imageJpegQuality' => 100]); + + $this->assertLessThan(strlen($high['data']), strlen($low['data'])); + } + + public function reEncodePathProvider() + { + return [ + 'a quarter turn, which GD does into a copy' => [6], + 'a half turn, which GD does in place' => [3], + ]; + } + + /** + * GD writes a JFIF segment of its own, at its default of 96 dpi, in place of the one it read + * + * @dataProvider reEncodePathProvider + */ + public function testTheDensityOfTheOriginalSurvivesTheReEncode($orientation) + { + $data = $this->withJfifDensity(file_get_contents($this->fixture('exif-orientation-' . $orientation . '.jpg')), 300); + $image = $this->renderData($data, self::$on); + + $this->assertSame(40, $image['w'], 'Corrected'); + $this->assertSame(300, $image['set-dpi'], 'Density read off the original'); + + if (function_exists('imageresolution')) { // PHP 7.2 + $this->assertSame(300, $this->jfifDensity($image['data']), 'Density written into the re-encoded segment'); + } + } + + /** + * GD decodes everything but CMYK to RGB and cannot write a one-component JPEG, so this is the one + * way a corrected image differs from its original beyond the correction: it grows to three channels + */ + public function testAGreyscaleImageIsCorrectedAndComesBackWithThreeChannels() + { + $file = $this->fixture('exif-orientation-6-gray.jpg'); + + $asStored = $this->render($file); + $corrected = $this->render($file, self::$on); + + $this->assertSame('DeviceGray', $asStored['cs']); + $this->assertSame(1, $asStored['ch']); + + $this->assertSame(40, $corrected['w']); + $this->assertSame(20, $corrected['h']); + $this->assertSame('DeviceRGB', $corrected['cs']); + $this->assertSame(3, $corrected['ch']); + } + + /** + * PHP 8 refuses a quality outside -1 to 100 with an exception, not a warning, where PHP 7 let libgd + * clamp it. Clamping first keeps the two the same, and keeps the output buffer the re-encode is + * written into from being left open + */ + public function testAQualityOutsideGdsRangeIsClampedRatherThanRefused() + { + $file = $this->fixture('exif-orientation-6.jpg'); + $level = ob_get_level(); + + $over = $this->render($file, self::$on + ['imageJpegQuality' => 150]); + $under = $this->render($file, self::$on + ['imageJpegQuality' => -5]); + + $this->assertSame(40, $over['w']); + $this->assertSame(40, $under['w']); + $this->assertLessThan(strlen($over['data']), strlen($under['data']), '150 is written at 100, and -5 at GD\'s default'); + $this->assertSame($level, ob_get_level()); + } + + /** + * The dimensions GD would allocate for come off the frame header, so a few bytes can claim an image + * that takes gigabytes to decode. One that would not fit is left the way it is stored + */ + public function testAnImageTooBigForMemoryLimitIsLeftAsStored() + { + $data = $this->withFrameDimensions(file_get_contents($this->fixture('exif-orientation-6.jpg')), 60000, 60000); + + $limit = ini_get('memory_limit'); + ini_set('memory_limit', '1G'); // Well above what the suite uses, well below the 14 GB a copy of the image would take + + try { + $image = $this->renderData($data, self::$on); + } finally { + ini_set('memory_limit', $limit); + } + + $this->assertSame(60000, $image['w'], 'Read as stored'); + $this->assertSame($data, $image['data']); + } + + /** + * The samples in this fixture are stored portrait, and the orientation tag is what makes it landscape + */ + public function testTheBoxTheImageIsDrawnInTurnsWithIt() + { + $corrected = $this->drawnBox(self::$on); + $asStored = $this->drawnBox(); + + $this->assertGreaterThan($corrected[1], $corrected[0], 'Drawn landscape once the orientation is read'); + $this->assertGreaterThan($asStored[0], $asStored[1], 'Drawn portrait when it is not'); + } + + /** + * The width and height, in points, of the box the image is scaled into + */ + private function drawnBox(array $config = []) + { + $this->mpdf = new Mpdf($config + ['mode' => 'c']); + $this->mpdf->compress = false; + $this->mpdf->WriteHTML(''); + + $pdf = $this->mpdf->Output('', 'S'); + + $this->assertSame(1, preg_match('/q ([\d.]+) 0 0 ([\d.]+) [\d.]+ [\d.]+ cm \/I\d+ Do Q/', $pdf, $m)); + + return [(float) $m[1], (float) $m[2]]; + } + + private function fixture($name) + { + return __DIR__ . '/../../data/img/' . $name; + } + + private function render($file, array $config = []) + { + $this->mpdf = new Mpdf($config + ['mode' => 'c']); + $this->mpdf->WriteHTML(''); + + return reset($this->mpdf->images); + } + + private function renderData($data, array $config = []) + { + return $this->render('data:image/jpeg;base64,' . base64_encode($data), $config); + } + + /** + * Put a JFIF segment (ITU-T T.871 6.3) giving this density ahead of any the image carries, which is + * where mPDF reads the first one it finds + */ + private function withJfifDensity($data, $dpi) + { + $app0 = "JFIF\0" . "\x01\x01" . "\x01" . pack('n', $dpi) . pack('n', $dpi) . "\x00\x00"; // Version 1.1, units 1 (dpi), no thumbnail + + return $this->afterSoi($data, "\xFF\xE0" . pack('n', strlen($app0) + 2) . $app0); + } + + /** + * The density, in dots per inch, of the first JFIF segment in a JPEG + */ + private function jfifDensity($data) + { + $this->assertSame(1, preg_match('/\xFF\xE0..JFIF\0..(.)(..)/s', $data, $m), 'Has a JFIF segment'); + $this->assertSame(1, ord($m[1]), 'In dots per inch'); + + return unpack('n', $m[2])[1]; + } + + /** + * Read the four quadrants of a JPEG, clockwise from the top left + */ + private function assertCorners(array $expected, $data) + { + $image = imagecreatefromstring($data); + $width = imagesx($image); + $height = imagesy($image); + + $points = [[0.25, 0.25], [0.75, 0.25], [0.75, 0.75], [0.25, 0.75]]; + + foreach ($points as $i => $point) { + + $rgb = imagecolorsforindex($image, imagecolorat($image, (int) ($width * $point[0]), (int) ($height * $point[1]))); + $actual = [$rgb['red'], $rgb['green'], $rgb['blue']]; + + foreach ($expected[$i] as $channel => $value) { + // JPEG is lossy, and 95 leaves ringing well inside a quadrant that is a solid colour + $this->assertEqualsWithDelta($value, $actual[$channel], 32, sprintf('Quadrant %d, channel %d, got %s', $i, $channel, implode(',', $actual))); + } + } + } + +} diff --git a/tests/Snapshots/ExifOrientationSnapshotTest.php b/tests/Snapshots/ExifOrientationSnapshotTest.php new file mode 100644 index 000000000..0f1feae09 --- /dev/null +++ b/tests/Snapshots/ExifOrientationSnapshotTest.php @@ -0,0 +1,84 @@ +mpdf and + * loading it with content + * + * @return void + * @internal Don't call any $this->mpdf->Output*() method + */ + public function generatePdf() + { + $rows = [[1, 2], [3, 4], [5, 6], [7, 8]]; + + ob_start(); + ?> + + +

mPDF

+

Exif Orientation

+ +

Every sample below holds the same picture, stored a different way up, with the Exif + Orientation tag that says which. With useImageExifOrientation on, all + eight have to be drawn the same way up as each other and as the browser draws them: twice as + wide as they are tall, red top left, green top right, blue bottom right, yellow bottom left.

+ +

The box each is drawn in has to turn with it. Every sample is given a width of 40mm and no + height, so the height comes off the corrected image, and a sample that was not corrected would + be drawn twice as tall as the others rather than half as tall.

+ + + + + + + + + + +
+ +

An image with no Exif at all

+

Nothing to correct, so it is embedded exactly as it was stored.

+ + + + + + +
none
+ mpdf = new \Mpdf\Mpdf(['useImageExifOrientation' => true, 'imageJpegQuality' => 95]); + $this->mpdf->SetBasePath(__DIR__ . '/../data'); + + $this->mpdf->WriteHTML($html); + } +} diff --git a/tests/data/img/exif-orientation-1.jpg b/tests/data/img/exif-orientation-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..52e660a09ded26d9e458735862bbc10ed30a1ed0 GIT binary patch literal 1173 zcmbV}e^69a6vxloxBK=7m@eXvXqsJE2>b=EV*Z-iR#=wZW+KU2aV9rFT$X7R)I~RA zUx2@;VG{g7N)1t#+Ds9xm^2N~1rp3gB~id77bumODPfh}_h8?SxreS16Dd zQb5H2g<*nO{=afw1o zNT*W%lc0;BltCmU;FuCbN(@(Gs2x;1xn#=TpA7&^go`DFl(!MaCp69C?c+FaTEaW# zvrG7Q5Gy4S(ONw*dwsSvrYLe*X;r;Uv#!xIC$nobc6rW@GPz>zy!nqu#XS|DuwY^G zilME)sSXPH<@4B@bW8`jai#=x8!ZL<=YE(?s63G-s60ueBb^92M<-eU47)} zvEw!GojCc?$EQB|^z@mtpMB*%*L42t3(eoOwzYqEsiX7q_dnj~zIm&sx9|4g(9gfz zy?1~3*O4**!$;$RAk9n&To~ZfSiDY8_8(k)6EKl51F67;iFOO%O0gtbOGN0`OS6k+ z$1E$AMXsx=Z}iAD%QHvk9q*7s>xgg?w;}w5L}_^hRI5*$<5_on>>Ty_foH=jI6AGPKA@L4Bdbr z#lod~5VTv^C&~6|c0M(%M^LlT$Juqa-lc0FoXTJyL*Vzy5&STSAng7S#m=xY8Yu#$ zF=R^WdWYMmVjPtS?j1%@(K3;W;Q9juOTMfNU3FEG9(Xp2jt?{<*x$sLBQS72?jq;m zE+a5i_jEo)aPCbX9mo%E^XE?XUAm(^Qs<8koTZCAb;gEq9T&~b8?nC1T@P@qxu5G8 z*?ff^ayXqOpJ$XG58WC6?Fnb|0mlh8&Pfhwx+f5HCykeAQu-$M?zINoMnVWSWnbhiYwsec{Uh literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-2.jpg b/tests/data/img/exif-orientation-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6546b72768a6d2f8a775bccd90b5cb88812775f0 GIT binary patch literal 1171 zcmbV}e^69a6vxlox9`1WL2+4d&8FGM3bJZ}AO_0B6Nw*-GnIf^G4TY!6)5>7C?dQO zOQD&j!5@*1j*(hfjSQKPW^D?DTY-wk52;{TS(VIj7X+4N-|aq}sek&TI(N=@?wxz? zneXRZ)Qc>ji`$X28Ngsz3<>}sz=t5Q0?2Smfd*ktQoJD^2!eo(cmWb2DmFPTCiTVS zm8>!AncRYGBU>68yp+|K6z6O;vWBDtHtD6f1hzDC>7u9E!jg>FbGDVS&#^0(D^Wkh zf(-W}2uWp9$Vo{lxtx^K6iv@0uBrK}^A|3+w6=ZUe#QJl*NvM$clY%6-Lec>Zx7q< z+`TtqcZ`lb8lRYSPDxw@kdLvj{v#J20wI(BfRVTe*>;?yN>2HQ(mpY3nT$fUE^N2L zcXe%j<0X#;%aR}ZWfomm&J75+1llFE8M1!|R`tKg{sQ}(>lS#C1pYiy1svEfh#Ib= z;DgygR?T#a>5pd7oIY+q5E9Lw7R{Ar&iOfl2geY6eMg;c7tIt@-aycD(X?q`DnRQj z$kk5Q@|StLI&wg)Lf|+SBCbNfAQ*aW*OLh9jpF)N!7+$nUs+|lX)KX*4Bq6Nx_2jQ zj^-nX5u7j7Az-!k;BRLkxONu7l1$E7==>1@gt< z)4*L3I~^wL@X7w>&I1puQRh2pu7~eSv$WF{{z8xUWc57$jC+lX>n(qzca-O!aq$yn zT{hczsu-PD2D1)`X&IdJC}-ITiCU7cLxV8sDaHDCuOKXo9NIX9E6oTO;0W zhKpI(DX1i-17+`oxXBP>K$vqr*h4pm!dyqOJT?eWptP6vp8al3wtx1=wsUj7`901( z`F_q1@8S?dW>gmK2FS{a0~r8NprUA^05nM<@HYs~&dkaLilX2Z@&WR&F+DdUZL2_Ab8QInOe(`4sl=rrZ)*2F%cF_q=LT6C~Vld4&ttiVA? z2NCH-QG$wu5YvK6#9~@3l}M%jWaKg_BWI*iS%6Hg5Q3}%0~CS6MriWzSCNFKB??B$ z_)Gqi;AK$CAQWO~N(mw*MJp-10%|e?iQk?u1bS}c(=#6|!qXb&d#X_}ap5XYqY zb#f14r9`zXAx#>xC69?Tg|4l!G|Qqko$Cq9y*0f&F@OIdxnjv9kA^?CVr6tpY+O?E zlPT-gZ%BVOBUATWR`v^9x4pQ1$4fg43U}=`?kOrhaImbrqOz*G_RYg}Z`B`p`@Lhw z8yZiXJk`{4=4|T+AAa=lC!c?DzWvLN3!N8xzq<1E)o-p{zj6D=pYHtJfA`+NkbU@p zV`Ow}{P!8>?A*L-!R_G$E(+*}SVaGkiwuDh32(p%T$HGSB&`%nmL*74XNjOY^xNc~oNVbXflWTZ$#ilZIBz2xxw?e+PExf06wK_BYo61kx0FJX#4_@IBKu z{TW}c0PiV;+7@=C4&j$?5iT?#RBQ8Bd;4t**$BT{+~%X!SsKB_E`)m$4O40E`W$A$ z?0qW5)r-*5jnK$j5w6W6M5t#1-BEmv*4b*{H+v2I%Ezzjxo`wWgccz-$X!`Fc^Dys zMTqy26U!Jvy|G6(l&wtLoC;#T^K}@dyD3J9!&_ zd9lK!=aS01bXFIe!lyQ-4qiIRyG$KN3rD&1F^^pv?pxY@zT2+0ceT#j3MPFw$~t}K zc9&r)_|uy=CyQT;=ondO+cW4>arA>uLMNASGQm2}tXJ*5h; rzmdT9ZR7{piH4~{t8>=DStm|R93w5i=f`b}U8dwI^~Ae54Bq<_9m(Qr literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-4.jpg b/tests/data/img/exif-orientation-4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c5a3e33e956abec740cbb4c9024fd9e983675465 GIT binary patch literal 1181 zcmbV}ZA?>F7{{O6+xE5vqD8QC`_O`Kg>BBFh{{|+2DSYlv(uqlHpI7znjuuET}EzN zhMixY@z!wQjqnZ7<- zyHcjx_VTX1+jX)M#iGSBd9gnKeVt6LQOPuKWU6E(%NHlSBr7b=+mpY~C|f04kt{-Y zApu(g@F^k1=L;ePLJ?bd6&WFlWPjL8o*m`zNRlU_ z_*8i0KMDF4!~%!`IZ23tBPK{Ofi8m-XTS^FV?ziR!6CUkK80;W-~sDQY@Z~tX&!cr zr%UlZaK*gnI7K>t*19|@zAz@qbfiHrclEiBSZ(jbyd_(T%tFy@$#Zj_pTA(CJRxyu z^0JiWD^_N_o|&auqt?8+e#2Wi8#leZb=&qGx}EvE^!tiS4Ev2AlzmiwprZ2Np`+C` zAAeGN?D&aK8=F4+yt(D{nbx+it?jn+7cO>oUB2?&_dopj(~Vzl{(7tL_8o`w_df<* zL&GDZ58O{YlT%Npy*@w7MF9B>3+q2};SdN8`vw%tMQ{wbNimlfr{G7YucPt`XT>L( z1Tm|RG@R=Y&RwFNh}}}uE1ErTsdK)YMGKStJ23PABKr&MZ!QN!k_3J{QVdF9^p@!f z=1Vy_RTqjXL2$x_pr||K`ht-JZMmK_1pPS(jLl;MQ3!rE1UnJ@R`D>IHV=<=q)D$+ zjJ%*+I+=)Ia1sIYE`2fAotmq@=a(XIeHDS=c-8m}Z;iCk78EL<3`-DPBM^vQaH@hL zyKj{efkefu?Ym(JRUq)~HX|6?jNo9pKb7vOMzE-mW_n6_0U@Jt+a8@nAk1duQM&_V zfPSQO+#BibH-=P>S1n%Ore$NEroj2@<9buo(Bmd)C8L`x4_!l0X*%S8eDjj+>~uo! z;M0Mt4g}wH)~2MiHoHCV)b?9lw8u8;KI*E^vP|hiaaWWrrS!x4jkh)go6q_!t(d*| zg0a+^T~=FHH*l%3;FR6zw6{xwu^88enL{ee5CZRk55)-5>U~-Zf(7(RyIb*I65Z2{ zK<>m~Yv`^nde1BV7xB7a6rZe8F&VE35S+?pPUC#5XLyfU<|s#W2x|7??I!OTyFvNj vzMO3LrXo;C16vWa^_AfSuG;HI=)-nvTWDu@pasFW>28jhKHQKdMR)!LaU$eb literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-5.jpg b/tests/data/img/exif-orientation-5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..baa2cc18f939df1863c339fa098355ef1eb3463f GIT binary patch literal 1192 zcmbV}e^69a6vxlox4Un5p@C&V(`MWi)PRw2Q4BG9!SW+0BT>Z4nQaZ(a7w`il#E_r zC^pk5pkX@H0LrhLAtYKTh7E-jn2|9_P;3xfepkx)nq#UinIX;V^(n37UrvBX6pmGOZyR~MNpf8d8KUloW*QY53q z)KbfT67&8*KojS@p-7_e+uuS3;QQzj3aC>Im=KV+Vq_Pz&pI)_k{f1|K{rtBC zZ+$*wTc{>7Dmv!n*tlK06Za(TedEn{k`JWl-%UMe$jHn(dMx{c6QAUtJXLV|)1u;Y z=RYsG@WsXQipy6jtEy{iuQq(w_`R{I`G;%Q+dF=~akI1Qmpi?`-tFtZcYkR3k$Gfv zY?p@ST({UEv*+ zEAfmdEURym`fN^^@!Egnwrs_^Eko-qJlYc3zXQwrUu1uQ{mpeBTuB0d9w`SJ?5(DA zJ+_&J?nga~=W~*{erCMjG0QnT5Ok@Nm9}66HBH5f8i$tYiX3BX0SKxu7|zyBRxEtu zm^F>;LvV#03p_*5CR(*l9fES7I-7I+6$HK=XPF0mT;*`Q#cd)7fuEuj!2=^#uDcas zsy#E>Fdb;$WwNRn^H&J;+F1i@MDQ8{rJb_c784t|>Yl}$2yCY(5j@2_{8%}2_eJSd zI|6*vv$?EklxeTx-08;bHIbja&l&%)O#Nn_a-Mjm{#FoE(-OkgYAu2LR^`tiVB;Or zz0C+1w(R$8wlQ{?&bRuvw6yjW+lx$rTT4c?RB4LR64YE8FJJhm%<5zs1_zw9&g&!> zQ2oSkd<`>nqvTS_TZXVfd;S1dSByZ7O@H|H6g_OzT3rxmo>*nuCDW`jvK(h-WF^HMiGMRS+; NgjKe>v)`h7e*$x(@QMHc literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-6-gray.jpg b/tests/data/img/exif-orientation-6-gray.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a6c207496ddda4e3c1754a3ce25d50074cbbefa GIT binary patch literal 337 zcmex=)5uU7^fS&p<(=v^X;_UBT1KUBN5B)m@>?!a!3;p|CVD zC$pqd!B)Z2fb0Kl24@ClCMFO90u~@*>6&2;-7ncwdkq{CQ75RUFft!OtgF%FmQIO&P5e8A9L2lZpg@HTG;si76S)Jk3B@`GN@)N9 literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-6-icc.jpg b/tests/data/img/exif-orientation-6-icc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c47ac6809b10b46d2fe89e09234e64a75755ab35 GIT binary patch literal 1345 zcmb`EZBSHI7{{Nxci&-VS(cZq8M*QnFxHAl3F6#=b)h8_+(gNyXz^vkX$V*Ww}#my z3CNiU!BR*W5GeUV2C`zc8v-U4IVK2*2Fv?P#jXNN3*6JWYg2ycLp42j&VSCi&vVZF zf6s&Zkp+B}N74=gs8k^!1ONiu2@)#+A1^l02$ZW7ij+ikLab`L5(qYV%$fQ_)NwIX z@=JTENB?Q|=`tQY|KEEw3~uqUs#t7?fY9|b3~+Kn=&@;IaU0N zyOMVA!E@cW|G+`*>uHB{hqH5XkLcfe_gKMug+;~hpC~Io`O(LxPFK{NtF5d5^t1B~ zUos>1)5Bm@5ZA-kC@Wx3vD95Ftyb)HS4C> z%YTz4z{a9E$^IEw{(mC-6YMXpJK#zZczC1~Xs}&oyy}N_ed6GQ?t0>&GiT_A#ju?FIFrm7Tay<<}W3-sMRe9^7V$Uvr7tQ z#K)1*+Bh~RqsNS$2=3CW;pFNzMgOu~2nuk8dXCv)SoCBH z45@}&H`*D|FoI5h1T#$tzRyKqSlejrV_Xm*a6L0zDSyYu+Eq1(pnt7)8NZk8F(3i%%$yAiW}W0IiHtXW%n6i2Fv<;&iX8wU#aWv z{<#%F;S;*7*>tT{e>(+%d++HU>u4n=O*Aemzb0=ApT2`N}!3Xau?xM`bbHLD$(=YIop9Wequs3nRo#16^?g4g3xgTJ(wl literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-6.jpg b/tests/data/img/exif-orientation-6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9b80e591699ceae7a167392dc96a46b67b1a27c8 GIT binary patch literal 1195 zcmbV}e@t6d6vxl&YhQmrQcC&ZG#MSg1TyUyLkDAdfesLq{lKx|j3T(LvKRz9VAYW4 zP%OAaWNf;D8-W2j{=o^OV`?h{=9uC#2P=$CD8GNGv>UWo%DdiI5>5O|JvaB8dvne` z`F_qtgUAg2@yD_c1Ei!t7yyWXAUuJ@Cjuy}IM66~Bqt;#;0yt;;RT3=ZK~Ax*uA?_ zqZR6dPaVlUq*fG$KfOs2QlQDsQ7e*?6BWt3;}aEyTQ`MnROA(8zL|YgtJtoHij<&X zPyrA3A_z`-T<}Rw1$;iqrvwz`+Cs625{iWsC2|vqC0yW>yPL$FyKqg`p7I1FDUb*$ zp{wLS3HlCXA_xI5l8^yUMvyWBb%P&97r5*ZE_^HmkK_v|A-3U$3od(L`y`1?3$SCH zEyj7^%LJYq!ec4$TcjiYh?f6!b2c<+#d)zE`nFYfy?-U4dIk$>>goep4@-) zagkSCW!_>#XBqiw!|lJi#f>3p}ENZ9azc#BKr&MZ?1dbP7?U@NEy&zy~_I1 zeVWAuRy>Iy_#Lx!rHq-qHf5~(<^=>NM|=_FB3SH~F3D%+alu;~5nMsws7$w2FRN@_ z)*R#4QftiWHUuSFruY1^iXHQFZB$E+x8r*D|(IYVdg14H46L8FgRla89MilLVg$lW^6WO&df>BZur zTD#v6J6tu`f8KA|_)246->)4AbWdpV=X2B+?cEFno&#t5E#ozqbhmyb{##v}&6-|o zepRnjwokBu9Ua;>W7q=(W%bP5bp(%s8GE~7oDDgFAkEHZ8J&Sz#=4H46CwyhV2_wQ zz|!Ac_*i$Ig%s41tr=|;P=VJ99`{)nSo N7bRhv>FQf(=uaxM>WcsX literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-7.jpg b/tests/data/img/exif-orientation-7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a2fe3df65351cb2d0afd8c798a90eef7623e2d67 GIT binary patch literal 1193 zcmbV}eNa?Y7{=ebclX}ig&A2Ep=646kyyc$1u-@4h6D&{i;G1$lZ0OzjEIOJ+dy|f z4bdEj5Y!xDND~bw!jI6jS(G)D7I#R#q{+bCGDc}x7uaR@-qX1-Q#1Wly=Trd=bZO^ zJiqs#el!H?grcl10IOF+1OP~ZApC*EBLZlwIM5*Yr6eXN;tT=r;Rc9@m*e#bacgz@ zr7FXw7qho-HmC}<^P^Ong8Zy)232xOk}4%NAxTxZIBM=ZRbD~n)~uaI)pFI6SULI; z;z5M(A_zf6LWoI0C1NotrX&m&CSCc-7tM@15nl*nm{ zp4#%C1hs-f3K|F?2?dB01gRj98A33+WXc{fg^z_0kzxr&V;eqr!zDj#pCqwq33iOL zB{&aag~WfhHjYxR$)weJ0nw$E_0rH4&DUq@yXtFMZu|`N}sp+RQhu-;KA0Bl)b&icsxZINh7Xjon7S?I9e{kU<5F+6ZXn~6m?GnHhV##bRc67-D=PVow8x_!|$o?Hz+5aN@3+!*M0q`XW{CT7T7~o!Q zvY+GkF1CX@)?uppSvS7tbjF^s1a!5OD6u<0tJ zWU?Y%s}O9RVbQrXx!&5K0|-V!5S;d8^UZcEzw+a7&Wzyh1?GFxsdR7cDl0$84lh^U zY#gzg?|6811%k$41eRk6?ho)@1pCzpdP)!+Z9*Um84mI$>L&4n9VX7=I8>3*V(`Wu zI@t6fgW$$FzLo#kf#5+JcV)aO^wz-~Q?FYw^3%f+&+g#nJJD>-vZTpZSo61ewUKQI zo-Fv1d%bFcZ|{HV$=+^eeFl1Lw()Cq=4!X`qA9{-Ir3-*0%c@P+Gq&3ak9Mc58gV) zrQrdJ~kpKe}4V8cXKRu(@-AUeHB4f9k;hQX*`@;=4A$J8@zfQ-^h5| z*@;nm4%@5smX!qCgZbpdY6Lk5oW<2VaEnZ~@O%Uwyw*KW%ik~YV{Ol!*LiRey069c z^*PRRn&R?|u~fFx=*(@+b%)JL=UNbSInrIEa{$5N6INX3bOfniwR?=tIJ{DLn;9`6 P(2vp?866GIdUWqk4!`c) literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-8.jpg b/tests/data/img/exif-orientation-8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e2824c86df33d8009c29754fede3847729271eb7 GIT binary patch literal 1194 zcmbV}drVVz6vxl)ZSO6GAO#flA1V)d%^`0UwZRHV4J$7Jmn^J2hnYjHMPSNR89H1R z0?sKq?HFU|wxn@_jD@W{oDTK}(TRdE5C>A&loq6=5AJWj3(1!3uWjd--^n>S=Xdh` z{0GlVal~C0jNJydo)9E8i|WQYP6U*%~22!yp45 zo<$Ix=W)g-IWOSzNj@c@sO3vL2r1furYNDK&_To*j+`7tPF%tbS$WD6kfcCFQ}lAn ze{!f3#6s`~cajhTPfU6}yL?tZfi_@4C^oI^~|hCoKE$DF@LSkG1R8`)>5}4+sp8h>Y5@ zb(?H=Y+U@F1bJ%OzVwXD{jcZb=H(Z>Rd_&kL|t;Uw5+`Hy{gk^-mgAeckZL}A78jw zf9bQv&zrtzzIOe~Z*I1<-fH`{{k!g-+dtm9`%`b<{a+poJbW}b^mzQ~ZxfTxru5S@ z#<}^I3nufT#maFJK(1h6ze4s8F8m1ukJ|ywaS^~F5e;6xI5d88PmU{`6)2K(36 zs3%eOx(|ccVFY?hke#p|Wcps4LSPO;a4j=uslzHk&=;MnF^3_zURtTuPNrIuEY7-_ zPZ3<2*N>eTo0ErYZAAzgC$t87x)nh{vhSdF(dtK(^KakbmtY* zvKj4S)iA3)had!Z9{b8hvO#JDX{*>g#=f4Z)EOxRGtqbwW0v*p^sVS-485a~-!Bpf z92GXkM*fVTy3OP{bPU1Hh;{_~rh40ouC&d5^1OdtC!1;XoTd@DIo>JNx=3$UG%buO zM&2zt*!xFe&nkOX-rmcXhg1lhBcDw^9O<78&1$}D- zT&ZUKczRoK@U02fr@g(bMHkqOpb861^;+k-vuUrG@qng*6~#x?fZwF+A`g64eY0<%YJ*O}CM O-0y>oUp3VlH1sDB2I#K< literal 0 HcmV?d00001 diff --git a/tests/data/img/exif-orientation-none.jpg b/tests/data/img/exif-orientation-none.jpg new file mode 100644 index 0000000000000000000000000000000000000000..33f0d18c9d6ae8ba6d968c45e311f4555dbadd2b GIT binary patch literal 1137 zcmbV}e^69a6vxloxBK4ig6S&$h^E;G3xTQND(0`LZCzm5btaOm6=!k-qy?r?P#4>b zeF6T68YaOXq~s7~sm&D8ib>P(Tp+=0R1yVTa)DBbnG#mneGhiu?LBB}roXCl=bX8B z?m1_^pL0+z8h}~mR8uNo7zVEh2M`Zy4H+r=jp-R{DBIR01%+{Xuw6?W>cd?`M()T}J@4j)fr?>Cc;Ly*%+_`&i_}7s!--Cza{s7BOh+G)p(^x{B z2Kxt>Fa%5@?tm1zFv)Jgag|gSr6p$TH;`FHbE21($|KfQ)i=5on&lazbF+7JDd)u` z4aSa%Xj5eW4y^2dk^KesH`gr)$1!1fxC(T@wlIgU21euYbL?6KTJ>ZO0#{G@2?Up! zx?#GKX>##-S0_&+_`TF)DWfavpH<^@E5|kISIyZg5!^k9prU0W8Ns#t z2$pRNd400KwTey{tbku+5h<*>~}_ z_E4QK&VPn2a@QFf#&vuYKYzsfGJnm_hs^za$Hrag89Ni#z?=)iI3 YPXpdy2i>0->U6p+Y=W~t0z-X&06g8@U;qFB literal 0 HcmV?d00001 diff --git a/tests/data/snapshots/exif-orientation.pdf b/tests/data/snapshots/exif-orientation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..08217300f179c9b7e6531df6c998b362c8fdecdf GIT binary patch literal 59176 zcmeFZbyQu=w&05e4eq{ig1c_q-QC??f=loK!7W&D3-0dj5)#}!xcl4W`}&@9&$+L= zZ;v-d|MOt1y~^gSS+#0bOJ+{MpaKoGXSHa zk%bvN=+oKE-W9+Ms#S((lruB6G7@(10O&A*3fQ^X8CbZO09@&Q^AR zRWmR#ftvjJ{P$+cW-bnH&L(Cq0G7Y>N;o^XIRbz{z~6oUm1k4|<(-Y}T^!$xF!2O1 zihxQ)&D^a_%#aP9MQRo=BP~Zf7Hh$g9H5k;X;0u%&);4@LUk|)5XILw)&+h&r-y+Kwr756DtHQSp z_|u=ozEv9{EL<`2k-rWyYUM^3wJBFSP=DzP8X%d@x~Pw?md?YcBtN`g;m!4yaJ3B~ z(ME;-=+DEscC5MruU_wKd=F3F)EZU$iI$Ql=~uosHl-bONOj;5#1&(A znFL)5ZZc*+3sXV9%sSWw`u9;xRIJ{vlccIfdKGDpJ>u9t)DL4!LtitP9lI=ebwZ4; zS9@6XmLwvbx1q<9p8`4+Qd>fPemmXkZWj{RdhX`2`;^-2m zn{e@Y3DKh6+NU1Z4Tkud*3}vkocZJc#d6L)*lQsAxWPTj_3BsCQk$?G+jq1IwnF|M zZ|XiKTAL^hO=z1Z{d>uibDi5by*cEoBqITj5*^$XnI^y9cuu{+?ZfH$VEgiT)hcWJ zxqhVbicb(7G$SyTX^9o@W0G5(d@+whd83XY;7+RHkcN0|6I$N8Lb4as-0UV5AWHX)R&Fz zFCd&EhlXo6)dO4WYnJEkozUsqCSlErOD;FDoNO3S8pCy6lwG#Pb9%i9H)X(rY) zrxa}_KkJN@w~8(cJL}0#Ou=@(Hl+!woVaox(eC50uP9Rm1cm*ETA5-@5Und9#5rhz z-4fMTfM%^pq8nMPfq>J{GX@`sXv;!LNS!p6e!^R*fdDUp$ZP?7YZfjwX2DG17j3Hr ze)`U)g{F@y?kBo2+NIVQ?~@n%X`ZelwILi;0Lr$Rz6ugMO9}(+_%k)Jyb`Q5?zWQH zNz%4|B6<-uRKfd;V$xe_YXBDXYd^AP#a;b%p-NNhzjeyk)>8hlr=;^2OS;*a-t;&M?ehT5;%gLu= zXJ-KGUzdRRF&udh$9$gYz1R3T;bcn+-l=nw`U}Q=BwxUh(CAEz=H`6>?yr;M)c$DY zE3n^K7BDWnLYiR5xD~&CIsKfjbV3hzJmckW!zP}$DfBucVEI97rMIv#J<+5c6sn1`!`iYsWNhi4R)12D=vINKT7!ZVr}y{Q!u0)75NnB!lC z#X*M&Jfn)6vFo2B@a-UE0_ibwF?*{4Fv@|>Od%m!Q8Q~JbvG3=XDf5i@ndRc?_y>O z&nRXOI$5mjEdY#Cpdwc*S5JCLc+hd>Vgi~3BYW336`;X#z76*6taMPbxB7DyalMuN zlUZ*q{?lari&-L4qHiT{*0KC=TL%(S@pN%Dvy-wncK~qz>5}nH&6|PFR*tR?&H(1O zQyp~7i)sMa*+2u=0O$Z%SwJ5wTpR#a4rTxwGaG=DoejXw$pYYFX9sXGF#}lGI02wT z^v}h{&h)4LPkSb|zvP%$L5~)|#s!l4BghU)aRXRE#T-lk4wgRx9IT*T*tl2#+@P?5 z1Ehrm)EfsE7l4xmbO#A?uz-4I<_2(bv4eU7U2n1=E7-ZY0NkK9oLrm$PF60EO7_3* zoFExy4p9EhB2YO7h;p7I*5&NGs7dxm9RL;%@vgb_>bg{95bb-e3Hfw+Cm_TFU1hruT zO#&#*#`)JQzV-h$n{WMtX6elbq(oI6B&0;;j2r>Xf5lz@Sg~(Qim7J#XhiR<6FKV>F%Mvi}a{>Kt| z3j~!x?LmI*37{4N#Z+b=;29O1O+l+3w8p8`L{va|6*osmTQj@25RnPAf&r#x<{&*F z)8&oqKta|YG5Y^-2awD^TKtJJL8gEtnE$fn%^5(ko{1SK<^#o^Ku`$D#18<9gTDTR zb^lWTx0JE@f6*N9m+;$0^grrB$v?yV59>_aoZn*GKXdWN<~Lic?9KjTx*Q!G-xU10 z{(Vb(bD_T<#eaLA-n6~R{&Bc}bM=3CB>W!_{cA4&XL}DQGB$FQG_$g>bOm_~H#~q* z^Y0ux^IPuC&xQX4=JXugtN?mekk2x+gBAiaGZQyx*}a9v7N8IsloEQ|u3SOB!Uf9w zwRyP$=vi1fKv`KcqdyxQ6DTd^YGi9=B4lr2YX*As07ezi)}jvJ;shn-tXy0`Yed7! z6ck{;Z6t5Co}hMb0luP zBf>vi;EzxIiw`idfkgg2%75Ea|0A+Lp4?N11p^D1KF#>8WNu2~ZK_HWY)hXw6u$p# zkQ=t2?Q)90yjT!;Q`hKwd@2aTJGb%0wXQpqXZ~E?wMHe=zKJ!{F5e~dR2aK;&N2o6 zNLr(H{@UKPR%hiz{v-aW{;l^^FXdO;QVBWES=$)znb}>h`AdDawNd@+7S8r#z0=1j z;Yj-WWohEaxjl8ABbg)LV;y|oQwf2`ALgBpv+DkjKX2?W!Tzs)o%t_-e{4gG`SvV zGr`9&Lr1xFHH1zLG;%aYQBqoVT62<+QBk2~r;ix5IWv^{twXi}@>wWz= z(a!qbly7p+ckOlW)uP2^l5h03@pa- zq4|_2*byGci8PBbIP2lG?e0|i1KGF+2X~~pw1EUttP}jp5A|! zgeFha%V+%tMb61-BWy*zx?$GcDAdQtSwXrJR(u;acO!BZeXl1PxxvsA#y9C;Z=S)< z$+@;WY1u6tM8lO>8Bg z))6C+ROur|h}XBQV(i0cB5_|uw!=tcMY_YVhdi!)F-S!qUO044wsH5!l?Qq9ZM37d7B3&FoCxw@N8xNVmM4@Zu#z2MWY@A~yUy4Xd7^SPQspeAKy{byrcOJ}n5C`zDPlV*AiCWoO zExB;-q|IY5>Asz6JUBUIh?vKc0#V5^&Wu>_yi!POxgh!Z?x{jXi-rKOE`c31j9xma zG*?*Oo4tZz(;oO|$a$z;4ycYicnpE(3LQe;5dx0Cw7f8*&++ok2k|QLszL*H(dbum z4j{0KNjw8$;e2frDLdd*yY#YVB}q}4J|_o#fm5;yHG$ir9C46^KgD0!RYJOmkIDIM z0{-LTV0ZU-#AeV;zR8Tppk(4LGc(P_JTcp6$W`^EH=y1 ztE@yS$19!y%e}`-9sx!IqJGFQqXx;pS-xenjr7V0drSx6-Z1NmW$Xz0l2odRcpf6+ ztjf_(EL5}ylZbeN(K)ry1n5YU*|4QVAijnZM4XRZc$~2cv>Q}?peJGp^$R5SOr$HI z8gecj^e*;;;j7NXT8DPG8%*OpBl=bs=_mNLtCkJr=$XVny6+s)>xw*(i>^*Yg5dk{ zXI|(*!L=@-?nT2J6x<+hVMvVicglT+-O8%g3|YYPeI+tIH9>W{PM@=DlY}CI5r(sL ziw?id_7tkU&eTmEem;M9PNSj}E8_<4Wp2E%3Qf7Q%-|r}+pOEcmn*8%mv*Z>lQd+) ztf#q9NQb(-*S^3{SQl~C_YDKkaqBRiRA|nTSZwGy;JbBBkbx?b?g}Yd0ZStvPEp0%74v><91RWSQJsH(DFZ1Y-}ljJ<*D4BqSvx}* zZyY4QQzEcP)&kVBz4nA5S2mpXx;kol?VmfWyR+AYZM(8H;m2ITS0rv{--8w{haF023vg>o}(%SXYJCUZj6lLC(V{aMDJ1 z<*&P6d6q5O*}XJnH-uEYB?*ME>1G=C)S_y`rtc``tz|nLnoPKFbGj>?QmbMm3M6(3)|XkA9VW*hMA zQu_|Xd%5$E7?^`~IJn)>-JSJq5;(Or74|zLn6&EpkN0~v*)LZrG!p~OT*wx)CRfzH zpNVMumK?boHtp(y?Z4q$!R2`)aNN5E93!wxw{d8Gj+ueB>8;w;c|Znwtu~sUJ78n^ zuW=2I?ap^Cr!!$6hQ|)A$EC_Zc@ozqZJej>!8z`qMziXt-@J70BNIODs|X9Y%-Xlv zHT#aYh1m3^{rWg`HaTgKm%{rnyHj-Fhu~NKvN}>8_7md8I(C-$j2PMnQ*Wz(7T&U) zYLr)6@wWS18q(5JjNgVQ`}X1bxGdXa^*--FIcM79b}`BOhI9MY?pM2`{56Yzo+>fn z{y+2A0J4H6NeBY85ej4hDTSUW4Jmpq%%3@9W;3xOMY0q}44O)%Bq9 z1jxFcJpA&Mmh{KUGrwZCCr4)Um0~w1Fe4FQzfYdA0rWD&b|d^As$r)yHLgQOz|= z9v?!CTj>%g&UG6`y^BmknvXgoj6?t#BJu@pi(4F}kWRDOxVvYE7AfjiN$1sg`)%hP zu7u&KQmb>6UsA{3l*=@B+z=_?1K@*<9=cBV(z1A0Fw%N`=TV6p4 zApm|~Fme;MY1z6X^U(dI*`386C3;EX_h|h5m!fmkGvfghiysy_p*;*(Lg0OQ#~hUw z#=%4^W-Ga3N53%HD|@t6Ov+O=st!@q8^1DBArKvUA z>8yOVTVinY@t%Babm;8dJN|;quk!KYVkg0ElF64_RiB5|*C;tG^y>E#5vborJ~9T^U8Ye@uO#L!y~NK6EG;>p5= zwlIaQM4XT$W+CSbGO5nEqBHaq!Tk}RBn%9gd(Y0r{>3b{NmZj1?HSY(2|_R{h2fh- zf$BNf@6#a(*xqx^8Fo2Jn3HjA>^RDnLQ`ADLnTh#sH*d8+OWb<8{QMl+?~;^SQP|2h zSTMLj2ktDv+>i@ZB_ZU6B!qqi)+p`_>6ij>6x_+B_B%9zh7Us71(%PWr(M| zdd2#w>8d4UW%1Z8&NL&O6{pB=&Aq!kLi$Z}=S=h*p-<|OSz^A&is+rSfcWER(#O9Q z08;y_lRyyOwYPV}}0XRL5+{b9OtjpUSe24*Wa+ zeTWPj(PT=YOX)-95i+wdd@f0NLix@Y%k%PxPzc+e_L0*HTKG=a!^7(%jU&dZ?y}WZ z>nV+O2CAHIT=B7z$eDcLI;)pgY`)eCkeBabWxkH=z(bbQu^3kqm%!%%HzLETpg-oW zO|^zK!4iVm!ez>2Gi|v7QTX#P!T0GNa8_gp$4=8avY>Ut?aLtsDjn;`PsAj?go~6< zcs&VwauZUFH8@8loGQJtvh7E?taxALE4wg#M-RYs_ouVN5s_}>Nm+0Fu8!wl&pzSP zA;Ic<1L^A?0;6#41f^I-N;6y0B-3&C`=^1=$D;iZAQeA%y5E}MS^<8JAdcm$S<4F7G>CZV}X*v7TaJ z83|A!z7ROQ9EH2gp$>SK)Jmbq$efbYYH9X0Yq$Y^-8aL3$G|%I)Q=s*<-f^g&T8=9 zB|VzWARs=;Oa!gczJkUrOW7R@VL_{4YYlz#ONIxZ5!}kTUQWl0!%XbV%z%d9Gh2_C zLMeEZd=`tL-=z^runv^uYPi9|p^unmOJ>K0ZvMzwG79pV18=?g2IBxeS4`?PrtUopzZ{5>9 zUramdV)v|@?N$~<c?Q*1y@ucSZ+f{$eQxX?xOl{ zxdYsLD};YbR=e)+uTn+c5c|8`c2@9tnfNKS@;%PmmvFhQ-|IzpYMn-flJ#%++9aoN zLnF!nU$;k3Z;wSLIlpUhHM&lm36be9UJe&IMREKV-PDS0%yh1Bw175m#FelrQ1hwD zP$y!K6!7i+;<&basbNe->~n&tIY?J|XM?ijz}rd`?5G7h(4$0hwx9EnftcsBfxrb{ zyGZ9#m?;Cjopo-u{|ontG@z2rS1x9X@mz!}WrIUxgU$@x9#H0)n20va?1ZKtq~Xv{ zi>>5I6|EcEnKX8r9N_}MIK-tq+lD;X`nH{RCQ0l@D1*!|EmOK6yH@DGB74iwzed=T z>9{NogcYblXVfR{@L`O|S>|Qv@Nfv{O4{nyk~z%ZmLoPxzi|?3AkXqBR}@qb5K{pQ zRWHZx!K;e$<_l49C}=&)xt=&BLdW9j3|h9ro=;4kvA@IG&e6z>No^)d?}U8rEV>v= z2#4W!;Raq)|Ck&UI1W`YzTs%|0jKA+#^OOR03Y!KzjGDm6;O3?Mlx()AF+^LARd^M zXcpa*t^LgRbpp0CDJFSwtt&x-^JRZ^5^rB1L{zR=oBP6NKH&EGfi|-cj(v>}^jG^6 zMDX#7Js1P`lOML5I5yyUou2}KWGe0}6g@wbQC>Apj(wG7E#n&|(SNnPYYxT@m+fEs zo^RzkM)MTy+J6u3jSjflxw6Er3DUmf#!r-WXTwyIapx$i*L%_r|A}*_DM>zH(!oCc zkqufq%;FL!3*vlENf!L^`V;Q?i7``fSXEgE!ES}#mZuc0&&~AmVKW5WvWE-p3cwWg_Blnz`j4kJ8TP;_ zIWWTDTt}>7y3fGLBtiVv3Hqoa zjd*-(tK;;)+H)BWB<(Q>@weXZ(%KS#T6`iOx(#?t?6ZcMWb3AZb7r}S<~vn>I7v)U zF%PCot+y3hxtLk}au?T2Rh67;zAVr{{QP*hSlRJ(apcL)(2m)B7vp>&%^k#ib$6y- z&+eHQm}LgB+~!08^(#67nJ&$s)x(J%){x&Y^$QF;$7bLxqOikdd!uY+o9E?2QMQ5d zL2PBft0I=xdJ%l5b_`@THg;d6&kjM8Q@Po-h>W+M=Y#L!-8_{+=XWi(pAAi!0d1A~ zI*ONL%qRtL$lo+#I`3vi8LMuE6ir;AafysQBl29kpT+~ew$)opQ)E)DSLYQ*_xoM# zA!izJvau2P*m_(um0bQBOT$-BnjaBT5I6)tY0uyD?IRRG*3) z$amf6oD`P4IgH=9mhH#pEv)F)KhT2Zwt?X_U%=qpU^SB2%ICFAop%0YbEM7o@mper z`n9`!oZNS?g_gRx%n>8mB>5b8KSUy&2ZwR|=LC1q8+LXATLQZAQJ_J+fDO!}yjh?!sD&m%;XD#!?d#Q-9^> zd$%_gg5`22Aa##&%m3uyiu$2W6Dh#Axv@$XdhO{U>Ts5B!i#2sh*vp`laO#QP~akc zI=<{r34B_N8g{|HXo`Wk9|s6%<~M4aK{bx_{i4;Rt;>6E5H#J8qdlwkz2acdk@7D8 z)`(?iL}Pi;+e(7q4^Lt{P?S7-tEQVnw*KHTU*j=hzvzYxRxQjCxFj+(S()9>%|kmdT@sPR!Ov8FOx-{2O!(N-q&jm>1%^x3_<``u+#^7-zv z%J$oe`>PUgH9=bDJX0WC^apew^cBzf#|!Dz=ge^n`4r`ZJqE83>r|2lJH}IXt>1F~ z!y`cNF*9WwD}eH35IORhCL&H{y8^6(}b5Ae6c_|onK$PdRpZ#AlGPa$NZ=>~0RvuK@E}wUodep2a zYq>;AI5a(D4&&my`wW(w&cTRe*TQ|tol+II)LJd|Fu8R;4^Hh#XU--U#bkFFEqtX) zd;e_on#ypq&2H2*s6Ps+Htpq@UxkOfEN5`os?=HJhd?xtknpSa!-CJeZM&-)j`HEM zv)}WA#krk+IveMw%11~_%MWdCPQi>bgLHRS?gRml^BbGWE!a&oZsKr1zZJ`FbY=&5 z*dg2GH1r^smXSW|x@`ods=hp((*PG_J2mg0Z)FZLm3@5nBsw8j_d<|ypgpS&kOqIt zh_kdI8D6#q+yW|jffrv4$_^FxU9CteQWesjvhlw1?5*7HPLCs0akld#5ZA-eR$-wj zViH2ZS(5W1uce=lj&L`l-r!Ku{??oMHs9kc))G&p{|LLXAbnN0@7&v)@c1PK`u%T# zryi$^FEXgN7rSzB*0<^-Rj6J5cxMJMcb#R(gRtn9F$d&R_xbDPlT>0wPNsgdHyQ_+ z1^iF(S%67FzhLw@i~+<$zeeJ*!(yhBrx6=UbBl|s_4K8y`XJ~Zhm9))Kx3hS?UB+5 zT!fQU4ue7A_TKH{!Jcb53iO{-I*4w1WXZ>cjq|clJOWb;P3p7#&)ya9@Y(eIOdP6p zE~k_z##TjIxemHu8y#n0{O^aJq9ST(sLaOvO^3$IAKnGQFittNb8k-s*EcPln4#(& z;W;+eqf2w>6(zce9$b$KKx4*p!w z*~N#7D+Yh-Qmn}ej~f!R@zB;RIV19lKeW$IC^wy-H$0YhQX;_U;q% zVNgSLXRDx)CGTq_oxuLBx&LD@Q5V^Y9~WV!%2F(uQ{f_3YVE zYGACU#jLVS_Fq4q?g9_?6YA1b)8So<7yoXgVoiPSqB#wN(@;CS z_o&nJgVoL_YwqFgDqdUhb_#8ITE?h2^wE)R0*+CJJ)C3lCAvJ40nUEQ`8|!15Q>Kj z<2=3jrKp+`-HKv5YF5k<=rS<}8W@Oj?(rSxR7KRfwB3d+KG4@4SG3T24 zWkb3~{2T$eLT%LFWm4)k2d`+muke!m2IgTQ>J>*^RY;GIJc$l<3v%<$+zjHp-`LBs zr2Qqs67EIRBkx%HISERMn{nuBl7pfN47vNB2f^owKO1kDC^DOai@*O~-?IWuWVG$U zal*?SU=z$<+_zDTgNJVeHl>xs>~2#~KBZ||kBM(G63vux*c~|fQD@sn)H#d;ZGnH%8iX+mVR*xSz8#e0gdzkA3}2?1OXtitV}nvS=T-kZ-NDyXAEP ziB<7KdB4`#;?+ez)pUVivS(TwsMpP~VIrkNwm;Tk*sDCM!+dzH7 zh}*y*M?68e8@?FnM-Sx*=4ZN)(n7sdqzSR3rm5cV!Y3q{G%W~$O>L zeY9@+qCN1D6ZZ)XlJC=H7a#aFVfC#xsFCFV|^2NNgsnG@TJ`5;X1aK6FOyTx_|t@f zxs|QRQD@`EQUbryCa(DNQSSw@lB1Xi>SW1IX|Oo*XXux4OVLZ-*L(mm=bn z60I4t9AURIrsiX#u(pX@Rt3ER7*X2E_w*cRV`B7pcfOR=VfRSvc)!bcTZ{|DOtQGU zTr$VZ=F5_49QW)}DnBeLvNXRa{I=Thj{Uy4+H*>Oza>x|0!d!E{`gftiMlYU@WqyX zR;oVTA0dVxJ;qE!+@y_n?t9S{bp}f&9?Q|jKpi4$hQrJOr^vPg%w#&>{eVz8@m_f@QCuTmG z2MRSUa^r&H6WIlr6=j1bH?kVbbt_^~)*Y-3HG-HaBV9iwmMsjT97k8&-=&`}x{(3f z)fh+d#O;3U=i3SG;J~40)`PU@CDc zgsh7xsA4LYJ59W+Va3UvE=hi1wf|m1&vE>a#4iu1m;tyc^KdOo;Gi;-^Lo0G!Y86o z`b&!&HmqF>2rQj45p-@u!f!hlY1{<7kY2MJ6)Jnxn8Q=7L|Izi7{)(}g=3y=@_imUG|?)qPRZa3+yMgGgl4ZbAELLIU-Fs@HF;;pElNkMNPnV=n5PbR zDe?Flw{LA^AznH+^P@M9!8fMqhN|Ldm`*z(VaQMuP+a;8u}4fAzBbUrxO7wRl(6PC z2g_z*bYv+Jj(THG)Tq+dx+6$OmCA%57ry#%?&vc3^Z1xD_!GVU)EVQ52srI=yPu%` z61#DecdpwZS`kJkPZANsOwZz5*lMxsp-GW;6uA)Xl-2Wr!Z~_-RRaxM+vaF_l2;c) z-09v`SLMLRonc=I=5ltK@3TOmlU9P-3Qg+gHCq0-lbjV(2C~}UT;EDnd}-p2D(W$$ zgPC4*@)hY~i~Xp)_rLc)q?NiQtTaq)>fd;m%dS@!Z`GnTm%FTJOYWSf=Q#7P_V((! z6I4D}B&XNTKe+YB*{u4<^J36pAJ1dSZoDK`IHw-X4|EQyIj11q)C>EqIyGIoA7w7p zdfApp^BqlE#^@et!BJ~@U}W1^u~rsn3{Q?^{czqr|Gsh3=+Z1dEG@UD{M=HCOz}~p zl<}i>sR3l=Y?AiWNriOcbMIk=Z0VilXjVlAG`&ygp6BGm0ZqJGDea>1hwFkY4TPw# z&-{x|wS=X|aMhnqZ{d?@R^5w};1Vj8Ge;lx>bNnN7Bfm;G7)uao_L>^n%ZgSSd$`b zQhy{c(^McfPgv0N7~v_d`e`j{w)a2cEGo`5Aer${->ffx)7JG&7_fXGO&l>8sJ_kp zy;Ay^S-L!G&o=UIfW=1b6z5*RBNA`xXsL#4&2n}WzUFbI++j`N`TY9%v~wqENs$9Q zvZl9?6NlbQr^J@tI&$+U-L6hc*8SxM-8==yPW+pi?Q9BfRH$Y15Ohy33(7Bb+o)th zbu9yZdJP;qcTGcj$AGTF3*&Ffu(GvjU(oU%^i>QrE$dagTsgXxAojnJ-+WO$!R%H; zo5t^YU$bi8i1qbK5SdL=(~3En_X=r1A+F@T>vAN?#XIMU`XQxvJTd#@+|{_Ww(25g zIdQ!>vVhc*Z!<>Qz&dRdM0FavGBzgpQrRzPHU*HW)v2n&wjFXx6kY0zM*Qeh+6_3( zbITn!@s`MV(^2N%e^4$(8^Wa8L8z;pFU6XVf!n@QsS{Bnq*7Hgu7C0aXBAN@C?|l$ zyB7{pYtYFv^EL}y(A+oV`}}3Jiy}=hWZpR_V%UiI@F*QdF;c`Cn36?H7MQyZDy#k4JA?o+5Mb}7@B*w&eZ}4dr*?cB8-m8T2XBrxlDH~+{KcySrD7K4w+sb;))g{6nAth9{6XgUUcQQ?jm%a|&dTw*P{%f(FmU=h{s(888WO|7$A zKpaF>npIi}x1d-`4kQT}H8-udvixH4wC8jcH8M}$PFqGFhMu_b#4pPMBdqWYvda(5 zT@;2xEj|rgA6<>TS~3!oQ_@rNWX23#(%i+(%*~hxqbFsh#$-lE5))hj(#Fay@*9Yv zQt}G2qv6RaXsl=w2hKX-RaT{3^oNEB;s-2l+z|)U&h`xq+|lfUF;?6y+dzJFSLCmf zd%r0y%yth4qQj6<_ejB^am%;J1p`Fy7}Hz^`X`~BaOL&Y<+IY0;H;WkEV-Gf=u@g= zzb3r<&EnkyPr2nWMa8OLIKo(qdi2=-v5T%j84IVyT>{N3ryI0KtHSE@r< zcX_@frJQ*!|A7SkZ4f^+MkS8OM3|9(puJ8R`6Q`Tu6d{+jV{U> z%f^YOGK@PcDkXK!RL9j5!SH#1XKrbFw7R+8Q< zT&eHj0gxXeh*4dY_sMqP#B)B3vy_G4@p6o7Zax{xv7}TO01XR|CL}3-Di-Af zTVgO}I0;EU-c8+WZ{)!LE|x|p!9&*p&emVbqFnBNGaf2MQ( zwE4Gp_Wy|*`ai&P{2SmR73#7x&!uc1Z0|IY2L3NxU zGeK{7gJ2!di~OvhoyZUVFgh@Z)uLV z;eq5?--sU&IrNt1W`ENM>imr`dTRr^{!lnfplNv{g+O)eEUX|(2XucUfIw+>kS**W z(uWl^=(qd-3#Id~0N0;2^PgXp|Nk+a|4W$8A20g*S^S@KI{zh-_uuAp{&MsG2CTyg zTC?=5T-*R=4rUOs!_3D14_JqVgN2#x4bu4^#188l>GR(vc9=QX|J%q8$l?B{$j)DM z;Xffe{{^=8|06s9UvWPF6J+O~7`6ZL{|=ZzMB@Jv+2Q73`%lQu4<9%mjQ)8CHH}+S zWG%^0g5MHQgaJ@;u&5|Q99l!tXb?lmQs$I!nB{Md2ZvG&+r$EUZVb}jH&qQVyhOBVd3gil)B zR%I&s>3ju@*yDmP!z{^-r&go=Ry)`cdikR&$KrNt=Mv3jThKu z%-y&CgXfG=iZAyW4du%UHi(-EGr0 zO^Q&@tl8Eq@?hujqK;&BKa67q-FMVno2(P<%S57J1%+V8!5)hqkbGkjY>tl{qJ|1o z#Z!pRkAo6=g0SL=oSOXEE=CTCM#Ex#Jr&Q(%ieC~(6+F};8Q}76Bc(FQ~dMAx>dl( z*bj4B&k=LO@D_oW7uO;)Gc)Cm51*bC&PvcGYY5>lZl{a1T@egk6vXXZi~r$v`1i5q zu&*J<9NEASq5Mb{$v+DRDYD^38Bd{LM26-XQ6nKroLfS*V6KFsDU#wv#7|KtM%hc` zP2;d(tppC_oLfRj3zbkK7UaFp7fYi?Fv}xgL*2;*CdR-klF$ezy!|bwz>m2_1A~yV|9GDOdmE`Urf-r4r62s4u}#N zox=3!NS!1O$L^h;xORGd(dFOKYtSJaQ2t7MBB-2_qDQ?@=V@m+xc zNrEm)@4W@Wm0A@?7MKJb%crR7eI*ZP#D`-`)|+H~m~9mjs<08p@A3ORiNp8>!?@SP>xfPwr}SOMeD*tF$oBvmo_&jy7*}^JIm}0?StRLa*uFUR#4wu)$a3@TeDrbxieHu2 z%sP4({^t3TCU{|sLHx_7^e%8NIwl&TK|#pvYp}vC=9@5gOU*M695$|9L%Yf!GCl&n_q`fN z?-5)bSeCz@NM*p@U<9qN^q^Vt^~bwM*)*Q&{{GT8zVxu9t=qs(3d4jhocN z(=;#gEnJ=jmgY#L1;NR&7>p^9ud?~RW3ov1JLbgywAIm&lET2MYXq!D$ja5+(q3l*bI`fq>(CdEHva4Lq-0%+Bc3;H}>?yUr~c zCxzbo7tZheDfvi%m4;AM(eUu^QHx0U0!$8guS8wA8@52)PD2VOV*%L# z1J~yL6G@L{4dxXbYUp#7gsY=!6$UE-l?-{DXafC}SO#-a$4?6j;)hkX?*$S?8#qnf z%$t$kH+IdkI%hSbIyc7)e(x&3jcb6NlB4CzNmC! zdzzUOq#%RsS7~yjxkqsxaQI5iW29=>W$0Mk6)?q=X2tQzA6~{f^0W1Vlz&ck_sC9| z?>X4R{oL)j%iYxA>8$P7OFu~c$nI+P|tmc|OI*n#){~``n#Kt#@$< zHGD92&uO>)#tf+DrQz_heSw-jQ`4_eTXH1e*#6JgxP#bpwu9j6&h>ex#t-QFjJl5R zRZKm=Of4aFkhb{;6B7f3z4A^V96KQU!3N7eE^{7m(#_EW3McN;a1;b*s^JH#KA^U4ArLJ-FAhfGHSZAZ)a|ja|I+STHM$!HV zuv^|M*5<6tWL|;)mhkzS<~h(0T+44Re{XLtq(S{e^P{=B(Z(2VNJzfXwxrkflEDF^ z2NB06%vmoa^we4uyGCW_^>*ti|FC>4Dh-4a($IcHEOrxZeq9%=)0eFt7h!)1IRsCQ zHV-~^pN-QynX~-`nrtIQ+AoG`jGRTlp)^XE59XBeltMz?_I50GgZ2-I&xl_tZ-H%I z?BW{!-ImwQQSmcZS2HtL#mXjbPEtw#4|{hR8(Gt)3ED0*yUfhY%*@Pem$}T$%*hv9#F#>V$~9s-#5 zLtOlFIG;!}l78Gvy^xh%Z)RlyvVGdP+qf%Nzw7t~#Z!5}h`Q;`3Kas2M@bSb5*~rq z9!0hyz|AZm-DtEd@AJWZZjTB9_`FB)ww{A=JnhqZSYMW;l|yy*N=pp#?s|iJn`3o? zsmyHy2B|5oJ=7EMq~8ygyX{1p?zKrHoT=vx->|bQ5<&`-!F1k&3{7dDyOK^HxSk#bs1DNOFQHAwzyt=6 zgTN6Uhfi{k^`rZx@s_Y%R%cxzJ$r2tA)hn4z_~|AgVrHTR<{B|=5hUzF_sRq*S8Ak zZm%bUv%Zkm)+9&XGac3ChLMq2-LE(PK;7Z~5Zu*{%g;jT#Ib3)W{a$Nmma)gAPpG@ z$9hDQ=ibvixY}wJHl6?;79okN9EMASM zGO$ceOJu8Rwb||d$nbpU$XaQ$^RMa?>2?e7k)IC8$mAD>YsKHIM?c?DP*EbHp;F){ zBaMeFA>QrphX1nvsb}k0(Kar^dvrnIHq6=10*K9Y;qHpgs)teR(`aH3g4XkZwhJHt zASf+CQ0SxNQ`pO7Kyl8jQdruO?=DwetbaVYp16CQM-I_qFY|A-xP4V^zM-uTN1a4*88(Chkstf zZOUWo!?3kNMV`?pPV>8+uGFfhTwzB&d4Ev)fMOH4^Tx+ZEqA*mc8O&B1D>mRPrDE$ z`R_JRe|&;#B9|o^U{L2#q6DW^+IBnKdX)p79$j|Lc_63`*f2w};!BS~%O&>~|^s(BTQa z{($Rtn1)f|M2E*k6ncW0#^Kl**}i&y1OjZyb>6VHe|WTP(jDV!U(m_yO+IPcq{_km z#+%qN;=X8z66wO3F02M0@G*F`jZeRV=*!yd$gcQF)*eyK!Q(J(W%-Hrc_`smm<^XQ^Ll=%U+cwx$c zYrc=MoM+bQqY2y5mHyU85=V{xy}g^N@jIwr*1~p}d$i``8UJG2^*tJ(^A&UsJb8|i zz&)4fN;#43b5SO!IYJ?Kpc@!J^0?W){&clkkN^IgunPtqfVARFm*GEeM>o}P{w-u< z@N&g3+^7c@a5|z-3H{ga8ooJ6***!za;7<3H4d2!gn|fNHgkI-e+9n3?+wX6~ zlALe6pM2ADp;4=P5dzk^TYb{j#G>R{nvjPd6XlXb0lfeN#A>&`fYnD{JV!;MHsg5_ z?m;43^u^&W2ZYHE4j(C>TVQd#u+2Hbr)%h2$n%QYwx+yXkVPUIhZ!vC?v!=)P4(6T+hP~} z>hb6j$HKzx-r?lRROja_@h5>z=NG!QKhe~W=N1hcrTEESZzsg~Us&kk2)4S~zcWg) z(|B(Ck+XeMdX9z9B{{t&1$nkIF@Z>iz~twhY3D{>oE`|<-99}x1k}BKy<3ook@XQK z9gb+N)#lM zbRVL8AqkMRpNhU#(n=q()t7%iWN)wzpJ{_P!U1m2#Hd*HcikYCYw-y%nneAm_7!tk zUGxHflN=f45%-`huT@8vo+3#|q?pLx=8?;H*@fon6kTZpj?`EQ*Ah)dp92EXDYu zRRN8e8?bm4aq=m=O!{pso=p6b3diqb_rN5Xn_VNSI(gPw*{sv@IziUyeDyfhc1mHo zqV^DdR+`tYgm=Gug?7c`m#Zyuy}Pnyd0M#w4|I_SJWbDFG;J?#Ofx0}4IzPnlv8Kd z1myvSSv!5-S~L@8V2yMMJPU++X0CZ5nUSo{`1$3q%>nlB@+ScR9z1DzsD4gfEIGD$ zgy&DJL>V?$j1!3WP8>0qLHuB;=s!zZnfw`Gcjx&H7X!>z zc!dH)!jafHm_t<_lg{20c+YDe%7^jYipc*4zFDx+`?j%h(2J^s;aV1NlX*L4D zw8Q(n93-^s?r`Zdf%`>OT<%@f5S+Jlb{Yo75Bindg>wJ=01wrf&#q*A){YuKT%@P4 zy&iNA&Gv7(>&g`z$_CVaxseLLdUW8Po}-S5v{=%_gxrSIlxDc|hsFh*K1LR#9%O^~t^PpMQA zghzOkg*+_it3}DZ%^oqM%maf;VIoI2g?i#VorEb{3t$`c`WU*pSKl~G!7pKWxae$` z17~&by4mnruYc>QeNWT5w~g@KhG!l65f`ecuz(zc{L7LBW&M;afQG@%IBHt%<)oN6 zW{`TR!u>+!(>pERRWQr>M#^*8(uG^Hj^6XMbw_`Q9hcSz)(b(zequOr8P|f48NR(7 zk_fZCltGdvKYNycOs|ybxp|FkrF|h-etuR?HlCbojQ>Mj1hkUThTGazeZzr!v!d)C zOq7ih(irBdj5kR(l`2yR(}t`&URiGuwjYR50)&x^69DGfiY0AJeb1`D~U%&gk2l&KYFKJEiye^y`UfXfi zH?(v1WSPgQGCd&oIHy&cKa=o*ToCy6IoKUQSou;8GY z6FB>gZ`z@UeKyT`hlpGRCVK^XyRUQZQY1~=Sd`DWbz9lOs;jlm~T&eOx9xheSGO3~8BMB+r(Y%KyUXN{{qXs4EXwJbI(9|@QFS()$~gx#9G0JnPj z@V1}m%_N~`?0#|~1UYZB1!|BVdncRmeyZ`V&GaIK+@^F^4Iuo!W^=ZND*t>6H&UGs zLc=Pvzz{Z4^Jy_{xGK-hECQ}3nZhSxI*N8dwmzH@cQ7Iwy8k@pO)s;(6W6!LqC0k# z+omV5jZrB4!^Z+RxOoPIRjA=&Y`U^#OauXl+eN&!2E?M%aKECPMcIIEL2reVdTdye z|FM7n?g_rp5Ww>~3Q?Wuo$aGT3!D11z(0U7tU(x?3;7pUEXG5KBOuZCSTtlgc9{$| zkivaLycLwXr|-5iy2W5t6{l=nyj!V~L=u*l4%@`iMkbpbtpo}cnrH`qwPWQ~M=;&zVnDE=6 zwcGb&TS)l4RkSi07Tt<1Hh;<1`!I-F`-4CKg!3%G#xkohK-b;v#c!k#VLm%$`bQi8 zjGdPP^5v_~`6zPw_4bOk&GEWyHX1KVR$q%c{ys+qS}H-~N7Z+e}wKdq@3!U&TSoa#K4oM8!(Xhx&v?m$i;lW@P`X zAix%IrFcV0nINAjnNOr_zogOr zxwG5s-1Z2}v>RQw$A~3V&~To?UL=EcA;^Nc8c{`*q+u86G0=C5f>uZkHp~VuOMQOz+3bnvvbR z`ok1Eqt%WNs2FbQ!EP#~UTG!pv5zyrfJ6SqWnuqM*!f)16m>dc4`;+JD`2+`XzH^> zh8g2hPyDwrTE=3gi!2rog1~RQ?%q2%vv{${+d@u;m|xYx`2FcI9+q`8pgkRjm}@Ty z4N&fqigvQ1m;}S>QKl_)z_0X(kJ#Cv`q{MzZjU0ugU~*csO&j9a}b+TYje2AF1w;E zf-4)VG+aB-*0C3Uz7XjIT~!lCfDuay$$R180?6m3<1Lum(N6-R9|=3OBSIZrBEli@ zn#R=rkSN1p2Q|93XxWH*Xub&+h0b%BCkT@SlOnQ}CdG$vljwL@vD&&Jh~6h zv&>WT$F1Xczo+p#y*kC*RXr2JEM64V>9!v3UzKzc*c?l-E z{%*GVUYKGAtZ9#uAhQVvt-*c!jZej_QNdc|!AZzx zZ|pkvE9gtc#ZA60qb&0H8XL-RpCW>IRi)UG$(m&`P|#Z6WFT`Ayow1t+E2LJkmZLM z&jf4l;*U$C9XGT~vl~B4KhBah6XsYtrb=rWN0P^7l1GfuekV9O z>tJ6*^Pqi~Oh&&4-*yFficl|T3EN^H>jpK7CY7ozH=}h%BMa5Ki~&SS94g=s$;kmpSZz7l^<_!uQu|Bv_zCI z_P>Fj6uA{-X0LQVDUhT3NNnDeo+0nbA0E~n%aVX<%7M~a6{rkWyKnF#y8%(=E>}~U zUJ97rAa&T&ZgVf}vj$l<$oT85(H^rtZ+=$w+}L;C(j7-UMS298m0}!IF%TH=E8n8A z{lS*5QP~l?*(61L-NWryiioTZzVp{lFjE!`cezS+QkE9Qg*$mM;ut;bXM`9yf(<3WaSB3oYjc!QbMiUL~^-LJ>ZtcuMcE~7$e zqf5>n@2qd}Q<_|6cVJ!oZ{p{Y?2+Y$RYJ{LZ@Bu`zr+t53HzP1Y_Sx|wyZMy-*G2H z*Biaz{OXY5I_7-FEo+M<<*a|i&*`Ss<)!n~!$0C@5r~3|Z<_K?)<5FsswkQYW4NGH zEn9QLp(MsLcCTFyi}%6kqnWAoh{Ky5Vcs5lGc540<6Ne$eCI~kFvsF$qnGZaY+ak^ zqyYGo-Y<5YBjoaN=1lu}M^wg=m#LY_AF?`ByxI8ffzFI`q^{GLRvnIu(N1@4q%OA} z70jqSm$Eh;Y$Z244I;$%OB(`4;0qHEI@MwgnDD<*=Wiw~>?ZA+yZi1YiHp)rJ<{|l zsbaw|6@4%0Bb?aBb}O0%E1fnUoQW&PY|L{Ly@S=mtzf!t{w+lqkbzTl_fuOZ*hx`Hrzh$LfELlqY_RpQJKkK+CuIf#u6qoIH?6 zoq|^V7C-1x9seeNn9vW9zOfGuQ%ZN@7c-N|UzHx$JuYwZNaFqWcQd9G`lPemIAsZd zw@jo=wtLl|K^ry6qgO*0qYP6!sZt$cQuf4w@TE;I_FH)JU>dsYWJ{{pSUO-{3j?p1 zv+%uGPMswu)n@3Ty{8EI{Z@1K%<&N#Zm1Fq)oiJQwllh5B*LgKI!Y9ng0k!r8?LiD zAAgHYr<6*V)|3xTYGpSXi+LhMOzaL0=gRmiSF5UyP45GjYP|L`rKeZsDca>W^&e7b zQ+q~d9#Ll=W&5VTCr{VzT9)nDwOTXUjSGve%6u{xL*v`Ab*fV{7OS(CPo!wgoK;E3 zUJV>n$z(g4EoIeR0-e2r-h8IVzQqq~3A4vP;wR=G@$&$_*0Bn`=oo5tc-ARY7~X7c z@w;!|Qen96=+5&zf|l1s^=k@TPV+PKlXhdv#93aopLODN)D3kxAmgo`E|UR{!nXU= zL!)#2Tl`=w)PIYg5(j`z^}mT958}kpZ}F2-axPkN23El{V8Jkg8lt7FY}N6O-{BDb z^mv)BV^VW$47U1xli~R+`_<9;^;R8pfR||LC%S4fdjjXoHLkO2{N3;K;+JvF!lK5@ zxB|v6>lzF{wIoq>TjpbcaXwg3s5wDR;TR(Mx=dZw7TsSsG-??J)fIuA^jE4JB`BHt zKTQ^a-{MDI)4Yti-;S+E4elTDlc$1*G^&b(38U|!Y1)`hW$E;f_*qpjEonZnio!RN zr9F0o6y8VPM@pDo0_BR0I>^v~HHnnmRxsaTc*R1jD9Y&7iEFk7Nj-ji3T<>V*cRao9U#`b$qK>`EdvClm&rQ&X7xAqbBK6Z)g(c@-%1T6uou`JLUu*-u2U0xZbUzUSMLV;+ zaFAtJhxkJS{>ZPkW2D(XmN;q!fc**boGJJ-XViFB`#?gSMvQ4~3Z64Q*oH(MTZ3Fa zIt}{!k44xTh?{{BOO};x2zHV!3`^6LO*rg?$^x!J_z!-ZCq|K$X+pWPngGj!>oQE- z*{xmYhC;PEX3Tk(IuRV;`=7%C`$*mIEzK-sOV_MM`uh%{*;p1;bW4^k5W$3 zW#~}#hwUu{%$YkF6lG{J$WBdCj)WyNDn~{%l9DK-cZF zq^c`uP#qoYA0_@UGbhY06FM-H#?a_$;^4)$QJ#0Wb&x6^98Kda1cPNp7EnIOTiBb+ zxF2;d9dwx8-^=SmqSZGBvJ#XNG+|VjJ+u^r1d^hsNmt8ANcx2Zks!5ekfEcMk)As# zPdgQDgo73^GRTCFgrM^yq=MEcLAp-)?smT+V=jKq(At6zd%Ph*RUviSiKUf*xRIr} zMnG;pfTGmgT`QO!k(8I7m7HI0N@7xeaxU5Fr$N7pecM7WnXx%c!(geqy@TW*Hr~*0 z@WVN{cCW;T^bLMS0Ov*MXo+UzvLO%*Q<6Vm<0}uo!H>!_edag#p$GZ~KjsGZrIAUL zoZn!8vyr1Xs5VYh2l5~A14{-l{s;W{{{wzJA5E|P6s?-5^h4NK5rCvIuzj&$whFDQ zSW>MgniqG}=7{ABr9Ptoy5%ImcDofGkU9sLwgLRY#y3ggqjtY~2b1?XSU>9SfwwmG zRp+a_W`Q(k#+0B2Lc>WDim<3-oixDDWKP>m7Z-mprXFB{y(p=}%vaE{wL>I23bJTh z=u0IO4uOw~EV1?|OHX<^Q#O@ItIB_apR9LnST*Jf71rnwEl-}P#+rvHMoLXY?cu>Y*L)MVr4Qci$!=lX zSrz7H6A`$A{zEs%M)#ofgs)fbGn;Lx{J*~bn|Iun%U`I)j)ZT%x9=}kVKd3MgPc-Z zBc#>J4oiREC$lpo35sLm)nnt8edE;G{-jWH3Xa~S)D-|K_X}wp&ed-9D)&Y49TMZe zk340?6L*dn*xp(}aM#qc#7%N7!Ad1lx6gc+^lqSW4fk=+O=PSXG-d!*kzKD;$ zv(0Yd(5{*yc}A?@$fn0j5>J?ANMr5HT|?9cBU6*22{b7%RimdZlcmev#HS%C^OP1B z#Kf-wF|nsi+>k9Ms<3o*?PW+kdPBUbxuxVnJ$g%)ro~Um>~F^GMOukJOGP$% zO?qPPU2rc;Qi&ibdy}H1EjdO(PdS)f&=8J1G$@4}6Mtie$)6Aff&?%e#Wi}9a0UHS zYZOpW>phY>yET_ez_j*vBWpvttuu+F|9oGUq*WH@Kvb+SOp^FbLh|p(h=K0h2p`ET zwT{$=2$JDP0jQMC9eMNXt3)$A0WtWX6mh(yS5PwwzaMNYOk#*Fkv#)BUEDxnSbxXJ zOmEiQj2+UMxS{d@A*26XoGb}=)*xtnDvEs#c{q63alWyFT@VXJvPds!M7#u0)P@L= zu{>qpUy+9JI`Tit1O7AIb`+A|At!b%Ec&oeu>>F5lHG`N?EV|^0jBMuj!4 zBq*0cMv`Isw85|hoo{ja3J!LlPywxil_ZEF&^U5G1h|0{?*qDYKf-;1Zfuc11US0+ z!>SQ(WPf^l{Itb5^-gpPMwXA&AHAcvfh5E7Tf8TWXaA!l@&{DX5aZ{%NPwp#Nmv|; zqF=JWZq^Rl&lhAb(6f}vq5jXWcj2#U%;Q%W@h=z>l|85b-T*QElMeAeLpJ{l1N7Z~ zPS)1O_J2E+=Nqg1SNQX7RsJ*l`PZ2L*_{6O;Lra#wg0SrzO~8!Nc()_m4Chc9m&JS z@SXPa?~y!=-zet$^?%Ka`Q|SFWzPRx#J|t^{|}7$x0sp#2!#1h`7-|>1jhVph5vmm z{%=c^f7Qc(SA_pN66HVY?tj8hSpG?G`ERmfSicn*E%P@WV`uyaX0b5+U;5-9H1Z$t z(|>X&n;kG3s;X-oT}!&2SB?i8EjX7rJs?Pska>I2AU`6AFmm=- z{T&e#wRKdSWN`Uy!{asMQp6mwn1>~Y$0TrB2FDs0l`Y$%=Z$62H1+b;px3|Jm$pJ9 zjV5`vpT2mzk6!FoOshK|wXQs_uG+UcfenJ1u;C^rD;cgJqrAQfQ9JM?QK2_P?|;K~}I8ZWY|e5I)$C?_Itig!4}zWzj)U4cGr z{e+;Y1T3vA{oyzxE>Bg*r0%=cWm4~}IziPstpWS^c^M!{E(BgiE{C&J9Cz2b%ds1s z(v0n%PnV|W=`n}E#6Me##IOoPxeCPb2!0YX5i-{i$nOVt{6VNA(%TPxR|M*T73!q` zT~(lf7Tz@js>_E&fl3w2g-~FL5DZkHi4eXqV~`REH-nTC5}svX!6D86X-0w-ESAqm z0d_1YYX0vzG10;RMYME3vOFsmsPDKK7EIo-TLnHUfq&@})Vvcja64DD^ytH!&>0;S z(C6md`ty}g_Wstyhl+z_;;N(h5V>COm}tv>(;E*j&^1p5bgycmZ6jKD5QIQA?g`p` z;oN4-3w`Flqx=dWoFR01%*VuLA0Xt&sgd+~3SMA2l~=!l8~PV1pLM0yBnjbrla4jt ze+cM6TdL(B;AFJ&_`S3F0()$WS?<<@@kW;A$}(z$J^Kde3SrN{-J`g|QFue)3Kj$7 zLlyKc^`y+w`ZdI2PbT%X%mZ0tuZ5`Rj+ej>ln4LGhE8cU^Ls^7@Ka!1Bh*35%6s>_ z`@PHE5~vWjLgrE0=MO#B%=?UiH*t^?$>2*#MNmJ|zfatej&Owj$Fd|%*qAOob_ym% zlzyQCT71%w(q{jtZdyqSzd0;B@+sF6s6O=_ayi#;6<&-{h~C~^C?*bsB}Hf({&ADW zHW~{e?nphR%np~O08NBiE5IyjgL?i4XRLakiTWTuB9jH*ns7a@|dQ(mW zEOCeCvY}J&LS}Q+$046lPA;)k9tt)6wo4mVLUX$yTRP}4%%!9p>FcpwH61G=HLS{j2l6jcDFBYoqx1@}_st$7@arqFcZakm9k z@gHq`DOxHa_}$g0`6ZKqq5kx7lp0;&!5mS>l`Y_v%6B5c;b9F$()nD-@d*(5E#<#5 zZ#ZUU`ocM9xibLM9{d3B#|pdFHv@BS7w2ZloFsQ+eBcj5H!x1vAG*^ZGy{%A)8)XK zv6O1;K!!YQq4fxwpMAmTK#<2&ys0k4pVqm!9nz5LJ7EY7W$BQ&$aXc&MWgd2%$`A@ z5MbcXZ(80wv?d9&JGsji3v~n^qV#`H<~XTET^9-!^V`H`uVR9xKsDk>Jjmijt`uB? zJVW|_rlX9(G9Q4d*Uhp~aWQ2Mz= ziE5nyZ=DozV|!eSdSunl-M$?M54?CWC+Y)kmImp=49|%>dg>1nM>Uqx>^YcLk+srg z&{GuWKiR8`&BMNHB5YO@jt)^`1X_R$!V~Pz2EstMVnI^oHcxt1B4;VITq38uym%%s zeFlZQZ2OD-m+!}tb3N&5hE%u+YN^ z%XNsHBLgg=>V~vxciD@jrtkqNIUTR^Igj@3p*DIfxBca10OhpI=bc^^E?}+@N9ihq z_v(jFdUYD}qWjTzWetdRvXDjh+Xmyd3yfANb9-^>LPk~dqw)rXwM11SRC zK=h6u6L5hFgGz`gdFK-kCepaETP_7U;0qHmSEj31q4h)4$#^}kx(o;Ic($9IPUUO4THW^zInSgV^D z{|b$|@&n`pW4(borXynv>%;3YDm@T7drxvRroRT1w<*nbh|yyUOjz7wCko)D@Sj30#wNQ*=Noh-ov->TEXHC1p|Kl`3cI;ZLrrh&iNvK z_$B(fHwy=KWBX3%ta>=|8&i~(IAkjQ0WDqpy??}icOrZ9dRa)7I>8Iwi`)?Dj zM~>!C>Z51z;l_>~OK;LSKF7I{q@#Kt?(zpXz4F;p;EutJ@N>XgT5N4cz$}-9DaY2p z#%479p<0W}V6K9ueuw;P7E2gfjl{Lh9(=>*POi`Z5s_Xc@FA&FdTC5ri7PUvEqx>_ zPk=O*A*L9XTD4ZAhx!?^d_zQX`P>LSUy7KQJ#O~vI_kzOl$|N?h6K9~YH)cU7whc- zEtlW=V%iK0`|R-E#b9Y)s8)Q4of}$UD@;ygvYh!sl6;|JrrzE%e|v-;gx4&d%@2II zHX||47>tBa_#2OCXfu_BVzBy8b6U0rjRgk2B9>4;A;dco2k7f;&v(RP&^O>do*E#a zNT;~akpX{M9fz;83u-+JoxGy9i3+dsqrIOot{o!pDW7;_KoIuMX8vsFZ4&L;BO;lD zavz!GvAbD$m7m==A>p{{YK5na-#YJ67sP9Wz3THtxqN%U9C%!s*Fhr<9Bxk8CxneM zQ-gC>hNO_?pb9Q~nucJ2<*#3EHBMQxS|04t_(S)wc6$P|b_{y~P}6y3 zdDh{GoLKAaRru(1Un)?<>Vcc4f#*(f#Gyu&{n_twM&@u!&960F zb3mSfT>Wr%5FjB2K*~T)LDE6iK-vJu9DGx_35xO3d!$6#nraB*To_Y63EQW`Y0C_l8c zqLz2XuN^vKMlaC@a%JK&(L^~qB&eqwq0dxGRP*7{1ED0uAcW434Flv`1QSRk;(|y# ziB#3BdWZ|qulJj;XR6qrZs1m}k!|$0hMnMU6$e5Cy+CFIV<=F}&_#Ner?WLc&hsb= z(k7Y z)>DGe-;u;6IDo!=6#Bpre{s%gpWXb)OM57770>r(Fnf}rDISsK`Eu-tU<2~8Np8)C zS$L-BEVaFAWlIjr*W$TM*pAz>`^el?1Hik0R1bb`v=G*kUE98^c~~82er-r?TI&x` z3=&V3f*r^rbUC$Yt8y9J0-t%?7*Gm!oA|*wj94H@wEpmJM}YW#ob>X*)Ly&Aa&S)LIkYErDg}yHGkfk z;yx7*yd$Vkm_6=eQ}5UQ!lq>3L20u(^lXDmEwo#Fzn3k?{+1E0iyp5Ud0M59*E zn;0MdRXP5(K+Th%em>a>H$fCAwy^M?pjD=fO(M39bFunp&tE>8ns#PjGq>yN`ET5i&lQ`M8pDM@OqlnRZm2755qwuf2q<|ejE z-!g*x!h=vc9gc?g!kHO%*DmLWdgk`2oxQ-;kCsre0X5K%uyF>xp@-n=CnkcD2#~?UN}vc~`wqzhTXA$F zt>a=NztH?IgSlvaAgqh}cMyCE26M8+#TH1V^f(mBNhGmku*>y%87;$*Tuq_!C3cWy z#>sUCxL){tfc%Vpjjuw)9w&~Ht(eLC>_%n~fe0deJ7O7H$mv0+6Ps&r}A8ZrRPsuF#$gInS@_lU`nc(1+6NZZYrJF@&OQ@OvpbG75>n z1za?{ax`~)JM~5}+Lu!~!lO=e>bmSF)H*^l6Uk-sMzY&d>t?fi8}II%sA8TB$A@OS zk$Emwl$wL(0}8H4O<;iMEZ^C3;jIiH%j{wCFnD{mrC>c|dk`IZ$~be_#o;*+t>O3> zIJhY1gmFs54I9vJpTZVBgT>Au2FZHSpj;&8O5oWIdNyLD8_EF=5X{eb9spcC>LAoT z=tbyhR9)&0(e!SLC6J*@%q$UWa-mfyMu(q{>B6C!yD_p|HEwqys4!?1I<5M>5ks7pfPK>TX$nc-^$OKvnnpCfj_#xfw#NUYXt~MrJt_5OI@q=d8K- ztM?MFf%z}5gsZ_pG+BnDt#XECYlUT(sd*vx6$6bC)vbk#h0UM(i96hYMvdX}EKWR? z?QiqZvOWWZsRC}SLc7s06`8%<0-SN=?>odu%a(T@GCbJQqa`V%6NM!?)Lk$ijeI-8 zr*%qByEN?uA+HWcVVd)AEX*k%c0K*FLjCbr&wZ>|>RxiyDvK8D;F~SJFbtPog5AnE zfiVNTgMxZ`u~4kS5eh@fjj3r&oa(HC(Zo=OWj5eE&G4UagKzq`@vL4Zw`{w8ycWmE z3!t7yj`*vz8V@*6lJ64|M>9`8jZcP#mmLe|QqzAUa6ff?-o9?Ty<}`VKk`Hy?W8~i zPQK)7gm!O79>>X3-?%CIjx3a!6Ka3(BHx?UU|h*7p24;5L<255UvtlM4|Lp)8GNn_ zHkk|M3za#*ASO3>&HK7ai@CYv(D|~HP*8)l?cl2VwDa?(VqFBF-<$4DPjH9LOwiB# zP2HiV!MQpH)h4+XEKvR^<`Y4^_Lk`@cYqaAX;)~Ya@L1{Pp|jA z4Sd7n@_v0jGy0{7zhf;;F4tGtk`B#ae*7Y-Ip>bJjd|iAL9x{lx-0RUBkKnFk@{5a zGL}cH7}a0bpa#4t^M;9C^BBh&73(IeMm4t=xvPIU`yg*B>%u2{$9yiZ9+5z;$A8inf&4h1WcOEWRiOZWVW+h(-E^1xQq>FXmV*=An_}j z?dDiL%KplZH%v}&yGe>6gT?X%4BS2K=u@=|E`VC37;1&EWR7FXh8O7K7qgk(I|J#% z??oWwO&GN)9?hlqnuZ8$*PGDRi+pZ;uj|oz5^uef@8`C1jD`Nc%uyj~;w5WUiv2~> zze6vQwRRu{>CHv8K2YuH^JU15$;DvsCqf@us9EJVRhy))e^#7A5(@Dqj_()Q%`XIF zkvEH&sn9QCa7YNN{y^eH#YLeU2%9Z~e1MD>9SR4iFpsk2D$uCND$^54j~FJQ;^07n zkXsNisxlhTycWGtus?+CH%ChqM0u9IvH!yU?$6x5j=_5c!s}eIb$K?!d@$5&%z#Cd zuCa&as+wHodi-YE3iC^DmucPGkOlRSwU38a>mp21__Ts3XxHS1RW42G`fSd0BO$5iEm5T^9agEvqO#BWgZI@8WMxxu6 z+~4lPo$U4||LJ80@*Jjl*%sZeJa0i#xkWov*+n79uOd@J^1@WGv4#`7$qFM;!28xP z`r5eORQ0Rfd3`OC-^q3RHMjf?;u34B?{f|vv3I?Iz6O6PK3RhLn%E6jH&R`KIu)V# zv%&wxP9Ejrda#lV)MmqQu8b283JR}(l0qZlnA8(kGqJ+T|1F4Z#p!NVfYj!*?BoO& zyU^-=&U!-9^~&oZ8FAVBGkmeU`TXTPU;cBeQ+-RDMPi#debOq_Qn;6_o-rrMjXA{( zp6xCDUTohI82q^nmpCaREh$kJH|pnT1qOXk_^!7F7gc!~y?l#FQupg4LL&MZd&jDU zgCm7sKQ%#uflM4$Awpp#U_Em`^m8LmUe});-H$zs0&&t6HZ&;MOq6>!T>r>Dp6qty z@3kMR)x`3NTkm=P&+z0_#T_qoN<9a1@e9<(sKjFu#rdWwi zY#7?B^C)A=%tqBK{Wh1w8D$;y_&Dhe4f~DtZp*YZeDfbuU}+=C!HmA82q^ALHbBBY6#6@K0fay?6rU^o?8^^?Tur0^z4$A^)U(g;_f&@0U#Q~v4KuWN|J}Qxh4k8qI?pIBf-vdLfH$4_$Jkee% zFApo$&z8kO%S4xO$S~JuQTdE`pK{r!Ub;gF#7NsrcsR@5WsQ9YVtWd`)|S7|1++Df zH(gq;=-f;(p4y@_>-^3ucL%^$^E>ULjPqwlk-$Rw@hEDX?7QBx&3hHEB@oc zo?v*BKpYj?2}5M{CfYBIPbfzoT$8bi92B@8@XTdCqe+QHG<`81pffJ6?dO}XDN8nH zz={O3S6j5`S`JkW!v_8r!VwWTz>@}*2P1LxGri^q}_CX>`+2 z={#B})`KmnY0<@By)Ij;AxIk*_cCcc&UM@U5=G(<6V*8FU%#`vlbIX_!u}Y^jkgGd z9b_9eMp=oY6g9#cqZ76tCemd5-Zq!$q5nBjW6(T02zBH1*F0(5&s#{=MTAe_B09Q_e$c1J>UD;Pz4CSM-+1QCK&3$A(*u~H7^Ql%KAU7`1IdJ4v( zF`^z>F7|#U=H6TjGRcBS$VuVs1YFVQx>7lp3Xxdk&|sw{E`kHF;<*dT{X%V=5jIHBbyNjN@XluGOj>@3_O zdd?4?Kx&ft=h8kI`ywiNURmXmzm?g=bo1=-!Cv_$xpX**^BEX^C-hLuyVvuRZ*-To zeBKAotIaWiS90VAzwqxan)65V=q%LHcBHw-f9kr*EUftBTkHhIWNp0sIIp>|vJK+& z&w?x#=F*3sD?A}c*dc^97s0hdctn4fV1$oen6uimSXRB`T@5z$%<$cvE)i?k>rIr9DNsxB@_T?0`@v7I7qPBv&zS4sO_{ z{yGQZVXNoJ-i1^dXXTq2V_~hlX@ri;*XM%|XPFYtv%Xx7zo)*(RVo)8KYnyzt9+SF zLFvVjrx=V2h|LGc zpi_@H)#fRexVC(6E}&!&dv?FcQK59E`<_~SE+6rx7XHRL{ptvn0$C3)>^#GM?GfJ) zTFwHtbi8aFHF%E@SQg6{jp@3b>1Fe~U5k4Z8p{&lD7|jK5~;@jTBEtWT?35j`taV7 zcEQu`8aU_ZD5TM48jl0d6I|;O3XU&Wed~r|&o7$krl8Dllas4& zvRlru!sz8uEb~mhV*A%gg(hifcTftBD??A}$**MW21o?W_wUwniBPDws%-KMToXW0 z7G&-JXzx3qqFA=Io2;NBNDxpNi2{<-AW5CZ>x^`9f*Wa$ar#82tzhn{bhE4bL zBM$~%pGfb|9zjnF2vI28ODvSeqOnJLV)`6N!mq(!MyKUw8obhtAJBfhU3L58s7<_Q z{00xw82fajBAZ6=dWaKpZ0=PwG=xYfYoAam&7Kj{?i{Zpv4AJpTPp{1pXNj;4i%;&5v zkujbDfo65X1g!9?nxb0F!CedA&tB4&#bG-Gp&1D4^W86_z<7V=rzyYh?dD%LyK7?; zSxnANI`MW<)e|cXB=MnEu#1 z)Vp*K#jwPsdNBpxZ}qdUG}Xf9kn<+gOqKzC=TL}3JLYW)4dl8Hi}g`Z=cg5NHiPOa zZzTTXq?l^|`aW;1_+5%}3v8XEn7*MkZmPKlMXSJ+w+|4m2Y~^m@c#+xOvga(m=zex*II3^+)@pdigJB`%gYjTS_$PEv zu#+F@L*DT~^{34E`$u|JG9NT|#lpU_k)spgF*a3AgOGZnL?J1rR?^Z}RAV=0VQSa% z3bd?*zE^aXV@$0ONnD;r$Sn{wFR@pdxMAfzxzs;ZY2%nk2_D# zx1Wc5yFb|G`dkfq%I^(d#q8~_FOaXl-X>tAJMFh4FBfRf_8!Ja<9gwn(|L6}F?H(R zQyIaU3kvov=M&-%3Mp;V#p`6n7S868Or^4~lv1`RnOsYF3{z?u;}lET_p)kETW&wE?=-07!v{uAO({nO$l3>zLlfV(NY?)vx;43b#_)^lx z^v)yl2cFmlF45Amv*U&b#|xDW-!D`&&g;1pbULFWo7XCGAVS zgN_vU%3^*s$w~?Ok_X zZ=Bz8&c4jte^<<=M7A@tSa#i1_uXlBJ%w9LV&kNA1x7w%A>~|Uv}b9)dc>xafJ;JD z^kwB8WZvFvJ7BpjRG(*iC4t?|u8e$v>o7N_;%dEyCmXC)*oBP9rP!{F@$fvnPJI`K z$|ZSm%j~rs3*BkW8~Vbkk`FE4y$$WtCA%dC=Xse&-(sGw>7YY2t{uJP(3FNzqYnnP z=IOn)4A_vCpG;y;N=sILtXAN@@y)8cXYf*$K6f%wteIi%x#aMoWbXC*l~ ztLQAB|A7Nb+2>Pto2FlOC1bH=6E)ZU0}Cf#!X-;)dX=~PEJ_s>(~N`ipQKORVDjfy zJXH9y=f&@^^) zQ%tzAynJ>)FloKvVNHbVmS6RG-p0J?fvv;`j@3M0*}o=ECr!ssr%^^xzM_n!tbX)< zGA@{InL3gB8}%paG;8}0&L7|(5bihKP2DxzU7)EQ_%V@;>lTojm(v|iZe35~)b$K& zL^<5In`>Gwl)Omu=Q9;DWm3-7;1aH(ZhV}%1m2wfU{(F zSIl^AVWx|fTBPJ)=~i)*h{^HPAZ*C#I}=RGZ)01D(KukE;c{{$Cjj~RgzbG#^thKFz>cqrl~pNJR5>L z+|KXKKddTq8!z&*IH1!UO_o;kF+L*geJt3wsmAIV<&X8@h$Nq)EgmCsS#B}@7H&vz z2bFThJfRKRY}UA|xKs<>3vaDJ%83Tgtd`}$3gJkfJ%dg}_uZicdw4C;Qd?f3TMre< zv)1pC^Xg3v5Ut}$ioWe6#HX*@U8vXOd4cNIv1GlPOQ!^4?#floXR2^Lzjd}YKS(zV zFXZ+@&Zj2vRW{3dwhw1ViaIVuPP=AsjIZ82Cowq7r>+>YW!Y!>!Aj(%cA|-Y@phgf zPs=yN#RvEObdT!OGx_%)B9m8Yo4YW!J=;ZiCAg|HM@;xq(K&Tfrk-?pS}%)V zh>lBI!$iLYs&ASwRI49~B%s)QtGrh}Ln?)07$Ec|IvFs%#+zbB`&=EbGLwXkwM<6V zv{PMalh#2c-k*%$HTn2E!M4|W0ov-eO^tvVrm^$>4tZDF{r9FViAl?0DUpc7!7xd` z?c2r0rWjFi* zA}IAv>b>rY(4}kHE#`}9-X7x@2kK00bjIgb7I5uG9OK*_34JcuzMW&+<*R7L8zW;i zE3mJI`^j_jA~XCdwe+96Dx0t$?Y5L9%P^-W314B_y1>Xy;Z+_DsTV7>zdqA;B(n>^ zEanxS3&2ice78)NfgF^3_mNaOg;P+Pl?E)A{tVfT!}j+cm@Ip zTx$YXkssQOKj0bd4zD(M%bXgpD=l>^?87&p|Eyfvn-Q+d^G$CqBfLz#XMVPe+R+K^ z*P~c4SP?1;HlHo!>Cltc=P!Lh#oQcMKh;lYi}AdAbc*WXn~GCcRl>BMle zSG~)ctF$E8ub-&;oe-nrnQoov^r<$Mi#^M)k`F%9%RT$@ROkS*w||+Kt}NgZH!14$ z)oJi4>l!py-38UjWsGHf~7(XwTs?J&_ORy)TufnFO+jROHE z-62g-dy4Vf8ZU@6+@}z4n7OcYz7o%S6VO?{wJqqgB45=wF?%`lfK6>hyIhUkYAb0mYA zWb#j&Z(i_)`oFX9XFW>2c6^)uQv-QuraIA4f7B!abUXY)lDmz>>YF4XUjF+QcROcL z%AKcuHjYLTRzk2(q8lj7{Bky$V`&x7?wzJ6ZBP_McB%EfY&t@2M!EK@Q89f$b#ZJk zx}> z9H9Yykv>6)Ii7q)G~_#Z?eRVhG}*=I4I+f3$qwpNw?%bnC9c*w3qf!xZ&HsZGTWUa zEOmzX5}wO2^&tb*#q24UhU_7m$sC<;8x8!rbfd4s95n_r{asxgqPJ{z^{EcUO))zH zsuBd9Gjqqoxsylqm$E1IaxY~cC6m{=5=PvCdT~@FYi-_(?|LAW%*(ag>wCuv5S^I>mXpE%dGS!+Ua8H)McRmTe-qthk5bSn;Vv}T(J#@2B z(qzMj)<=5Yzq6^yrl8BjzNoDG=+&O&1RNEx0h|9gF)@t`#LZwgT5kkDzqz-X zb7(*mF%8*keoCA{Nkz0kNGN_G_Ef(4MKig3d~dG|)MprFJlSAx}*k2_i?&r>(ds2eAw)UVrJOpIpuJ> z#@!w2bpLv{a?;D1@yytb>A?ZSfSOO_a!Tk@A(>DPJ@=zx9c>)0M>@CV+i}75+iy-8 z_`70ZhJ6__xKMIq4DKmrJZ-c_D4xrxwD?#-m4uTHMtc)3d<#1L~6V<%&Du&m2&0|N7c%*zS_&8_m2E$3hkbnQ76IQ3`bPU3g66!u^4rh%D&B# zpDJarmTbsC8dKHfP`7{2OX0UGcRa!dp+u%;Dp1lKG zV_t>Oi_)C9H`HT;8m)eIakA-oUC;0As|`IfvuO=M@nt-&i)q>&m?8ao`xC29{h*gX zSR1vf65q;o4Qpz=FLv{EK33gBw0mxoa7nzgH};+j_wO;Rl*gGw?Cs(CFN|F5P5$RG}CH-Mj71p-%6+S!g*3 z>vR}d>$$eR_k1YE*HV>3J;mR09JVsH6rcu>TBrSC;j-`Ga) z>`S`7eKq3m$!NqtGy07l#m@VJR674T-WhZojdr6% zO?b)*)g@!qHvuMa%jNZjhNbVsBDvDR8%?@~jGcRNQ@DQXl~)HIO{*q(?uJwy5KbSr zC<7}+#4};lH?*G*BoxfujNY49*NEZ{rKgGmQgh9}DlW%W=zVK=w{|@_9iF z8H~u5em2H?)r4ku1d`SkB(6R691DN%!4|LM6+BLEF$g{Tjmn%SvEH3Pg*WrT$H&sY-MlnH_W@T!?4HSB$g0%XQ7yjq( zc4&BT#%&cyQNOnVvWl6i(G5?V6wDut@rXM^NP`1D_m>by>=SG;T#>d74#Jz zOM&B*OjD_>$fuQaP=%hZu`BIIJ4232>#n$vjVQCqp>^ImkGJY0q)$QLnMSWL0RF3D<`2GDHCsc3l*UtFii2j z@z)o2YeovikE8rQR*NntVQ%QB@+>^^l++KoB%SLk5Tmf_j zy-b2D?{zWcb@LH?vlp_cUts_oVeXKx_rE4#UL;w=SH+o;l8FVb9asRwYj=#saN9E zA#HI&pWf1>tKJQJv!`lsVeQ?MZ^VO@M&;%(g}sa%y-|b)CTzgYmtEa+fM&$9SyC9b z_8N}vvBND4=#NTr#S=U)Kl;X$omZ0M^)Ua_uE{lnHA|SImG|X5&-z6HSU%ZcBFs=n zcf+l5SjGO~gIC0aCr^>#O?vB5HDnIzY8$ROTyy2;>vV&>udYZR|LU?RdX+d+N2_Nt^A-5Ge9_QYZp#m*EV&l#ZG^|Ee46uJ zf!j;%8_SBeWkfD{ITb$Xp_&kT3c1%xr*m^xWX^cH@y4mB6%sceICxqq+|(()Jw^W- zPsOA^vU8cUJJi6?$}@kZ)^c>2!QLoKp-AI>m=3NgP9dBsz^d#+b!jrEfu@3F&J`iR zHoC9nTD-o}T3!y#rd^ZlSdy#&Jlit2{d66YIU4a$IjOcWk(Z0W-Qqm}9 z^^{t77te+Kyj3bgyvegbb6tfu`PFH;1j=PRM>xcY-nX1L?U^O6Nzcf3J6SIj<$M~{ zw;@|8{>t~M{P-z%SfbNK3x-?lhQ$fyw0akwd;{EG%U^%bvmw)7R&nKh<6RwX0=Bz4 zMpGH0mPdHol8-pJazDmV58%nebP=_m-D>F9ONDjBs2?{R9mnw{)Wcsm7<&?xIk4T} z%waMl+Jl(#u0Ir3U?qD#k7s5YsyiTwosovU54ioX51-1II*aPv7F~J!STeq0fRlAy zX@B(@!@ISPZYJyf?{~vI4E5}!jDo)ozqO(c>q^lw4WjUVCq~rgSea1XpS)BaqA#|@ zUmjN9;!TG_m5)gn4raED=+kw_#|et~s`%XPgc{Pfx3zE=S=p$yassc3Djjn1Ik}kA z@RMSrMZF}9-oCZ6vY}RuEVi{nw~`z1zaIlN=scLV{&8-X1y ztu5_Ax&mxg00m&{us*xwtv}O9`{i>c{$f}$^=#H#8&#E#q>FO=?L;qj92{<4H$Bbg zK&QPli{5%SGE!dp{t^07by&Z$$Mw0+isUinSS4+@UTv}xH+P47bT?J(47{F(F+>T7 zhzr|mg>g%IYAsiUp~n>#`JN=3cy*ti5pWaO*7{)KfQk`pwC*9^NRbwF)?w&NkobCz<_@k!87qUk0g7SV!n|B* z8Bq!GWQ$tf^=DLOs3zH|O(Gug#!;*t!`1>dJ<4TGeH86Pfc9)#bempxLD*N;f<&L( z(dVvh>(P~3BZx-6{J0b#XS0Hn&!{p|SSGEmL~k})(x}k2C+gCh3iz_r&8n;PE$c&- z-9#ou5uYfFBJGw{Y2t?XZwK?~>F0l``IJEluJE%LhL6zK!RuT0>0Wi#SP#_GHaw?I zGw^aKNU)e%_@=WXijtLTh%d%XoA>aRZf&=2&qXo|`+E`=uVP^!x4p}m zDYzfkAL(-3?K3JtJa+mqY^XD|>>f^3U13I#rW%NVz7)HmFUj+AK+*nnAtGfXJ}teG zn-i{a1$J)T#nnMgUoCk$Chp+UaMyRG?lW`T&jX|j-MESl(%G%a-aQ;}XbWPVs%Cu%ar zuDH(T+25JUqjBp{u8nP$u03@gdo`LDzj=YO@>8H6TQri9H4WRLez+@wN@A?+mBn&K ztFvrxDUH`RQKFiY{Dx(v4nsd~K9t9nXtJZfCRHQDszo0eJq>MRZe|TJ@`G_1#Wq(N zxXCbW+?qwdv7YjSpgxd$8!{~zG>@G1ntCrk{-Qa-YE~_z`fBtLtD8?!aQD?{ZAvkY z=phz2{K=F}rl!42jJnbjuMqUou)~zPQcK$1&8CQNPb@yP@RK0=??l|19iZtQOy;a+ zif(YZ;g?i>rpV+)bLbtnW@W4`goJxGP~If!()U?%$`Rh^3BzWo5DDZEL?Z3xK7F&h zZ+pEvLCY0E)b|fTk0-d9yUsBoj9B$%U(#W9bK@09F_vYBNwqQXNY@>#`MN-ook z@I*Uav0TwEuD=^1L4Di63^Pd6yFII!uE3=J$Vt*WR-*C|Vw%5d^NYjwpFE zqIg5zzi2M(xL04e)1ngcUQhLDwel@B6X_G70Gdt^sRA$XW`fp`^;)LfoUDb^vc#`X0bh!8m-vqcYez9EYb|wk=o$=ru0-CxyLeZhmO_ zSpLPsx|TZvenm(=KPEc1==7lK$LW;HiMO79IVO_>f0GDhRbjy+X1is{H+E%JeHx>D zsdU;;`F*3(Gf5TVuMbFrs+(VnMDQ?J2$1oovOLWgtyhvZrOja72EzP4-^r+;kd2im zR$X(@*1qSSeYeZ%#VCmdC%z zi5Kt%&J;ko759u9q9+&t+n4}ajBK)50ErA=PKEIFID__JTAeEZExvG7->L@^1k zEXV22`qbI7C??z|CeJtRz7W(dPCl6u{PF>?VKTi(pOO7ZIBZB+o-EduHDl|l-33i$ zdBW}tc|u;ZzOCSy_1eCAP4#qnV8rxC+QUOAlL!5EumcmeoBQTMvi;cqr%W;OwUDVrF4= z5(d=ko`sc`k}N5&>^%>64J$V}XGa%jCo3lp2=vdN;mgbE$Xi)BTY^>oGd`rKAQ-sQ z-NVhw%#jo~jGF?O6dv5O1^{JcPT&-{b^sngiAMnLPmX@yaFf7!6-8x501pojFa`er z92O9l(^8PpQP;Wwv9aW~bFs34c=7Xqp};)d?>X5(ltITu6%7R?h!>QP<2uCE)6C(X zhc`qLjM7Vr8wKP5e6TJ&ypuit$wo+UvL_-WBp@UvA}0RrMRNKSG0ABXV&YR|r%sce zY~axuGSV|AA5JRyy(m5r0Ra&y2{FlUS^l4PxX%E^DS!&NMu0~F;8WlcP~hRd0F0pI zM87rf9~}VT;S&%N5tD$;AOka$od=swKmazH2y8K!+aLTMAfzCoyvi>_d_mKUgvpgk z;9+$7DQ4N?I%=(+O%_3Ow@0T*X=pFf(X+C#U*q5u5*87KirtWtS5Q>CrL3Z@qk9*o zr*B|kX=QC=d(Y0@!_({j18<+8$4{OHKMQ&OA|^KOW&Epz#EdtYS#Ps*-sP5jC@m}h zSW)?@zTwN)#-`?$*51DUfx)5Sk#AGeGqZE^3yVw3TiZLkd;156sG}3P@Bo6}#RB)g zkL=&%0y_Z@|6~kEPUOPFzkeb)1tHN@equ@)O%gNL3rqsw(#o>Y>BV)YnFX~rsmuHzgWu>Noq_6QN4ev^>^QI9$-!~t?J?5#Q+@CAms zjQH{ba}l{Hg9GCACb0LU2O|%YHZs*Q=WxLG=xH3#K7|9w7N(Jyvv3qM2@ar8LM!w3 zgkm2vqCCTKz(Z18_oT5`v9!x@V{G?67NatT zZCW;I!%Ta6d;90B2faj(@2xR-S3dPjz_5BFrkVSXa6muro%c?k(x<$$n`R6SBGRFeKR-2go2$cj9pX#2dNAQ+pPa-~$fe zGM7fVAR4NX786G-j3^g7Ms&0iTE0^h2fRk2vv1>oDDuO2I57@b)W-pF#f<0*tPK}- zPQ9T%P+A{3IpmBgfFE23JKX?ThZyz50Yc=M0mMOK!1u`sbQ5BX7t@CksPCc>gWPDG2=mIe($zFI4=`LdB1VVtraTpj`S`tNP3i)))<<9@-I; zpSGij_^yNlJkAYPGou|zfkQ?tZPQohBl=)0@H-}60+A5}Mer8?6BW}AlO{5ieniEY z>5rJRayS4m#R1dTKpbQ};s;SA2nX;KBhkH#TcXHYkw=$tz+CwS9FWk}Q+NoWZGaPE z2WFlPm5Eb` zoQv>x{`ZgNMvwQn+>aUG`SKow49v~#mr0#7-0>YMb)2^r8?@PtnZp6k!nId$fCh44 zH=NvNZEX$lJ?@H=vxWN1{M_7uqc?ol0(*Jkm=Oo`Tmc^zK^iz<_Bjq<0)=4PLSl%( z_TGS_AI>Abd^&lu$abOgpMhy$-<;dQM1s8%iI}U)L2N59Ze4gVfqeu%C{lQ_H>IbI z{XkjMZLoL0Ahu^vDTT+e(&tG5j5Q7jGDgl`t+c}dL`cU@Gyx9qgk$E@K0Xkw z6~|5?*5&pRk##})ldsADB`p3W{P({R7KH?U!Qu(8`hzY1B8&e)WN{UNj3>QLD~<>X zBG8oHYr+9`uqP>v%Sn3}@~w~iWh>aXe<0(ig%7OjJL8P4gR=@x;2|xRcIa#55d--@ z0P+grON{>sK7!!)Cu{sGKDHA4SVj{EP^#@(fbc+$HMT&YGNq@T1ELvsL40X*V8;R1 zq!p2qfsAMUE*$G2>c4@!5tD%foDrr75L+#AKxT{mtTzt$CgqIw74rS)&5v1~alY8n zg`zmt@e`ZudNXvCj(u$wkhM3lM((`PpWn3_khO{&XNSedkLnzXId^QB^n6TsWuu?g zs~wMJ5>_w7$l?H4uaIQg$B!UK_0sW1)r3n&CXUsv6>?$2|3(4fvv9Qh_+Ln%1P(Zi zcP2sng9VmKPmRNiH!zgs=n7$S?5#IgCT9llVF1T!XW@Wm67=nlLC9T@7q$*ZVhs?2 zaX7#&c&hFuM6#Me@-#tfck^O zd{EnlV{eV(fGuhqpd`J;f>e|~I**te1UXcq`d&7c?O=%l%!EXj*CTeIh#$*P{WdH4 z7X_UBZ|e8L;t={g`BdQ}gx%JbrC&e~@*}cHx(HE%=w&I}2FckPqbOD~QS!L@Rqej( z$1uwU^m9z^l}j$pJ!_l6M-QJI#SbA$C6P$2kJ80Q@g+FmL5hh9++KTf4k=pWt2l0A zkzx&37G*qqHXw!EBg4RNb?*m^j}Ku+H0S5{g|JdiCUCDIki{t?rpD8X4=@y4pqh&T z3322QiVmD66$B?o7kP02M=z*elZ#_nN9&MBG>ADraPEPJ{P2GEsy_~p_d`sAnmP`c z*+qO&ok1LdQ>CpQNE850CU|W+W1pm<;9xJcMb5h+*HzIH*9i8KuxGuNw%V4a(lD(< zhrGv5i1~*&;8P)XM}5@q(gdi1yC4s)9(BMcD~}&&ko+rMTJSFmssBR7Uxt_ek$K{m z;pM+!c=?5j|3RpD613vq&lQD#G+F;Ly!@ZxSJQSwxcwrfkCi$=3TGYZwZSP}lk7M{2a3Uju!{`7#IWmw19YVO z&+zuwR$X(ZgJnw4)NJA#*11dmjppb<&&9Vl@QeECQ* z_{0AGK61S^Qd+b)duzuq{(IRRq9^U}e*CI0NCSgFPIzKTdclPTyWm+;BiIkLI3RWj zu}zW&PMxkzZeYlyx67Hq`BoCNc-y`t4gh~21H==jdJm+{|HK`RTd!UGQ_Z4WaKtKSMJY4bz=8AtLTo|M0Rqs$KxIB``?(FA2EMDUN` zmdapQzki+)Y><_c|}6zexx>q3RnzoID*Ie&6wfgK|%Zl*x{as#u5q{C1&LJWs z_R~2;pdx>-PXH>&|8ts<$lv=w0Q&P735f9t{rwyQV*LDnmjmo7{-5)SLjQhVAz?8Q z@UHtoULjGzpZY)u3UF-@5Nr)xu4 zL`dYP`k;JZAkn{-g@PmeXPSqb**ymP-_uUeqmuzFovkPmAR0)khK-RfT)0#nU$G{6y(3oV*GpDNi#Q( S-|j(SC