Python piexif.dump() Examples

The following are 30 code examples of piexif.dump(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module piexif , or try the search function .
Example #1
Source File: s_test.py    From Piexif with MIT License 6 votes vote down vote up
def test_load_name_dict(self):
        thumbnail_io = io.BytesIO()
        thumb = Image.open(INPUT_FILE2)
        thumb.thumbnail((40, 40))
        thumb.save(thumbnail_io, "JPEG")
        thumb.close()
        thumb_data = thumbnail_io.getvalue()
        exif_dict = {"0th":ZEROTH_IFD,
                     "Exif":EXIF_IFD,
                     "GPS":GPS_IFD,
                     "Interop":INTEROP_IFD,
                     "1st":FIRST_IFD,
                     "thumbnail":thumb_data}
        exif_bytes = piexif.dump(exif_dict)
        im = Image.new("RGB", (80, 80))

        o = io.BytesIO()
        im.save(o, format="jpeg", exif=exif_bytes)
        im.close()
        o.seek(0)
        exif = piexif.load(o.getvalue(), True)
        print(exif) 
Example #2
Source File: s_test.py    From Piexif with MIT License 6 votes vote down vote up
def test_dump_and_load_specials2(self):
        """test dump and load special types(SingedByte, SiginedShort, DoubleFloat)"""
        zeroth_ifd_original = {
            ImageIFD.ZZZTestSByte:(-128, -128),
            ImageIFD.ZZZTestSShort:(-32768, -32768),
            ImageIFD.ZZZTestDFloat:(1.0e-100, 1.0e-100),
        }
        exif_dict = {"0th":zeroth_ifd_original}
        exif_bytes = piexif.dump(exif_dict)

        exif = piexif.load(exif_bytes)
        zeroth_ifd = exif["0th"]
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestSByte],
            zeroth_ifd[ImageIFD.ZZZTestSByte]
        )
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestSShort],
            zeroth_ifd[ImageIFD.ZZZTestSShort]
        )
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestDFloat],
            zeroth_ifd[ImageIFD.ZZZTestDFloat]
        ) 
Example #3
Source File: s_test.py    From Piexif with MIT License 6 votes vote down vote up
def test_dump_and_load_specials(self):
        """test dump and load special types(SingedByte, SiginedShort, DoubleFloat)"""
        zeroth_ifd_original = {
            ImageIFD.ZZZTestSByte:-128,
            ImageIFD.ZZZTestSShort:-32768,
            ImageIFD.ZZZTestDFloat:1.0e-100,
        }
        exif_dict = {"0th":zeroth_ifd_original}
        exif_bytes = piexif.dump(exif_dict)

        exif = piexif.load(exif_bytes)
        zeroth_ifd = exif["0th"]
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestSByte],
            zeroth_ifd[ImageIFD.ZZZTestSByte]
        )
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestSShort],
            zeroth_ifd[ImageIFD.ZZZTestSShort]
        )
        self.assertEqual(
            zeroth_ifd_original[ImageIFD.ZZZTestDFloat],
            zeroth_ifd[ImageIFD.ZZZTestDFloat]
        ) 
Example #4
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_fail3(self):
        exif_ifd = {ExifIFD.OECF: 1}
        exif_dict = {"Exif":exif_ifd}
        with self.assertRaises(ValueError):
            piexif.dump(exif_dict) 
Example #5
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_insert(self):
        """Can PIL open WebP that is inserted exif?"""
        IMAGE_DIR = "tests/images/"
        OUT_DIR = "tests/images/out/"
        files = [
            "tool1.webp",
            "pil1.webp",
            "pil2.webp",
            "pil3.webp",
            "pil_rgb.webp",
            "pil_rgba.webp",
        ]

        exif_dict = {
            "0th":{
                piexif.ImageIFD.Software: b"PIL",
                piexif.ImageIFD.Make: b"Make",
            }
        }
        exif_bytes = piexif.dump(exif_dict)
        
        for filename in files:
            try:
                Image.open(IMAGE_DIR + filename)
            except:
                print("Pillow can't read {}".format(filename))
                continue
            piexif.insert(exif_bytes, IMAGE_DIR + filename, OUT_DIR + "ii_" + filename)
            Image.open(OUT_DIR + "ii_" + filename) 
