-
Notifications
You must be signed in to change notification settings - Fork 2
/
__init__.py
148 lines (109 loc) · 4.23 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# vim: ft=python fileencoding=utf-8 sw=4 et sts=4
from functools import lru_cache
from typing import Any, BinaryIO
from vimiv import api
from vimiv.qt.gui import QPixmap, QImageReader
from vimiv.qt.core import QProcess
from vimiv.utils import log
_logger = log.module_logger(__name__)
def test_raf(header: bytes, _f: BinaryIO) -> bool:
return header[:15] == b"FUJIFILMCCD-RAW"
def test_cr2(header: bytes, _f: BinaryIO) -> bool:
return header[:2] in (b"II", b"MM") and header[8:10] == b"CR"
def test_orf(header: bytes, _f: BinaryIO) -> bool:
return header[:4] == b"IIRO"
def test_cr3(header: bytes, _f: BinaryIO) -> bool:
return (
header[4:8] == b"ftyp"
and header[8:11] == b"crx"
and header[16:24] == b"crx isom"
and header[28:32] == b"moov"
)
@lru_cache(maxsize=40)
def load_dcraw(path) -> QPixmap:
"""Extract thumbnail using `dcraw` and initialize QPixmap."""
process = QProcess()
process.start("dcraw", ["-e", "-c", path])
if not process.waitForFinished():
_logger.error(f"Process exited with code {process.exitCode()}")
raise OSError("Error waiting for process")
if (
process.exitStatus() != QProcess.ExitStatus.NormalExit
or process.exitCode() != 0
):
_logger.error(f"Process exited with code {process.exitCode()}")
stderr = process.readAllStandardError()
raise OSError(f"Error calling dcraw: '{stderr.data().decode()}'")
handler = QImageReader(process, "jpeg".encode())
handler.setAutoTransform(True)
process.closeWriteChannel()
process.terminate()
# Extract QImage from QImageReader and convert to QPixmap
pixmap = QPixmap()
pixmap.convertFromImage(handler.read())
return pixmap
def load_exiv2(path) -> QPixmap:
process = QProcess()
@lru_cache(maxsize=40)
def load_exiftool(path) -> QPixmap:
"""Extract thumbnail using `exiftool` and initialize QPixmap."""
import datetime
# Fix race condition when load_exiftool is called on same path in parallel
timestamp = datetime.datetime.now().strftime("%S%f")
process = QProcess()
process.start(
"exiftool",
[
"-b",
"-JpgFromRaw",
"-w!",
f"/tmp/vimiv-RawPrev%d%F_{timestamp}.jpg",
"-q",
"-execute",
"-tagsfromfile",
"@",
"-srcfile",
f"/tmp/vimiv-RawPrev{path}_{timestamp}.jpg",
"-overwrite_original",
"-common_args",
path,
],
)
if not process.waitForFinished():
_logger.error(f"Process exited with code {process.exitCode()}")
raise OSError("Error waiting for process")
if (
process.exitStatus() != QProcess.ExitStatus.NormalExit
or process.exitCode() != 0
):
_logger.error(f"Process exited with code {process.exitCode()}")
stderr = process.readAllStandardError()
raise OSError(f"Error calling exiftool: '{stderr.data().decode()}'")
# TODO reuse process
process = QProcess()
process.start("cat", [f"/tmp/vimiv-RawPrev{path}_{timestamp}.jpg"])
if not process.waitForFinished():
_logger.error(f"Process exited with code {process.exitCode()}")
raise OSError("Error waiting for process")
if (
process.exitStatus() != QProcess.ExitStatus.NormalExit
or process.exitCode() != 0
):
_logger.error(f"Process exited with code {process.exitCode()}")
stderr = process.readAllStandardError()
raise OSError(f"Error calling cat: '{stderr.data().decode()}'")
handler = QImageReader(process, "jpeg".encode())
handler.setAutoTransform(True)
process.closeWriteChannel()
process.terminate()
# Extract QImage from QImageReader and convert to QPixmap
pixmap = QPixmap()
pixmap.convertFromImage(handler.read())
return pixmap
def init(info: str, *_args: Any, **_kwargs: Any) -> None:
"""Setup RawPrev plugin by adding the raw handler"""
api.add_external_format("raf", test_raf, load_dcraw)
api.add_external_format("cr2", test_cr2, load_dcraw)
api.add_external_format("cr3", test_cr3, load_exiftool)
api.add_external_format("orf", test_orf, load_dcraw)
_logger.debug("Initialized RawPrev")