{"id":3210,"library":"piexif","title":"Piexif","description":"Piexif is a pure Python library designed to simplify EXIF data manipulation. It enables reading, writing, and removing EXIF tags from JPEG, WebP, and TIFF image files without relying on external image processing libraries. The library's current version is 1.1.3, and releases are made as needed to address issues or add features.","status":"active","version":"1.1.3","language":"en","source_language":"en","source_url":"https://github.com/hMatoba/Piexif","tags":["EXIF","metadata","image","jpeg","webp","tiff","pure-python"],"install":[{"cmd":"pip install piexif","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"While piexif is pure Python and has no hard dependencies, it is very commonly used in conjunction with Pillow (PIL Fork) for image loading, manipulation, and saving, especially when creating new images or handling complex image data flows.","package":"Pillow","optional":true}],"imports":[{"symbol":"piexif","correct":"import piexif"},{"note":"IFD constants and TAGS dictionary are attributes of the top-level piexif module.","symbol":"ImageIFD, ExifIFD, GPSIFD, InteropIFD, TAGS","correct":"import piexif\n# Access constants like:\npiexif.ImageIFD.Make\npiexif.TAGS['Exif'][piexif.ExifIFD.DateTimeOriginal]"}],"quickstart":{"code":"import piexif\nfrom PIL import Image\nimport os\n\n# Create a dummy JPEG file for demonstration\ndummy_image_path = \"dummy_image_with_exif.jpg\"\nnew_image_path = \"output_image_with_modified_exif.jpg\"\n\n# Create a simple image (requires Pillow)\nimg = Image.new('RGB', (60, 30), color = 'red')\nimg.save(dummy_image_path)\n\n# 1. Load EXIF data\ntry:\n    # Create a minimal EXIF dictionary\n    zeroth_ifd = {\n        piexif.ImageIFD.Make: \"PiexifTest\",\n        piexif.ImageIFD.XResolution: (72, 1),\n        piexif.ImageIFD.YResolution: (72, 1)\n    }\n    exif_ifd = {\n        piexif.ExifIFD.DateTimeOriginal: \"2026:04:11 12:34:56\"\n    }\n    exif_dict_initial = {\"0th\": zeroth_ifd, \"Exif\": exif_ifd, \"GPS\": {}, \"Interop\": {}, \"1st\": {}, \"thumbnail\": None}\n    exif_bytes_initial = piexif.dump(exif_dict_initial)\n\n    img.save(dummy_image_path, exif=exif_bytes_initial)\n\n    exif_dict = piexif.load(dummy_image_path)\n    print(\"Original Camera Make:\", exif_dict[\"0th\"][piexif.ImageIFD.Make])\n\n    # 2. Modify an EXIF tag\n    exif_dict[\"0th\"][piexif.ImageIFD.Make] = \"PiexifModified\"\n\n    # 3. Dump the modified EXIF data to bytes\n    exif_bytes = piexif.dump(exif_dict)\n\n    # 4. Insert the new EXIF data into an image (or save with Pillow)\n    img_to_modify = Image.open(dummy_image_path)\n    img_to_modify.save(new_image_path, exif=exif_bytes)\n\n    # 5. Verify the change\n    modified_exif_dict = piexif.load(new_image_path)\n    print(\"Modified Camera Make:\", modified_exif_dict[\"0th\"][piexif.ImageIFD.Make])\n\nfinally:\n    # Clean up dummy files\n    if os.path.exists(dummy_image_path):\n        os.remove(dummy_image_path)\n    if os.path.exists(new_image_path):\n        os.remove(new_image_path)\n","lang":"python","description":"This quickstart demonstrates how to load EXIF data from a JPEG image, modify a tag (e.g., the camera make), and then save the image with the updated EXIF information using piexif, often in conjunction with Pillow for image handling."},"warnings":[{"fix":"Update code to use `piexif.ImageIFD` for 0th IFD tags and pass a single dictionary (e.g., `{'0th': zeroth_ifd, 'Exif': exif_ifd, 'GPS': gps_ifd}`) to `piexif.dump()`.","message":"Version 1.0.0 introduced significant breaking changes. `piexif.ZerothIFD` was renamed to `piexif.ImageIFD`, and the `dump` function's argument signature changed from accepting three separate IFD dictionaries to a single combined dictionary.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"Convert negative coordinates to positive values and explicitly set the `GPSLatitudeRef` ('N' or 'S') and `GPSLongitudeRef` ('E' or 'W') tags to indicate the correct hemisphere. Custom helper functions for this conversion are often required.","message":"Piexif has known issues when handling negative GPS coordinates (longitude/latitude). Directly passing negative values can lead to errors during `piexif.dump()` due to expected unsigned values.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always check for the existence of the 'exif' key using `.get()` before attempting to load: `exif_bytes = img.info.get('exif'); if exif_bytes: exif_dict = piexif.load(exif_bytes)`.","message":"When loading EXIF data from an image, especially when integrating with Pillow (`PIL.Image.open(filename).info[\"exif\"]`), attempting to access `img.info[\"exif\"]` directly might raise a `KeyError` if the image file contains no EXIF data.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure input JPEG data is valid and well-formed. Implement robust error handling (e.g., `try-except InvalidImageDataError`) around `piexif` operations when dealing with user-provided or potentially malformed image files. Inspect the source image or thumbnail data if this error occurs.","message":"Functions like `piexif.dump()` or `piexif.transplant()` can raise an `InvalidImageDataError` if the input image data is malformed, corrupted, or contains an empty thumbnail segment, which `piexif` cannot process. This was partially addressed in version 1.0.12 with more explicit error handling.","severity":"gotcha","affected_versions":"<1.0.12 (less explicit errors), All versions (still possible with bad data)"},{"fix":"Manually update `exif_dict[\"0th\"][piexif.ImageIFD.XResolution]` and `exif_dict[\"0th\"][piexif.ImageIFD.YResolution]` with the new `(width, 1)` and `(height, 1)` tuples respectively, after resizing the image and before dumping the EXIF data.","message":"When resizing an image with Pillow and then saving it with modified EXIF data, the `XResolution` and `YResolution` tags in the `0th IFD` might not automatically update to reflect the new dimensions. This can lead to EXIF metadata that doesn't match the actual image size.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}