Example #6
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_insert_exif(self):
        """Can PIL open WebP that is inserted exif?"""
        IMAGE_DIR = "tests/images/"
        OUT_DIR = "tests/images/out/"
        files = [
            "tool1.webp",
            "pil1.webp",
            "pil2.webp",
            "pil3.webp",
            "pil_rgb.webp",
            "pil_rgba.webp",
        ]

        exif_dict = {
            "0th":{
                piexif.ImageIFD.Software: b"PIL",
                piexif.ImageIFD.Make: b"Make",
            }
        }

        for filename in files:
            try:
                Image.open(IMAGE_DIR + filename)
            except:
                print("Pillow can't read {}".format(filename))
                continue

            with open(IMAGE_DIR + filename, "rb") as f:
                data = f.read()
            exif_bytes = piexif.dump(exif_dict)
            exif_inserted = _webp.insert(data, exif_bytes)
            with open(OUT_DIR + "i_" + filename, "wb") as f:
                f.write(exif_inserted)
            Image.open(OUT_DIR + "i_" + filename) 
Example #7
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_encode_bad_encoding(self):
        """De we gracefully handle bad input when encoding?"""
        self.assertRaises(ValueError, helper.UserComment.dump, 'hello world', 'koi-8r') 
Example #8
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_encode_unicode(self):
        """Do we encode Unicode correctly?"""
        text = '\u3053\u3093\u306b\u3061\u306f\u4e16\u754c'
        expected = b'\x55\x4e\x49\x43\x4f\x44\x45\x00' + text.encode('utf_16_be')
        actual = helper.UserComment.dump(text, encoding='unicode')
        self.assertEqual(expected, actual) 
Example #9
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_encode_ascii(self):
        """Do we encode ASCII correctly?"""
        text = 'hello world'
        expected = b'\x41\x53\x43\x49\x49\x00\x00\x00hello world'
        actual = helper.UserComment.dump(text, encoding='ascii')
        self.assertEqual(expected, actual) 
Example #10
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_user_comment(self):
        # ascii
        header = b"\x41\x53\x43\x49\x49\x00\x00\x00"
        string = u"abcd"
        binary = header + string.encode("ascii")
        result = helper.UserComment.dump(string, "ascii")
        self.assertEqual(binary, result)

        # jis
        header = b"\x4a\x49\x53\x00\x00\x00\x00\x00"
        string = u"abcd"
        binary = header + string.encode("shift_jis")
        result = helper.UserComment.dump(string, "jis")
        self.assertEqual(binary, result)

        # unicode
        header = b"\x55\x4e\x49\x43\x4f\x44\x45\x00"
        string = u"abcd"
        binary = header + string.encode("utf-16-be")
        result = helper.UserComment.dump(string, "unicode")
        self.assertEqual(binary, result)

        # undefined
        header = b"\x00\x00\x00\x00\x00\x00\x00\x00"
        string = u"abcd"
        binary = header + string.encode("latin")
        self.assertRaises(ValueError, helper.UserComment.dump, string, "undefined") 
Example #11
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_insert_fail2(self):
        exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD}
        exif_bytes = piexif.dump(exif_dict)
        with  self.assertRaises(ValueError):
            piexif.insert(exif_bytes, I1, False)

# ------ 
Example #12
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_insert_fail1(self):
        with open(INPUT_FILE1, "rb") as f:
            data = f.read()
        with open("insert.jpg", "wb+") as f:
            f.write(data)
        exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD}
        exif_bytes = piexif.dump(exif_dict)
        with  self.assertRaises(ValueError):
            piexif.insert(exif_bytes, INPUT_FILE_TIF)
        os.remove("insert.jpg") 
Example #13
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_insert_m(self):
        """'insert' on memory.
        """
        exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD}
        exif_bytes = piexif.dump(exif_dict)
        o = io.BytesIO()
        piexif.insert(exif_bytes, I1, o)
        self.assertEqual(o.getvalue()[0:2], b"\xff\xd8")
        exif = load_exif_by_PIL(o) 
