使用Pillow在Python Lambda中生成GIF时图像方向异常求助
解决AWS Lambda中Pillow合成GIF时的图像方向异常问题
问题根源是图片的EXIF方向元数据:部分图片在拍摄或编辑后会携带旋转信息,Pillow默认不会自动应用这些旋转设置,导致合成GIF时两张图片方向不一致。
解决方案
添加一个辅助函数处理图片的EXIF方向,确保每张图片都以正确的原始方向显示后再合成GIF。
修改后的完整代码如下:
import json import boto3 from PIL import Image from io import BytesIO import uuid s3_client = boto3.client("s3") dynamodb = boto3.client("dynamodb") def fix_image_orientation(image): # 读取图片的EXIF方向信息 exif = image.getexif() orientation = exif.get(0x0112) # 根据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) return image def makeGIF(orig_string, after_string): # 打开图片并应用方向纠正 orig_img = Image.open(BytesIO(orig_string)) after_img = Image.open(BytesIO(after_string)) orig_img = fix_image_orientation(orig_img) after_img = fix_image_orientation(after_img) frames = [orig_img, after_img] frame_one = frames[0] frame_one.save('/tmp/new_gif.gif', format="GIF", append_images=[frames[1]], save_all=True, duration=600, loop=0, optimize=False) def lambda_handler(event, context): try: s3 = event["Records"][0]['s3'] print("S3 object reveived::",s3) if s3['object']['key'][-1] == '/': return splitted = s3['object']['key'].split("/") if len(splitted) != 3: print("ERROR:: Folder hierarchy is not valid!") return {} afterFilename = splitted[-1].replace("+", " ") print('Filename::', afterFilename) if afterFilename[0:6] not in ['after_', 'AFTER_', 'After_']: print('Error::', 'Filename does not starts with after_, After_ or AFTER_') return {} EXT = ['.jpg', '.jpeg', '.png'] origFilename = afterFilename[6:] origKey = f"original/{splitted[1]}/{origFilename}" fileWithoutExt = origFilename.split(".")[0] BUCKET = s3['bucket']['name'] file_content_orig = None try: file_content_orig = s3_client.get_object(Bucket=BUCKET, Key=origKey)["Body"].read() except: for ext in EXT: try: print("LOOKING::", f"original/{splitted[1]}/{fileWithoutExt}{ext}") file_content_orig = s3_client.get_object(Bucket=BUCKET, Key=f"original/{splitted[1]}/{fileWithoutExt}{ext}")["Body"].read() print("FOUND::", f"original/{splitted[1]}/{fileWithoutExt}{ext}") break except: pass if file_content_orig is None: print('Error::', 'No original image found looked (jpg, jpeg, png)') return {} print("LOOKING::", f"after/{splitted[1]}/{afterFilename}") file_content_after = s3_client.get_object(Bucket=BUCKET, Key=f"after/{splitted[1]}/{afterFilename}")["Body"].read() makeGIF(file_content_orig, file_content_after) gifKey = f"gif/{splitted[1]}/gif_{fileWithoutExt}.gif" with open('/tmp/new_gif.gif', 'rb') as f: s3_client.upload_fileobj(f, BUCKET, gifKey) itemId = uuid.uuid4().hex bucketLink = f"https://{BUCKET}.s3.us-east-2.amazonaws.com" print("bucketLink", bucketLink) item = { "id": {'S': itemId}, "folder_name": {'S': splitted[1]}, "image_name": {'S': origFilename}, "original_link": {'S': f"{bucketLink}/{origKey}"}, "download_link": {'S': f"{bucketLink}/{s3['object']['key']}"}, "gif_link": {'S': f"{bucketLink}/{gifKey}"} } dynamodb.put_item(TableName='fototone-db-table', Item = item) return { 'statusCode': 200, 'body': json.dumps({"message": "Successfully proceessed", "filename": origFilename }) } except Exception as ex: print("ERROR:: Some error occured", ex) return {}
关键说明
fix_image_orientation函数读取图片的EXIF方向标签(0x0112),根据不同的方向值对图片进行旋转纠正:- 3 = 图片需要旋转180度
- 6 = 图片需要逆时针旋转270度(等同于顺时针90度)
- 8 = 图片需要逆时针旋转90度
- 使用
expand=True参数确保旋转后的图片完整显示,不会被裁剪。
内容的提问来源于stack exchange,提问作者RareWatch
相关产品推荐
相关产品推荐

