geored commited on
Commit
fe41391
1 Parent(s): 88255d7

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +10 -0
  2. README.md +2 -8
  3. app.py +24 -0
  4. gtm/bin/Activate.ps1 +247 -0
  5. gtm/bin/RUST +8 -0
  6. gtm/bin/activate +70 -0
  7. gtm/bin/activate.csh +27 -0
  8. gtm/bin/activate.fish +69 -0
  9. gtm/bin/f2py +8 -0
  10. gtm/bin/fonttools +8 -0
  11. gtm/bin/huggingface-cli +8 -0
  12. gtm/bin/normalizer +8 -0
  13. gtm/bin/pip +8 -0
  14. gtm/bin/pip3 +8 -0
  15. gtm/bin/pip3.12 +8 -0
  16. gtm/bin/pyftmerge +8 -0
  17. gtm/bin/pyftsubset +8 -0
  18. gtm/bin/python +0 -0
  19. gtm/bin/python3 +0 -0
  20. gtm/bin/python3.12 +0 -0
  21. gtm/bin/tqdm +8 -0
  22. gtm/bin/ttx +8 -0
  23. gtm/bin/wheel +8 -0
  24. gtm/lib/python3.12/site-packages/PIL/.dylibs/libXau.6.0.0.dylib +0 -0
  25. gtm/lib/python3.12/site-packages/PIL/.dylibs/libbrotlicommon.1.1.0.dylib +0 -0
  26. gtm/lib/python3.12/site-packages/PIL/.dylibs/libbrotlidec.1.1.0.dylib +0 -0
  27. gtm/lib/python3.12/site-packages/PIL/.dylibs/libfreetype.6.dylib +3 -0
  28. gtm/lib/python3.12/site-packages/PIL/.dylibs/libharfbuzz.0.dylib +3 -0
  29. gtm/lib/python3.12/site-packages/PIL/.dylibs/libjpeg.62.4.0.dylib +0 -0
  30. gtm/lib/python3.12/site-packages/PIL/.dylibs/liblcms2.2.dylib +0 -0
  31. gtm/lib/python3.12/site-packages/PIL/.dylibs/liblzma.5.dylib +0 -0
  32. gtm/lib/python3.12/site-packages/PIL/.dylibs/libopenjp2.2.5.0.dylib +0 -0
  33. gtm/lib/python3.12/site-packages/PIL/.dylibs/libpng16.16.dylib +0 -0
  34. gtm/lib/python3.12/site-packages/PIL/.dylibs/libsharpyuv.0.dylib +0 -0
  35. gtm/lib/python3.12/site-packages/PIL/.dylibs/libtiff.6.dylib +0 -0
  36. gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebp.7.dylib +0 -0
  37. gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebpdemux.2.dylib +0 -0
  38. gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebpmux.3.dylib +0 -0
  39. gtm/lib/python3.12/site-packages/PIL/.dylibs/libxcb.1.1.0.dylib +0 -0
  40. gtm/lib/python3.12/site-packages/PIL/.dylibs/libz.1.3.dylib +0 -0
  41. gtm/lib/python3.12/site-packages/PIL/BdfFontFile.py +133 -0
  42. gtm/lib/python3.12/site-packages/PIL/BlpImagePlugin.py +475 -0
  43. gtm/lib/python3.12/site-packages/PIL/BmpImagePlugin.py +471 -0
  44. gtm/lib/python3.12/site-packages/PIL/BufrStubImagePlugin.py +74 -0
  45. gtm/lib/python3.12/site-packages/PIL/ContainerIO.py +121 -0
  46. gtm/lib/python3.12/site-packages/PIL/CurImagePlugin.py +75 -0
  47. gtm/lib/python3.12/site-packages/PIL/DcxImagePlugin.py +80 -0
  48. gtm/lib/python3.12/site-packages/PIL/DdsImagePlugin.py +566 -0
  49. gtm/lib/python3.12/site-packages/PIL/EpsImagePlugin.py +478 -0
  50. gtm/lib/python3.12/site-packages/PIL/ExifTags.py +381 -0
.gitattributes CHANGED
@@ -33,3 +33,13 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ gtm/lib/python3.12/site-packages/PIL/.dylibs/libfreetype.6.dylib filter=lfs diff=lfs merge=lfs -text
37
+ gtm/lib/python3.12/site-packages/PIL/.dylibs/libharfbuzz.0.dylib filter=lfs diff=lfs merge=lfs -text
38
+ gtm/lib/python3.12/site-packages/numpy/.dylibs/libgfortran.5.dylib filter=lfs diff=lfs merge=lfs -text
39
+ gtm/lib/python3.12/site-packages/numpy/.dylibs/libopenblas64_.0.dylib filter=lfs diff=lfs merge=lfs -text
40
+ gtm/lib/python3.12/site-packages/numpy/core/_multiarray_umath.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
41
+ gtm/lib/python3.12/site-packages/numpy/core/_simd.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
42
+ gtm/lib/python3.12/site-packages/pysam/libcbcf.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
43
+ gtm/lib/python3.12/site-packages/pysam/libcbcftools.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
44
+ gtm/lib/python3.12/site-packages/pysam/libchtslib.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
45
+ gtm/lib/python3.12/site-packages/tokenizers/tokenizers.cpython-312-darwin.so filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Gtmio
3
- emoji: 😻
4
- colorFrom: purple
5
- colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 4.21.0
8
- app_file: app.py
9
- pinned: false
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: gtmio
3
+ app_file: app.py
 
 
4
  sdk: gradio
5
  sdk_version: 4.21.0
 
 
6
  ---
 
 
app.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+
4
+ # Load the llama2 LLM model
5
+ model = pipeline("text-generation", model="llamalanguage/llama2", tokenizer="llamalanguage/llama2")
6
+
7
+ # Define the chat function that uses the LLM model
8
+ def chat_interface(input_text):
9
+ response = model(input_text, max_length=100, return_full_text=True)[0]["generated_text"]
10
+ response_words = response.split()
11
+ return response_words
12
+
13
+ # Create the Gradio interface
14
+ iface = gr.Interface(
15
+ fn=chat_interface,
16
+ inputs=gr.inputs.Textbox(lines=2, label="Input Text"),
17
+ outputs=gr.outputs.Textbox(label="Output Text"),
18
+ title="Chat Interface",
19
+ description="Enter text and get a response using the LLM model",
20
+ live=True # Enable live updates
21
+ )
22
+
23
+ # Launch the interface using Hugging Face Spaces
24
+ iface.launch(share=True)
gtm/bin/Activate.ps1 ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <#
2
+ .Synopsis
3
+ Activate a Python virtual environment for the current PowerShell session.
4
+
5
+ .Description
6
+ Pushes the python executable for a virtual environment to the front of the
7
+ $Env:PATH environment variable and sets the prompt to signify that you are
8
+ in a Python virtual environment. Makes use of the command line switches as
9
+ well as the `pyvenv.cfg` file values present in the virtual environment.
10
+
11
+ .Parameter VenvDir
12
+ Path to the directory that contains the virtual environment to activate. The
13
+ default value for this is the parent of the directory that the Activate.ps1
14
+ script is located within.
15
+
16
+ .Parameter Prompt
17
+ The prompt prefix to display when this virtual environment is activated. By
18
+ default, this prompt is the name of the virtual environment folder (VenvDir)
19
+ surrounded by parentheses and followed by a single space (ie. '(.venv) ').
20
+
21
+ .Example
22
+ Activate.ps1
23
+ Activates the Python virtual environment that contains the Activate.ps1 script.
24
+
25
+ .Example
26
+ Activate.ps1 -Verbose
27
+ Activates the Python virtual environment that contains the Activate.ps1 script,
28
+ and shows extra information about the activation as it executes.
29
+
30
+ .Example
31
+ Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
32
+ Activates the Python virtual environment located in the specified location.
33
+
34
+ .Example
35
+ Activate.ps1 -Prompt "MyPython"
36
+ Activates the Python virtual environment that contains the Activate.ps1 script,
37
+ and prefixes the current prompt with the specified string (surrounded in
38
+ parentheses) while the virtual environment is active.
39
+
40
+ .Notes
41
+ On Windows, it may be required to enable this Activate.ps1 script by setting the
42
+ execution policy for the user. You can do this by issuing the following PowerShell
43
+ command:
44
+
45
+ PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
46
+
47
+ For more information on Execution Policies:
48
+ https://go.microsoft.com/fwlink/?LinkID=135170
49
+
50
+ #>
51
+ Param(
52
+ [Parameter(Mandatory = $false)]
53
+ [String]
54
+ $VenvDir,
55
+ [Parameter(Mandatory = $false)]
56
+ [String]
57
+ $Prompt
58
+ )
59
+
60
+ <# Function declarations --------------------------------------------------- #>
61
+
62
+ <#
63
+ .Synopsis
64
+ Remove all shell session elements added by the Activate script, including the
65
+ addition of the virtual environment's Python executable from the beginning of
66
+ the PATH variable.
67
+
68
+ .Parameter NonDestructive
69
+ If present, do not remove this function from the global namespace for the
70
+ session.
71
+
72
+ #>
73
+ function global:deactivate ([switch]$NonDestructive) {
74
+ # Revert to original values
75
+
76
+ # The prior prompt:
77
+ if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
78
+ Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
79
+ Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
80
+ }
81
+
82
+ # The prior PYTHONHOME:
83
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
84
+ Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
85
+ Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
86
+ }
87
+
88
+ # The prior PATH:
89
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
90
+ Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
91
+ Remove-Item -Path Env:_OLD_VIRTUAL_PATH
92
+ }
93
+
94
+ # Just remove the VIRTUAL_ENV altogether:
95
+ if (Test-Path -Path Env:VIRTUAL_ENV) {
96
+ Remove-Item -Path env:VIRTUAL_ENV
97
+ }
98
+
99
+ # Just remove VIRTUAL_ENV_PROMPT altogether.
100
+ if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
101
+ Remove-Item -Path env:VIRTUAL_ENV_PROMPT
102
+ }
103
+
104
+ # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
105
+ if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
106
+ Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
107
+ }
108
+
109
+ # Leave deactivate function in the global namespace if requested:
110
+ if (-not $NonDestructive) {
111
+ Remove-Item -Path function:deactivate
112
+ }
113
+ }
114
+
115
+ <#
116
+ .Description
117
+ Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
118
+ given folder, and returns them in a map.
119
+
120
+ For each line in the pyvenv.cfg file, if that line can be parsed into exactly
121
+ two strings separated by `=` (with any amount of whitespace surrounding the =)
122
+ then it is considered a `key = value` line. The left hand string is the key,
123
+ the right hand is the value.
124
+
125
+ If the value starts with a `'` or a `"` then the first and last character is
126
+ stripped from the value before being captured.
127
+
128
+ .Parameter ConfigDir
129
+ Path to the directory that contains the `pyvenv.cfg` file.
130
+ #>
131
+ function Get-PyVenvConfig(
132
+ [String]
133
+ $ConfigDir
134
+ ) {
135
+ Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
136
+
137
+ # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
138
+ $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
139
+
140
+ # An empty map will be returned if no config file is found.
141
+ $pyvenvConfig = @{ }
142
+
143
+ if ($pyvenvConfigPath) {
144
+
145
+ Write-Verbose "File exists, parse `key = value` lines"
146
+ $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
147
+
148
+ $pyvenvConfigContent | ForEach-Object {
149
+ $keyval = $PSItem -split "\s*=\s*", 2
150
+ if ($keyval[0] -and $keyval[1]) {
151
+ $val = $keyval[1]
152
+
153
+ # Remove extraneous quotations around a string value.
154
+ if ("'""".Contains($val.Substring(0, 1))) {
155
+ $val = $val.Substring(1, $val.Length - 2)
156
+ }
157
+
158
+ $pyvenvConfig[$keyval[0]] = $val
159
+ Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
160
+ }
161
+ }
162
+ }
163
+ return $pyvenvConfig
164
+ }
165
+
166
+
167
+ <# Begin Activate script --------------------------------------------------- #>
168
+
169
+ # Determine the containing directory of this script
170
+ $VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
171
+ $VenvExecDir = Get-Item -Path $VenvExecPath
172
+
173
+ Write-Verbose "Activation script is located in path: '$VenvExecPath'"
174
+ Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
175
+ Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
176
+
177
+ # Set values required in priority: CmdLine, ConfigFile, Default
178
+ # First, get the location of the virtual environment, it might not be
179
+ # VenvExecDir if specified on the command line.
180
+ if ($VenvDir) {
181
+ Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
182
+ }
183
+ else {
184
+ Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
185
+ $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
186
+ Write-Verbose "VenvDir=$VenvDir"
187
+ }
188
+
189
+ # Next, read the `pyvenv.cfg` file to determine any required value such
190
+ # as `prompt`.
191
+ $pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
192
+
193
+ # Next, set the prompt from the command line, or the config file, or
194
+ # just use the name of the virtual environment folder.
195
+ if ($Prompt) {
196
+ Write-Verbose "Prompt specified as argument, using '$Prompt'"
197
+ }
198
+ else {
199
+ Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
200
+ if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
201
+ Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
202
+ $Prompt = $pyvenvCfg['prompt'];
203
+ }
204
+ else {
205
+ Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
206
+ Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
207
+ $Prompt = Split-Path -Path $venvDir -Leaf
208
+ }
209
+ }
210
+
211
+ Write-Verbose "Prompt = '$Prompt'"
212
+ Write-Verbose "VenvDir='$VenvDir'"
213
+
214
+ # Deactivate any currently active virtual environment, but leave the
215
+ # deactivate function in place.
216
+ deactivate -nondestructive
217
+
218
+ # Now set the environment variable VIRTUAL_ENV, used by many tools to determine
219
+ # that there is an activated venv.
220
+ $env:VIRTUAL_ENV = $VenvDir
221
+
222
+ if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
223
+
224
+ Write-Verbose "Setting prompt to '$Prompt'"
225
+
226
+ # Set the prompt to include the env name
227
+ # Make sure _OLD_VIRTUAL_PROMPT is global
228
+ function global:_OLD_VIRTUAL_PROMPT { "" }
229
+ Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
230
+ New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
231
+
232
+ function global:prompt {
233
+ Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
234
+ _OLD_VIRTUAL_PROMPT
235
+ }
236
+ $env:VIRTUAL_ENV_PROMPT = $Prompt
237
+ }
238
+
239
+ # Clear PYTHONHOME
240
+ if (Test-Path -Path Env:PYTHONHOME) {
241
+ Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
242
+ Remove-Item -Path Env:PYTHONHOME
243
+ }
244
+
245
+ # Add the venv to the PATH
246
+ Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
247
+ $Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
gtm/bin/RUST ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from RUST.__main__ import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/activate ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source bin/activate" *from bash*
2
+ # You cannot run it directly
3
+
4
+ deactivate () {
5
+ # reset old environment variables
6
+ if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
7
+ PATH="${_OLD_VIRTUAL_PATH:-}"
8
+ export PATH
9
+ unset _OLD_VIRTUAL_PATH
10
+ fi
11
+ if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
12
+ PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
13
+ export PYTHONHOME
14
+ unset _OLD_VIRTUAL_PYTHONHOME
15
+ fi
16
+
17
+ # Call hash to forget past commands. Without forgetting
18
+ # past commands the $PATH changes we made may not be respected
19
+ hash -r 2> /dev/null
20
+
21
+ if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
22
+ PS1="${_OLD_VIRTUAL_PS1:-}"
23
+ export PS1
24
+ unset _OLD_VIRTUAL_PS1
25
+ fi
26
+
27
+ unset VIRTUAL_ENV
28
+ unset VIRTUAL_ENV_PROMPT
29
+ if [ ! "${1:-}" = "nondestructive" ] ; then
30
+ # Self destruct!
31
+ unset -f deactivate
32
+ fi
33
+ }
34
+
35
+ # unset irrelevant variables
36
+ deactivate nondestructive
37
+
38
+ # on Windows, a path can contain colons and backslashes and has to be converted:
39
+ if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
40
+ # transform D:\path\to\venv to /d/path/to/venv on MSYS
41
+ # and to /cygdrive/d/path/to/venv on Cygwin
42
+ export VIRTUAL_ENV=$(cygpath "/Users/gorgigeorgievski/code/ai/gtmio/gtm")
43
+ else
44
+ # use the path as-is
45
+ export VIRTUAL_ENV="/Users/gorgigeorgievski/code/ai/gtmio/gtm"
46
+ fi
47
+
48
+ _OLD_VIRTUAL_PATH="$PATH"
49
+ PATH="$VIRTUAL_ENV/bin:$PATH"
50
+ export PATH
51
+
52
+ # unset PYTHONHOME if set
53
+ # this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
54
+ # could use `if (set -u; : $PYTHONHOME) ;` in bash
55
+ if [ -n "${PYTHONHOME:-}" ] ; then
56
+ _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
57
+ unset PYTHONHOME
58
+ fi
59
+
60
+ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
61
+ _OLD_VIRTUAL_PS1="${PS1:-}"
62
+ PS1="(gtm) ${PS1:-}"
63
+ export PS1
64
+ VIRTUAL_ENV_PROMPT="(gtm) "
65
+ export VIRTUAL_ENV_PROMPT
66
+ fi
67
+
68
+ # Call hash to forget past commands. Without forgetting
69
+ # past commands the $PATH changes we made may not be respected
70
+ hash -r 2> /dev/null
gtm/bin/activate.csh ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source bin/activate.csh" *from csh*.
2
+ # You cannot run it directly.
3
+
4
+ # Created by Davide Di Blasi <davidedb@gmail.com>.
5
+ # Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
6
+
7
+ alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
8
+
9
+ # Unset irrelevant variables.
10
+ deactivate nondestructive
11
+
12
+ setenv VIRTUAL_ENV "/Users/gorgigeorgievski/code/ai/gtmio/gtm"
13
+
14
+ set _OLD_VIRTUAL_PATH="$PATH"
15
+ setenv PATH "$VIRTUAL_ENV/bin:$PATH"
16
+
17
+
18
+ set _OLD_VIRTUAL_PROMPT="$prompt"
19
+
20
+ if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
21
+ set prompt = "(gtm) $prompt"
22
+ setenv VIRTUAL_ENV_PROMPT "(gtm) "
23
+ endif
24
+
25
+ alias pydoc python -m pydoc
26
+
27
+ rehash
gtm/bin/activate.fish ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source <venv>/bin/activate.fish" *from fish*
2
+ # (https://fishshell.com/). You cannot run it directly.
3
+
4
+ function deactivate -d "Exit virtual environment and return to normal shell environment"
5
+ # reset old environment variables
6
+ if test -n "$_OLD_VIRTUAL_PATH"
7
+ set -gx PATH $_OLD_VIRTUAL_PATH
8
+ set -e _OLD_VIRTUAL_PATH
9
+ end
10
+ if test -n "$_OLD_VIRTUAL_PYTHONHOME"
11
+ set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
12
+ set -e _OLD_VIRTUAL_PYTHONHOME
13
+ end
14
+
15
+ if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
16
+ set -e _OLD_FISH_PROMPT_OVERRIDE
17
+ # prevents error when using nested fish instances (Issue #93858)
18
+ if functions -q _old_fish_prompt
19
+ functions -e fish_prompt
20
+ functions -c _old_fish_prompt fish_prompt
21
+ functions -e _old_fish_prompt
22
+ end
23
+ end
24
+
25
+ set -e VIRTUAL_ENV
26
+ set -e VIRTUAL_ENV_PROMPT
27
+ if test "$argv[1]" != "nondestructive"
28
+ # Self-destruct!
29
+ functions -e deactivate
30
+ end
31
+ end
32
+
33
+ # Unset irrelevant variables.
34
+ deactivate nondestructive
35
+
36
+ set -gx VIRTUAL_ENV "/Users/gorgigeorgievski/code/ai/gtmio/gtm"
37
+
38
+ set -gx _OLD_VIRTUAL_PATH $PATH
39
+ set -gx PATH "$VIRTUAL_ENV/bin" $PATH
40
+
41
+ # Unset PYTHONHOME if set.
42
+ if set -q PYTHONHOME
43
+ set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
44
+ set -e PYTHONHOME
45
+ end
46
+
47
+ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
48
+ # fish uses a function instead of an env var to generate the prompt.
49
+
50
+ # Save the current fish_prompt function as the function _old_fish_prompt.
51
+ functions -c fish_prompt _old_fish_prompt
52
+
53
+ # With the original prompt function renamed, we can override with our own.
54
+ function fish_prompt
55
+ # Save the return status of the last command.
56
+ set -l old_status $status
57
+
58
+ # Output the venv prompt; color taken from the blue of the Python logo.
59
+ printf "%s%s%s" (set_color 4B8BBE) "(gtm) " (set_color normal)
60
+
61
+ # Restore the return status of the previous command.
62
+ echo "exit $old_status" | .
63
+ # Output the original/"old" prompt.
64
+ _old_fish_prompt
65
+ end
66
+
67
+ set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
68
+ set -gx VIRTUAL_ENV_PROMPT "(gtm) "
69
+ end
gtm/bin/f2py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from numpy.f2py.f2py2e import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/fonttools ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from fontTools.__main__ import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/huggingface-cli ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from huggingface_hub.commands.huggingface_cli import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/normalizer ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from charset_normalizer.cli import cli_detect
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(cli_detect())
gtm/bin/pip ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/pip3 ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/pip3.12 ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/pyftmerge ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from fontTools.merge import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/pyftsubset ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from fontTools.subset import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/python ADDED
Binary file (34.1 kB). View file
 