Example #14
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_roundtrip_files(self):
        files = glob.glob(os.path.join("tests", "images", "r_*.jpg"))
        for input_file in files:
            print(input_file)
            exif = piexif.load(input_file)
            exif_bytes = piexif.dump(exif)
            o = io.BytesIO()
            piexif.insert(exif_bytes, input_file, o)
            e = piexif.load(o.getvalue())

            t = e.pop("thumbnail")
            thumbnail = exif.pop("thumbnail")
            if t is not None:
                if not (b"\xe0" <= thumbnail[3:4] <= b"\xef"):
                    self.assertEqual(t, thumbnail)
                else:
                    print("Given JPEG doesn't follow exif thumbnail standard. "
                            "APPn segments in thumbnail should be removed, "
                            "whereas thumbnail JPEG has it. \n: " +
                            input_file)
                exif["1st"].pop(513)
                e["1st"].pop(513)
                exif["1st"].pop(514)
                e["1st"].pop(514)
            for ifd in e:
                if ifd == "0th":
                    if ImageIFD.ExifTag in exif["0th"]:
                        exif["0th"].pop(ImageIFD.ExifTag)
                        e["0th"].pop(ImageIFD.ExifTag)
                    if ImageIFD.GPSTag in exif["0th"]:
                        exif["0th"].pop(ImageIFD.GPSTag)
                        e["0th"].pop(ImageIFD.GPSTag)
                elif ifd == "Exif":
                    if ExifIFD.InteroperabilityTag in exif["Exif"]:
                        exif["Exif"].pop(ExifIFD.InteroperabilityTag)
                        e["Exif"].pop(ExifIFD.InteroperabilityTag)
                for key in exif[ifd]:
                    self.assertEqual(exif[ifd][key], e[ifd][key])
            print(" - pass")

# transplant ------ 
Example #15
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_and_load2(self):
        thumbnail_io = io.BytesIO()
        thumb = Image.open(INPUT_FILE2)
        thumb.thumbnail((40, 40))
        thumb.save(thumbnail_io, "JPEG")
        thumb.close()
        thumb_data = thumbnail_io.getvalue()
        exif_dict = {"0th":ZEROTH_IFD,
                     "Exif":EXIF_IFD,
                     "GPS":GPS_IFD,
                     "Interop":INTEROP_IFD,
                     "1st":FIRST_IFD,
                     "thumbnail":thumb_data}
        exif_bytes = piexif.dump(exif_dict)
        im = Image.new("RGB", (80, 80))

        o = io.BytesIO()
        im.save(o, format="jpeg", exif=exif_bytes)
        im.close()
        o.seek(0)
        exif = piexif.load(o.getvalue())
        exif["0th"].pop(ImageIFD.ExifTag) # pointer to exif IFD
        exif["0th"].pop(ImageIFD.GPSTag) # pointer to GPS IFD
        exif["Exif"].pop(ExifIFD.InteroperabilityTag)
        self.assertDictEqual(ZEROTH_IFD, exif["0th"])
        self.assertDictEqual(EXIF_IFD, exif["Exif"])
        self.assertDictEqual(GPS_IFD, exif["GPS"])
        self.assertDictEqual(INTEROP_IFD, exif["Interop"])
        exif["1st"].pop(513) # pointer to exif IFD
        exif["1st"].pop(514) # pointer to GPS IFD
        self.assertDictEqual(FIRST_IFD, exif["1st"])
        Image.open(io.BytesIO(exif["thumbnail"])).close() 
Example #16
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_fail4(self):
        exif_ifd = {ExifIFD.OECF: (1, 2, 3, 4, 5)}
        exif_dict = {"Exif":exif_ifd}
        with self.assertRaises(ValueError):
            piexif.dump(exif_dict)

# load and dump ------ 
Example #17
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_fail2(self):
        exif_ifd = {ExifIFD.DateTimeOriginal: 123}
        exif_dict = {"Exif":exif_ifd}
        with self.assertRaises(ValueError):
            piexif.dump(exif_dict) 
