RAW画像をjpegに変換、さらにサムネイル作成
デジカメのraw画像を、formからストレージにアップすると同時にjpegに変換し、サムネイルを作成するまで
環境
- Linux 5.14.0-362.8.1.el9_3.x86_64
- Python 3.9.18
- Django 4.2.14
pip install rawpy
pip install opencv-python
settings.py
FILE_ROOT = os.path.join(BASE_DIR, 'files')
PHOTO_PATH = FILE_ROOT + '/photo'
forms.py
from django import forms
class MultipleFileUploadForm(forms.Form):
files = MultipleFileField(label="ファイルを指定", help_text="一度に複数のファイルを指定し、アップロードできます")
memo = forms.CharField(max_length=200, label="メモ", required=False, help_text="検索対象ですので、検索しやすいように自由に記載くださ")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control form-control-sm'
templates/upload.html
{% load django_bootstrap5 %}
<form action="{% url 'dashboard:upload_photo' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="mb-3 col-md-12">
{% bootstrap_form form %}
</div>
</div>
<button type="submit" class="btn btn-primary btn-sm mt-2 w-25" name="button">アップロード</button>
</form>
views.py
import cv2, os, rawpy
from .forms import MultipleFileUploadForm
from .models import File
from accounts.models import CustomUser
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.files.storage import FileSystemStorage
from django.shortcuts import redirect
class UploadImageView(LoginRequiredMixin, FormView):
model = File
form_class = MultipleFileUploadForm
template_name = 'dashboard/upload_image.html'
def post(self, request):
files = request.FILES.getlist('files')
if not os.path.exists(settings.PHOTO_PATH + DS + str(self.request.user.pk)):
os.mkdir(settings.PHOTO_PATH + DS + str(self.request.user.pk))
if not os.path.exists(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'raw'):
os.mkdir(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'raw')
if not os.path.exists(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'jpeg'):
os.mkdir(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'jpeg')
if not os.path.exists(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'thumbnail'):
os.mkdir(settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'thumbnail')
fss = FileSystemStorage(location=settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'raw')
for file in files:
### 同一ファイルのアップ防止 ###
file_exist = File.objects.filter(
file_name=file.name,
).first()
if not file_exist:
fss.save(file.name, file)
# raw画像→jpeg変換
filename_no_extension = os.path.splitext(file.name)[0]
raw_file_path = settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'raw' + DS + file.name
jpeg_file_path = settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'jpeg' + DS + filename_no_extension + '.jpg'
thumb_file_path = settings.PHOTO_PATH + DS + str(self.request.user.pk) + DS + 'thumbnail' + DS + filename_no_extension + '_thumb.jpg'
raw = rawpy.imread(raw_file_path)
decoded = raw.postprocess(bright=1.21)[:, :, [2, 1, 0]]
cv2.imwrite(jpeg_file_path, decoded)
# 画像を読み込み
cv2_image = cv2.imread(jpeg_file_path)
# 画像のサイズを取得
h, w = cv2_image.shape[:2]
rate = round(300 / w, 2)
# 画像のサイズを指定:縦を300px横なりゆきにリサイズ
resized_image = cv2.resize(cv2_image, None, fx=rate, fy=rate)
cv2.imwrite(thumb_file_path, resized_image)
file_obj = File(
custom_user=CustomUser.objects.get(pk=self.request.user.pk),
type='写真',
file_name=file.name,
file_size=file.size / 1024,
memo=request.POST.get('memo'),
description=self.request.user.username + '-' + self.request.user.email + '-'+ str(uuid.uuid4())
)
file_obj.save()
return redirect('/dashboard/')
最後に
バリデーション、エラー時の対応をせねば..