fix: apply EXIF orientation to service record images in PDF/DOCX
Some checks failed
ERP CI/CD Pipeline / test (push) Has been cancelled
ERP CI/CD Pipeline / Deploy (server git pull + compose) (push) Has been cancelled

Smartphone photos often have EXIF orientation metadata (tags 6, 8, 3)
that rotates the display but doesn't transform the pixel data. When
PDFs/DOCX embedded images without applying this metadata, they appear
rotated 90/180/270 degrees.

Use ImageOps.exif_transpose(img) before resize/convert in both
_compress_image_for_pdf() and _compress_image_for_docx() to read EXIF
orientation and transpose the actual pixel data accordingly. This is
a standard Pillow function and is a no-op for images without EXIF.

Add regression test test_compress_image_for_docx_handles_exif_orientation
to verify images with EXIF tag 0x0112 (orientation=6) are transposed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-08-31 11:08:16 +02:00
parent aa690d4ac4
commit b985c285f9
2 changed files with 17 additions and 1 deletions

View File

@@ -252,6 +252,20 @@ class WorkOrderImagesEndpointTests(TestCase):
self.assertIsNotNone(result)
self.assertGreater(len(result.getvalue()), 0)
def test_compress_image_for_docx_handles_exif_orientation(self):
exif = Image.Exif()
exif[0x0112] = 6
file = BytesIO()
Image.new('RGB', (3000, 2000), color='green').save(file, format='JPEG', quality=85, exif=exif.tobytes())
file.seek(0)
uploaded = SimpleUploadedFile('rotated-phone.jpg', file.getvalue(), content_type='image/jpeg')
result = _compress_image_for_docx(uploaded)
self.assertIsNotNone(result)
self.assertGreater(len(result.getvalue()), 0)
def test_work_order_related_tasks_queryset_excludes_other_work_orders_for_same_vehicle(self):
other_work_order = WorkOrder.objects.create(
vehicle=self.vehicle,

View File

@@ -14,7 +14,7 @@ from pathlib import Path
from decimal import Decimal, InvalidOperation
from django.contrib.auth import get_user_model
from PIL import Image, UnidentifiedImageError
from PIL import Image, ImageOps, UnidentifiedImageError
from django.conf import settings
from django.core.mail import EmailMessage
from django.core.exceptions import ValidationError as DjangoValidationError
@@ -479,6 +479,7 @@ def _compress_image_for_pdf(image_field, max_width=800, quality=75):
try:
image_field.open('rb')
with Image.open(image_field) as img:
img = ImageOps.exif_transpose(img)
w, h = img.size
if w * h > _COMPRESS_IMAGE_MAX_MEGAPIXELS * 1_000_000:
return None
@@ -508,6 +509,7 @@ def _compress_image_for_docx(image_field, max_width=800, quality=80):
try:
image_field.open('rb')
with Image.open(image_field) as img:
img = ImageOps.exif_transpose(img)
w, h = img.size
if w * h > _COMPRESS_IMAGE_MAX_MEGAPIXELS * 1_000_000:
return None