Example #18
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump_fail(self):
        with open(os.path.join("tests", "images", "large.jpg"), "rb") as f:
            thumb_data = f.read()
        exif_dict = {"0th":ZEROTH_IFD,
                     "Exif":EXIF_IFD,
                     "GPS":GPS_IFD,
                     "Interop":INTEROP_IFD,
                     "1st":FIRST_IFD,
                     "thumbnail":thumb_data}
        with self.assertRaises(ValueError):
            piexif.dump(exif_dict) 
Example #19
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_dump(self):
        exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD}
        t = time.time()
        exif_bytes = piexif.dump(exif_dict)
        t_cost = time.time() - t
        print("'dump': {}[sec]".format(t_cost))
        im = Image.new("RGB", (8, 8))

        o = io.BytesIO()
        im.save(o, format="jpeg", exif=exif_bytes)
        im.close()
        o.seek(0)
        exif = load_exif_by_PIL(o) 
Example #20
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_load_unicode_filename(self):
        input_file = os.path.join(u"tests", u"images", u"r_sony.jpg")
        exif = piexif.load(input_file)
        e = load_exif_by_PIL(input_file)
        self._compare_piexifDict_PILDict(exif, e, p=False)

# dump ------ 
Example #21
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_load_from_pilImage_property(self):
        o = io.BytesIO()
        i = Image.open(INPUT_FILE1)
        exif = i.info["exif"]
        exif_dict = piexif.load(exif)
        exif_bytes = piexif.dump(exif_dict)
        i.save(o, "jpeg", exif=exif_bytes)
        i.close()
        o.seek(0)
        Image.open(o).close() 
Example #22
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_load_tif_m(self):
        with open(INPUT_FILE_TIF, "rb") as f:
            tif = f.read()
        exif = piexif.load(tif)
        zeroth_ifd = exif["0th"]
        exif_bytes = piexif.dump({"0th":zeroth_ifd})

        im = Image.new("RGB", (8, 8))
        o = io.BytesIO()
        im.save(o, format="jpeg", exif=exif_bytes)
        im.close()
        exif2 = piexif.load(o.getvalue())
        zeroth_ifd2 = exif2["0th"]
        self.assertDictEqual(zeroth_ifd, zeroth_ifd2) 
Example #23
Source File: s_test.py    From Piexif with MIT License 5 votes vote down vote up
def test_load_tif(self):
        exif = piexif.load(INPUT_FILE_TIF)
        zeroth_ifd = exif["0th"]
        exif_bytes = piexif.dump({"0th":zeroth_ifd})

        im = Image.new("RGB", (8, 8))
        o = io.BytesIO()
        im.save(o, format="jpeg", exif=exif_bytes)
        im.close()
        exif2 = piexif.load(o.getvalue())
        zeroth_ifd2 = exif2["0th"]
        self.assertDictEqual(zeroth_ifd, zeroth_ifd2) 
Example #24
Source File: exif_write.py    From mapillary_tools with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def write(self, filename=None):
        """Save exif data to file."""
        if filename is None:
            filename = self._filename

        exif_bytes = piexif.dump(self._ef)

        with open(self._filename, "rb") as fin:
            img = fin.read()
        try:
            piexif.insert(exif_bytes, img, filename)

        except IOError:
            type, value, traceback = sys.exc_info()
            print >> sys.stderr, "Error saving file:", value 
Example #25
Source File: exif_datetime.py    From icloud_photos_downloader with MIT License 5 votes vote down vote up
def set_photo_exif(path, date):
    """Set EXIF date on a photo, do nothing if there is an error"""
    try:
        exif_dict = piexif.load(path)
        exif_dict.get("1st")[306] = date
        exif_dict.get("Exif")[36867] = date
        exif_dict.get("Exif")[36868] = date
        exif_bytes = piexif.dump(exif_dict)
        piexif.insert(exif_bytes, path)
    except (ValueError, InvalidImageDataError):
        logger = setup_logger()
        logger.debug("Error setting EXIF data for %s", path)
        return 
