You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Django ResizedImageField转WebP时iPhone原图旋转异常求助

Django中ResizedImageField转换iPhone原图为WebP时旋转90度的解决方法

问题原因

iPhone拍摄的原图包含EXIF方向元数据,用于记录拍摄时的设备姿态(比如竖屏拍摄时会标记方向)。大部分图片查看器会自动读取该元数据纠正显示方向,但django-resized在转换为WebP格式时,若未正确处理该元数据,会导致图片像素本身未旋转,仅靠元数据标记方向——部分场景下读取元数据失败,最终显示时出现90度旋转。而经过编辑的图片已经将旋转操作直接应用到像素数据中,因此不存在这个问题。


解决方案

1. 修正django-resized旋转配置

你当前设置了DJANGORESIZED_DEFAULT_NORMALIZE_ROTATION = False,这个参数的作用是是否根据EXIF元数据自动纠正图片旋转,设为False会跳过该处理,这正是问题核心。修改settings.py:

DJANGORESIZED_DEFAULT_NORMALIZE_ROTATION = True

保存配置后重新上传iPhone原图测试,django-resized会自动读取EXIF方向信息并纠正旋转后再保存为WebP。

2. 升级django-resized版本

你使用的1.0.2版本可能存在WebP格式下EXIF旋转处理的bug,升级到最新稳定版可修复已知兼容性问题:

pip install --upgrade django-resized

3. 手动添加EXIF旋转处理(兜底方案)

如果上述方法仍未解决问题,可在模型中通过Pillow手动处理EXIF旋转,重写save方法:

首先导入依赖模块:

from PIL import Image, ExifTags
import os
from django.conf import settings

修改ArticleImage模型:

class ArticleImage(models.Model):
    upload_file = ResizedImageField(size=None, upload_to='article/image/%Y/%m/%d/', quality=95, force_format='WEBP', null=True, blank=False)
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='image', null=True)

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self.upload_file:
            file_path = os.path.join(settings.MEDIA_ROOT, self.upload_file.path)
            try:
                image = Image.open(file_path)
                # 获取EXIF方向标签
                orientation_tag = next(k for k, v in ExifTags.TAGS.items() if v == 'Orientation')
                exif_data = image._getexif()
                if exif_data and orientation_tag in exif_data:
                    orientation = exif_data[orientation_tag]
                    # 根据EXIF方向旋转图片
                    if orientation == 3:
                        image = image.rotate(180, expand=True)
                    elif orientation == 6:
                        image = image.rotate(270, expand=True)
                    elif orientation == 8:
                        image = image.rotate(90, expand=True)
                # 覆盖保存处理后的图片
                image.save(file_path, format='WEBP', quality=95)
            except (AttributeError, KeyError, IndexError, FileNotFoundError):
                # 无EXIF信息或处理失败时跳过
                pass

    def delete(self, *args, **kargs):
        if self.upload_file:
            os.remove(os.path.join(settings.MEDIA_ROOT, self.upload_file.path))
        super(ArticleImage, self).delete(*args, **kargs)

    def filename(self):
        return os.path.basename(self.upload_file.name)

该方法会在图片保存后,手动读取EXIF信息并纠正旋转,确保WebP图片的像素方向正确。


内容的提问来源于stack exchange,提问作者Won Jun Jang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:32:28