Skip to content

Commit c9b65b1

Browse files
authored
Add support for .NEF, .MOV, .HEIC, .M4A from @Log45
Add Support for more file types: .NEF, .MOV, .HEIC, .M4A
2 parents 7208b04 + 140d4cd commit c9b65b1

7 files changed

Lines changed: 138 additions & 2 deletions

File tree

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ MAINTAINER Computer Science House <rtp@csh.rit.edu>
44
ENV IMAGEIO_USERDIR /var/lib/gallery
55

66
RUN apt-get update && \
7-
apt-get install -y libldap-dev libsasl2-dev libmagic-dev ghostscript libldap-common && \
7+
apt-get install -y libldap-dev libsasl2-dev libmagic-dev ghostscript libldap-common imagemagick libheif1 libheif-dev libraw-dev libraw20 dcraw && \
88
apt-get autoremove --yes && \
99
apt-get clean autoclean && \
1010
sed -i \

gallery/file_modules/__init__.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Any, Dict, List, Optional, Tuple
44
from wand.image import Image
55
from wand.color import Color
6+
import rawpy
67

78
from gallery.util import DEFAULT_THUMBNAIL_NAME
89
from gallery.util import hash_file
@@ -65,6 +66,10 @@ def generate_thumbnail(self):
6566
from gallery.file_modules.txt import TXTFile
6667
from gallery.file_modules.mp3 import MP3File
6768
from gallery.file_modules.wav import WAVFile
69+
from gallery.file_modules.heic import HEICFile
70+
from gallery.file_modules.nef import NEFFile
71+
from gallery.file_modules.mov import MOVFile
72+
from gallery.file_modules.m4a import M4AFile
6873

6974
file_mimetype_relation = {
7075
"image/jpeg": JPEGFile,
@@ -76,20 +81,36 @@ def generate_thumbnail(self):
7681
"image/x-windows-bmp": BMPFile,
7782
"image/tiff": TIFFFile,
7883
"image/x-tiff": TIFFFile,
84+
"image/heic": HEICFile,
85+
"image/x-nikon-nef": NEFFile,
7986
"video/mp4": MP4File,
8087
"video/webm": WebMFile,
8188
"video/ogg": OggFile,
89+
"video/quicktime": MOVFile,
8290
"application/pdf": PDFFile,
8391
"text/plain": TXTFile,
8492
"audio/mpeg": MP3File,
85-
"audio/x-wav": WAVFile
93+
"audio/x-wav": WAVFile,
94+
"audio/mp4": M4AFile,
95+
"audio/x-m4a": M4AFile,
8696
}
8797

8898

8999
# classism
90100
def parse_file_info(file_path: str, dir_path: str) -> Tuple[str, Optional[FileModule]]:
91101
print("entering parse_file_info")
102+
92103
mime_type = magic.from_file(file_path, mime=True)
104+
105+
if "tif" in mime_type: # .nef is a special case, magic reads it as .tiff, but it is not processed correctly by the tiff module
106+
# check if it is a raw file
107+
try:
108+
with rawpy.imread(file_path): # this may cause issues for other raw files
109+
mime_type = "image/x-nikon-nef"
110+
except rawpy.LibRawFileUnsupportedError:
111+
pass
112+
except rawpy.LibRawIOError:
113+
pass
93114
print(mime_type)
94115
print(file_path)
95116

gallery/file_modules/heic.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
from PIL import Image as PILImage
3+
import pillow_heif
4+
5+
from gallery.file_modules import FileModule
6+
from gallery.util import hash_file
7+
8+
pillow_heif.register_heif_opener()
9+
10+
class HEICFile(FileModule):
11+
def __init__(self, file_path, dir_path):
12+
FileModule.__init__(self, file_path, dir_path)
13+
self.mime_type = "image/heic"
14+
15+
self.generate_thumbnail()
16+
17+
def generate_thumbnail(self):
18+
self.thumbnail_uuid = hash_file(self.file_path) + ".jpg"
19+
20+
thumb_path = os.path.join(self.dir_path, self.thumbnail_uuid)
21+
22+
img = PILImage.open(self.file_path).convert("RGB")
23+
24+
size = min(img.width, img.height)
25+
left = (img.width - size) // 2
26+
top = (img.height - size) // 2
27+
img = img.crop((left, top, left + size, top + size))
28+
29+
img = img.resize((256, 256))
30+
img.save(thumb_path, "JPEG")