Example #26
Source File: main.py    From spider_python with Apache License 2.0 5 votes vote down vote up
def write_image(self, image_path, gps_long, gps_lati):
        """
        修改文件夹下所有文件的属性
        :param image_path: 文件夹路径
        :return:
        """
        # 读取图片
        img = Image.open(image_path)

        try:
            exif_dict = piexif.load(img.info['exif'])
        except:
            print('加载文件地理位置异常!')
            return

        # 修改地理位置
        # GPS GPSLatitudeRef:N
        # GPS GPSLatitude:[22, 32, 189/20]
        # GPS GPSLongitudeRef:E
        # GPS GPSLongitude:[114, 1, 689/20]
        exif_dict['GPS'][2] = gps_to_dms(gps_lati)
        exif_dict['GPS'][4] = gps_to_dms(gps_long)

        exif_bytes = piexif.dump(exif_dict)

        # 写入到新的图片中去
        img.save(image_path, 'jpeg', exif=exif_bytes) 
Example #27
Source File: exif_processing.py    From upload-scripts with MIT License 5 votes vote down vote up
def add_gps_tags(path: str, gps_tags: {str: any}):
    """This method will add gps tags to the photo found at path"""
    exif_dict = piexif.load(path)
    for tag, tag_value in gps_tags.items():
        exif_dict["GPS"][tag] = tag_value
    exif_bytes = piexif.dump(exif_dict)
    piexif.insert(exif_bytes, path) 
Example #28
Source File: imageprocessing.py    From fastclass with Apache License 2.0 4 votes vote down vote up
def resize(
    files: List[str],
    outpath: Optional[str] = None,
    size: Tuple[int, int] = (299, 299),
    urls: Optional[Dict[str, str]] = None,
) -> Optional[Dict[str, str]]:
    """Resize image to specified size"""
    should_resize = size[0] > 0 and size[1] > 0
    if should_resize:
        print(f"(2) Resizing images to {size}")
    else:
        print("Not resizing images")

    sources = None
    if urls:
        sources = {}

    with tqdm(total=len(files)) as t:
        for fcnt, f in enumerate(files):
            im = Image.open(f)
            if should_resize:
                try:
                    im.thumbnail(size, Image.ANTIALIAS)
                except OSError:
                    # skip truncated files
                    continue

                bg = Image.new("RGBA", size, (255, 255, 255, 0))
                bg.paste(
                    im,
                    (int((size[0] - im.size[0]) / 2), int((size[1] - im.size[1]) / 2)),
                )

            else:
                bg = im

            try:
                bg = bg.convert("RGB")
            except OSError:
                t.update(1)
                continue

            fname, _ = os.path.splitext(os.path.basename(f))
            out = os.path.join(outpath, fname + ".jpg")
            bg.save(out)

            if urls:
                # embed source in image
                tag_data = piexif.helper.UserComment.dump(
                    "source: " + urls[os.path.basename(f)]
                )
                exif_dict = piexif.load(out)
                exif_dict["Exif"][piexif.ExifIFD.UserComment] = tag_data
                exif_bytes = piexif.dump(exif_dict)
                bg.save(out, exif=exif_bytes)

                sources[os.path.basename(out)] = urls[os.path.basename(f)]

            t.update(1)

    return sources 