gtm/bin/python3 ADDED
Binary file (34.1 kB). View file
 
gtm/bin/python3.12 ADDED
Binary file (34.1 kB). View file
 
gtm/bin/tqdm ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from tqdm.cli import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/ttx ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from fontTools.ttx import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/bin/wheel ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/Users/gorgigeorgievski/code/ai/gtmio/gtm/bin/python3.12
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from wheel.cli import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
gtm/lib/python3.12/site-packages/PIL/.dylibs/libXau.6.0.0.dylib ADDED
Binary file (53.3 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libbrotlicommon.1.1.0.dylib ADDED
Binary file (186 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libbrotlidec.1.1.0.dylib ADDED
Binary file (88.6 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libfreetype.6.dylib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d9adc9fc79969a87c8583759c634a534ea9d5ec695148544c6e03758f5916d92
3
+ size 1115184
gtm/lib/python3.12/site-packages/PIL/.dylibs/libharfbuzz.0.dylib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d40d9521c7d88b04f527828f2062b77e88e4cc4d11818b5730e56f11ca70959f
3
+ size 4287408
gtm/lib/python3.12/site-packages/PIL/.dylibs/libjpeg.62.4.0.dylib ADDED
Binary file (809 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/liblcms2.2.dylib ADDED
Binary file (526 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/liblzma.5.dylib ADDED
Binary file (309 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libopenjp2.2.5.0.dylib ADDED
Binary file (636 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libpng16.16.dylib ADDED
Binary file (313 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libsharpyuv.0.dylib ADDED
Binary file (70.1 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libtiff.6.dylib ADDED
Binary file (756 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebp.7.dylib ADDED
Binary file (691 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebpdemux.2.dylib ADDED
Binary file (53.7 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libwebpmux.3.dylib ADDED
Binary file (90 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libxcb.1.1.0.dylib ADDED
Binary file (262 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/.dylibs/libz.1.3.dylib ADDED
Binary file (176 kB). View file
 
gtm/lib/python3.12/site-packages/PIL/BdfFontFile.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library
3
+ # $Id$
4
+ #
5
+ # bitmap distribution font (bdf) file parser
6
+ #
7
+ # history:
8
+ # 1996-05-16 fl created (as bdf2pil)
9
+ # 1997-08-25 fl converted to FontFile driver
10
+ # 2001-05-25 fl removed bogus __init__ call
11
+ # 2002-11-20 fl robustification (from Kevin Cazabon, Dmitry Vasiliev)
12
+ # 2003-04-22 fl more robustification (from Graham Dumpleton)
13
+ #
14
+ # Copyright (c) 1997-2003 by Secret Labs AB.
15
+ # Copyright (c) 1997-2003 by Fredrik Lundh.
16
+ #
17
+ # See the README file for information on usage and redistribution.
18
+ #
19
+
20
+ """
21
+ Parse X Bitmap Distribution Format (BDF)
22
+ """
23
+ from __future__ import annotations
24
+
25
+ from typing import BinaryIO
26
+
27
+ from . import FontFile, Image
28
+
29
+ bdf_slant = {
30
+ "R": "Roman",
31
+ "I": "Italic",
32
+ "O": "Oblique",
33
+ "RI": "Reverse Italic",
34
+ "RO": "Reverse Oblique",
35
+ "OT": "Other",
36
+ }
37
+
38
+ bdf_spacing = {"P": "Proportional", "M": "Monospaced", "C": "Cell"}
39
+
40
+
41
+ def bdf_char(
42
+ f: BinaryIO,
43
+ ) -> (
44
+ tuple[
45
+ str,
46
+ int,
47
+ tuple[tuple[int, int], tuple[int, int, int, int], tuple[int, int, int, int]],
48
+ Image.Image,
49
+ ]
50
+ | None
51
+ ):
52
+ # skip to STARTCHAR
53
+ while True:
54
+ s = f.readline()
55
+ if not s:
56
+ return None
57
+ if s[:9] == b"STARTCHAR":
58
+ break
59
+ id = s[9:].strip().decode("ascii")
60
+
61
+ # load symbol properties
62
+ props = {}
63
+ while True:
64
+ s = f.readline()
65
+ if not s or s[:6] == b"BITMAP":
66
+ break
67
+ i = s.find(b" ")
68
+ props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii")
69
+
70
+ # load bitmap
71
+ bitmap = bytearray()
72
+ while True:
73
+ s = f.readline()
74
+ if not s or s[:7] == b"ENDCHAR":
75
+ break
76
+ bitmap += s[:-1]
77
+
78
+ # The word BBX
79
+ # followed by the width in x (BBw), height in y (BBh),
80
+ # and x and y displacement (BBxoff0, BByoff0)
81
+ # of the lower left corner from the origin of the character.
82
+ width, height, x_disp, y_disp = (int(p) for p in props["BBX"].split())
83
+
84
+ # The word DWIDTH
85
+ # followed by the width in x and y of the character in device pixels.
86
+ dwx, dwy = (int(p) for p in props["DWIDTH"].split())
87
+
88
+ bbox = (
89
+ (dwx, dwy),
90
+ (x_disp, -y_disp - height, width + x_disp, -y_disp),
91
+ (0, 0, width, height),
92
+ )
93
+
94
+ try:
95
+ im = Image.frombytes("1", (width, height), bitmap, "hex", "1")
96
+ except ValueError:
97
+ # deal with zero-width characters
98
+ im = Image.new("1", (width, height))
99
+
100
+ return id, int(props["ENCODING"]), bbox, im
101
+
102
+
103
+ class BdfFontFile(FontFile.FontFile):
104
+ """Font file plugin for the X11 BDF format."""
105
+
106
+ def __init__(self, fp: BinaryIO):
107
+ super().__init__()
108
+
109
+ s = fp.readline()
110
+ if s[:13] != b"STARTFONT 2.1":
111
+ msg = "not a valid BDF file"
112
+ raise SyntaxError(msg)
113
+
114
+ props = {}
115
+ comments = []
116
+
117
+ while True:
118
+ s = fp.readline()
119
+ if not s or s[:13] == b"ENDPROPERTIES":
120
+ break
121
+ i = s.find(b" ")
122
+ props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii")
123
+ if s[:i] in [b"COMMENT", b"COPYRIGHT"]:
124
+ if s.find(b"LogicalFontDescription") < 0:
125
+ comments.append(s[i + 1 : -1].decode("ascii"))
126
+
127
+ while True:
128
+ c = bdf_char(fp)
129
+ if not c:
130
+ break
131
+ id, ch, (xy, dst, src), im = c
132
+ if 0 <= ch < len(self.glyph):
133
+ self.glyph[ch] = xy, dst, src, im
gtm/lib/python3.12/site-packages/PIL/BlpImagePlugin.py ADDED
@@ -0,0 +1,475 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Blizzard Mipmap Format (.blp)
3
+ Jerome Leclanche <jerome@leclan.ch>
4
+
5
+ The contents of this file are hereby released in the public domain (CC0)
6
+ Full text of the CC0 license:
7
+ https://creativecommons.org/publicdomain/zero/1.0/
8
+
9
+ BLP1 files, used mostly in Warcraft III, are not fully supported.
10
+ All types of BLP2 files used in World of Warcraft are supported.
11
+
12
+ The BLP file structure consists of a header, up to 16 mipmaps of the
13
+ texture
14
+
15
+ Texture sizes must be powers of two, though the two dimensions do
16
+ not have to be equal; 512x256 is valid, but 512x200 is not.
17
+ The first mipmap (mipmap #0) is the full size image; each subsequent
18
+ mipmap halves both dimensions. The final mipmap should be 1x1.
19
+
20
+ BLP files come in many different flavours:
21
+ * JPEG-compressed (type == 0) - only supported for BLP1.
22
+ * RAW images (type == 1, encoding == 1). Each mipmap is stored as an
23
+ array of 8-bit values, one per pixel, left to right, top to bottom.
24
+ Each value is an index to the palette.
25
+ * DXT-compressed (type == 1, encoding == 2):
26
+ - DXT1 compression is used if alpha_encoding == 0.
27
+ - An additional alpha bit is used if alpha_depth == 1.
28
+ - DXT3 compression is used if alpha_encoding == 1.
29
+ - DXT5 compression is used if alpha_encoding == 7.
30
+ """
31
+ from __future__ import annotations
32
+
33
+ import os
34
+ import struct
35
+ from enum import IntEnum
36
+ from io import BytesIO
37
+
38
+ from . import Image, ImageFile
39
+
40
+
41
+ class Format(IntEnum):
42
+ JPEG = 0
43
+
44
+
45
+ class Encoding(IntEnum):
46
+ UNCOMPRESSED = 1
47
+ DXT = 2
48
+ UNCOMPRESSED_RAW_BGRA = 3
49
+
50
+
51
+ class AlphaEncoding(IntEnum):
52
+ DXT1 = 0
53
+ DXT3 = 1
54
+ DXT5 = 7
55
+
56
+
57
+ def unpack_565(i):
58
+ return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
59
+
60
+
61
+ def decode_dxt1(data, alpha=False):
62
+ """
63
+ input: one "row" of data (i.e. will produce 4*width pixels)
64
+ """
65
+
66
+ blocks = len(data) // 8 # number of blocks in row
67
+ ret = (bytearray(), bytearray(), bytearray(), bytearray())
68
+
69
+ for block in range(blocks):
70
+ # Decode next 8-byte block.
71
+ idx = block * 8
72
+ color0, color1, bits = struct.unpack_from("<HHI", data, idx)
73
+
74
+ r0, g0, b0 = unpack_565(color0)
75
+ r1, g1, b1 = unpack_565(color1)
76
+
77
+ # Decode this block into 4x4 pixels
78
+ # Accumulate the results onto our 4 row accumulators
79
+ for j in range(4):
80
+ for i in range(4):
81
+ # get next control op and generate a pixel
82
+
83
+ control = bits & 3
84
+ bits = bits >> 2
85
+
86
+ a = 0xFF
87
+ if control == 0:
88
+ r, g, b = r0, g0, b0
89
+ elif control == 1:
90
+ r, g, b = r1, g1, b1
91
+ elif control == 2:
92
+ if color0 > color1:
93
+ r = (2 * r0 + r1) // 3
94
+ g = (2 * g0 + g1) // 3
95
+ b = (2 * b0 + b1) // 3
96
+ else:
97
+ r = (r0 + r1) // 2
98
+ g = (g0 + g1) // 2
99
+ b = (b0 + b1) // 2
100
+ elif control == 3:
101
+ if color0 > color1:
102
+ r = (2 * r1 + r0) // 3
103
+ g = (2 * g1 + g0) // 3
104
+ b = (2 * b1 + b0) // 3
105
+ else:
106
+ r, g, b, a = 0, 0, 0, 0
107
+
108
+ if alpha:
109
+ ret[j].extend([r, g, b, a])
110
+ else:
111
+ ret[j].extend([r, g, b])
112
+
113
+ return ret
114
+
115
+
116
+ def decode_dxt3(data):
117
+ """
118
+ input: one "row" of data (i.e. will produce 4*width pixels)
119
+ """
120
+
121
+ blocks = len(data) // 16 # number of blocks in row
122
+ ret = (bytearray(), bytearray(), bytearray(), bytearray())
123
+
124
+ for block in range(blocks):
125
+ idx = block * 16
126
+ block = data[idx : idx + 16]
127
+ # Decode next 16-byte block.
128
+ bits = struct.unpack_from("<8B", block)
129
+ color0, color1 = struct.unpack_from("<HH", block, 8)
130
+
131
+ (code,) = struct.unpack_from("<I", block, 12)
132
+
133
+ r0, g0, b0 = unpack_565(color0)
134
+ r1, g1, b1 = unpack_565(color1)
135
+
136
+ for j in range(4):
137
+ high = False # Do we want the higher bits?
138
+ for i in range(4):
139
+ alphacode_index = (4 * j + i) // 2
140
+ a = bits[alphacode_index]
141
+ if high:
142
+ high = False
143
+ a >>= 4
144
+ else:
145
+ high = True
146
+ a &= 0xF
147
+ a *= 17 # We get a value between 0 and 15
148
+
149
+ color_code = (code >> 2 * (4 * j + i)) & 0x03
150
+
151
+ if color_code == 0:
152
+ r, g, b = r0, g0, b0
153
+ elif color_code == 1:
154
+ r, g, b = r1, g1, b1
155
+ elif color_code == 2:
156
+ r = (2 * r0 + r1) // 3
157
+ g = (2 * g0 + g1) // 3
158
+ b = (2 * b0 + b1) // 3
159
+ elif color_code == 3:
160
+ r = (2 * r1 + r0) // 3
161
+ g = (2 * g1 + g0) // 3
162
+ b = (2 * b1 + b0) // 3
163
+
164
+ ret[j].extend([r, g, b, a])
165
+
166
+ return ret
167
+
168
+
169
+ def decode_dxt5(data):
170
+ """
171
+ input: one "row" of data (i.e. will produce 4 * width pixels)
172
+ """
173
+
174
+ blocks = len(data) // 16 # number of blocks in row
175
+ ret = (bytearray(), bytearray(), bytearray(), bytearray())
176
+
177
+ for block in range(blocks):
178
+ idx = block * 16
179
+ block = data[idx : idx + 16]
180
+ # Decode next 16-byte block.
181
+ a0, a1 = struct.unpack_from("<BB", block)
182
+
183
+ bits = struct.unpack_from("<6B", block, 2)
184
+ alphacode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24)
185
+ alphacode2 = bits[0] | (bits[1] << 8)
186
+
187
+ color0, color1 = struct.unpack_from("<HH", block, 8)
188
+
189
+ (code,) = struct.unpack_from("<I", block, 12)
190
+
191
+ r0, g0, b0 = unpack_565(color0)
192
+ r1, g1, b1 = unpack_565(color1)
193
+
194
+ for j in range(4):
195
+ for i in range(4):
196
+ # get next control op and generate a pixel
197
+ alphacode_index = 3 * (4 * j + i)
198
+
199
+ if alphacode_index <= 12:
200
+ alphacode = (alphacode2 >> alphacode_index) & 0x07
201
+ elif alphacode_index == 15:
202
+ alphacode = (alphacode2 >> 15) | ((alphacode1 << 1) & 0x06)
203
+ else: # alphacode_index >= 18 and alphacode_index <= 45
204
+ alphacode = (alphacode1 >> (alphacode_index - 16)) & 0x07
205
+
206
+ if alphacode == 0:
207
+ a = a0
208
+ elif alphacode == 1:
209
+ a = a1
210
+ elif a0 > a1:
211
+ a = ((8 - alphacode) * a0 + (alphacode - 1) * a1) // 7
212
+ elif alphacode == 6:
213
+ a = 0
214
+ elif alphacode == 7:
215
+ a = 255
216
+ else:
217
+ a = ((6 - alphacode) * a0 + (alphacode - 1) * a1) // 5
218
+
219
+ color_code = (code >> 2 * (4 * j + i)) & 0x03
220
+
221
+ if color_code == 0:
222
+ r, g, b = r0, g0, b0
223
+ elif color_code == 1:
224
+ r, g, b = r1, g1, b1
225
+ elif color_code == 2:
226
+ r = (2 * r0 + r1) // 3
227
+ g = (2 * g0 + g1) // 3
228
+ b = (2 * b0 + b1) // 3
229
+ elif color_code == 3:
230
+ r = (2 * r1 + r0) // 3
231
+ g = (2 * g1 + g0) // 3
232
+ b = (2 * b1 + b0) // 3
233
+
234
+ ret[j].extend([r, g, b, a])
235
+
236
+ return ret
237
+
238
+
239
+ class BLPFormatError(NotImplementedError):
240
+ pass
241
+
242
+
243
+ def _accept(prefix):
244
+ return prefix[:4] in (b"BLP1", b"BLP2")
245
+
246
+
247
+ class BlpImageFile(ImageFile.ImageFile):
248
+ """
249
+ Blizzard Mipmap Format
250
+ """
251
+
252
+ format = "BLP"
253
+ format_description = "Blizzard Mipmap Format"
254
+
255
+ def _open(self):
256
+ self.magic = self.fp.read(4)
257
+
258
+ self.fp.seek(5, os.SEEK_CUR)
259
+ (self._blp_alpha_depth,) = struct.unpack("<b", self.fp.read(1))
260
+
261
+ self.fp.seek(2, os.SEEK_CUR)
262
+ self._size = struct.unpack("<II", self.fp.read(8))
263
+
264
+ if self.magic in (b"BLP1", b"BLP2"):
265
+ decoder = self.magic.decode()
266
+ else:
267
+ msg = f"Bad BLP magic {repr(self.magic)}"
268
+ raise BLPFormatError(msg)
269
+
270
+ self._mode = "RGBA" if self._blp_alpha_depth else "RGB"
271
+ self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
272
+
273
+
274
+ class _BLPBaseDecoder(ImageFile.PyDecoder):
275
+ _pulls_fd = True
276
+
277
+ def decode(self, buffer):
278
+ try:
279
+ self._read_blp_header()
280
+ self._load()
281
+ except struct.error as e:
282
+ msg = "Truncated BLP file"
283
+ raise OSError(msg) from e
284
+ return -1, 0
285
+
286
+ def _read_blp_header(self):
287
+ self.fd.seek(4)
288
+ (self._blp_compression,) = struct.unpack("<i", self._safe_read(4))
289
+
290
+ (self._blp_encoding,) = struct.unpack("<b", self._safe_read(1))
291
+ (self._blp_alpha_depth,) = struct.unpack("<b", self._safe_read(1))
292
+ (self._blp_alpha_encoding,) = struct.unpack("<b", self._safe_read(1))
293
+ self.fd.seek(1, os.SEEK_CUR) # mips
294
+
295
+ self.size = struct.unpack("<II", self._safe_read(8))
296
+
297
+ if isinstance(self, BLP1Decoder):
298
+ # Only present for BLP1
299
+ (self._blp_encoding,) = struct.unpack("<i", self._safe_read(4))
300
+ self.fd.seek(4, os.SEEK_CUR) # subtype
301
+
302
+ self._blp_offsets = struct.unpack("<16I", self._safe_read(16 * 4))
303
+ self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4))
304
+
305
+ def _safe_read(self, length):
306
+ return ImageFile._safe_read(self.fd, length)
307
+
308
+ def _read_palette(self):
309
+ ret = []
310
+ for i in range(256):
311
+ try:
312
+ b, g, r, a = struct.unpack("<4B", self._safe_read(4))
313
+ except struct.error:
314
+ break
315
+ ret.append((b, g, r, a))
316
+ return ret
317
+
318
+ def _read_bgra(self, palette):
319
+ data = bytearray()
320
+ _data = BytesIO(self._safe_read(self._blp_lengths[0]))
321
+ while True:
322
+ try:
323
+ (offset,) = struct.unpack("<B", _data.read(1))
324
+ except struct.error:
325
+ break
326
+ b, g, r, a = palette[offset]
327
+ d = (r, g, b)
328
+ if self._blp_alpha_depth:
329
+ d += (a,)
330
+ data.extend(d)
331
+ return data
332
+
333
+
334
+ class BLP1Decoder(_BLPBaseDecoder):
335
+ def _load(self):
336
+ if self._blp_compression == Format.JPEG:
337
+ self._decode_jpeg_stream()
338
+
339
+ elif self._blp_compression == 1:
340
+ if self._blp_encoding in (4, 5):
341
+ palette = self._read_palette()
342
+ data = self._read_bgra(palette)
343
+ self.set_as_raw(bytes(data))
344
+ else:
345
+ msg = f"Unsupported BLP encoding {repr(self._blp_encoding)}"
346
+ raise BLPFormatError(msg)
347
+ else:
348
+ msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
349
+ raise BLPFormatError(msg)
350
+
351
+ def _decode_jpeg_stream(self):
352
+ from .JpegImagePlugin import JpegImageFile
353
+
354
+ (jpeg_header_size,) = struct.unpack("<I", self._safe_read(4))
355
+ jpeg_header = self._safe_read(jpeg_header_size)
356
+ self._safe_read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
357
+ data = self._safe_read(self._blp_lengths[0])
358
+ data = jpeg_header + data
359
+ data = BytesIO(data)
360
+ image = JpegImageFile(data)
361
+ Image._decompression_bomb_check(image.size)
362
+ if image.mode == "CMYK":
363
+ decoder_name, extents, offset, args = image.tile[0]
364
+ image.tile = [(decoder_name, extents, offset, (args[0], "CMYK"))]
365
+ r, g, b = image.convert("RGB").split()
366
+ image = Image.merge("RGB", (b, g, r))
367
+ self.set_as_raw(image.tobytes())
368
+
369
+
370
+ class BLP2Decoder(_BLPBaseDecoder):
371
+ def _load(self):
372
+ palette = self._read_palette()
373
+
374
+ self.fd.seek(self._blp_offsets[0])
375
+
376
+ if self._blp_compression == 1:
377
+ # Uncompressed or DirectX compression
378
+
379
+ if self._blp_encoding == Encoding.UNCOMPRESSED:
380
+ data = self._read_bgra(palette)
381
+
382
+ elif self._blp_encoding == Encoding.DXT:
383
+ data = bytearray()
384
+ if self._blp_alpha_encoding == AlphaEncoding.DXT1:
385
+ linesize = (self.size[0] + 3) // 4 * 8
386
+ for yb in range((self.size[1] + 3) // 4):
387
+ for d in decode_dxt1(
388
+ self._safe_read(linesize), alpha=bool(self._blp_alpha_depth)
389
+ ):
390
+ data += d
391
+
392
+ elif self._blp_alpha_encoding == AlphaEncoding.DXT3:
393
+ linesize = (self.size[0] + 3) // 4 * 16
394
+ for yb in range((self.size[1] + 3) // 4):
395
+ for d in decode_dxt3(self._safe_read(linesize)):
396
+ data += d
397
+
398
+ elif self._blp_alpha_encoding == AlphaEncoding.DXT5:
399
+ linesize = (self.size[0] + 3) // 4 * 16
400
+ for yb in range((self.size[1] + 3) // 4):
401
+ for d in decode_dxt5(self._safe_read(linesize)):
402
+ data += d
403
+ else:
404
+ msg = f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
405
+ raise BLPFormatError(msg)
406
+ else:
407
+ msg = f"Unknown BLP encoding {repr(self._blp_encoding)}"
408
+ raise BLPFormatError(msg)
409
+
410
+ else:
411
+ msg = f"Unknown BLP compression {repr(self._blp_compression)}"
412
+ raise BLPFormatError(msg)
413
+
414
+ self.set_as_raw(bytes(data))
415
+
416
+
417
+ class BLPEncoder(ImageFile.PyEncoder):
418
+ _pushes_fd = True
419
+
420
+ def _write_palette(self):
421
+ data = b""
422
+ palette = self.im.getpalette("RGBA", "RGBA")
423
+ for i in range(len(palette) // 4):
424
+ r, g, b, a = palette[i * 4 : (i + 1) * 4]
425
+ data += struct.pack("<4B", b, g, r, a)
426
+ while len(data) < 256 * 4:
427
+ data += b"\x00" * 4
428
+ return data
429
+
430
+ def encode(self, bufsize):
431
+ palette_data = self._write_palette()
432
+
433
+ offset = 20 + 16 * 4 * 2 + len(palette_data)
434
+ data = struct.pack("<16I", offset, *((0,) * 15))
435
+
436
+ w, h = self.im.size
437
+ data += struct.pack("<16I", w * h, *((0,) * 15))
438
+
439
+ data += palette_data
440
+
441
+ for y in range(h):
442
+ for x in range(w):
443
+ data += struct.pack("<B", self.im.getpixel((x, y)))
444
+
445
+ return len(data), 0, data
446
+
447
+
448
+ def _save(im, fp, filename):
449
+ if im.mode != "P":
450
+ msg = "Unsupported BLP image mode"
451
+ raise ValueError(msg)
452
+
453
+ magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2"
454
+ fp.write(magic)
455
+
456
+ fp.write(struct.pack("<i", 1)) # Uncompressed or DirectX compression
457
+ fp.write(struct.pack("<b", Encoding.UNCOMPRESSED))
458
+ fp.write(struct.pack("<b", 1 if im.palette.mode == "RGBA" else 0))
459
+ fp.write(struct.pack("<b", 0)) # alpha encoding
460
+ fp.write(struct.pack("<b", 0)) # mips
461
+ fp.write(struct.pack("<II", *im.size))
462
+ if magic == b"BLP1":
463
+ fp.write(struct.pack("<i", 5))
464
+ fp.write(struct.pack("<i", 0))
465
+
466
+ ImageFile._save(im, fp, [("BLP", (0, 0) + im.size, 0, im.mode)])
467
+
468
+
469
+ Image.register_open(BlpImageFile.format, BlpImageFile, _accept)
470
+ Image.register_extension(BlpImageFile.format, ".blp")
471
+ Image.register_decoder("BLP1", BLP1Decoder)
472
+ Image.register_decoder("BLP2", BLP2Decoder)
473
+
474
+ Image.register_save(BlpImageFile.format, _save)
475
+ Image.register_encoder("BLP", BLPEncoder)
gtm/lib/python3.12/site-packages/PIL/BmpImagePlugin.py ADDED
@@ -0,0 +1,471 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # BMP file handler
6
+ #
7
+ # Windows (and OS/2) native bitmap storage format.
8
+ #
9
+ # history:
10
+ # 1995-09-01 fl Created
11
+ # 1996-04-30 fl Added save
12
+ # 1997-08-27 fl Fixed save of 1-bit images
13
+ # 1998-03-06 fl Load P images as L where possible
14
+ # 1998-07-03 fl Load P images as 1 where possible
15
+ # 1998-12-29 fl Handle small palettes
16
+ # 2002-12-30 fl Fixed load of 1-bit palette images
17
+ # 2003-04-21 fl Fixed load of 1-bit monochrome images
18
+ # 2003-04-23 fl Added limited support for BI_BITFIELDS compression
19
+ #
20
+ # Copyright (c) 1997-2003 by Secret Labs AB
21
+ # Copyright (c) 1995-2003 by Fredrik Lundh
22
+ #
23
+ # See the README file for information on usage and redistribution.
24
+ #
25
+ from __future__ import annotations
26
+
27
+ import os
28
+
29
+ from . import Image, ImageFile, ImagePalette
30
+ from ._binary import i16le as i16
31
+ from ._binary import i32le as i32
32
+ from ._binary import o8
33
+ from ._binary import o16le as o16
34
+ from ._binary import o32le as o32
35
+
36
+ #
37
+ # --------------------------------------------------------------------
38
+ # Read BMP file
39
+
40
+ BIT2MODE = {
41
+ # bits => mode, rawmode
42
+ 1: ("P", "P;1"),
43
+ 4: ("P", "P;4"),
44
+ 8: ("P", "P"),
45
+ 16: ("RGB", "BGR;15"),
46
+ 24: ("RGB", "BGR"),
47
+ 32: ("RGB", "BGRX"),
48
+ }
49
+
50
+
51
+ def _accept(prefix):
52
+ return prefix[:2] == b"BM"
53
+
54
+
55
+ def _dib_accept(prefix):
56
+ return i32(prefix) in [12, 40, 64, 108, 124]
57
+
58
+
59
+ # =============================================================================
60
+ # Image plugin for the Windows BMP format.
61
+ # =============================================================================
62
+ class BmpImageFile(ImageFile.ImageFile):
63
+ """Image plugin for the Windows Bitmap format (BMP)"""
64
+
65
+ # ------------------------------------------------------------- Description
66
+ format_description = "Windows Bitmap"
67
+ format = "BMP"
68
+
69
+ # -------------------------------------------------- BMP Compression values
70
+ COMPRESSIONS = {"RAW": 0, "RLE8": 1, "RLE4": 2, "BITFIELDS": 3, "JPEG": 4, "PNG": 5}
71
+ for k, v in COMPRESSIONS.items():
72
+ vars()[k] = v
73
+
74
+ def _bitmap(self, header=0, offset=0):
75
+ """Read relevant info about the BMP"""
76
+ read, seek = self.fp.read, self.fp.seek
77
+ if header:
78
+ seek(header)
79
+ # read bmp header size @offset 14 (this is part of the header size)
80
+ file_info = {"header_size": i32(read(4)), "direction": -1}
81
+
82
+ # -------------------- If requested, read header at a specific position
83
+ # read the rest of the bmp header, without its size
84
+ header_data = ImageFile._safe_read(self.fp, file_info["header_size"] - 4)
85
+
86
+ # -------------------------------------------------- IBM OS/2 Bitmap v1
87
+ # ----- This format has different offsets because of width/height types
88
+ if file_info["header_size"] == 12:
89
+ file_info["width"] = i16(header_data, 0)
90
+ file_info["height"] = i16(header_data, 2)
91
+ file_info["planes"] = i16(header_data, 4)
92
+ file_info["bits"] = i16(header_data, 6)
93
+ file_info["compression"] = self.RAW
94
+ file_info["palette_padding"] = 3
95
+
96
+ # --------------------------------------------- Windows Bitmap v2 to v5
97
+ # v3, OS/2 v2, v4, v5
98
+ elif file_info["header_size"] in (40, 64, 108, 124):
99
+ file_info["y_flip"] = header_data[7] == 0xFF
100
+ file_info["direction"] = 1 if file_info["y_flip"] else -1
101
+ file_info["width"] = i32(header_data, 0)
102
+ file_info["height"] = (
103
+ i32(header_data, 4)
104
+ if not file_info["y_flip"]
105
+ else 2**32 - i32(header_data, 4)
106
+ )
107
+ file_info["planes"] = i16(header_data, 8)
108
+ file_info["bits"] = i16(header_data, 10)
109
+ file_info["compression"] = i32(header_data, 12)
110
+ # byte size of pixel data
111
+ file_info["data_size"] = i32(header_data, 16)
112
+ file_info["pixels_per_meter"] = (
113
+ i32(header_data, 20),
114
+ i32(header_data, 24),
115
+ )
116
+ file_info["colors"] = i32(header_data, 28)
117
+ file_info["palette_padding"] = 4
118
+ self.info["dpi"] = tuple(x / 39.3701 for x in file_info["pixels_per_meter"])
119
+ if file_info["compression"] == self.BITFIELDS:
120
+ if len(header_data) >= 52:
121
+ for idx, mask in enumerate(
122
+ ["r_mask", "g_mask", "b_mask", "a_mask"]
123
+ ):
124
+ file_info[mask] = i32(header_data, 36 + idx * 4)
125
+ else:
126
+ # 40 byte headers only have the three components in the
127
+ # bitfields masks, ref:
128
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
129
+ # See also
130
+ # https://github.com/python-pillow/Pillow/issues/1293
131
+ # There is a 4th component in the RGBQuad, in the alpha
132
+ # location, but it is listed as a reserved component,
133
+ # and it is not generally an alpha channel
134
+ file_info["a_mask"] = 0x0
135
+ for mask in ["r_mask", "g_mask", "b_mask"]:
136
+ file_info[mask] = i32(read(4))
137
+ file_info["rgb_mask"] = (
138
+ file_info["r_mask"],
139
+ file_info["g_mask"],
140
+ file_info["b_mask"],
141
+ )
142
+ file_info["rgba_mask"] = (
143
+ file_info["r_mask"],
144
+ file_info["g_mask"],
145
+ file_info["b_mask"],
146
+ file_info["a_mask"],
147
+ )
148
+ else:
149
+ msg = f"Unsupported BMP header type ({file_info['header_size']})"
150
+ raise OSError(msg)
151
+
152
+ # ------------------ Special case : header is reported 40, which
153
+ # ---------------------- is shorter than real size for bpp >= 16
154
+ self._size = file_info["width"], file_info["height"]
155
+
156
+ # ------- If color count was not found in the header, compute from bits
157
+ file_info["colors"] = (
158
+ file_info["colors"]
159
+ if file_info.get("colors", 0)
160
+ else (1 << file_info["bits"])
161
+ )
162
+ if offset == 14 + file_info["header_size"] and file_info["bits"] <= 8:
163
+ offset += 4 * file_info["colors"]
164
+
165
+ # ---------------------- Check bit depth for unusual unsupported values
166
+ self._mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
167
+ if self.mode is None:
168
+ msg = f"Unsupported BMP pixel depth ({file_info['bits']})"
169
+ raise OSError(msg)
170
+
171
+ # ---------------- Process BMP with Bitfields compression (not palette)
172
+ decoder_name = "raw"
173
+ if file_info["compression"] == self.BITFIELDS:
174
+ SUPPORTED = {
175
+ 32: [
176
+ (0xFF0000, 0xFF00, 0xFF, 0x0),
177
+ (0xFF000000, 0xFF0000, 0xFF00, 0x0),
178
+ (0xFF000000, 0xFF0000, 0xFF00, 0xFF),
179
+ (0xFF, 0xFF00, 0xFF0000, 0xFF000000),
180
+ (0xFF0000, 0xFF00, 0xFF, 0xFF000000),
181
+ (0x0, 0x0, 0x0, 0x0),
182
+ ],
183
+ 24: [(0xFF0000, 0xFF00, 0xFF)],
184
+ 16: [(0xF800, 0x7E0, 0x1F), (0x7C00, 0x3E0, 0x1F)],
185
+ }
186
+ MASK_MODES = {
187
+ (32, (0xFF0000, 0xFF00, 0xFF, 0x0)): "BGRX",
188
+ (32, (0xFF000000, 0xFF0000, 0xFF00, 0x0)): "XBGR",
189
+ (32, (0xFF000000, 0xFF0000, 0xFF00, 0xFF)): "ABGR",
190
+ (32, (0xFF, 0xFF00, 0xFF0000, 0xFF000000)): "RGBA",
191
+ (32, (0xFF0000, 0xFF00, 0xFF, 0xFF000000)): "BGRA",
192
+ (32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
193
+ (24, (0xFF0000, 0xFF00, 0xFF)): "BGR",
194
+ (16, (0xF800, 0x7E0, 0x1F)): "BGR;16",
195
+ (16, (0x7C00, 0x3E0, 0x1F)): "BGR;15",
196
+ }
197
+ if file_info["bits"] in SUPPORTED:
198
+ if (
199
+ file_info["bits"] == 32
200
+ and file_info["rgba_mask"] in SUPPORTED[file_info["bits"]]
201
+ ):
202
+ raw_mode = MASK_MODES[(file_info["bits"], file_info["rgba_mask"])]
203
+ self._mode = "RGBA" if "A" in raw_mode else self.mode
204
+ elif (
205
+ file_info["bits"] in (24, 16)
206
+ and file_info["rgb_mask"] in SUPPORTED[file_info["bits"]]
207
+ ):
208
+ raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
209
+ else:
210
+ msg = "Unsupported BMP bitfields layout"
211
+ raise OSError(msg)
212
+ else:
213
+ msg = "Unsupported BMP bitfields layout"
214
+ raise OSError(msg)
215
+ elif file_info["compression"] == self.RAW:
216
+ if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
217
+ raw_mode, self._mode = "BGRA", "RGBA"
218
+ elif file_info["compression"] in (self.RLE8, self.RLE4):
219
+ decoder_name = "bmp_rle"
220
+ else:
221
+ msg = f"Unsupported BMP compression ({file_info['compression']})"
222
+ raise OSError(msg)
223
+
224
+ # --------------- Once the header is processed, process the palette/LUT
225
+ if self.mode == "P": # Paletted for 1, 4 and 8 bit images
226
+ # ---------------------------------------------------- 1-bit images
227
+ if not (0 < file_info["colors"] <= 65536):
228
+ msg = f"Unsupported BMP Palette size ({file_info['colors']})"
229
+ raise OSError(msg)
230
+ else:
231
+ padding = file_info["palette_padding"]
232
+ palette = read(padding * file_info["colors"])
233
+ grayscale = True
234
+ indices = (
235
+ (0, 255)
236
+ if file_info["colors"] == 2
237
+ else list(range(file_info["colors"]))
238
+ )
239
+
240
+ # ----------------- Check if grayscale and ignore palette if so
241
+ for ind, val in enumerate(indices):
242
+ rgb = palette[ind * padding : ind * padding + 3]
243
+ if rgb != o8(val) * 3:
244
+ grayscale = False
245
+
246
+ # ------- If all colors are gray, white or black, ditch palette
247
+ if grayscale:
248
+ self._mode = "1" if file_info["colors"] == 2 else "L"
249
+ raw_mode = self.mode
250
+ else:
251
+ self._mode = "P"
252
+ self.palette = ImagePalette.raw(
253
+ "BGRX" if padding == 4 else "BGR", palette
254
+ )
255
+
256
+ # ---------------------------- Finally set the tile data for the plugin
257
+ self.info["compression"] = file_info["compression"]
258
+ args = [raw_mode]
259
+ if decoder_name == "bmp_rle":
260
+ args.append(file_info["compression"] == self.RLE4)
261
+ else:
262
+ args.append(((file_info["width"] * file_info["bits"] + 31) >> 3) & (~3))
263
+ args.append(file_info["direction"])
264
+ self.tile = [
265
+ (
266
+ decoder_name,
267
+ (0, 0, file_info["width"], file_info["height"]),
268
+ offset or self.fp.tell(),
269
+ tuple(args),
270
+ )
271
+ ]
272
+
273
+ def _open(self):
274
+ """Open file, check magic number and read header"""
275
+ # read 14 bytes: magic number, filesize, reserved, header final offset
276
+ head_data = self.fp.read(14)
277
+ # choke if the file does not have the required magic bytes
278
+ if not _accept(head_data):
279
+ msg = "Not a BMP file"
280
+ raise SyntaxError(msg)
281
+ # read the start position of the BMP image data (u32)
282
+ offset = i32(head_data, 10)
283
+ # load bitmap information (offset=raster info)
284
+ self._bitmap(offset=offset)
285
+
286
+
287
+ class BmpRleDecoder(ImageFile.PyDecoder):
288
+ _pulls_fd = True
289
+
290
+ def decode(self, buffer):
291
+ rle4 = self.args[1]
292
+ data = bytearray()
293
+ x = 0
294
+ while len(data) < self.state.xsize * self.state.ysize:
295
+ pixels = self.fd.read(1)
296
+ byte = self.fd.read(1)
297
+ if not pixels or not byte:
298
+ break
299
+ num_pixels = pixels[0]
300
+ if num_pixels:
301
+ # encoded mode
302
+ if x + num_pixels > self.state.xsize:
303
+ # Too much data for row
304
+ num_pixels = max(0, self.state.xsize - x)
305
+ if rle4:
306
+ first_pixel = o8(byte[0] >> 4)
307
+ second_pixel = o8(byte[0] & 0x0F)
308
+ for index in range(num_pixels):
309
+ if index % 2 == 0:
310
+ data += first_pixel
311
+ else:
312
+ data += second_pixel
313
+ else:
314
+ data += byte * num_pixels
315
+ x += num_pixels
316
+ else:
317
+ if byte[0] == 0:
318
+ # end of line
319
+ while len(data) % self.state.xsize != 0:
320
+ data += b"\x00"
321
+ x = 0
322
+ elif byte[0] == 1:
323
+ # end of bitmap
324
+ break
325
+ elif byte[0] == 2:
326
+ # delta
327
+ bytes_read = self.fd.read(2)
328
+ if len(bytes_read) < 2:
329
+ break
330
+ right, up = self.fd.read(2)
331
+ data += b"\x00" * (right + up * self.state.xsize)
332
+ x = len(data) % self.state.xsize
333
+ else:
334
+ # absolute mode
335
+ if rle4:
336
+ # 2 pixels per byte
337
+ byte_count = byte[0] // 2
338
+ bytes_read = self.fd.read(byte_count)
339
+ for byte_read in bytes_read:
340
+ data += o8(byte_read >> 4)
341
+ data += o8(byte_read & 0x0F)
342
+ else:
343
+ byte_count = byte[0]
344
+ bytes_read = self.fd.read(byte_count)
345
+ data += bytes_read
346
+ if len(bytes_read) < byte_count:
347
+ break
348
+ x += byte[0]
349
+
350
+ # align to 16-bit word boundary
351
+ if self.fd.tell() % 2 != 0:
352
+ self.fd.seek(1, os.SEEK_CUR)
353
+ rawmode = "L" if self.mode == "L" else "P"
354
+ self.set_as_raw(bytes(data), (rawmode, 0, self.args[-1]))
355
+ return -1, 0
356
+
357
+
358
+ # =============================================================================
359
+ # Image plugin for the DIB format (BMP alias)
360
+ # =============================================================================
361
+ class DibImageFile(BmpImageFile):
362
+ format = "DIB"
363
+ format_description = "Windows Bitmap"
364
+
365
+ def _open(self):
366
+ self._bitmap()
367
+
368
+
369
+ #
370
+ # --------------------------------------------------------------------
371
+ # Write BMP file
372
+
373
+
374
+ SAVE = {
375
+ "1": ("1", 1, 2),
376
+ "L": ("L", 8, 256),
377
+ "P": ("P", 8, 256),
378
+ "RGB": ("BGR", 24, 0),
379
+ "RGBA": ("BGRA", 32, 0),
380
+ }
381
+
382
+
383
+ def _dib_save(im, fp, filename):
384
+ _save(im, fp, filename, False)
385
+
386
+
387
+ def _save(im, fp, filename, bitmap_header=True):
388
+ try:
389
+ rawmode, bits, colors = SAVE[im.mode]
390
+ except KeyError as e:
391
+ msg = f"cannot write mode {im.mode} as BMP"
392
+ raise OSError(msg) from e
393
+
394
+ info = im.encoderinfo
395
+
396
+ dpi = info.get("dpi", (96, 96))
397
+
398
+ # 1 meter == 39.3701 inches
399
+ ppm = tuple(int(x * 39.3701 + 0.5) for x in dpi)
400
+
401
+ stride = ((im.size[0] * bits + 7) // 8 + 3) & (~3)
402
+ header = 40 # or 64 for OS/2 version 2
403
+ image = stride * im.size[1]
404
+
405
+ if im.mode == "1":
406
+ palette = b"".join(o8(i) * 4 for i in (0, 255))
407
+ elif im.mode == "L":
408
+ palette = b"".join(o8(i) * 4 for i in range(256))
409
+ elif im.mode == "P":
410
+ palette = im.im.getpalette("RGB", "BGRX")
411
+ colors = len(palette) // 4
412
+ else:
413
+ palette = None
414
+
415
+ # bitmap header
416
+ if bitmap_header:
417
+ offset = 14 + header + colors * 4
418
+ file_size = offset + image
419
+ if file_size > 2**32 - 1:
420
+ msg = "File size is too large for the BMP format"
421
+ raise ValueError(msg)
422
+ fp.write(
423
+ b"BM" # file type (magic)
424
+ + o32(file_size) # file size
425
+ + o32(0) # reserved
426
+ + o32(offset) # image data offset
427
+ )
428
+
429
+ # bitmap info header
430
+ fp.write(
431
+ o32(header) # info header size
432
+ + o32(im.size[0]) # width
433
+ + o32(im.size[1]) # height
434
+ + o16(1) # planes
435
+ + o16(bits) # depth
436
+ + o32(0) # compression (0=uncompressed)
437
+ + o32(image) # size of bitmap
438
+ + o32(ppm[0]) # resolution
439
+ + o32(ppm[1]) # resolution
440
+ + o32(colors) # colors used
441
+ + o32(colors) # colors important
442
+ )
443
+
444
+ fp.write(b"\0" * (header - 40)) # padding (for OS/2 format)
445
+
446
+ if palette:
447
+ fp.write(palette)
448
+
449
+ ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, stride, -1))])
450
+
451
+
452
+ #
453
+ # --------------------------------------------------------------------
454
+ # Registry
455
+
456
+
457
+ Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
458
+ Image.register_save(BmpImageFile.format, _save)
459
+
460
+ Image.register_extension(BmpImageFile.format, ".bmp")
461
+
462
+ Image.register_mime(BmpImageFile.format, "image/bmp")
463
+
464
+ Image.register_decoder("bmp_rle", BmpRleDecoder)
465
+
466
+ Image.register_open(DibImageFile.format, DibImageFile, _dib_accept)
467
+ Image.register_save(DibImageFile.format, _dib_save)
468
+
469
+ Image.register_extension(DibImageFile.format, ".dib")
470
+
471
+ Image.register_mime(DibImageFile.format, "image/bmp")
gtm/lib/python3.12/site-packages/PIL/BufrStubImagePlugin.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library
3
+ # $Id$
4
+ #
5
+ # BUFR stub adapter
6
+ #
7
+ # Copyright (c) 1996-2003 by Fredrik Lundh
8
+ #
9
+ # See the README file for information on usage and redistribution.
10
+ #
11
+ from __future__ import annotations
12
+
13
+ from . import Image, ImageFile
14
+
15
+ _handler = None
16
+
17
+
18
+ def register_handler(handler):
19
+ """
20
+ Install application-specific BUFR image handler.
21
+
22
+ :param handler: Handler object.
23
+ """
24
+ global _handler
25
+ _handler = handler
26
+
27
+
28
+ # --------------------------------------------------------------------
29
+ # Image adapter
30
+
31
+
32
+ def _accept(prefix):
33
+ return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
34
+
35
+
36
+ class BufrStubImageFile(ImageFile.StubImageFile):
37
+ format = "BUFR"
38
+ format_description = "BUFR"
39
+
40
+ def _open(self):
41
+ offset = self.fp.tell()
42
+
43
+ if not _accept(self.fp.read(4)):
44
+ msg = "Not a BUFR file"
45
+ raise SyntaxError(msg)
46
+
47
+ self.fp.seek(offset)
48
+
49
+ # make something up
50
+ self._mode = "F"
51
+ self._size = 1, 1
52
+
53
+ loader = self._load()
54
+ if loader:
55
+ loader.open(self)
56
+
57
+ def _load(self):
58
+ return _handler
59
+
60
+
61
+ def _save(im, fp, filename):
62
+ if _handler is None or not hasattr(_handler, "save"):
63
+ msg = "BUFR save handler not installed"
64
+ raise OSError(msg)
65
+ _handler.save(im, fp, filename)
66
+
67
+
68
+ # --------------------------------------------------------------------
69
+ # Registry
70
+
71
+ Image.register_open(BufrStubImageFile.format, BufrStubImageFile, _accept)
72
+ Image.register_save(BufrStubImageFile.format, _save)
73
+
74
+ Image.register_extension(BufrStubImageFile.format, ".bufr")
gtm/lib/python3.12/site-packages/PIL/ContainerIO.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # a class to read from a container file
6
+ #
7
+ # History:
8
+ # 1995-06-18 fl Created
9
+ # 1995-09-07 fl Added readline(), readlines()
10
+ #
11
+ # Copyright (c) 1997-2001 by Secret Labs AB
12
+ # Copyright (c) 1995 by Fredrik Lundh
13
+ #
14
+ # See the README file for information on usage and redistribution.
15
+ #
16
+ from __future__ import annotations
17
+
18
+ import io
19
+ from typing import IO, AnyStr, Generic, Literal
20
+
21
+
22
+ class ContainerIO(Generic[AnyStr]):
23
+ """
24
+ A file object that provides read access to a part of an existing
25
+ file (for example a TAR file).
26
+ """
27
+
28
+ def __init__(self, file: IO[AnyStr], offset: int, length: int) -> None:
29
+ """
30
+ Create file object.
31
+
32
+ :param file: Existing file.
33
+ :param offset: Start of region, in bytes.
34
+ :param length: Size of region, in bytes.
35
+ """
36
+ self.fh: IO[AnyStr] = file
37
+ self.pos = 0
38
+ self.offset = offset
39
+ self.length = length
40
+ self.fh.seek(offset)
41
+
42
+ ##
43
+ # Always false.
44
+
45
+ def isatty(self) -> bool:
46
+ return False
47
+
48
+ def seek(self, offset: int, mode: Literal[0, 1, 2] = io.SEEK_SET) -> None:
49
+ """
50
+ Move file pointer.
51
+
52
+ :param offset: Offset in bytes.
53
+ :param mode: Starting position. Use 0 for beginning of region, 1
54
+ for current offset, and 2 for end of region. You cannot move
55
+ the pointer outside the defined region.
56
+ """
57
+ if mode == 1:
58
+ self.pos = self.pos + offset
59
+ elif mode == 2:
60
+ self.pos = self.length + offset
61
+ else:
62
+ self.pos = offset
63
+ # clamp
64
+ self.pos = max(0, min(self.pos, self.length))
65
+ self.fh.seek(self.offset + self.pos)
66
+
67
+ def tell(self) -> int:
68
+ """
69
+ Get current file pointer.
70
+
71
+ :returns: Offset from start of region, in bytes.
72
+ """
73
+ return self.pos
74
+
75
+ def read(self, n: int = 0) -> AnyStr:
76
+ """
77
+ Read data.
78
+
79
+ :param n: Number of bytes to read. If omitted or zero,
80
+ read until end of region.
81
+ :returns: An 8-bit string.
82
+ """
83
+ if n:
84
+ n = min(n, self.length - self.pos)
85
+ else:
86
+ n = self.length - self.pos
87
+ if not n: # EOF
88
+ return b"" if "b" in self.fh.mode else "" # type: ignore[return-value]
89
+ self.pos = self.pos + n
90
+ return self.fh.read(n)
91
+
92
+ def readline(self) -> AnyStr:
93
+ """
94
+ Read a line of text.
95
+
96
+ :returns: An 8-bit string.
97
+ """
98
+ s: AnyStr = b"" if "b" in self.fh.mode else "" # type: ignore[assignment]
99
+ newline_character = b"\n" if "b" in self.fh.mode else "\n"
100
+ while True:
101
+ c = self.read(1)
102
+ if not c:
103
+ break
104
+ s = s + c
105
+ if c == newline_character:
106
+ break
107
+ return s
108
+
109
+ def readlines(self) -> list[AnyStr]:
110
+ """
111
+ Read multiple lines of text.
112
+
113
+ :returns: A list of 8-bit strings.
114
+ """
115
+ lines = []
116
+ while True:
117
+ s = self.readline()
118
+ if not s:
119
+ break
120
+ lines.append(s)
121
+ return lines
gtm/lib/python3.12/site-packages/PIL/CurImagePlugin.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # Windows Cursor support for PIL
6
+ #
7
+ # notes:
8
+ # uses BmpImagePlugin.py to read the bitmap data.
9
+ #
10
+ # history:
11
+ # 96-05-27 fl Created
12
+ #
13
+ # Copyright (c) Secret Labs AB 1997.
14
+ # Copyright (c) Fredrik Lundh 1996.
15
+ #
16
+ # See the README file for information on usage and redistribution.
17
+ #
18
+ from __future__ import annotations
19
+
20
+ from . import BmpImagePlugin, Image
21
+ from ._binary import i16le as i16
22
+ from ._binary import i32le as i32
23
+
24
+ #
25
+ # --------------------------------------------------------------------
26
+
27
+
28
+ def _accept(prefix):
29
+ return prefix[:4] == b"\0\0\2\0"
30
+
31
+
32
+ ##
33
+ # Image plugin for Windows Cursor files.
34
+
35
+
36
+ class CurImageFile(BmpImagePlugin.BmpImageFile):
37
+ format = "CUR"
38
+ format_description = "Windows Cursor"
39
+
40
+ def _open(self):
41
+ offset = self.fp.tell()
42
+
43
+ # check magic
44
+ s = self.fp.read(6)
45
+ if not _accept(s):
46
+ msg = "not a CUR file"
47
+ raise SyntaxError(msg)
48
+
49
+ # pick the largest cursor in the file
50
+ m = b""
51
+ for i in range(i16(s, 4)):
52
+ s = self.fp.read(16)
53
+ if not m:
54
+ m = s
55
+ elif s[0] > m[0] and s[1] > m[1]:
56
+ m = s
57
+ if not m:
58
+ msg = "No cursors were found"
59
+ raise TypeError(msg)
60
+
61
+ # load as bitmap
62
+ self._bitmap(i32(m, 12) + offset)
63
+
64
+ # patch up the bitmap height
65
+ self._size = self.size[0], self.size[1] // 2
66
+ d, e, o, a = self.tile[0]
67
+ self.tile[0] = d, (0, 0) + self.size, o, a
68
+
69
+
70
+ #
71
+ # --------------------------------------------------------------------
72
+
73
+ Image.register_open(CurImageFile.format, CurImageFile, _accept)
74
+
75
+ Image.register_extension(CurImageFile.format, ".cur")
gtm/lib/python3.12/site-packages/PIL/DcxImagePlugin.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # DCX file handling
6
+ #
7
+ # DCX is a container file format defined by Intel, commonly used
8
+ # for fax applications. Each DCX file consists of a directory
9
+ # (a list of file offsets) followed by a set of (usually 1-bit)
10
+ # PCX files.
11
+ #
12
+ # History:
13
+ # 1995-09-09 fl Created
14
+ # 1996-03-20 fl Properly derived from PcxImageFile.
15
+ # 1998-07-15 fl Renamed offset attribute to avoid name clash
16
+ # 2002-07-30 fl Fixed file handling
17
+ #
18
+ # Copyright (c) 1997-98 by Secret Labs AB.
19
+ # Copyright (c) 1995-96 by Fredrik Lundh.
20
+ #
21
+ # See the README file for information on usage and redistribution.
22
+ #
23
+ from __future__ import annotations
24
+
25
+ from . import Image
26
+ from ._binary import i32le as i32
27
+ from .PcxImagePlugin import PcxImageFile
28
+
29
+ MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then?
30
+
31
+
32
+ def _accept(prefix):
33
+ return len(prefix) >= 4 and i32(prefix) == MAGIC
34
+
35
+
36
+ ##
37
+ # Image plugin for the Intel DCX format.
38
+
39
+
40
+ class DcxImageFile(PcxImageFile):
41
+ format = "DCX"
42
+ format_description = "Intel DCX"
43
+ _close_exclusive_fp_after_loading = False
44
+
45
+ def _open(self):
46
+ # Header
47
+ s = self.fp.read(4)
48
+ if not _accept(s):
49
+ msg = "not a DCX file"
50
+ raise SyntaxError(msg)
51
+
52
+ # Component directory
53
+ self._offset = []
54
+ for i in range(1024):
55
+ offset = i32(self.fp.read(4))
56
+ if not offset:
57
+ break
58
+ self._offset.append(offset)
59
+
60
+ self._fp = self.fp
61
+ self.frame = None
62
+ self.n_frames = len(self._offset)
63
+ self.is_animated = self.n_frames > 1
64
+ self.seek(0)
65
+
66
+ def seek(self, frame):
67
+ if not self._seek_check(frame):
68
+ return
69
+ self.frame = frame
70
+ self.fp = self._fp
71
+ self.fp.seek(self._offset[frame])
72
+ PcxImageFile._open(self)
73
+
74
+ def tell(self):
75
+ return self.frame
76
+
77
+
78
+ Image.register_open(DcxImageFile.format, DcxImageFile, _accept)
79
+
80
+ Image.register_extension(DcxImageFile.format, ".dcx")
gtm/lib/python3.12/site-packages/PIL/DdsImagePlugin.py ADDED
@@ -0,0 +1,566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A Pillow loader for .dds files (S3TC-compressed aka DXTC)
3
+ Jerome Leclanche <jerome@leclan.ch>
4
+
5
+ Documentation:
6
+ https://web.archive.org/web/20170802060935/http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_compression_s3tc.txt
7
+
8
+ The contents of this file are hereby released in the public domain (CC0)
9
+ Full text of the CC0 license:
10
+ https://creativecommons.org/publicdomain/zero/1.0/
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import io
15
+ import struct
16
+ import sys
17
+ from enum import IntEnum, IntFlag
18
+
19
+ from . import Image, ImageFile, ImagePalette
20
+ from ._binary import i32le as i32
21
+ from ._binary import o8
22
+ from ._binary import o32le as o32
23
+
24
+ # Magic ("DDS ")
25
+ DDS_MAGIC = 0x20534444
26
+
27
+
28
+ # DDS flags
29
+ class DDSD(IntFlag):
30
+ CAPS = 0x1
31
+ HEIGHT = 0x2
32
+ WIDTH = 0x4
33
+ PITCH = 0x8
34
+ PIXELFORMAT = 0x1000
35
+ MIPMAPCOUNT = 0x20000
36
+ LINEARSIZE = 0x80000
37
+ DEPTH = 0x800000
38
+
39
+
40
+ # DDS caps
41
+ class DDSCAPS(IntFlag):
42
+ COMPLEX = 0x8
43
+ TEXTURE = 0x1000
44
+ MIPMAP = 0x400000
45
+
46
+
47
+ class DDSCAPS2(IntFlag):
48
+ CUBEMAP = 0x200
49
+ CUBEMAP_POSITIVEX = 0x400
50
+ CUBEMAP_NEGATIVEX = 0x800
51
+ CUBEMAP_POSITIVEY = 0x1000
52
+ CUBEMAP_NEGATIVEY = 0x2000
53
+ CUBEMAP_POSITIVEZ = 0x4000
54
+ CUBEMAP_NEGATIVEZ = 0x8000
55
+ VOLUME = 0x200000
56
+
57
+
58
+ # Pixel Format
59
+ class DDPF(IntFlag):
60
+ ALPHAPIXELS = 0x1
61
+ ALPHA = 0x2
62
+ FOURCC = 0x4
63
+ PALETTEINDEXED8 = 0x20
64
+ RGB = 0x40
65
+ LUMINANCE = 0x20000
66
+
67
+
68
+ # dxgiformat.h
69
+ class DXGI_FORMAT(IntEnum):
70
+ UNKNOWN = 0
71
+ R32G32B32A32_TYPELESS = 1
72
+ R32G32B32A32_FLOAT = 2
73
+ R32G32B32A32_UINT = 3
74
+ R32G32B32A32_SINT = 4
75
+ R32G32B32_TYPELESS = 5
76
+ R32G32B32_FLOAT = 6
77
+ R32G32B32_UINT = 7
78
+ R32G32B32_SINT = 8
79
+ R16G16B16A16_TYPELESS = 9
80
+ R16G16B16A16_FLOAT = 10
81
+ R16G16B16A16_UNORM = 11
82
+ R16G16B16A16_UINT = 12
83
+ R16G16B16A16_SNORM = 13
84
+ R16G16B16A16_SINT = 14
85
+ R32G32_TYPELESS = 15
86
+ R32G32_FLOAT = 16
87
+ R32G32_UINT = 17
88
+ R32G32_SINT = 18
89
+ R32G8X24_TYPELESS = 19
90
+ D32_FLOAT_S8X24_UINT = 20
91
+ R32_FLOAT_X8X24_TYPELESS = 21
92
+ X32_TYPELESS_G8X24_UINT = 22
93
+ R10G10B10A2_TYPELESS = 23
94
+ R10G10B10A2_UNORM = 24
95
+ R10G10B10A2_UINT = 25
96
+ R11G11B10_FLOAT = 26
97
+ R8G8B8A8_TYPELESS = 27
98
+ R8G8B8A8_UNORM = 28
99
+ R8G8B8A8_UNORM_SRGB = 29
100
+ R8G8B8A8_UINT = 30
101
+ R8G8B8A8_SNORM = 31
102
+ R8G8B8A8_SINT = 32
103
+ R16G16_TYPELESS = 33
104
+ R16G16_FLOAT = 34
105
+ R16G16_UNORM = 35
106
+ R16G16_UINT = 36
107
+ R16G16_SNORM = 37
108
+ R16G16_SINT = 38
109
+ R32_TYPELESS = 39
110
+ D32_FLOAT = 40
111
+ R32_FLOAT = 41
112
+ R32_UINT = 42
113
+ R32_SINT = 43
114
+ R24G8_TYPELESS = 44
115
+ D24_UNORM_S8_UINT = 45
116
+ R24_UNORM_X8_TYPELESS = 46
117
+ X24_TYPELESS_G8_UINT = 47
118
+ R8G8_TYPELESS = 48
119
+ R8G8_UNORM = 49
120
+ R8G8_UINT = 50
121
+ R8G8_SNORM = 51
122
+ R8G8_SINT = 52
123
+ R16_TYPELESS = 53
124
+ R16_FLOAT = 54
125
+ D16_UNORM = 55
126
+ R16_UNORM = 56
127
+ R16_UINT = 57
128
+ R16_SNORM = 58
129
+ R16_SINT = 59
130
+ R8_TYPELESS = 60
131
+ R8_UNORM = 61
132
+ R8_UINT = 62
133
+ R8_SNORM = 63
134
+ R8_SINT = 64
135
+ A8_UNORM = 65
136
+ R1_UNORM = 66
137
+ R9G9B9E5_SHAREDEXP = 67
138
+ R8G8_B8G8_UNORM = 68
139
+ G8R8_G8B8_UNORM = 69
140
+ BC1_TYPELESS = 70
141
+ BC1_UNORM = 71
142
+ BC1_UNORM_SRGB = 72
143
+ BC2_TYPELESS = 73
144
+ BC2_UNORM = 74
145
+ BC2_UNORM_SRGB = 75
146
+ BC3_TYPELESS = 76
147
+ BC3_UNORM = 77
148
+ BC3_UNORM_SRGB = 78
149
+ BC4_TYPELESS = 79
150
+ BC4_UNORM = 80
151
+ BC4_SNORM = 81
152
+ BC5_TYPELESS = 82
153
+ BC5_UNORM = 83
154
+ BC5_SNORM = 84
155
+ B5G6R5_UNORM = 85
156
+ B5G5R5A1_UNORM = 86
157
+ B8G8R8A8_UNORM = 87
158
+ B8G8R8X8_UNORM = 88
159
+ R10G10B10_XR_BIAS_A2_UNORM = 89
160
+ B8G8R8A8_TYPELESS = 90
161
+ B8G8R8A8_UNORM_SRGB = 91
162
+ B8G8R8X8_TYPELESS = 92
163
+ B8G8R8X8_UNORM_SRGB = 93
164
+ BC6H_TYPELESS = 94
165
+ BC6H_UF16 = 95
166
+ BC6H_SF16 = 96
167
+ BC7_TYPELESS = 97
168
+ BC7_UNORM = 98
169
+ BC7_UNORM_SRGB = 99
170
+ AYUV = 100
171
+ Y410 = 101
172
+ Y416 = 102
173
+ NV12 = 103
174
+ P010 = 104
175
+ P016 = 105
176
+ OPAQUE_420 = 106
177
+ YUY2 = 107
178
+ Y210 = 108
179
+ Y216 = 109
180
+ NV11 = 110
181
+ AI44 = 111
182
+ IA44 = 112
183
+ P8 = 113
184
+ A8P8 = 114
185
+ B4G4R4A4_UNORM = 115
186
+ P208 = 130
187
+ V208 = 131
188
+ V408 = 132
189
+ SAMPLER_FEEDBACK_MIN_MIP_OPAQUE = 189
190
+ SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE = 190
191
+
192
+
193
+ class D3DFMT(IntEnum):
194
+ UNKNOWN = 0
195
+ R8G8B8 = 20
196
+ A8R8G8B8 = 21
197
+ X8R8G8B8 = 22
198
+ R5G6B5 = 23
199
+ X1R5G5B5 = 24
200
+ A1R5G5B5 = 25
201
+ A4R4G4B4 = 26
202
+ R3G3B2 = 27
203
+ A8 = 28
204
+ A8R3G3B2 = 29
205
+ X4R4G4B4 = 30
206
+ A2B10G10R10 = 31
207
+ A8B8G8R8 = 32
208
+ X8B8G8R8 = 33
209
+ G16R16 = 34
210
+ A2R10G10B10 = 35
211
+ A16B16G16R16 = 36
212
+ A8P8 = 40
213
+ P8 = 41
214
+ L8 = 50
215
+ A8L8 = 51
216
+ A4L4 = 52
217
+ V8U8 = 60
218
+ L6V5U5 = 61
219
+ X8L8V8U8 = 62
220
+ Q8W8V8U8 = 63
221
+ V16U16 = 64
222
+ A2W10V10U10 = 67
223
+ D16_LOCKABLE = 70
224
+ D32 = 71
225
+ D15S1 = 73
226
+ D24S8 = 75
227
+ D24X8 = 77
228
+ D24X4S4 = 79
229
+ D16 = 80
230
+ D32F_LOCKABLE = 82
231
+ D24FS8 = 83
232
+ D32_LOCKABLE = 84
233
+ S8_LOCKABLE = 85
234
+ L16 = 81
235
+ VERTEXDATA = 100
236
+ INDEX16 = 101
237
+ INDEX32 = 102
238
+ Q16W16V16U16 = 110
239
+ R16F = 111
240
+ G16R16F = 112
241
+ A16B16G16R16F = 113
242
+ R32F = 114
243
+ G32R32F = 115
244
+ A32B32G32R32F = 116
245
+ CxV8U8 = 117
246
+ A1 = 118
247
+ A2B10G10R10_XR_BIAS = 119
248
+ BINARYBUFFER = 199
249
+
250
+ UYVY = i32(b"UYVY")
251
+ R8G8_B8G8 = i32(b"RGBG")
252
+ YUY2 = i32(b"YUY2")
253
+ G8R8_G8B8 = i32(b"GRGB")
254
+ DXT1 = i32(b"DXT1")
255
+ DXT2 = i32(b"DXT2")
256
+ DXT3 = i32(b"DXT3")
257
+ DXT4 = i32(b"DXT4")
258
+ DXT5 = i32(b"DXT5")
259
+ DX10 = i32(b"DX10")
260
+ BC4S = i32(b"BC4S")
261
+ BC4U = i32(b"BC4U")
262
+ BC5S = i32(b"BC5S")
263
+ BC5U = i32(b"BC5U")
264
+ ATI1 = i32(b"ATI1")
265
+ ATI2 = i32(b"ATI2")
266
+ MULTI2_ARGB8 = i32(b"MET1")
267
+
268
+
269
+ # Backward compatibility layer
270
+ module = sys.modules[__name__]
271
+ for item in DDSD:
272
+ setattr(module, "DDSD_" + item.name, item.value)
273
+ for item in DDSCAPS:
274
+ setattr(module, "DDSCAPS_" + item.name, item.value)
275
+ for item in DDSCAPS2:
276
+ setattr(module, "DDSCAPS2_" + item.name, item.value)
277
+ for item in DDPF:
278
+ setattr(module, "DDPF_" + item.name, item.value)
279
+
280
+ DDS_FOURCC = DDPF.FOURCC
281
+ DDS_RGB = DDPF.RGB
282
+ DDS_RGBA = DDPF.RGB | DDPF.ALPHAPIXELS
283
+ DDS_LUMINANCE = DDPF.LUMINANCE
284
+ DDS_LUMINANCEA = DDPF.LUMINANCE | DDPF.ALPHAPIXELS
285
+ DDS_ALPHA = DDPF.ALPHA
286
+ DDS_PAL8 = DDPF.PALETTEINDEXED8
287
+
288
+ DDS_HEADER_FLAGS_TEXTURE = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT
289
+ DDS_HEADER_FLAGS_MIPMAP = DDSD.MIPMAPCOUNT
290
+ DDS_HEADER_FLAGS_VOLUME = DDSD.DEPTH
291
+ DDS_HEADER_FLAGS_PITCH = DDSD.PITCH
292
+ DDS_HEADER_FLAGS_LINEARSIZE = DDSD.LINEARSIZE
293
+
294
+ DDS_HEIGHT = DDSD.HEIGHT
295
+ DDS_WIDTH = DDSD.WIDTH
296
+
297
+ DDS_SURFACE_FLAGS_TEXTURE = DDSCAPS.TEXTURE
298
+ DDS_SURFACE_FLAGS_MIPMAP = DDSCAPS.COMPLEX | DDSCAPS.MIPMAP
299
+ DDS_SURFACE_FLAGS_CUBEMAP = DDSCAPS.COMPLEX
300
+
301
+ DDS_CUBEMAP_POSITIVEX = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_POSITIVEX
302
+ DDS_CUBEMAP_NEGATIVEX = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_NEGATIVEX
303
+ DDS_CUBEMAP_POSITIVEY = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_POSITIVEY
304
+ DDS_CUBEMAP_NEGATIVEY = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_NEGATIVEY
305
+ DDS_CUBEMAP_POSITIVEZ = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_POSITIVEZ
306
+ DDS_CUBEMAP_NEGATIVEZ = DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_NEGATIVEZ
307
+
308
+ DXT1_FOURCC = D3DFMT.DXT1
309
+ DXT3_FOURCC = D3DFMT.DXT3
310
+ DXT5_FOURCC = D3DFMT.DXT5
311
+
312
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = DXGI_FORMAT.R8G8B8A8_TYPELESS
313
+ DXGI_FORMAT_R8G8B8A8_UNORM = DXGI_FORMAT.R8G8B8A8_UNORM
314
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = DXGI_FORMAT.R8G8B8A8_UNORM_SRGB
315
+ DXGI_FORMAT_BC5_TYPELESS = DXGI_FORMAT.BC5_TYPELESS
316
+ DXGI_FORMAT_BC5_UNORM = DXGI_FORMAT.BC5_UNORM
317
+ DXGI_FORMAT_BC5_SNORM = DXGI_FORMAT.BC5_SNORM
318
+ DXGI_FORMAT_BC6H_UF16 = DXGI_FORMAT.BC6H_UF16
319
+ DXGI_FORMAT_BC6H_SF16 = DXGI_FORMAT.BC6H_SF16
320
+ DXGI_FORMAT_BC7_TYPELESS = DXGI_FORMAT.BC7_TYPELESS
321
+ DXGI_FORMAT_BC7_UNORM = DXGI_FORMAT.BC7_UNORM
322
+ DXGI_FORMAT_BC7_UNORM_SRGB = DXGI_FORMAT.BC7_UNORM_SRGB
323
+
324
+
325
+ class DdsImageFile(ImageFile.ImageFile):
326
+ format = "DDS"
327
+ format_description = "DirectDraw Surface"
328
+
329
+ def _open(self):
330
+ if not _accept(self.fp.read(4)):
331
+ msg = "not a DDS file"
332
+ raise SyntaxError(msg)
333
+ (header_size,) = struct.unpack("<I", self.fp.read(4))
334
+ if header_size != 124:
335
+ msg = f"Unsupported header size {repr(header_size)}"
336
+ raise OSError(msg)
337
+ header_bytes = self.fp.read(header_size - 4)
338
+ if len(header_bytes) != 120:
339
+ msg = f"Incomplete header: {len(header_bytes)} bytes"
340
+ raise OSError(msg)
341
+ header = io.BytesIO(header_bytes)
342
+
343
+ flags, height, width = struct.unpack("<3I", header.read(12))
344
+ self._size = (width, height)
345
+ extents = (0, 0) + self.size
346
+
347
+ pitch, depth, mipmaps = struct.unpack("<3I", header.read(12))
348
+ struct.unpack("<11I", header.read(44)) # reserved
349
+
350
+ # pixel format
351
+ pfsize, pfflags, fourcc, bitcount = struct.unpack("<4I", header.read(16))
352
+ n = 0
353
+ rawmode = None
354
+ if pfflags & DDPF.RGB:
355
+ # Texture contains uncompressed RGB data
356
+ if pfflags & DDPF.ALPHAPIXELS:
357
+ self._mode = "RGBA"
358
+ mask_count = 4
359
+ else:
360
+ self._mode = "RGB"
361
+ mask_count = 3
362
+
363
+ masks = struct.unpack(f"<{mask_count}I", header.read(mask_count * 4))
364
+ self.tile = [("dds_rgb", extents, 0, (bitcount, masks))]
365
+ return
366
+ elif pfflags & DDPF.LUMINANCE:
367
+ if bitcount == 8:
368
+ self._mode = "L"
369
+ elif bitcount == 16 and pfflags & DDPF.ALPHAPIXELS:
370
+ self._mode = "LA"
371
+ else:
372
+ msg = f"Unsupported bitcount {bitcount} for {pfflags}"
373
+ raise OSError(msg)
374
+ elif pfflags & DDPF.PALETTEINDEXED8:
375
+ self._mode = "P"
376
+ self.palette = ImagePalette.raw("RGBA", self.fp.read(1024))
377
+ elif pfflags & DDPF.FOURCC:
378
+ offset = header_size + 4
379
+ if fourcc == D3DFMT.DXT1:
380
+ self._mode = "RGBA"
381
+ self.pixel_format = "DXT1"
382
+ n = 1
383
+ elif fourcc == D3DFMT.DXT3:
384
+ self._mode = "RGBA"
385
+ self.pixel_format = "DXT3"
386
+ n = 2
387
+ elif fourcc == D3DFMT.DXT5:
388
+ self._mode = "RGBA"
389
+ self.pixel_format = "DXT5"
390
+ n = 3
391
+ elif fourcc in (D3DFMT.BC4U, D3DFMT.ATI1):
392
+ self._mode = "L"
393
+ self.pixel_format = "BC4"
394
+ n = 4
395
+ elif fourcc == D3DFMT.BC5S:
396
+ self._mode = "RGB"
397
+ self.pixel_format = "BC5S"
398
+ n = 5
399
+ elif fourcc in (D3DFMT.BC5U, D3DFMT.ATI2):
400
+ self._mode = "RGB"
401
+ self.pixel_format = "BC5"
402
+ n = 5
403
+ elif fourcc == D3DFMT.DX10:
404
+ offset += 20
405
+ # ignoring flags which pertain to volume textures and cubemaps
406
+ (dxgi_format,) = struct.unpack("<I", self.fp.read(4))
407
+ self.fp.read(16)
408
+ if dxgi_format in (
409
+ DXGI_FORMAT.BC1_UNORM,
410
+ DXGI_FORMAT.BC1_TYPELESS,
411
+ ):
412
+ self._mode = "RGBA"
413
+ self.pixel_format = "BC1"
414
+ n = 1
415
+ elif dxgi_format in (DXGI_FORMAT.BC4_TYPELESS, DXGI_FORMAT.BC4_UNORM):
416
+ self._mode = "L"
417
+ self.pixel_format = "BC4"
418
+ n = 4
419
+ elif dxgi_format in (DXGI_FORMAT.BC5_TYPELESS, DXGI_FORMAT.BC5_UNORM):
420
+ self._mode = "RGB"
421
+ self.pixel_format = "BC5"
422
+ n = 5
423
+ elif dxgi_format == DXGI_FORMAT.BC5_SNORM:
424
+ self._mode = "RGB"
425
+ self.pixel_format = "BC5S"
426
+ n = 5
427
+ elif dxgi_format == DXGI_FORMAT.BC6H_UF16:
428
+ self._mode = "RGB"
429
+ self.pixel_format = "BC6H"
430
+ n = 6
431
+ elif dxgi_format == DXGI_FORMAT.BC6H_SF16:
432
+ self._mode = "RGB"
433
+ self.pixel_format = "BC6HS"
434
+ n = 6
435
+ elif dxgi_format in (
436
+ DXGI_FORMAT.BC7_TYPELESS,
437
+ DXGI_FORMAT.BC7_UNORM,
438
+ DXGI_FORMAT.BC7_UNORM_SRGB,
439
+ ):
440
+ self._mode = "RGBA"
441
+ self.pixel_format = "BC7"
442
+ n = 7
443
+ if dxgi_format == DXGI_FORMAT.BC7_UNORM_SRGB:
444
+ self.info["gamma"] = 1 / 2.2
445
+ elif dxgi_format in (
446
+ DXGI_FORMAT.R8G8B8A8_TYPELESS,
447
+ DXGI_FORMAT.R8G8B8A8_UNORM,
448
+ DXGI_FORMAT.R8G8B8A8_UNORM_SRGB,
449
+ ):
450
+ self._mode = "RGBA"
451
+ if dxgi_format == DXGI_FORMAT.R8G8B8A8_UNORM_SRGB:
452
+ self.info["gamma"] = 1 / 2.2
453
+ else:
454
+ msg = f"Unimplemented DXGI format {dxgi_format}"
455
+ raise NotImplementedError(msg)
456
+ else:
457
+ msg = f"Unimplemented pixel format {repr(fourcc)}"
458
+ raise NotImplementedError(msg)
459
+ else:
460
+ msg = f"Unknown pixel format flags {pfflags}"
461
+ raise NotImplementedError(msg)
462
+
463
+ if n:
464
+ self.tile = [
465
+ ImageFile._Tile("bcn", extents, offset, (n, self.pixel_format))
466
+ ]
467
+ else:
468
+ self.tile = [ImageFile._Tile("raw", extents, 0, rawmode or self.mode)]
469
+
470
+ def load_seek(self, pos):
471
+ pass
472
+
473
+
474
+ class DdsRgbDecoder(ImageFile.PyDecoder):
475
+ _pulls_fd = True
476
+
477
+ def decode(self, buffer):
478
+ bitcount, masks = self.args
479
+
480
+ # Some masks will be padded with zeros, e.g. R 0b11 G 0b1100
481
+ # Calculate how many zeros each mask is padded with
482
+ mask_offsets = []
483
+ # And the maximum value of each channel without the padding
484
+ mask_totals = []
485
+ for mask in masks:
486
+ offset = 0
487
+ if mask != 0:
488
+ while mask >> (offset + 1) << (offset + 1) == mask:
489
+ offset += 1
490
+ mask_offsets.append(offset)
491
+ mask_totals.append(mask >> offset)
492
+
493
+ data = bytearray()
494
+ bytecount = bitcount // 8
495
+ while len(data) < self.state.xsize * self.state.ysize * len(masks):
496
+ value = int.from_bytes(self.fd.read(bytecount), "little")
497
+ for i, mask in enumerate(masks):
498
+ masked_value = value & mask
499
+ # Remove the zero padding, and scale it to 8 bits
500
+ data += o8(
501
+ int(((masked_value >> mask_offsets[i]) / mask_totals[i]) * 255)
502
+ )
503
+ self.set_as_raw(bytes(data))
504
+ return -1, 0
505
+
506
+
507
+ def _save(im, fp, filename):
508
+ if im.mode not in ("RGB", "RGBA", "L", "LA"):
509
+ msg = f"cannot write mode {im.mode} as DDS"
510
+ raise OSError(msg)
511
+
512
+ alpha = im.mode[-1] == "A"
513
+ if im.mode[0] == "L":
514
+ pixel_flags = DDPF.LUMINANCE
515
+ rawmode = im.mode
516
+ if alpha:
517
+ rgba_mask = [0x000000FF, 0x000000FF, 0x000000FF]
518
+ else:
519
+ rgba_mask = [0xFF000000, 0xFF000000, 0xFF000000]
520
+ else:
521
+ pixel_flags = DDPF.RGB
522
+ rawmode = im.mode[::-1]
523
+ rgba_mask = [0x00FF0000, 0x0000FF00, 0x000000FF]
524
+
525
+ if alpha:
526
+ r, g, b, a = im.split()
527
+ im = Image.merge("RGBA", (a, r, g, b))
528
+ if alpha:
529
+ pixel_flags |= DDPF.ALPHAPIXELS
530
+ rgba_mask.append(0xFF000000 if alpha else 0)
531
+
532
+ flags = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PITCH | DDSD.PIXELFORMAT
533
+ bitcount = len(im.getbands()) * 8
534
+ pitch = (im.width * bitcount + 7) // 8
535
+
536
+ fp.write(
537
+ o32(DDS_MAGIC)
538
+ + struct.pack(
539
+ "<7I",
540
+ 124, # header size
541
+ flags, # flags
542
+ im.height,
543
+ im.width,
544
+ pitch,
545
+ 0, # depth
546
+ 0, # mipmaps
547
+ )
548
+ + struct.pack("11I", *((0,) * 11)) # reserved
549
+ # pfsize, pfflags, fourcc, bitcount
550
+ + struct.pack("<4I", 32, pixel_flags, 0, bitcount)
551
+ + struct.pack("<4I", *rgba_mask) # dwRGBABitMask
552
+ + struct.pack("<5I", DDSCAPS.TEXTURE, 0, 0, 0, 0)
553
+ )
554
+ ImageFile._save(
555
+ im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))]
556
+ )
557
+
558
+
559
+ def _accept(prefix):
560
+ return prefix[:4] == b"DDS "
561
+
562
+
563
+ Image.register_open(DdsImageFile.format, DdsImageFile, _accept)
564
+ Image.register_decoder("dds_rgb", DdsRgbDecoder)
565
+ Image.register_save(DdsImageFile.format, _save)
566
+ Image.register_extension(DdsImageFile.format, ".dds")
gtm/lib/python3.12/site-packages/PIL/EpsImagePlugin.py ADDED
@@ -0,0 +1,478 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # EPS file handling
6
+ #
7
+ # History:
8
+ # 1995-09-01 fl Created (0.1)
9
+ # 1996-05-18 fl Don't choke on "atend" fields, Ghostscript interface (0.2)
10
+ # 1996-08-22 fl Don't choke on floating point BoundingBox values
11
+ # 1996-08-23 fl Handle files from Macintosh (0.3)
12
+ # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
13
+ # 2003-09-07 fl Check gs.close status (from Federico Di Gregorio) (0.5)
14
+ # 2014-05-07 e Handling of EPS with binary preview and fixed resolution
15
+ # resizing
16
+ #
17
+ # Copyright (c) 1997-2003 by Secret Labs AB.
18
+ # Copyright (c) 1995-2003 by Fredrik Lundh
19
+ #
20
+ # See the README file for information on usage and redistribution.
21
+ #
22
+ from __future__ import annotations
23
+
24
+ import io
25
+ import os
26
+ import re
27
+ import subprocess
28
+ import sys
29
+ import tempfile
30
+
31
+ from . import Image, ImageFile
32
+ from ._binary import i32le as i32
33
+ from ._deprecate import deprecate
34
+
35
+ # --------------------------------------------------------------------
36
+
37
+
38
+ split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
39
+ field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
40
+
41
+ gs_binary = None
42
+ gs_windows_binary = None
43
+
44
+
45
+ def has_ghostscript():
46
+ global gs_binary, gs_windows_binary
47
+ if gs_binary is None:
48
+ if sys.platform.startswith("win"):
49
+ if gs_windows_binary is None:
50
+ import shutil
51
+
52
+ for binary in ("gswin32c", "gswin64c", "gs"):
53
+ if shutil.which(binary) is not None:
54
+ gs_windows_binary = binary
55
+ break
56
+ else:
57
+ gs_windows_binary = False
58
+ gs_binary = gs_windows_binary
59
+ else:
60
+ try:
61
+ subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL)
62
+ gs_binary = "gs"
63
+ except OSError:
64
+ gs_binary = False
65
+ return gs_binary is not False
66
+
67
+
68
+ def Ghostscript(tile, size, fp, scale=1, transparency=False):
69
+ """Render an image using Ghostscript"""
70
+ global gs_binary
71
+ if not has_ghostscript():
72
+ msg = "Unable to locate Ghostscript on paths"
73
+ raise OSError(msg)
74
+
75
+ # Unpack decoder tile
76
+ decoder, tile, offset, data = tile[0]
77
+ length, bbox = data
78
+
79
+ # Hack to support hi-res rendering
80
+ scale = int(scale) or 1
81
+ width = size[0] * scale
82
+ height = size[1] * scale
83
+ # resolution is dependent on bbox and size
84
+ res_x = 72.0 * width / (bbox[2] - bbox[0])
85
+ res_y = 72.0 * height / (bbox[3] - bbox[1])
86
+
87
+ out_fd, outfile = tempfile.mkstemp()
88
+ os.close(out_fd)
89
+
90
+ infile_temp = None
91
+ if hasattr(fp, "name") and os.path.exists(fp.name):
92
+ infile = fp.name
93
+ else:
94
+ in_fd, infile_temp = tempfile.mkstemp()
95
+ os.close(in_fd)
96
+ infile = infile_temp
97
+
98
+ # Ignore length and offset!
99
+ # Ghostscript can read it
100
+ # Copy whole file to read in Ghostscript
101
+ with open(infile_temp, "wb") as f:
102
+ # fetch length of fp
103
+ fp.seek(0, io.SEEK_END)
104
+ fsize = fp.tell()
105
+ # ensure start position
106
+ # go back
107
+ fp.seek(0)
108
+ lengthfile = fsize
109
+ while lengthfile > 0:
110
+ s = fp.read(min(lengthfile, 100 * 1024))
111
+ if not s:
112
+ break
113
+ lengthfile -= len(s)
114
+ f.write(s)
115
+
116
+ device = "pngalpha" if transparency else "ppmraw"
117
+
118
+ # Build Ghostscript command
119
+ command = [
120
+ gs_binary,
121
+ "-q", # quiet mode
122
+ f"-g{width:d}x{height:d}", # set output geometry (pixels)
123
+ f"-r{res_x:f}x{res_y:f}", # set input DPI (dots per inch)
124
+ "-dBATCH", # exit after processing
125
+ "-dNOPAUSE", # don't pause between pages
126
+ "-dSAFER", # safe mode
127
+ f"-sDEVICE={device}",
128
+ f"-sOutputFile={outfile}", # output file
129
+ # adjust for image origin
130
+ "-c",
131
+ f"{-bbox[0]} {-bbox[1]} translate",
132
+ "-f",
133
+ infile, # input file
134
+ # showpage (see https://bugs.ghostscript.com/show_bug.cgi?id=698272)
135
+ "-c",
136
+ "showpage",
137
+ ]
138
+
139
+ # push data through Ghostscript
140
+ try:
141
+ startupinfo = None
142
+ if sys.platform.startswith("win"):
143
+ startupinfo = subprocess.STARTUPINFO()
144
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
145
+ subprocess.check_call(command, startupinfo=startupinfo)
146
+ out_im = Image.open(outfile)
147
+ out_im.load()
148
+ finally:
149
+ try:
150
+ os.unlink(outfile)
151
+ if infile_temp:
152
+ os.unlink(infile_temp)
153
+ except OSError:
154
+ pass
155
+
156
+ im = out_im.im.copy()
157
+ out_im.close()
158
+ return im
159
+
160
+
161
+ class PSFile:
162
+ """
163
+ Wrapper for bytesio object that treats either CR or LF as end of line.
164
+ This class is no longer used internally, but kept for backwards compatibility.
165
+ """
166
+
167
+ def __init__(self, fp):
168
+ deprecate(
169
+ "PSFile",
170
+ 11,
171
+ action="If you need the functionality of this class "
172
+ "you will need to implement it yourself.",
173
+ )
174
+ self.fp = fp
175
+ self.char = None
176
+
177
+ def seek(self, offset, whence=io.SEEK_SET):
178
+ self.char = None
179
+ self.fp.seek(offset, whence)
180
+
181
+ def readline(self):
182
+ s = [self.char or b""]
183
+ self.char = None
184
+
185
+ c = self.fp.read(1)
186
+ while (c not in b"\r\n") and len(c):
187
+ s.append(c)
188
+ c = self.fp.read(1)
189
+
190
+ self.char = self.fp.read(1)
191
+ # line endings can be 1 or 2 of \r \n, in either order
192
+ if self.char in b"\r\n":
193
+ self.char = None
194
+
195
+ return b"".join(s).decode("latin-1")
196
+
197
+
198
+ def _accept(prefix):
199
+ return prefix[:4] == b"%!PS" or (len(prefix) >= 4 and i32(prefix) == 0xC6D3D0C5)
200
+
201
+
202
+ ##
203
+ # Image plugin for Encapsulated PostScript. This plugin supports only
204
+ # a few variants of this format.
205
+
206
+
207
+ class EpsImageFile(ImageFile.ImageFile):
208
+ """EPS File Parser for the Python Imaging Library"""
209
+
210
+ format = "EPS"
211
+ format_description = "Encapsulated Postscript"
212
+
213
+ mode_map = {1: "L", 2: "LAB", 3: "RGB", 4: "CMYK"}
214
+
215
+ def _open(self):
216
+ (length, offset) = self._find_offset(self.fp)
217
+
218
+ # go to offset - start of "%!PS"
219
+ self.fp.seek(offset)
220
+
221
+ self._mode = "RGB"
222
+ self._size = None
223
+
224
+ byte_arr = bytearray(255)
225
+ bytes_mv = memoryview(byte_arr)
226
+ bytes_read = 0
227
+ reading_header_comments = True
228
+ reading_trailer_comments = False
229
+ trailer_reached = False
230
+
231
+ def check_required_header_comments():
232
+ if "PS-Adobe" not in self.info:
233
+ msg = 'EPS header missing "%!PS-Adobe" comment'
234
+ raise SyntaxError(msg)
235
+ if "BoundingBox" not in self.info:
236
+ msg = 'EPS header missing "%%BoundingBox" comment'
237
+ raise SyntaxError(msg)
238
+
239
+ def _read_comment(s):
240
+ nonlocal reading_trailer_comments
241
+ try:
242
+ m = split.match(s)
243
+ except re.error as e:
244
+ msg = "not an EPS file"
245
+ raise SyntaxError(msg) from e
246
+
247
+ if m:
248
+ k, v = m.group(1, 2)
249
+ self.info[k] = v
250
+ if k == "BoundingBox":
251
+ if v == "(atend)":
252
+ reading_trailer_comments = True
253
+ elif not self._size or (
254
+ trailer_reached and reading_trailer_comments
255
+ ):
256
+ try:
257
+ # Note: The DSC spec says that BoundingBox
258
+ # fields should be integers, but some drivers
259
+ # put floating point values there anyway.
260
+ box = [int(float(i)) for i in v.split()]
261
+ self._size = box[2] - box[0], box[3] - box[1]
262
+ self.tile = [
263
+ ("eps", (0, 0) + self.size, offset, (length, box))
264
+ ]
265
+ except Exception:
266
+ pass
267
+ return True
268
+
269
+ while True:
270
+ byte = self.fp.read(1)
271
+ if byte == b"":
272
+ # if we didn't read a byte we must be at the end of the file
273
+ if bytes_read == 0:
274
+ break
275
+ elif byte in b"\r\n":
276
+ # if we read a line ending character, ignore it and parse what
277
+ # we have already read. if we haven't read any other characters,
278
+ # continue reading
279
+ if bytes_read == 0:
280
+ continue
281
+ else:
282
+ # ASCII/hexadecimal lines in an EPS file must not exceed
283
+ # 255 characters, not including line ending characters
284
+ if bytes_read >= 255:
285
+ # only enforce this for lines starting with a "%",
286
+ # otherwise assume it's binary data
287
+ if byte_arr[0] == ord("%"):
288
+ msg = "not an EPS file"
289
+ raise SyntaxError(msg)
290
+ else:
291
+ if reading_header_comments:
292
+ check_required_header_comments()
293
+ reading_header_comments = False
294
+ # reset bytes_read so we can keep reading
295
+ # data until the end of the line
296
+ bytes_read = 0
297
+ byte_arr[bytes_read] = byte[0]
298
+ bytes_read += 1
299
+ continue
300
+
301
+ if reading_header_comments:
302
+ # Load EPS header
303
+
304
+ # if this line doesn't start with a "%",
305
+ # or does start with "%%EndComments",
306
+ # then we've reached the end of the header/comments
307
+ if byte_arr[0] != ord("%") or bytes_mv[:13] == b"%%EndComments":
308
+ check_required_header_comments()
309
+ reading_header_comments = False
310
+ continue
311
+
312
+ s = str(bytes_mv[:bytes_read], "latin-1")
313
+ if not _read_comment(s):
314
+ m = field.match(s)
315
+ if m:
316
+ k = m.group(1)
317
+ if k[:8] == "PS-Adobe":
318
+ self.info["PS-Adobe"] = k[9:]
319
+ else:
320
+ self.info[k] = ""
321
+ elif s[0] == "%":
322
+ # handle non-DSC PostScript comments that some
323
+ # tools mistakenly put in the Comments section
324
+ pass
325
+ else:
326
+ msg = "bad EPS header"
327
+ raise OSError(msg)
328
+ elif bytes_mv[:11] == b"%ImageData:":
329
+ # Check for an "ImageData" descriptor
330
+ # https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577413_pgfId-1035096
331
+
332
+ # Values:
333
+ # columns
334
+ # rows
335
+ # bit depth (1 or 8)
336
+ # mode (1: L, 2: LAB, 3: RGB, 4: CMYK)
337
+ # number of padding channels
338
+ # block size (number of bytes per row per channel)
339
+ # binary/ascii (1: binary, 2: ascii)
340
+ # data start identifier (the image data follows after a single line
341
+ # consisting only of this quoted value)
342
+ image_data_values = byte_arr[11:bytes_read].split(None, 7)
343
+ columns, rows, bit_depth, mode_id = (
344
+ int(value) for value in image_data_values[:4]
345
+ )
346
+
347
+ if bit_depth == 1:
348
+ self._mode = "1"
349
+ elif bit_depth == 8:
350
+ try:
351
+ self._mode = self.mode_map[mode_id]
352
+ except ValueError:
353
+ break
354
+ else:
355
+ break
356
+
357
+ self._size = columns, rows
358
+ return
359
+ elif trailer_reached and reading_trailer_comments:
360
+ # Load EPS trailer
361
+
362
+ # if this line starts with "%%EOF",
363
+ # then we've reached the end of the file
364
+ if bytes_mv[:5] == b"%%EOF":
365
+ break
366
+
367
+ s = str(bytes_mv[:bytes_read], "latin-1")
368
+ _read_comment(s)
369
+ elif bytes_mv[:9] == b"%%Trailer":
370
+ trailer_reached = True
371
+ bytes_read = 0
372
+
373
+ check_required_header_comments()
374
+
375
+ if not self._size:
376
+ msg = "cannot determine EPS bounding box"
377
+ raise OSError(msg)
378
+
379
+ def _find_offset(self, fp):
380
+ s = fp.read(4)
381
+
382
+ if s == b"%!PS":
383
+ # for HEAD without binary preview
384
+ fp.seek(0, io.SEEK_END)
385
+ length = fp.tell()
386
+ offset = 0
387
+ elif i32(s) == 0xC6D3D0C5:
388
+ # FIX for: Some EPS file not handled correctly / issue #302
389
+ # EPS can contain binary data
390
+ # or start directly with latin coding
391
+ # more info see:
392
+ # https://web.archive.org/web/20160528181353/http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
393
+ s = fp.read(8)
394
+ offset = i32(s)
395
+ length = i32(s, 4)
396
+ else:
397
+ msg = "not an EPS file"
398
+ raise SyntaxError(msg)
399
+
400
+ return length, offset
401
+
402
+ def load(self, scale=1, transparency=False):
403
+ # Load EPS via Ghostscript
404
+ if self.tile:
405
+ self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency)
406
+ self._mode = self.im.mode
407
+ self._size = self.im.size
408
+ self.tile = []
409
+ return Image.Image.load(self)
410
+
411
+ def load_seek(self, *args, **kwargs):
412
+ # we can't incrementally load, so force ImageFile.parser to
413
+ # use our custom load method by defining this method.
414
+ pass
415
+
416
+
417
+ # --------------------------------------------------------------------
418
+
419
+
420
+ def _save(im, fp, filename, eps=1):
421
+ """EPS Writer for the Python Imaging Library."""
422
+
423
+ # make sure image data is available
424
+ im.load()
425
+
426
+ # determine PostScript image mode
427
+ if im.mode == "L":
428
+ operator = (8, 1, b"image")
429
+ elif im.mode == "RGB":
430
+ operator = (8, 3, b"false 3 colorimage")
431
+ elif im.mode == "CMYK":
432
+ operator = (8, 4, b"false 4 colorimage")
433
+ else:
434
+ msg = "image mode is not supported"
435
+ raise ValueError(msg)
436
+
437
+ if eps:
438
+ # write EPS header
439
+ fp.write(b"%!PS-Adobe-3.0 EPSF-3.0\n")
440
+ fp.write(b"%%Creator: PIL 0.1 EpsEncode\n")
441
+ # fp.write("%%CreationDate: %s"...)
442
+ fp.write(b"%%%%BoundingBox: 0 0 %d %d\n" % im.size)
443
+ fp.write(b"%%Pages: 1\n")
444
+ fp.write(b"%%EndComments\n")
445
+ fp.write(b"%%Page: 1 1\n")
446
+ fp.write(b"%%ImageData: %d %d " % im.size)
447
+ fp.write(b'%d %d 0 1 1 "%s"\n' % operator)
448
+
449
+ # image header
450
+ fp.write(b"gsave\n")
451
+ fp.write(b"10 dict begin\n")
452
+ fp.write(b"/buf %d string def\n" % (im.size[0] * operator[1]))
453
+ fp.write(b"%d %d scale\n" % im.size)
454
+ fp.write(b"%d %d 8\n" % im.size) # <= bits
455
+ fp.write(b"[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
456
+ fp.write(b"{ currentfile buf readhexstring pop } bind\n")
457
+ fp.write(operator[2] + b"\n")
458
+ if hasattr(fp, "flush"):
459
+ fp.flush()
460
+
461
+ ImageFile._save(im, fp, [("eps", (0, 0) + im.size, 0, None)])
462
+
463
+ fp.write(b"\n%%%%EndBinary\n")
464
+ fp.write(b"grestore end\n")
465
+ if hasattr(fp, "flush"):
466
+ fp.flush()
467
+
468
+
469
+ # --------------------------------------------------------------------
470
+
471
+
472
+ Image.register_open(EpsImageFile.format, EpsImageFile, _accept)
473
+
474
+ Image.register_save(EpsImageFile.format, _save)
475
+
476
+ Image.register_extensions(EpsImageFile.format, [".ps", ".eps"])
477
+
478
+ Image.register_mime(EpsImageFile.format, "application/postscript")
gtm/lib/python3.12/site-packages/PIL/ExifTags.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # EXIF tags
6
+ #
7
+ # Copyright (c) 2003 by Secret Labs AB
8
+ #
9
+ # See the README file for information on usage and redistribution.
10
+ #
11
+
12
+ """
13
+ This module provides constants and clear-text names for various
14
+ well-known EXIF tags.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ from enum import IntEnum
19
+
20
+
21
+ class Base(IntEnum):
22
+ # possibly incomplete
23
+ InteropIndex = 0x0001
24
+ ProcessingSoftware = 0x000B
25
+ NewSubfileType = 0x00FE
26
+ SubfileType = 0x00FF
27
+ ImageWidth = 0x0100
28
+ ImageLength = 0x0101
29
+ BitsPerSample = 0x0102
30
+ Compression = 0x0103
31
+ PhotometricInterpretation = 0x0106
32
+ Thresholding = 0x0107
33
+ CellWidth = 0x0108
34
+ CellLength = 0x0109
35
+ FillOrder = 0x010A
36
+ DocumentName = 0x010D
37
+ ImageDescription = 0x010E
38
+ Make = 0x010F
39
+ Model = 0x0110
40
+ StripOffsets = 0x0111
41
+ Orientation = 0x0112
42
+ SamplesPerPixel = 0x0115
43
+ RowsPerStrip = 0x0116
44
+ StripByteCounts = 0x0117
45
+ MinSampleValue = 0x0118
46
+ MaxSampleValue = 0x0119
47
+ XResolution = 0x011A
48
+ YResolution = 0x011B
49
+ PlanarConfiguration = 0x011C
50
+ PageName = 0x011D
51
+ FreeOffsets = 0x0120
52
+ FreeByteCounts = 0x0121
53
+ GrayResponseUnit = 0x0122
54
+ GrayResponseCurve = 0x0123
55
+ T4Options = 0x0124
56
+ T6Options = 0x0125
57
+ ResolutionUnit = 0x0128
58
+ PageNumber = 0x0129
59
+ TransferFunction = 0x012D
60
+ Software = 0x0131
61
+ DateTime = 0x0132
62
+ Artist = 0x013B
63
+ HostComputer = 0x013C
64
+ Predictor = 0x013D
65
+ WhitePoint = 0x013E
66
+ PrimaryChromaticities = 0x013F
67
+ ColorMap = 0x0140
68
+ HalftoneHints = 0x0141
69
+ TileWidth = 0x0142
70
+ TileLength = 0x0143
71
+ TileOffsets = 0x0144
72
+ TileByteCounts = 0x0145
73
+ SubIFDs = 0x014A
74
+ InkSet = 0x014C
75
+ InkNames = 0x014D
76
+ NumberOfInks = 0x014E
77
+ DotRange = 0x0150
78
+ TargetPrinter = 0x0151
79
+ ExtraSamples = 0x0152
80
+ SampleFormat = 0x0153
81
+ SMinSampleValue = 0x0154
82
+ SMaxSampleValue = 0x0155
83
+ TransferRange = 0x0156
84
+ ClipPath = 0x0157
85
+ XClipPathUnits = 0x0158
86
+ YClipPathUnits = 0x0159
87
+ Indexed = 0x015A
88
+ JPEGTables = 0x015B
89
+ OPIProxy = 0x015F
90
+ JPEGProc = 0x0200
91
+ JpegIFOffset = 0x0201
92
+ JpegIFByteCount = 0x0202
93
+ JpegRestartInterval = 0x0203
94
+ JpegLosslessPredictors = 0x0205
95
+ JpegPointTransforms = 0x0206
96
+ JpegQTables = 0x0207
97
+ JpegDCTables = 0x0208
98
+ JpegACTables = 0x0209
99
+ YCbCrCoefficients = 0x0211
100
+ YCbCrSubSampling = 0x0212
101
+ YCbCrPositioning = 0x0213
102
+ ReferenceBlackWhite = 0x0214
103
+ XMLPacket = 0x02BC
104
+ RelatedImageFileFormat = 0x1000
105
+ RelatedImageWidth = 0x1001
106
+ RelatedImageLength = 0x1002
107
+ Rating = 0x4746
108
+ RatingPercent = 0x4749
109
+ ImageID = 0x800D
110
+ CFARepeatPatternDim = 0x828D
111
+ BatteryLevel = 0x828F
112
+ Copyright = 0x8298
113
+ ExposureTime = 0x829A
114
+ FNumber = 0x829D
115
+ IPTCNAA = 0x83BB
116
+ ImageResources = 0x8649
117
+ ExifOffset = 0x8769
118
+ InterColorProfile = 0x8773
119
+ ExposureProgram = 0x8822
120
+ SpectralSensitivity = 0x8824
121
+ GPSInfo = 0x8825
122
+ ISOSpeedRatings = 0x8827
123
+ OECF = 0x8828
124
+ Interlace = 0x8829
125
+ TimeZoneOffset = 0x882A
126
+ SelfTimerMode = 0x882B
127
+ SensitivityType = 0x8830
128
+ StandardOutputSensitivity = 0x8831
129
+ RecommendedExposureIndex = 0x8832
130
+ ISOSpeed = 0x8833
131
+ ISOSpeedLatitudeyyy = 0x8834
132
+ ISOSpeedLatitudezzz = 0x8835
133
+ ExifVersion = 0x9000
134
+ DateTimeOriginal = 0x9003
135
+ DateTimeDigitized = 0x9004
136
+ OffsetTime = 0x9010
137
+ OffsetTimeOriginal = 0x9011
138
+ OffsetTimeDigitized = 0x9012
139
+ ComponentsConfiguration = 0x9101
140
+ CompressedBitsPerPixel = 0x9102
141
+ ShutterSpeedValue = 0x9201
142
+ ApertureValue = 0x9202
143
+ BrightnessValue = 0x9203
144
+ ExposureBiasValue = 0x9204
145
+ MaxApertureValue = 0x9205
146
+ SubjectDistance = 0x9206
147
+ MeteringMode = 0x9207
148
+ LightSource = 0x9208
149
+ Flash = 0x9209
150
+ FocalLength = 0x920A
151
+ Noise = 0x920D
152
+ ImageNumber = 0x9211
153
+ SecurityClassification = 0x9212
154
+ ImageHistory = 0x9213
155
+ TIFFEPStandardID = 0x9216
156
+ MakerNote = 0x927C
157
+ UserComment = 0x9286
158
+ SubsecTime = 0x9290
159
+ SubsecTimeOriginal = 0x9291
160
+ SubsecTimeDigitized = 0x9292
161
+ AmbientTemperature = 0x9400
162
+ Humidity = 0x9401
163
+ Pressure = 0x9402
164
+ WaterDepth = 0x9403
165
+ Acceleration = 0x9404
166
+ CameraElevationAngle = 0x9405
167
+ XPTitle = 0x9C9B
168
+ XPComment = 0x9C9C
169
+ XPAuthor = 0x9C9D
170
+ XPKeywords = 0x9C9E
171
+ XPSubject = 0x9C9F
172
+ FlashPixVersion = 0xA000
173
+ ColorSpace = 0xA001
174
+ ExifImageWidth = 0xA002
175
+ ExifImageHeight = 0xA003
176
+ RelatedSoundFile = 0xA004
177
+ ExifInteroperabilityOffset = 0xA005
178
+ FlashEnergy = 0xA20B
179
+ SpatialFrequencyResponse = 0xA20C
180
+ FocalPlaneXResolution = 0xA20E
181
+ FocalPlaneYResolution = 0xA20F
182
+ FocalPlaneResolutionUnit = 0xA210
183
+ SubjectLocation = 0xA214
184
+ ExposureIndex = 0xA215
185
+ SensingMethod = 0xA217
186
+ FileSource = 0xA300
187
+ SceneType = 0xA301
188
+ CFAPattern = 0xA302
189
+ CustomRendered = 0xA401
190
+ ExposureMode = 0xA402
191
+ WhiteBalance = 0xA403
192
+ DigitalZoomRatio = 0xA404
193
+ FocalLengthIn35mmFilm = 0xA405
194
+ SceneCaptureType = 0xA406
195
+ GainControl = 0xA407
196
+ Contrast = 0xA408
197
+ Saturation = 0xA409
198
+ Sharpness = 0xA40A
199
+ DeviceSettingDescription = 0xA40B
200
+ SubjectDistanceRange = 0xA40C
201
+ ImageUniqueID = 0xA420
202
+ CameraOwnerName = 0xA430
203
+ BodySerialNumber = 0xA431
204
+ LensSpecification = 0xA432
205
+ LensMake = 0xA433
206
+ LensModel = 0xA434
207
+ LensSerialNumber = 0xA435
208
+ CompositeImage = 0xA460
209
+ CompositeImageCount = 0xA461
210
+ CompositeImageExposureTimes = 0xA462
211
+ Gamma = 0xA500
212
+ PrintImageMatching = 0xC4A5
213
+ DNGVersion = 0xC612
214
+ DNGBackwardVersion = 0xC613
215
+ UniqueCameraModel = 0xC614
216
+ LocalizedCameraModel = 0xC615
217
+ CFAPlaneColor = 0xC616
218
+ CFALayout = 0xC617
219
+ LinearizationTable = 0xC618
220
+ BlackLevelRepeatDim = 0xC619
221
+ BlackLevel = 0xC61A
222
+ BlackLevelDeltaH = 0xC61B
223
+ BlackLevelDeltaV = 0xC61C
224
+ WhiteLevel = 0xC61D
225
+ DefaultScale = 0xC61E
226
+ DefaultCropOrigin = 0xC61F
227
+ DefaultCropSize = 0xC620
228
+ ColorMatrix1 = 0xC621
229
+ ColorMatrix2 = 0xC622
230
+ CameraCalibration1 = 0xC623
231
+ CameraCalibration2 = 0xC624
232
+ ReductionMatrix1 = 0xC625
233
+ ReductionMatrix2 = 0xC626
234
+ AnalogBalance = 0xC627
235
+ AsShotNeutral = 0xC628
236
+ AsShotWhiteXY = 0xC629
237
+ BaselineExposure = 0xC62A
238
+ BaselineNoise = 0xC62B
239
+ BaselineSharpness = 0xC62C
240
+ BayerGreenSplit = 0xC62D
241
+ LinearResponseLimit = 0xC62E
242
+ CameraSerialNumber = 0xC62F
243
+ LensInfo = 0xC630
244
+ ChromaBlurRadius = 0xC631
245
+ AntiAliasStrength = 0xC632
246
+ ShadowScale = 0xC633
247
+ DNGPrivateData = 0xC634
248
+ MakerNoteSafety = 0xC635
249
+ CalibrationIlluminant1 = 0xC65A
250
+ CalibrationIlluminant2 = 0xC65B
251
+ BestQualityScale = 0xC65C
252
+ RawDataUniqueID = 0xC65D
253
+ OriginalRawFileName = 0xC68B
254
+ OriginalRawFileData = 0xC68C
255
+ ActiveArea = 0xC68D
256
+ MaskedAreas = 0xC68E
257
+ AsShotICCProfile = 0xC68F
258
+ AsShotPreProfileMatrix = 0xC690
259
+ CurrentICCProfile = 0xC691
260
+ CurrentPreProfileMatrix = 0xC692
261
+ ColorimetricReference = 0xC6BF
262
+ CameraCalibrationSignature = 0xC6F3
263
+ ProfileCalibrationSignature = 0xC6F4
264
+ AsShotProfileName = 0xC6F6
265
+ NoiseReductionApplied = 0xC6F7
266
+ ProfileName = 0xC6F8
267
+ ProfileHueSatMapDims = 0xC6F9
268
+ ProfileHueSatMapData1 = 0xC6FA
269
+ ProfileHueSatMapData2 = 0xC6FB
270
+ ProfileToneCurve = 0xC6FC
271
+ ProfileEmbedPolicy = 0xC6FD
272
+ ProfileCopyright = 0xC6FE
273
+ ForwardMatrix1 = 0xC714
274
+ ForwardMatrix2 = 0xC715
275
+ PreviewApplicationName = 0xC716
276
+ PreviewApplicationVersion = 0xC717
277
+ PreviewSettingsName = 0xC718
278
+ PreviewSettingsDigest = 0xC719
279
+ PreviewColorSpace = 0xC71A
280
+ PreviewDateTime = 0xC71B
281
+ RawImageDigest = 0xC71C
282
+ OriginalRawFileDigest = 0xC71D
283
+ SubTileBlockSize = 0xC71E
284
+ RowInterleaveFactor = 0xC71F
285
+ ProfileLookTableDims = 0xC725
286
+ ProfileLookTableData = 0xC726
287
+ OpcodeList1 = 0xC740
288
+ OpcodeList2 = 0xC741
289
+ OpcodeList3 = 0xC74E
290
+ NoiseProfile = 0xC761
291
+
292
+
293
+ """Maps EXIF tags to tag names."""
294
+ TAGS = {
295
+ **{i.value: i.name for i in Base},
296
+ 0x920C: "SpatialFrequencyResponse",
297
+ 0x9214: "SubjectLocation",
298
+ 0x9215: "ExposureIndex",
299
+ 0x828E: "CFAPattern",
300
+ 0x920B: "FlashEnergy",
301
+ 0x9216: "TIFF/EPStandardID",
302
+ }
303
+
304
+
305
+ class GPS(IntEnum):
306
+ GPSVersionID = 0
307
+ GPSLatitudeRef = 1
308
+ GPSLatitude = 2
309
+ GPSLongitudeRef = 3
310
+ GPSLongitude = 4
311
+ GPSAltitudeRef = 5
312
+ GPSAltitude = 6
313
+ GPSTimeStamp = 7
314
+ GPSSatellites = 8
315
+ GPSStatus = 9
316
+ GPSMeasureMode = 10
317
+ GPSDOP = 11
318
+ GPSSpeedRef = 12
319
+ GPSSpeed = 13
320
+ GPSTrackRef = 14
321
+ GPSTrack = 15
322
+ GPSImgDirectionRef = 16
323
+ GPSImgDirection = 17
324
+ GPSMapDatum = 18
325
+ GPSDestLatitudeRef = 19
326
+ GPSDestLatitude = 20
327
+ GPSDestLongitudeRef = 21
328
+ GPSDestLongitude = 22
329
+ GPSDestBearingRef = 23
330
+ GPSDestBearing = 24
331
+ GPSDestDistanceRef = 25
332
+ GPSDestDistance = 26
333
+ GPSProcessingMethod = 27
334
+ GPSAreaInformation = 28
335
+ GPSDateStamp = 29
336
+ GPSDifferential = 30
337
+ GPSHPositioningError = 31
338
+
339
+
340
+ """Maps EXIF GPS tags to tag names."""
341
+ GPSTAGS = {i.value: i.name for i in GPS}
342
+
343
+
344
+ class Interop(IntEnum):
345
+ InteropIndex = 1
346
+ InteropVersion = 2
347
+ RelatedImageFileFormat = 4096
348
+ RelatedImageWidth = 4097
349
+ RleatedImageHeight = 4098
350
+
351
+
352
+ class IFD(IntEnum):
353
+ Exif = 34665
354
+ GPSInfo = 34853
355
+ Makernote = 37500
356
+ Interop = 40965
357
+ IFD1 = -1
358
+
359
+
360
+ class LightSource(IntEnum):
361
+ Unknown = 0
362
+ Daylight = 1
363
+ Fluorescent = 2
364
+ Tungsten = 3
365
+ Flash = 4
366
+ Fine = 9
367
+ Cloudy = 10
368
+ Shade = 11
369
+ DaylightFluorescent = 12
370
+ DayWhiteFluorescent = 13
371
+ CoolWhiteFluorescent = 14
372
+ WhiteFluorescent = 15
373
+ StandardLightA = 17
374
+ StandardLightB = 18
375
+ StandardLightC = 19
376
+ D55 = 20
377
+ D65 = 21
378
+ D75 = 22
379
+ D50 = 23
380
+ ISO = 24
381
+ Other = 255