gallery/file_modules/m4a.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
from wand.image import Image
3+
4+
from gallery.file_modules import FileModule
5+
from gallery.util import hash_file
6+
7+
class M4AFile(FileModule):
8+
def __init__(self, file_path, dir_path):
9+
FileModule.__init__(self, file_path, dir_path)
10+
self.mime_type = "audio/mp4"
11+
12+
self.generate_thumbnail()
13+
14+
def generate_thumbnail(self):
15+
self.thumbnail_uuid = hash_file(self.file_path) + ".jpg"
16+
17+
with Image(filename="thumbnails/reedphoto.jpg") as bg:
18+
bg.save(filename=os.path.join(self.dir_path, self.thumbnail_uuid))

gallery/file_modules/mov.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from moviepy.editor import VideoFileClip
2+
import os
3+
from wand.image import Image
4+
from wand.color import Color
5+
6+
from gallery.file_modules import FileModule
7+
from gallery.util import hash_file
8+
9+
10+
class MOVFile(FileModule):
11+
12+
def __init__(self, file_path, dir_path):
13+
FileModule.__init__(self, file_path, dir_path)
14+
self.mime_type = "video/quicktime"
15+
16+
self.generate_thumbnail()
17+
18+
def generate_thumbnail(self):
19+
self.thumbnail_uuid = hash_file(self.file_path) + ".jpg"
20+
thumbnail_loc = os.path.join(self.dir_path, self.thumbnail_uuid)
21+
22+
clip = VideoFileClip(self.file_path)
23+
time_mark = clip.duration * 0.05
24+
clip.save_frame(thumbnail_loc, t=time_mark)
25+
26+
with Image(filename=thumbnail_loc) as img:
27+
with img.clone() as image:
28+
size = image.width if image.width < image.height else image.height
29+
image.crop(width=size, height=size, gravity='center')
30+
image.resize(256, 256)
31+
image.background_color = Color("#EEEEEE")
32+
image.format = 'jpeg'
33+
image.save(filename=thumbnail_loc)

gallery/file_modules/nef.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os
2+
import rawpy
3+
import imageio
4+
5+
from gallery.file_modules import FileModule
6+
from gallery.util import hash_file
7+
8+
9+
class NEFFile(FileModule):
10+
def __init__(self, file_path, dir_path):
11+
FileModule.__init__(self, file_path, dir_path)
12+
self.mime_type = "image/x-nikon-nef"
13+
14+
self.generate_thumbnail()
15+
16+
def generate_thumbnail(self):
17+
self.thumbnail_uuid = hash_file(self.file_path) + ".jpg"
18+
thumb_path = os.path.join(self.dir_path, self.thumbnail_uuid)
19+
20+
with rawpy.imread(self.file_path) as raw:
21+
rgb = raw.postprocess(output_bps=8)
22+
23+
h, w, _ = rgb.shape
24+
size = min(h, w)
25+
y = (h - size) // 2
26+
x = (w - size) // 2
27+
rgb = rgb[y:y+size, x:x+size]
28+
29+
imageio.imwrite(thumb_path, rgb)

requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,8 @@ Werkzeug==3.1.3
7070
wrapt==1.17.2
7171
xmltodict==0.14.2
7272
zipp==3.19.1
73+
# NEF and HEIC support
74+
pillow==11.1.0
75+
pillow_heif==1.2.0
76+
rawpy==0.26.1
77+
imageio==2.4.0

0 commit comments

Comments
 (0)