Example #29
Source File: s_test.py    From Piexif with MIT License 4 votes vote down vote up
def test_dump_and_load3(self):
        ascii_v = ["a", "ab", "abc", "abcd", "abcde"]
        undefined_v = [b"\x00",
                       b"\x00\x01",
                       b"\x00\x01\x02",
                       b"\x00\x01\x02\x03",
                       b"\x00\x01\x02\x03\x04"]
        byte_v = [255,
                  (255, 254),
                  (255, 254, 253),
                  (255, 254, 253, 252),
                  (255, 254, 253, 252, 251)]
        short_v = [65535,
                   (65535, 65534),
                   (65535, 65534, 65533),
                   (65535, 65534, 65533, 65532),
                   (65535, 65534, 65533, 65532, 65531)]
        long_v = [4294967295,
                  (4294967295, 4294967294),
                  (4294967295, 4294967294, 4294967293),
                  (4294967295, 4294967294, 4294967293, 4294967292),
                  (5, 4, 3, 2, 1)]
        rational_v = [(4294967295, 4294967294),
                      ((4294967295, 4294967294), (4294967293, 4294967292)),
                      ((1, 2), (3, 4), (5, 6)),
                      ((1, 2), (3, 4), (5, 6), (7, 8)),
                      ((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))]
        srational_v = [(2147483647, -2147483648),
                       ((2147483647, -2147483648), (2147483645, 2147483644)),
                       ((1, 2), (3, 4), (5, 6)),
                       ((1, 2), (3, 4), (5, 6), (7, 8)),
                       ((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))]
        for x in range(5):
            exif_dict = {
                "0th":{ImageIFD.ProcessingSoftware:ascii_v[x],
                       ImageIFD.InterColorProfile:undefined_v[x],
                       ImageIFD.SubfileType:short_v[x],
                       ImageIFD.WhitePoint:rational_v[x],
                       ImageIFD.BlackLevelDeltaH:srational_v[x]},
                "Exif":{ExifIFD.ISOSpeed:long_v[x]},
                "GPS":{GPSIFD.GPSVersionID:byte_v[x]},}
            exif_bytes = piexif.dump(exif_dict)
            e = piexif.load(exif_bytes)
            self.assertEqual(
                e["0th"][ImageIFD.ProcessingSoftware].decode("latin1"),
                ascii_v[x])
            self.assertEqual(
                e["0th"][ImageIFD.InterColorProfile], undefined_v[x])
            self.assertEqual(e["0th"][ImageIFD.SubfileType], short_v[x])
            self.assertEqual(e["0th"][ImageIFD.WhitePoint], rational_v[x])
            self.assertEqual(
                e["0th"][ImageIFD.BlackLevelDeltaH], srational_v[x])
            self.assertEqual(e["Exif"][ExifIFD.ISOSpeed], long_v[x])
            self.assertEqual(e["GPS"][GPSIFD.GPSVersionID], byte_v[x]) 
Example #30
Source File: image_views.py    From cccatalog-api with MIT License 4 votes vote down vote up
def get(self, request, identifier, format=None):
        params = WatermarkQueryStringSerializer(data=request.query_params)
        if not params.is_valid():
            return input_error_response()
        try:
            image_record = Image.objects.get(identifier=identifier)
        except Image.DoesNotExist:
            return Response(status=404, data='Not Found')
        image_url = str(image_record.url)
        image_info = {
            'title': image_record.title,
            'creator': image_record.creator,
            'license': image_record.license,
            'license_version': image_record.license_version
        }
        # Create the actual watermarked image.
        watermarked, exif = watermark(
            image_url, image_info, params.data['watermark']
        )
        # Re-insert EXIF metadata.
        if exif:
            exif_bytes = piexif.dump(exif)
        else:
            exif_bytes = None
        img_bytes = io.BytesIO()
        _save_wrapper(watermarked, exif_bytes, img_bytes)
        if params.data['embed_metadata']:
            # Embed ccREL metadata with XMP.
            work_properties = {
                'creator': image_record.creator,
                'license_url': image_record.license_url,
                'attribution': image_record.attribution,
                'work_landing_page': image_record.foreign_landing_url,
                'identifier': str(image_record.identifier)
            }
            try:
                with_xmp = ccrel.embed_xmp_bytes(img_bytes, work_properties)
                return FileResponse(with_xmp, content_type='image/jpeg')
            except (libxmp.XMPError, AttributeError) as e:
                # Just send the EXIF-ified file if libxmp fails to add metadata.
                log.error(
                    'Failed to add XMP metadata to {}'
                    .format(image_record.identifier)
                )
                log.error(e)
                response = HttpResponse(content_type='image/jpeg')
                _save_wrapper(watermarked, exif_bytes, response)
                return response
        else:
            response = HttpResponse(img_bytes, content_type='image/jpeg')
            _save_wrapper(watermarked, exif_bytes, response)
            return response