chunklate 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. Chunklate.py +2578 -0
  2. chunklate/__init__.py +108 -0
  3. chunklate/ancillary.py +59 -0
  4. chunklate/ancillary_runtime.py +57 -0
  5. chunklate/bruteforce.py +1156 -0
  6. chunklate/bruteforce_result.py +132 -0
  7. chunklate/bruteforce_runtime.py +3525 -0
  8. chunklate/bruteforce_viewer.py +221 -0
  9. chunklate/checkpoint.py +338 -0
  10. chunklate/checkpoint_actions_runtime.py +1079 -0
  11. chunklate/checkpoint_runtime.py +933 -0
  12. chunklate/chunk_info.py +1700 -0
  13. chunklate/chunk_name_runtime.py +816 -0
  14. chunklate/chunk_order.py +378 -0
  15. chunklate/chunk_order_runtime.py +529 -0
  16. chunklate/chunk_report.py +545 -0
  17. chunklate/chunk_scanner.py +266 -0
  18. chunklate/chunk_state.py +362 -0
  19. chunklate/chunk_state_runtime.py +183 -0
  20. chunklate/chunk_story.py +55 -0
  21. chunklate/chunk_validation_runtime.py +277 -0
  22. chunklate/cli.py +840 -0
  23. chunklate/compression_signatures.py +437 -0
  24. chunklate/crc32_forge.py +182 -0
  25. chunklate/decisions.py +116 -0
  26. chunklate/deflate_crc_solver.py +1875 -0
  27. chunklate/deflate_header.py +774 -0
  28. chunklate/deflate_probe.py +1518 -0
  29. chunklate/deflate_reverse.py +243 -0
  30. chunklate/dummy_chunk.py +101 -0
  31. chunklate/dummy_chunk_runtime.py +571 -0
  32. chunklate/error_log.py +110 -0
  33. chunklate/fixit_felix.py +1966 -0
  34. chunklate/fixit_felix_runtime.py +11071 -0
  35. chunklate/fog_of_war.py +275 -0
  36. chunklate/full_chunk_forcer.py +300 -0
  37. chunklate/getinfo_runtime.py +451 -0
  38. chunklate/getspec_runtime.py +179 -0
  39. chunklate/gpu_opengl.py +163 -0
  40. chunklate/gpu_runtime.py +28 -0
  41. chunklate/history.py +7 -0
  42. chunklate/idat.py +1837 -0
  43. chunklate/idat_bruteforce.py +18999 -0
  44. chunklate/idat_chain.py +254 -0
  45. chunklate/idat_crc_forge.py +2287 -0
  46. chunklate/idat_kraft_opengl_backend.py +224 -0
  47. chunklate/image_viewer.py +195 -0
  48. chunklate/libpng_check.py +141 -0
  49. chunklate/libpng_runtime.py +98 -0
  50. chunklate/magic_runtime.py +2634 -0
  51. chunklate/main_runtime.py +1938 -0
  52. chunklate/messages.py +5 -0
  53. chunklate/name_shift.py +237 -0
  54. chunklate/name_shift_runtime.py +275 -0
  55. chunklate/nearby.py +279 -0
  56. chunklate/nearby_runtime.py +684 -0
  57. chunklate/output.py +787 -0
  58. chunklate/package_update.py +140 -0
  59. chunklate/palette.py +45 -0
  60. chunklate/palette_runtime.py +920 -0
  61. chunklate/palette_ui.py +641 -0
  62. chunklate/platform_runtime.py +175 -0
  63. chunklate/png.py +5798 -0
  64. chunklate/prompts.py +67 -0
  65. chunklate/question_runtime.py +359 -0
  66. chunklate/relics.py +1221 -0
  67. chunklate/relics_runtime.py +855 -0
  68. chunklate/relics_ui.py +271 -0
  69. chunklate/repair_routes.py +72 -0
  70. chunklate/runtime_state.py +266 -0
  71. chunklate/smash_backend.py +966 -0
  72. chunklate/smash_bruteforce.py +579 -0
  73. chunklate/smash_checkpoint.py +182 -0
  74. chunklate/smash_opengl_backend.py +1077 -0
  75. chunklate/sorting.py +11 -0
  76. chunklate/spec_length_runtime.py +56 -0
  77. chunklate/specs.py +1147 -0
  78. chunklate/stdio.py +51 -0
  79. chunklate/ui.py +738 -0
  80. chunklate/ui_runtime.py +97 -0
  81. chunklate/ultimate_opengl_backend.py +1384 -0
  82. chunklate/ultimate_reference_ui.py +895 -0
  83. chunklate/writer.py +133 -0
  84. chunklate/writer_runtime.py +676 -0
  85. chunklate/youshallpass_runtime.py +198 -0
  86. chunklate-0.1.0.dist-info/METADATA +411 -0
  87. chunklate-0.1.0.dist-info/RECORD +90 -0
  88. chunklate-0.1.0.dist-info/WHEEL +5 -0
  89. chunklate-0.1.0.dist-info/entry_points.txt +2 -0
  90. chunklate-0.1.0.dist-info/top_level.txt +2 -0
Chunklate.py ADDED
@@ -0,0 +1,2578 @@
1
+ #!/usr/bin/env python3
2
+ from argparse import ArgumentParser, SUPPRESS
3
+ from datetime import datetime
4
+ import os
5
+ import sys
6
+
7
+
8
+ def Local_Venv_Python(script_path=None, *, os_name=None):
9
+ root = os.path.dirname(os.path.abspath(script_path or __file__))
10
+ os_name = os.name if os_name is None else os_name
11
+ if os_name == "nt":
12
+ candidate = os.path.join(root, ".venv", "Scripts", "python.exe")
13
+ else:
14
+ candidate = os.path.join(root, ".venv", "bin", "python")
15
+ if os.path.exists(candidate):
16
+ return candidate
17
+ return None
18
+
19
+
20
+ def Should_Reexec_Local_Venv(script_path=None, executable=None, env=None):
21
+ env = env if env is not None else os.environ
22
+ if env.get("CHUNKLATE_NO_VENV_REEXEC"):
23
+ return False
24
+ venv_python = Local_Venv_Python(script_path)
25
+ if not venv_python:
26
+ return False
27
+ current = executable or sys.executable
28
+ return os.path.normcase(os.path.abspath(current)) != os.path.normcase(os.path.abspath(venv_python))
29
+
30
+
31
+ def Maybe_Reexec_Local_Venv():
32
+ if __name__ != "__main__" or not Should_Reexec_Local_Venv():
33
+ return
34
+ venv_python = Local_Venv_Python()
35
+ os.execv(venv_python, [venv_python, os.path.abspath(__file__), *sys.argv[1:]])
36
+
37
+
38
+ Maybe_Reexec_Local_Venv()
39
+
40
+ MISSING_IMPORT_ERRORS = {}
41
+
42
+ try:
43
+ from PIL import Image,ImageShow,ImageTk
44
+ except ImportError as exc:
45
+ MISSING_IMPORT_ERRORS["Pillow"] = exc
46
+ Image = ImageShow = ImageTk = None
47
+
48
+ try:
49
+ from inputimeout import TimeoutOccurred, inputimeout
50
+ except ImportError as exc:
51
+ MISSING_IMPORT_ERRORS["inputimeout"] = exc
52
+ TimeoutOccurred = TimeoutError
53
+ def inputimeout(prompt="", timeout=None):
54
+ return input(prompt)
55
+
56
+ try:
57
+ import numpy as np
58
+ except ImportError as exc:
59
+ MISSING_IMPORT_ERRORS["numpy"] = exc
60
+ np = None
61
+
62
+ try:
63
+ import tkinter
64
+ except ImportError as exc:
65
+ MISSING_IMPORT_ERRORS["tkinter"] = exc
66
+ tkinter = None
67
+
68
+ import random, time, zlib, io, inspect, types, collections, itertools, shutil, shlex, subprocess
69
+
70
+ try:
71
+ import cv2
72
+ except ImportError as exc:
73
+ MISSING_IMPORT_ERRORS["opencv-python"] = exc
74
+ cv2 = None
75
+
76
+ try:
77
+ import psutil
78
+ except ImportError as exc:
79
+ MISSING_IMPORT_ERRORS["psutil"] = exc
80
+ psutil = None
81
+
82
+ try:
83
+ import imagehash
84
+ except ImportError as exc:
85
+ MISSING_IMPORT_ERRORS["ImageHash"] = exc
86
+ imagehash = None
87
+
88
+ try:
89
+ import colorama
90
+ except ImportError as exc:
91
+ MISSING_IMPORT_ERRORS["colorama"] = exc
92
+ colorama = None
93
+
94
+ from chunklate import ancillary, ancillary_runtime, bruteforce, checkpoint, checkpoint_actions_runtime, checkpoint_runtime, chunk_info, chunk_name_runtime, chunk_order, chunk_order_runtime, chunk_report, chunk_scanner, chunk_state, chunk_state_runtime, chunk_story, chunk_validation_runtime, cli, decisions, dummy_chunk, dummy_chunk_runtime, error_log, fixit_felix, fixit_felix_runtime, full_chunk_forcer, getinfo_runtime, getspec_runtime, history, image_viewer, libpng_check, libpng_runtime, magic_runtime, main_runtime, name_shift, name_shift_runtime, nearby, nearby_runtime, output, package_update, palette, palette_runtime, palette_ui, platform_runtime, prompts, question_runtime, relics, relics_runtime, relics_ui, runtime_state, smash_bruteforce, sorting, spec_length_runtime, specs, stdio, ui, ui_runtime, ultimate_reference_ui, writer, writer_runtime, youshallpass_runtime
95
+ from chunklate.png import (
96
+ chunk_type_crc_matches,
97
+ detect_png_signature_recovery,
98
+ legacy_crc_checkpoint_args,
99
+ legacy_crc_decision,
100
+ legacy_crc_debug_lines,
101
+ legacy_crc_monkey_lines,
102
+ legacy_find_magic_checkpoint_args,
103
+ legacy_length_checkpoint_args,
104
+ legacy_length_decision,
105
+ validate_png_structure,
106
+ )
107
+
108
+
109
+ RUNTIME_IMPORTS = (
110
+ ("Pillow", "PIL.Image/PIL.ImageTk", lambda: Image is not None and ImageShow is not None and ImageTk is not None),
111
+ ("inputimeout", "inputimeout", lambda: "inputimeout" not in MISSING_IMPORT_ERRORS),
112
+ ("numpy", "numpy", lambda: np is not None),
113
+ ("opencv-python", "cv2", lambda: cv2 is not None),
114
+ ("psutil", "psutil", lambda: psutil is not None),
115
+ ("ImageHash", "imagehash", lambda: imagehash is not None),
116
+ ("python3-tk", "tkinter", lambda: tkinter is not None),
117
+ ("colorama", "colorama", lambda: colorama is not None),
118
+ )
119
+
120
+
121
+ def Missing_Runtime_Dependencies():
122
+ missing = []
123
+ for package, import_name, is_available in RUNTIME_IMPORTS:
124
+ if not is_available():
125
+ missing.append((package, import_name, MISSING_IMPORT_ERRORS.get(package)))
126
+ return tuple(missing)
127
+
128
+
129
+ def Format_Missing_Runtime_Dependencies(missing, *, os_name=None):
130
+ os_name = os.name if os_name is None else os_name
131
+ root = os.path.dirname(os.path.abspath(__file__))
132
+ bootstrap_command = Bootstrap_Command(os_name=os_name)
133
+ local_python = Local_Venv_Python(os_name=os_name) or platform_runtime.local_venv_python(root, os_name=os_name)
134
+ run_command = platform_runtime.format_command(
135
+ [local_python, os.path.abspath(__file__), "-f", "<file>"],
136
+ os_name=os_name,
137
+ )
138
+ lines = [
139
+ "Missing runtime dependencies; Chunklate cannot safely continue.",
140
+ "",
141
+ "Missing imports:",
142
+ ]
143
+ for package, import_name, error in missing:
144
+ lines.append("- %s (import %s)" % (package, import_name))
145
+ if error is not None:
146
+ lines.append(" error: %s" % error)
147
+ lines.extend(
148
+ [
149
+ "",
150
+ "Install/refresh the local virtual environment with:",
151
+ " %s" % platform_runtime.format_command(bootstrap_command, os_name=os_name),
152
+ "",
153
+ "Then run Chunklate with:",
154
+ " %s" % run_command,
155
+ ]
156
+ )
157
+ if any(package == "python3-tk" for package, _, _ in missing) and os_name != "nt":
158
+ lines.extend(
159
+ [
160
+ "",
161
+ "Tkinter is a system Python module on many Linux distributions.",
162
+ "On Debian/Ubuntu install it with: sudo apt install python3-tk",
163
+ ]
164
+ )
165
+ elif any(package == "python3-tk" for package, _, _ in missing):
166
+ lines.extend(
167
+ [
168
+ "",
169
+ "Tkinter is normally installed by the official Python for Windows installer.",
170
+ "Repair or reinstall Python with the Tcl/Tk option enabled if tkinter is missing.",
171
+ ]
172
+ )
173
+ return "\n".join(lines)
174
+
175
+
176
+ def Bootstrap_Script_Path(script_path=None, *, os_name=None):
177
+ root = os.path.dirname(os.path.abspath(script_path or __file__))
178
+ return platform_runtime.bootstrap_python_script(
179
+ root,
180
+ os_name=os.name if os_name is None else os_name,
181
+ )
182
+
183
+
184
+ def Bootstrap_Command(script_path=None, *, os_name=None):
185
+ root = os.path.dirname(os.path.abspath(script_path or __file__))
186
+ return platform_runtime.bootstrap_command(
187
+ root,
188
+ executable=sys.executable,
189
+ os_name=os.name if os_name is None else os_name,
190
+ )
191
+
192
+
193
+ def Can_Prompt_Dependency_Install(stdin=None):
194
+ stream = stdin or sys.stdin
195
+ return (
196
+ not NODIALOGUE
197
+ and not AUTO
198
+ and hasattr(stream, "isatty")
199
+ and stream.isatty()
200
+ )
201
+
202
+
203
+ def Prompt_Dependency_Install(missing, *, input_func=input, stdin=None, runner=subprocess.run):
204
+ print(Format_Missing_Runtime_Dependencies(missing), file=sys.stderr)
205
+ if not Can_Prompt_Dependency_Install(stdin):
206
+ return False
207
+
208
+ answer = input_func("Install/refresh missing dependencies now? (yes/no): ").strip().lower()
209
+ if answer not in ("y", "yes"):
210
+ return False
211
+
212
+ command = Bootstrap_Command()
213
+ print("Running: %s" % platform_runtime.format_command(command), file=sys.stderr)
214
+ result = runner(command, cwd=os.path.dirname(os.path.abspath(__file__)))
215
+ return getattr(result, "returncode", 0) == 0
216
+
217
+
218
+ def Reexec_Local_Venv_Or_Exit():
219
+ venv_python = Local_Venv_Python()
220
+ if not venv_python:
221
+ print("Dependency install finished, but .venv Python was not found.", file=sys.stderr)
222
+ sys.exit(1)
223
+ os.execv(venv_python, [venv_python, os.path.abspath(__file__), *sys.argv[1:]])
224
+
225
+
226
+ def Configure_Terminal_Color():
227
+ global USE_COLOR
228
+ platform_runtime.configure_text_stream_errors(sys.stdout, sys.stderr)
229
+ decision = platform_runtime.decide_terminal_color(
230
+ COLOR_MODE,
231
+ stream=sys.stdout,
232
+ os_name=os.name,
233
+ platform=sys.platform,
234
+ colorama_module=colorama,
235
+ )
236
+ USE_COLOR = decision.use_color
237
+ return decision
238
+
239
+
240
+ def Ensure_Runtime_Dependencies(*, prompt_installer=Prompt_Dependency_Install, reexec=Reexec_Local_Venv_Or_Exit):
241
+ missing = Missing_Runtime_Dependencies()
242
+ if missing:
243
+ if prompt_installer(missing):
244
+ reexec()
245
+ return True
246
+ sys.exit(1)
247
+ return True
248
+
249
+
250
+ def Check_Package_Update(*, current_version=None, fetch_latest=package_update.latest_pypi_version):
251
+ return package_update.check_package_update(
252
+ current_version=current_version,
253
+ fetch_latest=fetch_latest,
254
+ )
255
+
256
+
257
+ def Format_Package_Update_Message(status):
258
+ return package_update.format_update_message(status, python_executable=sys.executable)
259
+
260
+
261
+ def Should_Run_Package_Update_Check(args, *, argv0=None):
262
+ if bool(getattr(args, "NO_UPDATE_CHECK", False)):
263
+ return False
264
+ return True
265
+
266
+
267
+ def Can_Prompt_Package_Update(stdin=None):
268
+ stream = stdin or sys.stdin
269
+ return (
270
+ not NODIALOGUE
271
+ and not AUTO
272
+ and hasattr(stream, "isatty")
273
+ and stream.isatty()
274
+ )
275
+
276
+
277
+ def Prompt_Package_Update_Continue(status, *, input_func=input, stdin=None, stream=None):
278
+ if not status.update_available:
279
+ return True
280
+ out = stream or sys.stderr
281
+ print(Format_Package_Update_Message(status), file=out)
282
+ if not Can_Prompt_Package_Update(stdin):
283
+ print("Continuing with the installed version.", file=out)
284
+ return True
285
+ while True:
286
+ answer = input_func("Continue with this older Chunklate anyway? (yes/no): ").strip().lower()
287
+ if answer in ("y", "yes"):
288
+ return True
289
+ if answer in ("n", "no"):
290
+ return False
291
+ print("I need yes or no before continuing with an older package.", file=out)
292
+
293
+
294
+ def Ensure_Package_Current_Or_Continue(
295
+ *,
296
+ checker=Check_Package_Update,
297
+ prompt_continue=Prompt_Package_Update_Continue,
298
+ exit_process=sys.exit,
299
+ ):
300
+ status = checker()
301
+ if status.up_to_date is None:
302
+ return True
303
+ if prompt_continue(status):
304
+ return True
305
+ exit_process(1)
306
+ return False
307
+
308
+
309
+ def Betterror(error_msg, def_name): ##useless since 3.11
310
+ return error_log.betterror_from_namespace(globals(), error_msg, def_name)
311
+
312
+
313
+ def Error_Log(Err_to_log):
314
+ return error_log.append_error_log_from_namespace(globals(), Err_to_log)
315
+
316
+
317
+ # Relics state model:
318
+ # - PandoraBox holds current-file findings that still need a decision or repair.
319
+ # Keys look like "Function_Error_N:message"; values are "<Chunk>_Tool_N" dicts.
320
+ # - Cornucopia holds fixes already accepted by CheckPoint/FixItFelix.
321
+ # - WriteClone snapshots those two stores into Pandemonium/ArkOfCovenant so
322
+ # Relics can react to the repair history when libpng reports a later failure.
323
+ def CheckPoint_Record_Finding(registration):
324
+ if registration.side_note is not None:
325
+ SideNotes.append(registration.side_note)
326
+ return relics.record_checkpoint_registration(PandoraBox, Cornucopia, registration)
327
+
328
+
329
+ def CheckPoint_Apply_Flags(flags):
330
+ if not flags:
331
+ return
332
+ globals().update(flags)
333
+
334
+
335
+ def CheckPoint_Print_Libpng_Critical(info):
336
+ PRINT("\n-\033[1;31;49mCriticalHit\033[m: %s" % info)
337
+
338
+
339
+ def CheckPoint_Discard_Libpng_Warning():
340
+ for nb, key in enumerate(PandoraBox):
341
+ if "libpng warning:" in str(key):
342
+ relics.discard_pandora_error(PandoraBox, key)
343
+ SideNotes.append("-Found False-Positive :[Error:-%s]." % (str(key)))
344
+ break
345
+
346
+
347
+ def CheckPoint_Libpng_End_Success(message):
348
+ saved_path = Current_Display_Image_Path()
349
+ visual_reference_note = Final_Image_Visual_Reference_Note(saved_path)
350
+ if visual_reference_note:
351
+ Candy(
352
+ "Cowsay",
353
+ visual_reference_note,
354
+ "com",
355
+ )
356
+ SideNotes.append("-Visual reference route: %s" % visual_reference_note)
357
+ PRINT("-Visual reference route: %s" % visual_reference_note)
358
+ TheEnd()
359
+ return
360
+
361
+ Candy(
362
+ "Cowsay",
363
+ message,
364
+ "good",
365
+ )
366
+ Candy("Cowsay", "Your file is here: %s" % saved_path, "good")
367
+ PRINT(Candy("Color", "green", "-Saved in : %s") % saved_path)
368
+ Open_Final_Image_Once(saved_path)
369
+ TheEnd()
370
+
371
+
372
+ def _Valid_Png_Path(path):
373
+ if not path or not os.path.exists(path):
374
+ return False
375
+ try:
376
+ with open(path, "rb") as file:
377
+ return validate_png_structure(output.clone_bytes(file.read())).ok
378
+ except (OSError, ValueError):
379
+ return False
380
+
381
+
382
+ def Current_Display_Image_Path():
383
+ sample_dir = output.clone_folder(FILE_Origin, FILE_DIR)
384
+ clone_path = os.path.join(sample_dir, Sample_Name) if Sample_Name else ""
385
+ if SAVE_COUNT > 0:
386
+ candidates = (clone_path, Sample, FILE_Origin)
387
+ else:
388
+ candidates = (Sample, FILE_Origin)
389
+ for path in candidates:
390
+ if _Valid_Png_Path(path):
391
+ return path
392
+ for path in candidates:
393
+ if path:
394
+ return path
395
+ return ""
396
+
397
+
398
+ def _Load_Rgba_Image(path):
399
+ if Image is None or not path:
400
+ return None
401
+ try:
402
+ with Image.open(path) as image:
403
+ return image.convert("RGBA")
404
+ except Exception:
405
+ return None
406
+
407
+
408
+ def Final_Image_Visual_Reference_Note(path):
409
+ reference_path = Ultimate_Linefeed_Reference()
410
+ if not reference_path:
411
+ return ""
412
+ if not _Valid_Png_Path(path):
413
+ return ""
414
+ if not os.path.exists(reference_path):
415
+ return "PNG is structurally valid; visual repair needs a reference/ROI, but the configured reference is missing: %s." % reference_path
416
+
417
+ candidate = _Load_Rgba_Image(path)
418
+ reference = _Load_Rgba_Image(reference_path)
419
+ if candidate is None or reference is None:
420
+ return "PNG is structurally valid; visual repair needs a reference/ROI, but I could not decode the configured reference."
421
+ if candidate.size != reference.size:
422
+ return "PNG is structurally valid; visual mismatch detected against the reference size %s vs %s; repair needs reference/ROI." % (
423
+ candidate.size,
424
+ reference.size,
425
+ )
426
+ if candidate.tobytes() != reference.tobytes():
427
+ return "PNG is structurally valid; visual mismatch detected against the reference; repair needs reference/ROI."
428
+ return ""
429
+
430
+
431
+ def Open_Final_Image_Once(path):
432
+ global FINAL_IMAGE_OPEN_REQUESTED
433
+
434
+ if FINAL_IMAGE_OPEN_REQUESTED:
435
+ return None
436
+ if Has_Unresolved_Findings():
437
+ return None
438
+ if not _Valid_Png_Path(path):
439
+ return None
440
+ if SAVE_COUNT == 0 and path in (Sample, FILE_Origin):
441
+ Candy(
442
+ "Cowsay",
443
+ "Wtf... why did you give that to me? It's perfect!",
444
+ "good",
445
+ )
446
+ FINAL_IMAGE_OPEN_REQUESTED = True
447
+ return Open_Final_Image(path)
448
+
449
+
450
+ def Open_Current_Final_Image_If_Valid():
451
+ return Open_Final_Image_Once(Current_Display_Image_Path())
452
+
453
+
454
+ def Has_Unresolved_Findings():
455
+ return bool(PandoraBox)
456
+
457
+
458
+ def Open_Final_Image(path, emit=None):
459
+ emit = PRINT if emit is None else emit
460
+ if not sys.stdout.isatty():
461
+ return None
462
+ try:
463
+ with open(path, "rb") as file:
464
+ validation = validate_png_structure(output.clone_bytes(file.read()))
465
+ except (OSError, ValueError):
466
+ validation = None
467
+ if validation is None or not validation.ok:
468
+ emit(Candy("Color", "yellow", "-Not opening image automatically: PNG structure is not valid."))
469
+ return None
470
+
471
+ result = image_viewer.open_image(path)
472
+ if result.success:
473
+ emit(Candy("Color", "green", "-Opening image with : %s") % result.opener)
474
+ else:
475
+ emit(Candy("Color", "yellow", "-Could not open image automatically: %s") % result.error)
476
+ return result
477
+
478
+
479
+ ACTIVE_PREVIEW_IMAGE = None
480
+ LAST_PROGRESS_LINE = ""
481
+ PREVIEW_OUTPUT_FOLDER = "Bruteforce_Previews"
482
+
483
+
484
+ def Close_Preview_Image():
485
+ global ACTIVE_PREVIEW_IMAGE
486
+
487
+ preview = ACTIVE_PREVIEW_IMAGE
488
+ ACTIVE_PREVIEW_IMAGE = None
489
+ if preview is None:
490
+ return False
491
+ close = getattr(preview, "close", None)
492
+ if close is None:
493
+ return False
494
+ try:
495
+ return bool(close())
496
+ except Exception:
497
+ return False
498
+
499
+
500
+ def Preview_Repair_Image(data, label, *, show=True, emit=None, announce=True):
501
+ global ACTIVE_PREVIEW_IMAGE
502
+
503
+ emit = PRINT if emit is None else emit
504
+ Close_Preview_Image()
505
+ preview_bytes = output.clone_bytes(data)
506
+ validation = validate_png_structure(preview_bytes)
507
+ if not validation.ok:
508
+ emit(Candy("Color", "yellow", "-Preview skipped: PNG structure is not valid."))
509
+ return None
510
+
511
+ folder = output.ensure_clone_folder(FILE_Origin, FILE_DIR)
512
+ safe_label = "".join(
513
+ char if char.isalnum() or char in ("-", "_", ".") else "_"
514
+ for char in str(label)
515
+ )
516
+ preview_folder = os.path.join(folder, PREVIEW_OUTPUT_FOLDER)
517
+ os.makedirs(preview_folder, exist_ok=True)
518
+ path = os.path.join(preview_folder, "_Preview_%s.png" % safe_label)
519
+ with open(path, "wb") as file:
520
+ file.write(preview_bytes)
521
+
522
+ if announce:
523
+ emit(Candy("Color", "green", "-Preview image : %s") % path)
524
+ if not show:
525
+ return types.SimpleNamespace(success=False, path=path, opened=False)
526
+ ACTIVE_PREVIEW_IMAGE = Open_Final_Image(path, emit=emit)
527
+ if ACTIVE_PREVIEW_IMAGE is None:
528
+ return types.SimpleNamespace(success=False, path=path, opened=False)
529
+ return ACTIVE_PREVIEW_IMAGE
530
+
531
+
532
+ def Ultimate_Linefeed_Checkpoint_Path():
533
+ return globals().get("ULTIMATE_LINEFEED_CHECKPOINT_PATH") or os.path.join(
534
+ output.ensure_clone_folder(FILE_Origin, FILE_DIR),
535
+ "_ULF.checkpoint.jsonl",
536
+ )
537
+
538
+
539
+ def Ultimate_Linefeed_Progress_Path():
540
+ return globals().get("ULTIMATE_LINEFEED_PROGRESS_PATH") or os.path.join(
541
+ output.ensure_clone_folder(FILE_Origin, FILE_DIR),
542
+ "_ULF.progress.json",
543
+ )
544
+
545
+
546
+ def Ultimate_Linefeed_Source_Path():
547
+ return globals().get("ULTIMATE_LINEFEED_SOURCE_PATH") or os.path.join(
548
+ output.ensure_clone_folder(FILE_Origin, FILE_DIR),
549
+ "_ULF.Source.png",
550
+ )
551
+
552
+
553
+ def _Ultimate_Linefeed_Budget_Decision(mode, estimate, manual_budget=None):
554
+ total = int(getattr(estimate, "total_combinations", 0) or 0)
555
+ return magic_runtime.idat_bruteforce.ultimate_linefeed_budget_decision(
556
+ total,
557
+ mode,
558
+ manual_budget=manual_budget,
559
+ )
560
+
561
+
562
+ def _Ultimate_Linefeed_Print_Budget_Menu(estimate):
563
+ total = int(getattr(estimate, "total_combinations", 0) or 0)
564
+ operations = int(getattr(estimate, "operation_count", 0) or 0)
565
+ depth = int(getattr(estimate, "max_depth", 0) or 0)
566
+ lines = [
567
+ "Ultimate budget no jutsu:",
568
+ "operations: %s" % format(operations, ","),
569
+ "max depth: %s" % depth,
570
+ "possible combinations: %s" % format(total, ","),
571
+ *magic_runtime.idat_bruteforce.ultimate_linefeed_universe_atom_comparison_lines(total),
572
+ "",
573
+ "Enter a number from 1 to 10.",
574
+ "",
575
+ "1. quick total / 100000",
576
+ "2. normal total / 50000",
577
+ "3. deep total / 10000",
578
+ "4. very deep total / 1000",
579
+ "5. deeeeeeep total / 100",
580
+ "6. abyssal total / 10",
581
+ "7. inception total / 2",
582
+ "8. no limit",
583
+ "9. manual exact candidate budget",
584
+ "10. quit like a looser.",
585
+ ]
586
+ Prompt_Candy("Cowsay", "\n".join(lines), "com")
587
+
588
+
589
+ def _Ultimate_Linefeed_Manual_Budget():
590
+ while True:
591
+ try:
592
+ value = input("Exact candidate budget > ").strip()
593
+ except EOFError:
594
+ return None
595
+ try:
596
+ budget = int(value)
597
+ except ValueError:
598
+ PRINT(Candy("Color", "red", "-Budget must be a positive integer."))
599
+ continue
600
+ if budget > 0:
601
+ return budget
602
+ PRINT(Candy("Color", "red", "-Budget must be greater than zero."))
603
+
604
+
605
+ def Ultimate_Linefeed_Budget(estimate=None):
606
+ if globals().get("ULTIMATE_LINEFEED_UNBOUNDED", False):
607
+ return _Ultimate_Linefeed_Budget_Decision("unbounded", estimate)
608
+ budget = globals().get("ULTIMATE_LINEFEED_BUDGET", None)
609
+ if budget is None:
610
+ if globals().get("AUTO", False) or globals().get("NODIALOGUE", False):
611
+ return _Ultimate_Linefeed_Budget_Decision("normal", estimate)
612
+ choices = {
613
+ "1": "quick",
614
+ "2": "normal",
615
+ "": "normal",
616
+ "3": "deep",
617
+ "4": "very_deep",
618
+ "5": "deeeeeeep",
619
+ "6": "abyssal",
620
+ "7": "inception",
621
+ "8": "unbounded",
622
+ "9": "manual",
623
+ "10": "abort",
624
+ }
625
+ while True:
626
+ _Ultimate_Linefeed_Print_Budget_Menu(estimate)
627
+ try:
628
+ choice = input("Ultimate budget choice number [2 normal] > ").strip().lower()
629
+ except EOFError:
630
+ choice = ""
631
+ mode = choices.get(choice)
632
+ if mode is None:
633
+ PRINT(Candy("Color", "red", "-Enter a number from 1 to 10."))
634
+ continue
635
+ if mode == "manual":
636
+ manual_budget = _Ultimate_Linefeed_Manual_Budget()
637
+ if manual_budget is None:
638
+ return _Ultimate_Linefeed_Budget_Decision("normal", estimate)
639
+ return _Ultimate_Linefeed_Budget_Decision(
640
+ "manual",
641
+ estimate,
642
+ manual_budget=manual_budget,
643
+ )
644
+ return _Ultimate_Linefeed_Budget_Decision(mode, estimate)
645
+ return magic_runtime.idat_bruteforce.UltimateLinefeedBudgetDecision(
646
+ "override",
647
+ int(budget),
648
+ coverage=magic_runtime.idat_bruteforce.ultimate_linefeed_budget_coverage(
649
+ int(getattr(estimate, "total_combinations", 0) or 0),
650
+ int(budget),
651
+ ),
652
+ )
653
+
654
+
655
+ def _Ultimate_Linefeed_Recommended_Workers():
656
+ return platform_runtime.recommended_worker_count(profile="normal")
657
+
658
+
659
+ def _Ultimate_Linefeed_Worker_Profile_Counts():
660
+ cpu_count = platform_runtime.detected_cpu_count()
661
+ return {
662
+ "cpu": cpu_count,
663
+ "min": platform_runtime.recommended_worker_count(cpu_count, profile="min"),
664
+ "normal": platform_runtime.recommended_worker_count(cpu_count, profile="normal"),
665
+ "max": platform_runtime.recommended_worker_count(cpu_count, profile="max"),
666
+ }
667
+
668
+
669
+ def _Ultimate_Linefeed_Workers_From_Value(value):
670
+ if value is None:
671
+ return None
672
+ text = str(value).strip().lower()
673
+ if text in ("auto", "normal"):
674
+ return platform_runtime.recommended_worker_count(profile="normal")
675
+ if text in ("min", "max"):
676
+ return platform_runtime.recommended_worker_count(profile=text)
677
+ return max(0, int(text))
678
+
679
+
680
+ def _Ultimate_Linefeed_Print_Worker_Menu():
681
+ counts = _Ultimate_Linefeed_Worker_Profile_Counts()
682
+ lines = [
683
+ "Ultimate CPU worker no jutsu:",
684
+ "CPU detected: %s" % counts["cpu"],
685
+ "min workers: %s" % counts["min"],
686
+ "normal workers: %s" % counts["normal"],
687
+ "max workers: %s" % counts["max"],
688
+ "",
689
+ "Choose how many Cpu workers to use (0,min, normal, max, or enter an exact number).",
690
+ "",
691
+ "0. disabled",
692
+ "min. CPU / 4",
693
+ "normal. CPU / 2",
694
+ "max. CPU - 1",
695
+ "custom. enter an exact worker count",
696
+ "",
697
+ "Empty keeps Ultimate single-process.",
698
+ ]
699
+ Prompt_Candy("Cowsay", "\n".join(lines), "com")
700
+
701
+
702
+ def Ultimate_Linefeed_Workers():
703
+ configured = globals().get("ULTIMATE_LINEFEED_WORKERS", None)
704
+ if configured is not None:
705
+ return _Ultimate_Linefeed_Workers_From_Value(configured)
706
+ if globals().get("AUTO", False) or globals().get("NODIALOGUE", False):
707
+ return 0
708
+
709
+ while True:
710
+ _Ultimate_Linefeed_Print_Worker_Menu()
711
+ try:
712
+ choice = input("Ultimate worker profile [0 disabled] > ").strip().lower()
713
+ except EOFError:
714
+ choice = ""
715
+ if choice == "":
716
+ return 0
717
+ if choice in ("min", "normal", "max", "auto"):
718
+ return _Ultimate_Linefeed_Workers_From_Value(choice)
719
+ if choice == "custom":
720
+ try:
721
+ choice = input("Custom Ultimate worker count > ").strip().lower()
722
+ except EOFError:
723
+ choice = ""
724
+ try:
725
+ workers = int(choice)
726
+ except ValueError:
727
+ PRINT(Candy("Color", "red", "-Enter 0, min, normal, max, custom, or a worker count."))
728
+ continue
729
+ if workers >= 0:
730
+ return workers
731
+ PRINT(Candy("Color", "red", "-Worker count must be zero or higher."))
732
+
733
+
734
+ def Ultimate_Linefeed_Reference():
735
+ return str(globals().get("ULTIMATE_LINEFEED_REFERENCE", "") or "")
736
+
737
+
738
+ def Ultimate_Linefeed_Reference_Mode():
739
+ mode = str(globals().get("ULTIMATE_LINEFEED_REFERENCE_MODE", "exact") or "exact").strip().lower()
740
+ return mode if mode in ("exact", "similar") else "exact"
741
+
742
+
743
+ def Ultimate_Linefeed_Reference_Regions():
744
+ return str(globals().get("ULTIMATE_LINEFEED_REFERENCE_REGIONS", "") or "")
745
+
746
+
747
+ def Ultimate_Linefeed_Reference_Region_Editor():
748
+ return bool(globals().get("ULTIMATE_LINEFEED_REFERENCE_REGION_EDITOR", False))
749
+
750
+
751
+ def Ultimate_Linefeed_Reference_Region_Editor_Run(source_path, reference_path, regions_path, source_data=b""):
752
+ return ultimate_reference_ui.open_ultimate_reference_region_editor(
753
+ source_path,
754
+ reference_path,
755
+ regions_path,
756
+ candidate_data=source_data,
757
+ )
758
+
759
+
760
+ def Ultimate_Linefeed_Visual_Gallery_Limit():
761
+ return int(globals().get("ULTIMATE_LINEFEED_VISUAL_GALLERY_LIMIT", 100) or 0)
762
+
763
+
764
+ def Ultimate_Linefeed_Visual_Min_Coverage():
765
+ return float(globals().get("ULTIMATE_LINEFEED_VISUAL_MIN_COVERAGE", 0.95) or 0.0)
766
+
767
+
768
+ def Ultimate_Linefeed_Live_Preview_Folder():
769
+ return os.path.join(output.ensure_clone_folder(FILE_Origin, FILE_DIR), PREVIEW_OUTPUT_FOLDER)
770
+
771
+
772
+ def Announce_Ultimate_Linefeed_Live_Preview_Folder(preview_folder):
773
+ global ULTIMATE_LINEFEED_LIVE_PREVIEW_FOLDER_REPORTED
774
+ if ULTIMATE_LINEFEED_LIVE_PREVIEW_FOLDER_REPORTED == preview_folder:
775
+ return
776
+ ULTIMATE_LINEFEED_LIVE_PREVIEW_FOLDER_REPORTED = preview_folder
777
+ PRINT_With_Loader_Redraw(Candy("Color", "green", "-Preview folder : %s") % preview_folder)
778
+
779
+
780
+ def Ultimate_Linefeed_Candidate_Preview(candidate, tested, budget):
781
+ timeout = float(globals().get("ULTIMATE_LINEFEED_PREVIEW_TIMEOUT", 5.0) or 0.0)
782
+ show_preview = bool(globals().get("ULTIMATE_LINEFEED_SHOW_PREVIEWS", False))
783
+ Announce_Ultimate_Linefeed_Live_Preview_Folder(Ultimate_Linefeed_Live_Preview_Folder())
784
+
785
+ after = getattr(candidate, "after", None)
786
+ scanlines = getattr(after, "usable_scanlines", "unknown")
787
+ height = getattr(after, "height", "unknown")
788
+ adler_status = getattr(after, "adler_status", "adler_unknown")
789
+ label = "UltimateLive_%09d_%s_of_%s_%s" % (
790
+ int(tested),
791
+ scanlines,
792
+ height,
793
+ adler_status,
794
+ )
795
+ preview = Preview_Repair_Image(
796
+ candidate.data,
797
+ label,
798
+ show=show_preview,
799
+ emit=lambda _message: None,
800
+ announce=False,
801
+ )
802
+ if preview is None:
803
+ return None
804
+ if not show_preview:
805
+ return preview
806
+ if not getattr(preview, "success", False):
807
+ Close_Preview_Image()
808
+ return preview
809
+ try:
810
+ if timeout > 0:
811
+ time.sleep(timeout)
812
+ finally:
813
+ Close_Preview_Image()
814
+ return preview
815
+
816
+
817
+ def CheckPoint_Runtime():
818
+ return checkpoint_runtime.build_checkpoint_runtime_from_namespace(globals())
819
+
820
+
821
+ def CheckPoint_Set_Brute_LvL(value):
822
+ global Brute_LvL
823
+
824
+ Brute_LvL = value
825
+
826
+
827
+ def CheckPoint_Action_Runtime():
828
+ return checkpoint_actions_runtime.build_checkpoint_action_runtime_from_namespace(globals())
829
+
830
+ def CheckPoint_Apply_Action_Decision(decision, chunk, info, toolkit):
831
+ return checkpoint_actions_runtime.apply_action_decision(
832
+ CheckPoint_Action_Runtime(),
833
+ decision,
834
+ chunk,
835
+ info,
836
+ toolkit,
837
+ )
838
+
839
+
840
+ def Pandemonium_Remember_Current_Sample():
841
+ relics.remember_sample(Pandemonium, ArkOfCovenant, Sample, PandoraBox, Cornucopia)
842
+
843
+
844
+ def IDAT_Bytes_Nbr(): # tmpworkaround
845
+ global IBN
846
+ IBN = specs.estimate_idat_bytes_from_hex(DATAX, tuple(CHUNKS))
847
+ return IBN
848
+
849
+
850
+
851
+ def Max_Res():
852
+ try:
853
+ MaxRes, size = specs.estimate_max_resolution_from_file(FILE_Origin)
854
+ if DEBUG:
855
+ PRINT("Size:%s"%str(size))
856
+ PRINT(
857
+ "-Maximum resolution estimation based on file size: %s*%s"
858
+ % (MaxRes, MaxRes)
859
+ )
860
+ except Exception as e:
861
+ Betterror(e, inspect.stack()[0][3])
862
+ PRINT(Candy("Color", "red", "Error:%s")% Candy("Color", "yellow", e))
863
+ TheEnd()
864
+
865
+ return MaxRes
866
+
867
+
868
+ def GetSpec(GetChunk,Mode,Fields=["All"],StructIndex=None,IterNbr=1):
869
+ return getspec_runtime.run_getspec_from_namespace(
870
+ globals(),
871
+ GetChunk,
872
+ Mode,
873
+ Fields,
874
+ StructIndex,
875
+ IterNbr,
876
+ )
877
+
878
+
879
+ def Sync_Chunk_Info_Legacy_State(section=None):
880
+ if hasattr(section, "legacy_globals"):
881
+ globals().update(section.legacy_globals())
882
+ return None
883
+ return chunk_state_runtime.sync_state_to_legacy(globals(), CHUNK_INFO_STATE, section)
884
+
885
+
886
+ def Sync_Chunk_Info_State_From_Legacy(section=None):
887
+ return chunk_state_runtime.sync_legacy_to_state(CHUNK_INFO_STATE, globals(), section)
888
+
889
+
890
+ def Chunk_Report_Color(color, value):
891
+ return Candy("Color", color, value)
892
+
893
+
894
+ def Chunky_Report(name):
895
+ return Candy("Chunky", name)
896
+
897
+
898
+ ####
899
+ def GetInfo_Set_Legacy(**values):
900
+ globals().update(values)
901
+
902
+
903
+ def GetInfo_Runtime():
904
+ return getinfo_runtime.GetInfoRuntime(
905
+ chunk_state=CHUNK_INFO_STATE,
906
+ set_legacy=GetInfo_Set_Legacy,
907
+ sync_legacy=Sync_Chunk_Info_Legacy_State,
908
+ max_resolution=Max_Res,
909
+ checkpoint=CheckPoint,
910
+ emit=PRINT,
911
+ candy=Candy,
912
+ color=Chunk_Report_Color,
913
+ chunky=Chunky_Report,
914
+ raw_length=Raw_Length,
915
+ orig_cl=Orig_CL,
916
+ ihdr_color=IHDR_Color,
917
+ ihdr_depth=IHDR_Depht,
918
+ chunks_history=tuple(Chunks_History),
919
+ private_chunks=tuple(PRIVATE_CHUNKS),
920
+ allchunks=tuple(ALLCHUNKS),
921
+ )
922
+
923
+
924
+ def GetInfo(Chunk, data, Dummy=False):
925
+ globals().update(
926
+ iCCP_Name="",
927
+ iTXt_String="",
928
+ iTXt_Key="",
929
+ zTXt_Key="",
930
+ tEXt_Text="",
931
+ tEXt_Key="",
932
+ )
933
+
934
+ getinfo_runtime.run_getinfo(GetInfo_Runtime(), Chunk, data)
935
+
936
+ if Dummy is False:
937
+ CheckChunkOrder(Chunk, "TheGoodPlace")
938
+ return
939
+
940
+
941
+ ####
942
+
943
+
944
+ def YouShallPass_Runtime():
945
+ return youshallpass_runtime.YouShallPassRuntime(
946
+ chunk_state=CHUNK_INFO_STATE,
947
+ sync_state=Sync_Chunk_Info_State_From_Legacy,
948
+ chunks_history=tuple(Chunks_History),
949
+ orig_cl=Orig_CL,
950
+ )
951
+
952
+
953
+ def YouShallPass(Chunk, data):
954
+ return youshallpass_runtime.youshallpass(YouShallPass_Runtime(), Chunk, data)
955
+
956
+
957
+ def ChunkbyChunk(offset):
958
+ ChunkScan = chunk_scanner.scan_legacy_chunk(DATA_BYTES, offset)
959
+ Sync_Chunk_Info_Legacy_State(ChunkScan)
960
+
961
+ Candy("Title", "Chunk Infos:")
962
+ chunk_report.render_legacy_chunk_window(
963
+ ChunkScan.window,
964
+ PRINT,
965
+ lambda color, value: Candy("Color", color, value),
966
+ )
967
+
968
+ return
969
+
970
+
971
+ def GroundhogDay(NewDay):
972
+
973
+ Relaunch = runtime_state.groundhogday_relaunch_args(sys.argv, NewDay)
974
+ sys.argv[:] = Relaunch.argv
975
+ if DEBUG is True:
976
+ PRINT("sys.executable was %s"% sys.executable)
977
+ PRINT("argv is %s"% Relaunch.strargs)
978
+ PRINT("rebooting chunklate")
979
+ if PAUSEDEBUG is True:
980
+ Pause("Pause:Reboot")
981
+ os.execv(sys.executable, Relaunch.exec_args)
982
+
983
+
984
+ def Chunklate(sec):
985
+
986
+ for line in ui.render_chunklate_banner(os.name, random.randint, use_color=USE_COLOR):
987
+ print(line)
988
+
989
+ if sec:
990
+ time.sleep(sec)
991
+
992
+
993
+ def Minibar_Group(Indication=""):
994
+ return "".join("#" if char.isdigit() else char for char in str(Indication))
995
+
996
+
997
+ def Minibar(Indication=""):
998
+ global CharPos
999
+ global GoBack
1000
+ global Loading_txt
1001
+ global Loading_sep
1002
+ global PROGRESS_LINE_ACTIVE
1003
+ minibar_group = Minibar_Group(Indication)
1004
+ if minibar_group != Loading_sep:
1005
+ Loading_txt = ""
1006
+ CharPos = 1
1007
+ GoBack = False
1008
+ Loading_sep = minibar_group
1009
+ Step = ui.minibar_step(Indication, Loading_txt, CharPos, GoBack, MAXCHAR)
1010
+ Loading_txt = Step.loading_text
1011
+ CharPos = Step.char_pos
1012
+ GoBack = Step.go_back
1013
+ if Step.should_print:
1014
+ print(Loading_txt + "\033[K", end="\r")
1015
+ PROGRESS_LINE_ACTIVE = True
1016
+
1017
+
1018
+ def Loadingbar(fishs, fishsize, loop, build):
1019
+ global PROGRESS_LINE_ACTIVE
1020
+ global LAST_PROGRESS_LINE
1021
+ result = ui.run_loadingbar_from_namespace(globals(), fishs, fishsize, loop, build)
1022
+ if not build:
1023
+ if result is not None:
1024
+ LAST_PROGRESS_LINE = result.text
1025
+ PROGRESS_LINE_ACTIVE = True
1026
+ return result
1027
+
1028
+
1029
+ def Finish_Progress_Line(*, clear=False):
1030
+ global PROGRESS_LINE_ACTIVE
1031
+ if PROGRESS_LINE_ACTIVE:
1032
+ if clear:
1033
+ print("\r\033[K", end="")
1034
+ else:
1035
+ print("")
1036
+ PROGRESS_LINE_ACTIVE = False
1037
+
1038
+
1039
+ def Redraw_Progress_Line():
1040
+ global PROGRESS_LINE_ACTIVE
1041
+ if LAST_PROGRESS_LINE:
1042
+ print(LAST_PROGRESS_LINE + "\033[K", end="\r")
1043
+ PROGRESS_LINE_ACTIVE = True
1044
+
1045
+
1046
+ def PRINT_With_Loader_Redraw(msg):
1047
+ was_active = PROGRESS_LINE_ACTIVE
1048
+ Finish_Progress_Line(clear=True)
1049
+ if DEBUGFILE is True:
1050
+ DebugNotes.append(msg)
1051
+ output.append_terminal_transcript(globals(), msg)
1052
+ ui.emit_printable_message(print, msg, max_columns=MAXCHAR, no_dialogue=NODIALOGUE)
1053
+ if was_active:
1054
+ Redraw_Progress_Line()
1055
+
1056
+
1057
+ def Sumform(waitforit, switch):
1058
+ return output.summary_separator(waitforit, switch, MAXCHAR)
1059
+
1060
+
1061
+ def Summarise(infos, Summary_Footer=False):
1062
+ return output.run_summarise_from_namespace(globals(), infos, Summary_Footer)
1063
+
1064
+
1065
+ def Prepare_Immediate_Summary():
1066
+ return output.ensure_immediate_summary_notes(globals())
1067
+
1068
+
1069
+ def Legacy_UI_Runtime():
1070
+ return ui_runtime.LegacyUiRuntime(
1071
+ emit=PRINT,
1072
+ random_int=random.randint,
1073
+ max_columns=MAXCHAR,
1074
+ no_dialogue=NODIALOGUE,
1075
+ use_color=USE_COLOR,
1076
+ pause_dialogue_enabled=PAUSEDIALOGUE,
1077
+ pause_dialogue=lambda: prompts.pause_dialogue(Transcript_Input, PAUSEDIALOGUE),
1078
+ pause_state=DIALOGUE_PAUSE_STATE,
1079
+ )
1080
+
1081
+
1082
+ def Candy(mode, arg, data=None):
1083
+ return Legacy_UI_Runtime().candy(mode, arg, data)
1084
+
1085
+
1086
+ def Prompt_Candy(mode, arg, data=None):
1087
+ def emit(message):
1088
+ output.append_terminal_transcript(globals(), message)
1089
+ print(message, flush=True)
1090
+
1091
+ return ui_runtime.LegacyUiRuntime(
1092
+ emit=emit,
1093
+ random_int=random.randint,
1094
+ max_columns=MAXCHAR,
1095
+ no_dialogue=False,
1096
+ use_color=USE_COLOR,
1097
+ ).candy(mode, arg, data)
1098
+
1099
+
1100
+ def SplitDigits(lst):
1101
+ return sorting.natural_sort_key(lst)
1102
+
1103
+
1104
+ def DigDigits(dig):
1105
+ return sorting.digit_or_text(dig)
1106
+
1107
+
1108
+ def ChunkStory(action, Chunk, start, end, chuck_length):
1109
+ global Chunks_History
1110
+ global Chunks_History_Index
1111
+
1112
+ if action == "add":
1113
+ chunk_story.add(Chunks_History, Chunks_History_Index, Chunk, start, end, chuck_length)
1114
+ elif action == "del":
1115
+ try:
1116
+ chunk_story.delete_legacy(Chunks_History, Chunks_History_Index, Chunk)
1117
+ except Exception as e:
1118
+ Betterror(e, inspect.stack()[0][3])
1119
+ if DEBUG is True:
1120
+ PRINT(Candy("Color", "red", "Error:%s")% Candy("Color", "yellow", e))
1121
+ if PAUSEDEBUG is True:
1122
+ Pause("Pause:Chunkstory")
1123
+
1124
+
1125
+ def Clear_Terminal_Dialogue_Pause():
1126
+ DIALOGUE_PAUSE_STATE.pending = False
1127
+ DIALOGUE_PAUSE_STATE.paused_in_group = False
1128
+ DIALOGUE_PAUSE_STATE.rendering_dialogue = False
1129
+
1130
+
1131
+ def Record_Terminal_Transcript(message):
1132
+ output.append_terminal_transcript(globals(), message)
1133
+
1134
+
1135
+ def Transcript_Input(prompt=""):
1136
+ answer = input(prompt)
1137
+ Record_Terminal_Transcript("%s%s" % (prompt, answer))
1138
+ return answer
1139
+
1140
+
1141
+ def TheEnd():
1142
+ Clear_Terminal_Dialogue_Pause()
1143
+ if DEBUG is True:
1144
+ for line in output.the_end_debug_lines(
1145
+ Chunks_History_Index,
1146
+ idatcounter,
1147
+ Chunks_History,
1148
+ IDAT_Bytes_Len,
1149
+ ):
1150
+ PRINT(line)
1151
+ if PAUSEDEBUG is True:
1152
+ Pause("ThenEnd debug")
1153
+ Open_Current_Final_Image_If_Valid()
1154
+ Summarise(None, True)
1155
+ Chunklate(0)
1156
+ Candy("Cowsay", "See you Space Cowboy...", "good")
1157
+ sys.exit(0)
1158
+
1159
+
1160
+ def ToBitstory(bytenbr):
1161
+ global Bytes_History
1162
+ history.append_byte_history(Bytes_History, bytenbr)
1163
+
1164
+
1165
+ def stderr_redirector(stream):
1166
+ return stdio.stderr_redirector(stream)
1167
+
1168
+ def Product(chunk_data,color_type,gen_nbr=None):
1169
+ yield from specs.iter_product_values(chunk_data, color_type)
1170
+
1171
+
1172
+ class Tk_Gen_Scale_Plte:
1173
+
1174
+ def __init__(self, master=None, label='', value=0,to=None,from_=None,ln=None,afn=None,bfn=None,h=None,w=None,nbr=None):
1175
+ widget = palette_ui.create_palette_scale(
1176
+ tkinter_module=tkinter,
1177
+ master=master,
1178
+ label=label,
1179
+ value=value,
1180
+ from_=from_,
1181
+ to=to,
1182
+ length=ln,
1183
+ command=lambda event: Tk_ImgUpdate_Plte(event,nbr=nbr,bfn=bfn,afn=afn,h=h,w=w),
1184
+ grid_options={"padx": 10, "pady": 5},
1185
+ )
1186
+ self.var = widget.var
1187
+ self.s = widget.scale
1188
+ self.swatch = widget.swatch
1189
+ self.container = widget.container
1190
+ def clean(self):
1191
+ if hasattr(self, "container") and hasattr(self.container, "destroy"):
1192
+ self.container.destroy()
1193
+ else:
1194
+ self.s.destroy()
1195
+
1196
+
1197
+ def Tk_Render_Plte_Preview(wanabyte, w, h, frame=None):
1198
+ return palette_runtime.render_palette_preview_from_namespace(globals(), wanabyte, w, h, frame)
1199
+
1200
+
1201
+ def Sync_Palette_Legacy_State():
1202
+ return palette_runtime.sync_palette_legacy_state(globals(), palette_state)
1203
+
1204
+
1205
+ def Tk_ImgUpdate_Plte(event,nbr=None,bfn=None,afn=None,w=None,h=None):
1206
+ return palette_runtime.update_palette_value_from_namespace(globals(), event, nbr, bfn, afn, w, h)
1207
+
1208
+ # if DEBUG:
1209
+ # PRINT("PlteId : %s Value : %s Plte_Blst[PlteId]:%s bvalue: %s Lnx_New : %s"%(str(nbr),str(event),str(Plte_Blst[nbr]),str(bvalue),str(Lnx_New)))
1210
+
1211
+ def Tk_X11_Randomize_Plte(bfn=None,afn=None,w=None,h=None):
1212
+ return palette_runtime.apply_random_palette_colors_from_namespace(globals(), X11_Colors, bfn, afn, w, h)
1213
+
1214
+ def Tk_X11_Plte(bfn=None,afn=None,w=None,h=None):
1215
+ return palette_runtime.apply_palette_colors_from_namespace(globals(), X11_Colors, bfn, afn, w, h)
1216
+
1217
+
1218
+ def Tk_Web_Safe_Randomize_Plte(bfn=None,afn=None,w=None,h=None):
1219
+ return palette_runtime.apply_random_palette_colors_from_namespace(globals(), Web_Safe_Colors, bfn, afn, w, h)
1220
+
1221
+ def Tk_Web_Safe_Plte(bfn=None,afn=None,w=None,h=None):
1222
+ return palette_runtime.apply_palette_colors_from_namespace(globals(), Web_Safe_Colors, bfn, afn, w, h)
1223
+
1224
+
1225
+ def Tk_Randomize_Plte(bfn=None,afn=None,w=None,h=None):
1226
+ return palette_runtime.randomize_palette_from_namespace(globals(), bfn, afn, w, h)
1227
+
1228
+ def Tk_update_scrollregion_Plte(event):
1229
+ canvas = getattr(event, "widget", None)
1230
+ if canvas is None or not hasattr(canvas, "bbox"):
1231
+ canvas = globals().get("canvas_slider")
1232
+ if canvas is not None and hasattr(canvas, "bbox"):
1233
+ canvas.configure(scrollregion=canvas.bbox("all"))
1234
+
1235
+ def Tk_Save_Plte(Tkwin,Cancel,ChunkLength,DataOffset,FromError,wanabyte):
1236
+ return palette_runtime.save_manual_palette_from_namespace(
1237
+ globals(),
1238
+ Tkwin,
1239
+ Cancel,
1240
+ ChunkLength,
1241
+ DataOffset,
1242
+ FromError,
1243
+ wanabyte,
1244
+ )
1245
+
1246
+
1247
+ def Guess_Palettes_Nbr(bfn,afn):
1248
+ return palette_runtime.guess_palette_count_from_namespace(globals(), bfn, afn)
1249
+
1250
+
1251
+
1252
+ def Tk_Manual_Plte(
1253
+ File,
1254
+ ChunkName,
1255
+ ChunkLength,
1256
+ DataOffset,
1257
+ FromError,
1258
+ DataHex=None,
1259
+ ):
1260
+ PaletteEditor = palette_runtime.create_manual_palette_editor_from_namespace(
1261
+ globals(),
1262
+ File,
1263
+ ChunkName,
1264
+ ChunkLength,
1265
+ DataOffset,
1266
+ FromError,
1267
+ data_hex=DataHex,
1268
+ )
1269
+ PaletteEditor.window.mainloop()
1270
+
1271
+
1272
+ def SmashBruteBrawl(
1273
+ File,
1274
+ ChunkName,
1275
+ ChunkLength,
1276
+ DataOffset,
1277
+ FromError,
1278
+ EditMode="Replace",
1279
+ BfMode="Brutus",
1280
+ BruteCrc=True,
1281
+ BruteLength=True,
1282
+ OldCrc=False,
1283
+ BruteLevel=None,
1284
+ ):
1285
+ return smash_bruteforce.run_legacy_smash_brute_brawl_from_namespace(
1286
+ globals(),
1287
+ File,
1288
+ ChunkName,
1289
+ ChunkLength,
1290
+ DataOffset,
1291
+ FromError,
1292
+ EditMode,
1293
+ BfMode,
1294
+ BruteCrc,
1295
+ BruteLength,
1296
+ OldCrc,
1297
+ brute_level=BruteLevel,
1298
+ )
1299
+
1300
+
1301
+
1302
+
1303
+ def FullChunkForcerNoCrc(
1304
+ File, Chunk, DataOffset, ChunkLength, FromError
1305
+ ): ## need to be merged with SmashBruteBrawl
1306
+ return full_chunk_forcer.run_full_chunk_forcer_no_crc_from_namespace(
1307
+ globals(),
1308
+ File,
1309
+ Chunk,
1310
+ DataOffset,
1311
+ ChunkLength,
1312
+ FromError,
1313
+ )
1314
+
1315
+
1316
+
1317
+
1318
+ def Deferred_Linefeed_Signature_Repair(data_bytes, sample_name, linefeed_pattern):
1319
+ globals()["DEFERRED_LINEFEED_SIGNATURE_REPAIR"] = {
1320
+ "data_bytes": data_bytes,
1321
+ "sample_name": sample_name,
1322
+ "linefeed_pattern": linefeed_pattern,
1323
+ }
1324
+ return True
1325
+
1326
+
1327
+ def Clear_Deferred_FindMagic_Repair():
1328
+ globals()["DEFERRED_LINEFEED_SIGNATURE_REPAIR"] = None
1329
+
1330
+
1331
+ def Apply_Deferred_FindMagic_Repair():
1332
+ return magic_runtime.run_deferred_linefeed_signature_repair_from_namespace(globals())
1333
+
1334
+
1335
+ def Run_Ultimate_Linefeed_Direct_Resume():
1336
+ return magic_runtime.run_ultimate_linefeed_direct_resume_from_namespace(globals())
1337
+
1338
+
1339
+ def Run_Smash_Brute_Brawl_Direct_Resume():
1340
+ return smash_bruteforce.run_smash_brute_brawl_direct_resume_from_namespace(globals())
1341
+
1342
+
1343
+ def FindMagic():
1344
+ return magic_runtime.run_find_magic_from_namespace(globals())
1345
+
1346
+
1347
+ def FindFuckingMagic():
1348
+ return magic_runtime.run_find_fucking_magic_from_namespace(globals())
1349
+
1350
+
1351
+ def Ancillary(Chunk):
1352
+ global Bad_Ancillary
1353
+ Bad_Ancillary = ancillary_runtime.run_ancillary_check(
1354
+ ancillary_runtime.AncillaryRuntime(
1355
+ candy=Candy,
1356
+ emit=PRINT,
1357
+ betterror=Betterror,
1358
+ ),
1359
+ Chunk,
1360
+ )
1361
+
1362
+
1363
+ def NullFind(data, search4=None):
1364
+ return nearby.null_find(data, search4)
1365
+
1366
+
1367
+ def LibpngCheck(file):
1368
+ return libpng_runtime.run_libpng_check(
1369
+ libpng_runtime.LibpngCheckRuntime(
1370
+ candy=Candy,
1371
+ emit=PRINT,
1372
+ checkpoint=CheckPoint,
1373
+ ),
1374
+ libpng_runtime.LibpngCheckContext(
1375
+ sample_name=Sample_Name,
1376
+ libpng_errors=LIBPNG_ERR,
1377
+ cv2_module=cv2,
1378
+ image_module=Image,
1379
+ stderr_redirector=stderr_redirector,
1380
+ warning_reader=KnownBadSrgbProfileWarning,
1381
+ pending_errors=tuple(PandoraBox),
1382
+ ),
1383
+ file,
1384
+ )
1385
+
1386
+
1387
+ def KnownBadSrgbProfileWarning(file):
1388
+ return libpng_runtime.run_known_bad_srgb_profile_warning(file)
1389
+
1390
+
1391
+ def Double_Check(CType, ChunkLen, LastCType):
1392
+ return nearby_runtime.run_double_check_from_namespace(globals(), CType, ChunkLen, LastCType)
1393
+
1394
+
1395
+ def RandomSample(data,colortype,chunk_format):
1396
+ return specs.random_sample_hex(data, colortype, chunk_format, random.random)
1397
+
1398
+
1399
+ def DummyChunk_Runtime():
1400
+ return dummy_chunk_runtime.DummyChunkRuntime(
1401
+ data_hex=DATAX,
1402
+ side_notes=SideNotes,
1403
+ candy=Candy,
1404
+ emit=PRINT,
1405
+ checkpoint=CheckPoint,
1406
+ end=TheEnd,
1407
+ pause=Pause,
1408
+ get_spec=GetSpec,
1409
+ spec_length=SpecLength,
1410
+ random_sample=RandomSample,
1411
+ repair_note=fixit_felix.repair_note,
1412
+ debug=DEBUG,
1413
+ pause_debug=PAUSEDEBUG,
1414
+ question=Question,
1415
+ file_origin=FILE_Origin,
1416
+ write_clone=WriteClone,
1417
+ )
1418
+
1419
+
1420
+ def DummyChunk(Chunkname, bad_pos, bad_start, bad_end, FromError): ##TODO bad_pos is not used well enough
1421
+ return dummy_chunk_runtime.run_dummy_chunk(
1422
+ DummyChunk_Runtime(),
1423
+ Chunkname,
1424
+ bad_pos,
1425
+ bad_start,
1426
+ bad_end,
1427
+ FromError,
1428
+ )
1429
+
1430
+
1431
+ def Remove_Extra_Bytes_Before_Chunk(CType, LastCType, Excluded):
1432
+ return nearby_runtime.run_remove_extra_bytes_before_chunk_from_namespace(
1433
+ globals(),
1434
+ CType,
1435
+ LastCType,
1436
+ Excluded,
1437
+ )
1438
+
1439
+
1440
+ def NearbyChunk(CType, ChunkLen, LastCType, DoubleCheck, FromError=None):
1441
+ return nearby_runtime.run_nearby_chunk_from_namespace(
1442
+ globals(),
1443
+ CType,
1444
+ ChunkLen,
1445
+ LastCType,
1446
+ DoubleCheck,
1447
+ FromError,
1448
+ )
1449
+
1450
+
1451
+ def TheGoodPlace(Missplaced_Chunkname, Missplaced_Chunkpos, ToFix_Chunkname):
1452
+ return chunk_order_runtime.run_the_good_place_from_namespace(
1453
+ globals(),
1454
+ Missplaced_Chunkname,
1455
+ Missplaced_Chunkpos,
1456
+ ToFix_Chunkname,
1457
+ )
1458
+
1459
+
1460
+ def CheckChunkOrder(lastchunk, mode):
1461
+ return chunk_order_runtime.run_check_chunk_order_from_namespace(globals(), lastchunk, mode)
1462
+
1463
+
1464
+
1465
+ def NameShift():
1466
+ return name_shift_runtime.run_name_shift_from_namespace(globals())
1467
+
1468
+
1469
+ def BruteChunk_Crc_Matches(candidates):
1470
+ try:
1471
+ # Add validation to check if Raw_Data and Raw_Crc are not empty
1472
+ if not Raw_Data or Raw_Data.strip() == '':
1473
+ return []
1474
+ if not Raw_Crc or Raw_Crc.strip() == '':
1475
+ return []
1476
+
1477
+ chunk_data = bytes.fromhex(Raw_Data)
1478
+ stored_crc = int(Raw_Crc, 16)
1479
+ except Exception as e:
1480
+ Betterror(e, inspect.stack()[0][3])
1481
+ return []
1482
+
1483
+ return chunk_type_crc_matches(chunk_data, stored_crc, candidates)
1484
+
1485
+
1486
+ def BruteChunk_Save_Auto_Name(CType, FromError, ChunkName, reason):
1487
+ return chunk_name_runtime.save_auto_name_from_namespace(
1488
+ globals(),
1489
+ CType,
1490
+ FromError,
1491
+ ChunkName,
1492
+ reason,
1493
+ )
1494
+
1495
+
1496
+ def ChunkName_Runtime():
1497
+ return chunk_name_runtime.build_chunk_name_runtime_from_namespace(globals())
1498
+
1499
+
1500
+ def ChunkName_Context():
1501
+ return chunk_name_runtime.build_chunk_name_context_from_namespace(globals())
1502
+
1503
+
1504
+ def BruteChunk(CType, LastCType, ChunkLen, FromError):
1505
+ return chunk_name_runtime.run_brute_chunk_from_namespace(
1506
+ globals(),
1507
+ CType,
1508
+ LastCType,
1509
+ ChunkLen,
1510
+ FromError,
1511
+ )
1512
+
1513
+
1514
+ def CheckChunkName(ChunkType, ChunkLen, LastCType, Next=None):
1515
+ return chunk_name_runtime.run_check_chunk_name_from_namespace(
1516
+ globals(),
1517
+ ChunkType,
1518
+ ChunkLen,
1519
+ LastCType,
1520
+ Next,
1521
+ )
1522
+
1523
+
1524
+ def SpecLength(chunk_name, chunk_length=None):
1525
+ return spec_length_runtime.run_spec_length(
1526
+ spec_length_runtime.SpecLengthRuntime(
1527
+ candy=Candy,
1528
+ emit=PRINT,
1529
+ end=TheEnd,
1530
+ get_spec=GetSpec,
1531
+ side_notes=SideNotes,
1532
+ ),
1533
+ chunk_name,
1534
+ chunk_length,
1535
+ )
1536
+
1537
+
1538
+ def CheckLength(Cdata, Clen, Ctype):
1539
+ return chunk_validation_runtime.run_check_length_from_namespace(
1540
+ globals(),
1541
+ Cdata,
1542
+ Clen,
1543
+ Ctype,
1544
+ )
1545
+
1546
+
1547
+
1548
+
1549
+ def Question(
1550
+ id=None,
1551
+ idhash=None,
1552
+ skipauto=False,
1553
+ timeout_seconds=None,
1554
+ timeout_default=None,
1555
+ ):
1556
+ globals()["LAST_QUESTION_STATUS"] = None
1557
+
1558
+ def asker(prompt):
1559
+ if timeout_seconds is None:
1560
+ return Transcript_Input(prompt)
1561
+ try:
1562
+ answer = inputimeout(prompt, timeout=timeout_seconds)
1563
+ Record_Terminal_Transcript("%s%s" % (prompt, answer))
1564
+ return answer
1565
+ except TimeoutOccurred:
1566
+ default_answer = "yes" if timeout_default is True else "no"
1567
+ Record_Terminal_Transcript(
1568
+ "%s%s [timeout after %s seconds]"
1569
+ % (prompt, default_answer, timeout_seconds)
1570
+ )
1571
+ PRINT("")
1572
+ PRINT(
1573
+ "-Question timed out after %s seconds; auto-answering %s.\n"
1574
+ % (timeout_seconds, default_answer)
1575
+ )
1576
+ return default_answer
1577
+
1578
+ runtime = question_runtime.QuestionRuntime(
1579
+ history=IFOP,
1580
+ nodialogue=NODIALOGUE,
1581
+ auto=AUTO,
1582
+ clear=CLEAR_SCREEN_ACTIVE_THIS_PASS,
1583
+ debug=DEBUG,
1584
+ pause_debug=PAUSEDEBUG,
1585
+ offset=CLoffI,
1586
+ asker=asker,
1587
+ candy=Candy,
1588
+ emit=PRINT,
1589
+ pause=Pause,
1590
+ end=TheEnd,
1591
+ prompt_candy=Prompt_Candy,
1592
+ status_sink=lambda status: globals().__setitem__("LAST_QUESTION_STATUS", status),
1593
+ )
1594
+ try:
1595
+ return question_runtime.ask_question(runtime, id, idhash, skipauto=skipauto)
1596
+ finally:
1597
+ Clear_Terminal_Dialogue_Pause()
1598
+ Close_Preview_Image()
1599
+
1600
+
1601
+ def Checksum(Ctype, Cdata, Crc, next=None):
1602
+ return chunk_validation_runtime.run_checksum_from_namespace(
1603
+ globals(),
1604
+ Ctype,
1605
+ Cdata,
1606
+ Crc,
1607
+ next,
1608
+ )
1609
+
1610
+
1611
+ def RemoveChunk(start,length,infos):
1612
+ return writer_runtime.run_remove_chunk(
1613
+ writer_runtime.ClonePatchRuntime(
1614
+ data_hex=DATAX,
1615
+ candy=Candy,
1616
+ emit=PRINT,
1617
+ betterror=Betterror,
1618
+ write_clone=WriteClone,
1619
+ set_show_must_go_on=lambda value: globals().__setitem__("Show_Must_Go_On", value),
1620
+ ),
1621
+ start,
1622
+ length,
1623
+ infos,
1624
+ )
1625
+
1626
+ def SaveClone(DataFix, start, end, infos):
1627
+ return writer_runtime.run_save_clone(
1628
+ writer_runtime.ClonePatchRuntime(
1629
+ data_hex=DATAX,
1630
+ candy=Candy,
1631
+ emit=PRINT,
1632
+ betterror=Betterror,
1633
+ write_clone=WriteClone,
1634
+ set_show_must_go_on=lambda value: globals().__setitem__("Show_Must_Go_On", value),
1635
+ save_debug_payloads=lambda label, start, end, payloads: writer_runtime.save_clone_debug_payloads(
1636
+ FILE_Origin,
1637
+ FILE_DIR,
1638
+ label,
1639
+ start,
1640
+ end,
1641
+ payloads,
1642
+ ),
1643
+ side_notes=SideNotes,
1644
+ ),
1645
+ DataFix,
1646
+ start,
1647
+ end,
1648
+ infos,
1649
+ )
1650
+
1651
+
1652
+ def WriteClone(data,infos):
1653
+ return writer_runtime.run_write_clone_from_namespace(globals(), data, infos)
1654
+
1655
+
1656
+ def Relics_Runtime():
1657
+ return relics_runtime.build_relics_runtime_from_namespace(globals())
1658
+
1659
+
1660
+ def Relics_Context(FromError):
1661
+ return relics_runtime.build_relics_context_from_namespace(globals(), FromError)
1662
+
1663
+
1664
+ def Relics(FromError):
1665
+ return relics_runtime.handle_relics_from_namespace(globals(), FromError)
1666
+
1667
+
1668
+ def Naming(filename):
1669
+
1670
+ target = output.next_clone_target(filename, FILE_DIR)
1671
+ return (target.name, target.directory)
1672
+
1673
+ def LockDown():
1674
+ Candy("Title", "LockDown: ", Candy("Color", "white", Chunk))
1675
+
1676
+ for folder in output.lockdown_folder_lines(FILE_Origin, FILE_DIR):
1677
+ PRINT(folder)
1678
+
1679
+
1680
+ def FixItFelix_Set_Skip_Bad_Crc(value):
1681
+ global Skip_Bad_Crc
1682
+
1683
+ Skip_Bad_Crc = value
1684
+
1685
+
1686
+ def FixItFelix_Set_Old_Bad_Crc(value):
1687
+ global Old_Bad_Crc
1688
+
1689
+ Old_Bad_Crc = value
1690
+
1691
+
1692
+ def FixItFelix_Wrong_Crc_Runtime():
1693
+ return fixit_felix_runtime.build_wrong_crc_runtime_from_namespace(globals())
1694
+
1695
+
1696
+ def FixItFelix_Wrong_Crc(key, chkd, PandoraBox_len):
1697
+ CrcDecision = fixit_felix.wrong_crc_decision(
1698
+ key,
1699
+ solved=str(key) in Cornucopia,
1700
+ pandora_box_len=PandoraBox_len,
1701
+ )
1702
+
1703
+ CrcTools = None
1704
+ if CrcDecision.action != "already_in_cornucopia":
1705
+ try:
1706
+ chkd = relics.resolve_tool_prefix(PandoraBox[key], chkd)
1707
+ CrcTools = relics.wrong_crc_tools(PandoraBox[key], chkd)
1708
+ except KeyError:
1709
+ Candy(
1710
+ "Cowsay",
1711
+ "CRC repair data is missing for this malformed chunk. I will leave it to the chunk-name/length repair path.",
1712
+ "com",
1713
+ )
1714
+ FixItFelix_Set_Skip_Bad_Crc(True)
1715
+ return False, None
1716
+
1717
+ success, result = fixit_felix_runtime.apply_wrong_crc(
1718
+ FixItFelix_Wrong_Crc_Runtime(),
1719
+ CrcDecision,
1720
+ chkd,
1721
+ CrcTools,
1722
+ )
1723
+
1724
+ return success, result
1725
+
1726
+
1727
+ def FixItFelix_Set_Skip_Bad_Libpng(value):
1728
+ global Skip_Bad_Libpng
1729
+
1730
+ Skip_Bad_Libpng = value
1731
+
1732
+
1733
+ def FixItFelix_Libpng_Error_Runtime():
1734
+ return fixit_felix_runtime.build_libpng_error_runtime_from_namespace(globals())
1735
+
1736
+
1737
+ def FixItFelix_Libpng_Error(key, chkd):
1738
+ return fixit_felix_runtime.apply_libpng_error(
1739
+ FixItFelix_Libpng_Error_Runtime(),
1740
+ fixit_felix.libpng_error_decision(
1741
+ key,
1742
+ solved=str(key) in Cornucopia,
1743
+ skip_bad_libpng=Skip_Bad_Libpng,
1744
+ ),
1745
+ chkd,
1746
+ )
1747
+
1748
+
1749
+ def FixItFelix_Set_Skip_Bad_Next_Name(value):
1750
+ global Skip_Bad_Next_Name
1751
+
1752
+ Skip_Bad_Next_Name = value
1753
+
1754
+
1755
+ def FixItFelix_Set_Skip_Bad_Current_Name(value):
1756
+ global Skip_Bad_Current_Name
1757
+
1758
+ Skip_Bad_Current_Name = value
1759
+
1760
+
1761
+ def FixItFelix_Wrong_Chunk_Name_Runtime():
1762
+ return fixit_felix_runtime.build_wrong_chunk_name_runtime_from_namespace(globals())
1763
+
1764
+
1765
+ def FixItFelix_Wrong_Chunk_Name(key, chkd):
1766
+ if Skip_Bad_Current_Name is False:
1767
+ NameDecision = fixit_felix.wrong_chunk_name_decision(
1768
+ key,
1769
+ solved=str(key) in Cornucopia,
1770
+ bad_crc=Bad_Crc,
1771
+ )
1772
+
1773
+ NameTools = None
1774
+ name_chkd = chkd
1775
+ if NameDecision.action != "save_existing_solution":
1776
+ name_chkd = relics.resolve_tool_prefix(PandoraBox[key], chkd)
1777
+ NameTools = relics.wrong_chunk_name_tools(PandoraBox[key], name_chkd)
1778
+
1779
+ return fixit_felix_runtime.apply_wrong_chunk_name(
1780
+ FixItFelix_Wrong_Chunk_Name_Runtime(),
1781
+ NameDecision,
1782
+ name_chkd,
1783
+ NameTools,
1784
+ )
1785
+
1786
+ return False, None
1787
+
1788
+
1789
+ def FixItFelix_Set_Skip_Bad_No_Next_Chunk(value):
1790
+ global Skip_Bad_No_Next_Chunk
1791
+
1792
+ Skip_Bad_No_Next_Chunk = value
1793
+
1794
+
1795
+ def FixItFelix_Set_EOF(value):
1796
+ global EOF
1797
+
1798
+ EOF = value
1799
+
1800
+
1801
+ def FixItFelix_No_NextChunk_Runtime():
1802
+ return fixit_felix_runtime.build_no_next_chunk_runtime_from_namespace(globals())
1803
+
1804
+
1805
+ def FixItFelix_No_NextChunk_Decision_Chunk(Chunk, chkd, no_next_chkd, tools):
1806
+ if Chunk in (None, b"", ""):
1807
+ return tools.chunk_type
1808
+ if no_next_chkd != chkd:
1809
+ return tools.chunk_type
1810
+ return Chunk
1811
+
1812
+
1813
+ def FixItFelix_No_NextChunk(key, chkd, Chunk):
1814
+ global Skip_Bad_No_Next_Chunk
1815
+
1816
+ if Skip_Bad_No_Next_Chunk is False:
1817
+ no_next_chkd = relics.resolve_tool_prefix(PandoraBox[key], chkd)
1818
+ NoNextTools = relics.no_next_chunk_tools(PandoraBox[key], no_next_chkd)
1819
+ decision_chunk = FixItFelix_No_NextChunk_Decision_Chunk(
1820
+ Chunk,
1821
+ chkd,
1822
+ no_next_chkd,
1823
+ NoNextTools,
1824
+ )
1825
+ NoNextDecision = fixit_felix.no_next_chunk_decision(
1826
+ current_chunk=decision_chunk,
1827
+ chunk_type=NoNextTools.chunk_type,
1828
+ chunk_length=NoNextTools.chunk_length,
1829
+ bad_critical=Bad_Critical,
1830
+ )
1831
+ return fixit_felix_runtime.apply_no_next_chunk(
1832
+ FixItFelix_No_NextChunk_Runtime(),
1833
+ NoNextDecision,
1834
+ key,
1835
+ no_next_chkd,
1836
+ NoNextTools,
1837
+ )
1838
+
1839
+ return False, None
1840
+
1841
+
1842
+ def FixItFelix_Gama_Zero_Runtime():
1843
+ return fixit_felix_runtime.build_gama_zero_runtime_from_namespace(globals())
1844
+
1845
+
1846
+ def FixItFelix_Gama_Zero(key):
1847
+ return fixit_felix_runtime.apply_gama_zero(
1848
+ FixItFelix_Gama_Zero_Runtime(),
1849
+ fixit_felix.gama_zero_decision(key),
1850
+ )
1851
+
1852
+
1853
+ def FixItFelix_Critical_Miss_Runtime():
1854
+ return fixit_felix_runtime.build_critical_miss_runtime_from_namespace(globals())
1855
+
1856
+
1857
+ def FixItFelix_Critical_Miss(key):
1858
+ return fixit_felix_runtime.apply_critical_miss(
1859
+ FixItFelix_Critical_Miss_Runtime(),
1860
+ fixit_felix.critical_miss_decision(
1861
+ key,
1862
+ debug=DEBUG,
1863
+ pause_debug=PAUSEDEBUG,
1864
+ ),
1865
+ )
1866
+
1867
+
1868
+ def FixItFelix_Automatic_Repair_Runtime():
1869
+ return fixit_felix_runtime.build_automatic_repair_runtime_from_namespace(globals())
1870
+
1871
+
1872
+ def FixItFelix_Apply_Repair(repair):
1873
+ return fixit_felix_runtime.apply_repair(
1874
+ FixItFelix_Automatic_Repair_Runtime(),
1875
+ repair,
1876
+ )
1877
+
1878
+
1879
+ def FixItFelix_Try_Automatic_Repair(name):
1880
+ global Bad_Libpng
1881
+
1882
+ repair_intent = fixit_felix.automatic_repair_intent(name, PandoraBox)
1883
+ repair = fixit_felix.automatic_repair(
1884
+ name,
1885
+ DATA_BYTES,
1886
+ PandoraBox,
1887
+ known_chunk_types=ALLCHUNKS,
1888
+ auto=AUTO,
1889
+ nodialogue=NODIALOGUE,
1890
+ max_saves=MAX_SAVES,
1891
+ )
1892
+ if repair is None:
1893
+ failure_explanation = fixit_felix.automatic_repair_failure_explanation(
1894
+ name,
1895
+ PandoraBox,
1896
+ )
1897
+ if failure_explanation is not None:
1898
+ Candy("Cowsay", failure_explanation, "bad")
1899
+ SideNotes.append("-FixItFelix:%s." % failure_explanation)
1900
+ return None
1901
+
1902
+ if repair_intent is not None:
1903
+ Candy("Cowsay", repair_intent, "com")
1904
+
1905
+ if name == "hist_out_of_place_cleanup":
1906
+ if NODIALOGUE:
1907
+ for key in list(PandoraBox):
1908
+ key_text = str(key)
1909
+ if "hIST: out of place" in key_text or "hIST chunk must appear before" in key_text:
1910
+ relics.discard_pandora_error(PandoraBox, key)
1911
+ SideNotes.append(
1912
+ "-Keeping optional hIST chunk(s): non-interactive mode cannot confirm metadata removal."
1913
+ )
1914
+ Bad_Libpng = False
1915
+ return True
1916
+ if not AUTO and not Question(
1917
+ id="hIST Optional Metadata Removal:-Remove hIST chunk(s) to silence libpng?"
1918
+ ):
1919
+ for key in list(PandoraBox):
1920
+ key_text = str(key)
1921
+ if "hIST: out of place" in key_text or "hIST chunk must appear before" in key_text:
1922
+ relics.discard_pandora_error(PandoraBox, key)
1923
+ SideNotes.append("-Keeping optional hIST chunk(s) as requested.")
1924
+ PRINT("-Keeping hIST chunk(s) as requested.")
1925
+ Bad_Libpng = False
1926
+ return True
1927
+
1928
+ if name == "ihdr_rebuild":
1929
+ crc_bruteforce_result = fixit_felix_runtime.try_ihdr_stored_crc_bruteforce(
1930
+ FixItFelix_Automatic_Repair_Runtime(),
1931
+ repair,
1932
+ )
1933
+ if crc_bruteforce_result is not None:
1934
+ return crc_bruteforce_result
1935
+
1936
+ return FixItFelix_Apply_Repair(repair)
1937
+
1938
+
1939
+ def FixItFelix_Runtime_Callbacks():
1940
+ return fixit_felix_runtime.build_legacy_fixit_felix_handlers_from_namespace(globals())
1941
+
1942
+
1943
+ def FixItFelix_Runtime():
1944
+ return fixit_felix_runtime.build_fixit_felix_runtime_from_namespace(globals())
1945
+
1946
+
1947
+ def FixItFelix_Tool_Prefix(Chunk):
1948
+ if isinstance(Chunk, str):
1949
+ return Chunk + "_Tool_"
1950
+ try:
1951
+ return Chunk.decode(errors="ignore") + "_Tool_"
1952
+ except AttributeError as e:
1953
+ Betterror(e, "FixItFelix")
1954
+ return fixit_felix.tool_prefix_for_chunk(Chunk)
1955
+
1956
+
1957
+ def FixItFelix(Chunk=None):
1958
+ Candy("Title", "Fix It Felix: ", Candy("Color", "white", Chunk))
1959
+ ##TODOFIND A WAY TO MAKE IT READABLE
1960
+
1961
+ global Show_Must_Go_On
1962
+
1963
+ chkd = FixItFelix_Tool_Prefix(Chunk)
1964
+ RunResult = fixit_felix_runtime.run_fixit_felix_pipeline_from_namespace(
1965
+ globals(),
1966
+ Chunk,
1967
+ chkd,
1968
+ )
1969
+ if RunResult.should_return:
1970
+ return RunResult.result
1971
+
1972
+ Show_Must_Go_On = True
1973
+
1974
+ def CheckPoint(error, fixed, function, chunk, infos, *ToolKit):
1975
+ if DEBUGFILE is True:
1976
+ DebugNotes.extend(
1977
+ checkpoint_runtime.checkpoint_debug_lines(
1978
+ error=error,
1979
+ fixed=fixed,
1980
+ function=function,
1981
+ infos=infos,
1982
+ chunk=chunk,
1983
+ toolkit=ToolKit,
1984
+ pandora_keys=tuple(PandoraBox),
1985
+ )
1986
+ )
1987
+ return checkpoint_runtime.run_checkpoint_from_namespace(
1988
+ globals(),
1989
+ error=error,
1990
+ fixed=fixed,
1991
+ function=function,
1992
+ chunk=chunk,
1993
+ infos=infos,
1994
+ toolkit=ToolKit,
1995
+ )
1996
+
1997
+
1998
+ def Pause(msg):
1999
+ prompts.pause_with_legacy_eof_report(
2000
+ Transcript_Input,
2001
+ msg,
2002
+ error_emit=print,
2003
+ stderr_redirector=stderr_redirector,
2004
+ stream_factory=io.BytesIO,
2005
+ )
2006
+ return ()
2007
+
2008
+ def PRINT(msg):
2009
+ Finish_Progress_Line()
2010
+ if DEBUGFILE is True:
2011
+ DebugNotes.append(msg)
2012
+ output.append_terminal_transcript(globals(), msg)
2013
+ ui.emit_printable_message(print, msg, max_columns=MAXCHAR, no_dialogue=NODIALOGUE)
2014
+
2015
+ # else:
2016
+ # print("-not print-")
2017
+ # print(msg)
2018
+
2019
+
2020
+ def DebugPrint(*args, **kwargs):
2021
+ if DEBUGFILE is True:
2022
+ DebugNotes.append(" ".join(str(arg) for arg in args))
2023
+ print(*args, **kwargs)
2024
+
2025
+ def main():
2026
+ parser = cli.configure_parser(ArgumentParser())
2027
+ Args, unknown = parser.parse_known_args()
2028
+ MainOptions = main_runtime.apply_main_cli_options_from_namespace(
2029
+ globals(),
2030
+ Args,
2031
+ unknown,
2032
+ argv_len=len(sys.argv),
2033
+ parser=parser,
2034
+ )
2035
+ if MainOptions is None:
2036
+ return
2037
+ Ensure_Runtime_Dependencies()
2038
+ Configure_Terminal_Color()
2039
+ if Should_Run_Package_Update_Check(Args):
2040
+ Ensure_Package_Current_Or_Continue()
2041
+
2042
+ while True:
2043
+ MainLoopState = main_runtime.run_main_loop_once_from_namespace(globals())
2044
+ if MainLoopState.should_return:
2045
+ return
2046
+
2047
+
2048
+ ###
2049
+
2050
+
2051
+ ###
2052
+
2053
+ MINIMAL_CHUNKS = list(specs.MINIMAL_CHUNKS)
2054
+ CRITICAL_CHUNKS = list(specs.CRITICAL_CHUNKS)
2055
+ CHUNKS = list(specs.CHUNKS)
2056
+ PRIVATE_CHUNKS = list(specs.PRIVATE_CHUNKS)
2057
+ BEFORE_PLTE = list(specs.BEFORE_PLTE)
2058
+ AFTER_PLTE = list(specs.AFTER_PLTE)
2059
+ BEFORE_IDAT = list(specs.BEFORE_IDAT)
2060
+ BEFORE_IDAT2 = list(specs.BEFORE_IDAT2)
2061
+ UNIQUE_CHUNK = list(specs.UNIQUE_CHUNK)
2062
+ NO_ORDER_CHUNKS = list(specs.NO_ORDER_CHUNKS)
2063
+ CHUNKS_LEN_NOT_FIXED = list(specs.CHUNKS_LEN_NOT_FIXED)
2064
+ ALLCHUNKS = list(specs.ALLCHUNKS)
2065
+ LIBPNG_ERR = list(specs.LIBPNG_ERR)
2066
+
2067
+
2068
+
2069
+ IFOP = []
2070
+ Chunks_History = []
2071
+ IDAT_Bytes_Len_History = []
2072
+ Chunks_History_Index = []
2073
+ pCAL_Param = []
2074
+ PLTE_R = []
2075
+ PLTE_G = []
2076
+ PLTE_B = []
2077
+ Plte_Blst = []
2078
+ palette_state = None
2079
+ slider_list = []
2080
+ wanabyte = b""
2081
+ sPLT_Name = []
2082
+ sPLT_Depht = []
2083
+ sPLT_Red = []
2084
+ sPLT_Green = []
2085
+ sPLT_Blue = []
2086
+ sPLT_Alpha = []
2087
+ sPLT_Freq = []
2088
+ hIST = []
2089
+ tEXt_Key_List = []
2090
+ tEXt_Str_List = []
2091
+ iTXt_String_List = []
2092
+ iTXt_Key_List = []
2093
+ tRNS_Index = []
2094
+ zTXt_Key_List = []
2095
+ zTXt_Str_List = []
2096
+ ThksForTheFish = []
2097
+ SideNotes = []
2098
+ DebugNotes = []
2099
+ TerminalTranscript = []
2100
+ ERRORSFLAG = []
2101
+
2102
+ PandoraBox = {}
2103
+ Cornucopia = {}
2104
+ IDAT_CRC_PATCH_FAILED = False
2105
+ IDAT_CRC_PATCH_FAILED_FINDING = None
2106
+ IDAT_CRC_DEFER_EXPLAINED = False
2107
+ IDAT_CRC_DEFERRED_FINDINGS = set()
2108
+ IDAT_CRC_DEFERRED_ROUTES = set()
2109
+ IDAT_DEFLATE_PROBE_KEYS = set()
2110
+ WRONG_CHUNK_NAME_TRIED_ROUTES = set()
2111
+ REPAIR_ROUTE_STATES = {}
2112
+ NEARBY_FOUND_LATER_IEND = None
2113
+ FOG_OF_WAR_BAD_CHUNKS = set()
2114
+ FOG_OF_WAR_LAST_MAP = None
2115
+ FOG_OF_WAR_LAST_WIDTH = None
2116
+ FOG_OF_WAR_LAST_RENDER_KEY = None
2117
+ FOG_OF_WAR_PREVIEW_CHUNK = None
2118
+ FOG_OF_WAR_PREVIEW_ERROR = False
2119
+ ArkOfCovenant = {}
2120
+ Pandemonium = {}
2121
+ CHUNK_INFO_STATE = chunk_state.ChunkInfoState()
2122
+
2123
+
2124
+ MAXCHAR = shutil.get_terminal_size(fallback=(120, 24)).columns - 1
2125
+ # TMPFIX = False
2126
+
2127
+ FirStart = True
2128
+ Switch = False
2129
+ GoBack = False
2130
+ CharPos = 1
2131
+ Loading_sep = ""
2132
+ PROGRESS_LINE_ACTIVE = False
2133
+ Have_A_KitKat = False
2134
+ TmpFixIHDR = False
2135
+ Warning = False
2136
+ Summary_Header = True
2137
+ Bad_Current_Name = False
2138
+ Bad_Ancillary = False
2139
+ Bad_No_Next_Chunk = False
2140
+ Bad_Next_Name = False
2141
+ Bad_Next_Ancillary = False
2142
+ Bad_Length = False
2143
+ Bad_Infos = False
2144
+ Bad_Crc = False
2145
+ Bad_Critical = False
2146
+ Bad_Missplaced = False
2147
+ Bad_Libpng = False
2148
+ Skip_Bad_Current_Name = False
2149
+ Skip_Bad_Ancillary = False
2150
+ Skip_Bad_No_Next_Chunk = False
2151
+ Skip_Bad_Next_Name = False
2152
+ Skip_Bad_Next_Ancillary = False
2153
+ Skip_Bad_Length = False
2154
+ Skip_Bad_Infos = False
2155
+ Skip_Bad_Crc = False
2156
+ Skip_Bad_Critical = False
2157
+ Skip_Bad_Missplaced = False
2158
+ Skip_Bad_Libpng = False
2159
+ EOF = False
2160
+ Show_Must_Go_On = False
2161
+ CLEAR = False
2162
+ CLEAR_SCREEN_ACTIVE_THIS_PASS = False
2163
+ LAST_QUESTION_STATUS = None
2164
+ FINAL_IMAGE_OPEN_REQUESTED = False
2165
+ CRASH = False
2166
+ PAUSE = False
2167
+ DEBUG = False
2168
+ DEBUGFILE = False
2169
+ PAUSEDEBUG = False
2170
+ PAUSEERROR = False
2171
+ PAUSEDIALOGUE = False
2172
+ DIALOGUE_PAUSE_STATE = ui_runtime.LegacyDialoguePauseState()
2173
+ NODIALOGUE = False
2174
+ AUTO = False
2175
+ COLOR_MODE = "auto"
2176
+ USE_COLOR = os.name != "nt"
2177
+ CLONESWAR = False
2178
+ MAX_SAVES = None
2179
+ SAVE_COUNT = 0
2180
+ ULTIMATE_LINEFEED_PREVIEW_TIMEOUT = 5.0
2181
+ ULTIMATE_LINEFEED_SHOW_PREVIEWS = False
2182
+ ULTIMATE_LINEFEED_REFERENCE_MODE = "exact"
2183
+ ULTIMATE_LINEFEED_REFERENCE_REGIONS = ""
2184
+ ULTIMATE_LINEFEED_REFERENCE_REGION_EDITOR = False
2185
+ ULTIMATE_LINEFEED_VISUAL_GALLERY_LIMIT = 100
2186
+ ULTIMATE_LINEFEED_VISUAL_MIN_COVERAGE = 0.95
2187
+ ULTIMATE_LINEFEED_RESUME = "ask"
2188
+ ULTIMATE_LINEFEED_LIVE_PREVIEW_FOLDER_REPORTED = ""
2189
+ SMASH_BRUTE_BRAWL_RESUME = "ask"
2190
+ SMASH_BRUTE_BRAWL_WORKERS = None
2191
+
2192
+ FishPos = 0
2193
+ LenFishList = 0
2194
+ Brute_LvL = 0
2195
+ IBN = 0
2196
+ IDAT_Bytes_Len = 0
2197
+ IDAT_Datastream = ""
2198
+ idatcounter = 0
2199
+ ETA = 0
2200
+ Old_Bad_Crc = ""
2201
+ IDAT_Avg_Len = ""
2202
+ FILE_Origin = ""
2203
+ FILE_DIR = ""
2204
+ Loading_txt = ""
2205
+ DIFF = ""
2206
+ DATAX = ""
2207
+ DATA_BYTES = b""
2208
+ Sample_Name = ""
2209
+ Sample = ""
2210
+
2211
+ Raw_Length = ""
2212
+ Raw_Data = ""
2213
+ Raw_Crc = ""
2214
+ Raw_NextChunk = ""
2215
+ Raw_Type = ""
2216
+ Orig_CL = ""
2217
+ Orig_CT = ""
2218
+ Orig_NC = ""
2219
+ Orig_CD = ""
2220
+ Orig_CRC = ""
2221
+ CLoffX = ""
2222
+ CLoffB = ""
2223
+ CLoffI = ""
2224
+ CToffX = ""
2225
+ CToffB = ""
2226
+ CToffI = ""
2227
+ NCoffX = ""
2228
+ NCoffB = ""
2229
+ NCoffI = ""
2230
+ NCoff_CRC = ""
2231
+ Bad_Ancillary = ""
2232
+ CDoffX = ""
2233
+ CDoffB = ""
2234
+ CDoffI = ""
2235
+ CrcoffX = ""
2236
+ CrcoffB = ""
2237
+ CrcoffI = ""
2238
+ iCCP_Name = ""
2239
+ iCCP_Method = ""
2240
+ iCCP_Profile = ""
2241
+ IHDR_Height = 0
2242
+ IHDR_Width = 0
2243
+ IHDR_Depht = ""
2244
+ IHDR_Color = ""
2245
+ IHDR_Method = ""
2246
+ IHDR_Filter = ""
2247
+ IHDR_Interlace = ""
2248
+ bKGD_Gray = ""
2249
+ bKGD_Red = ""
2250
+ bKGD_Green = ""
2251
+ bKGD_Blue = ""
2252
+ bKGD_Index = ""
2253
+ sRGB = ""
2254
+
2255
+ pCAL_Key = ""
2256
+ pCAL_Zero = ""
2257
+ pCAL_Max = ""
2258
+ pCAL_Eq = ""
2259
+ pCAL_PNBR = ""
2260
+
2261
+ cHRM_WhiteX = ""
2262
+ cHRM_WhiteY = ""
2263
+ cHRM_Redx = ""
2264
+ cHRM_Redy = ""
2265
+ cHRM_Greenx = ""
2266
+ cHRM_Greeny = ""
2267
+ cHRM_Bluex = ""
2268
+ cHRM_Bluey = ""
2269
+
2270
+ gAMA = ""
2271
+
2272
+ pHYs_Y = ""
2273
+ pHYs_X = ""
2274
+ pHYs_Unit = ""
2275
+ sTER = ""
2276
+ gIFID = ""
2277
+ gIFCD = ""
2278
+ gIFDT = ""
2279
+ gIFgM = ""
2280
+ gIFgU = ""
2281
+ gIFgT = ""
2282
+
2283
+ sBIT_Gray = ""
2284
+ sBIT_TrueR = ""
2285
+ sBIT_TrueG = ""
2286
+ sBIT_TrueB = ""
2287
+ sBIT_GrayScale = ""
2288
+ sBIT_GrayAlpha = ""
2289
+ sBIT_TrueAlphaR = ""
2290
+ sBIT_TrueAlphaG = ""
2291
+ sBIT_TrueAlphaB = ""
2292
+ sBIT_TrueAlpha = ""
2293
+
2294
+ tEXt_Key = ""
2295
+ tEXt_Text = ""
2296
+
2297
+ iTXt_String = ""
2298
+ iTXt_Key = ""
2299
+ tIME_Yr = ""
2300
+ tIME_Mth = ""
2301
+ tIME_Day = ""
2302
+ tIME_Hr = ""
2303
+ tIME_Min = ""
2304
+ tIME_Sec = ""
2305
+ tRNS_Gray = ""
2306
+ tRNS_TrueR = ""
2307
+ tRNS_TrueG = ""
2308
+ tRNS_TrueB = ""
2309
+
2310
+ zTXt_Key = ""
2311
+ zTXt_Meth = ""
2312
+ zTXt_Text = ""
2313
+ eXIf_endian = ""
2314
+
2315
+ Web_Safe_Colors =['000000', '000033', '000066', '000099', '0000cc', '0000ff', '003300', '003333', '003366', '003399', '0033cc', '0033ff', '006600', '006633', '006666', '006699', '0066cc', '0066ff', '009900', '009933', '009966', '009999', '0099cc', '0099ff', '00cc00', '00cc33', '00cc66', '00cc99', '00cccc', '00ccff', '00ff00', '00ff33', '00ff66', '00ff99', '00ffcc', '00ffff', '330000', '330033', '330066', '330099', '3300cc', '3300ff', '333300', '333333', '333366', '333399', '3333cc', '3333ff', '336600', '336633', '336666', '336699', '3366cc', '3366ff', '339900', '339933', '339966', '339999', '3399cc', '3399ff', '33cc00', '33cc33', '33cc66', '33cc99', '33cccc', '33ccff', '33ff00', '33ff33', '33ff66', '33ff99', '33ffcc', '33ffff', '660000', '660033', '660066', '660099', '6600cc', '6600ff', '663300', '663333', '663366', '663399', '6633cc', '6633ff', '666600', '666633', '666666', '666699', '6666cc', '6666ff', '669900', '669933', '669966', '669999', '6699cc', '6699ff', '66cc00', '66cc33', '66cc66', '66cc99', '66cccc', '66ccff', '66ff00', '66ff33', '66ff66', '66ff99', '66ffcc', '66ffff', '990000', '990033', '990066', '990099', '9900cc', '9900ff', '993300', '993333', '993366', '993399', '9933cc', '9933ff', '996600', '996633', '996666', '996699', '9966cc', '9966ff', '999900', '999933', '999966', '999999', '9999cc', '9999ff', '99cc00', '99cc33', '99cc66', '99cc99', '99cccc', '99ccff', '99ff00', '99ff33', '99ff66', '99ff99', '99ffcc', '99ffff', 'cc0000', 'cc0033', 'cc0066', 'cc0099', 'cc00cc', 'cc00ff', 'cc3300', 'cc3333', 'cc3366', 'cc3399', 'cc33cc', 'cc33ff', 'cc6600', 'cc6633', 'cc6666', 'cc6699', 'cc66cc', 'cc66ff', 'cc9900', 'cc9933', 'cc9966', 'cc9999', 'cc99cc', 'cc99ff', 'cccc00', 'cccc33', 'cccc66', 'cccc99', 'cccccc', 'ccccff', 'ccff00', 'ccff33', 'ccff66', 'ccff99', 'ccffcc', 'ccffff', 'ff0000', 'ff0033', 'ff0066', 'ff0099', 'ff00cc', 'ff00ff', 'ff3300', 'ff3333', 'ff3366', 'ff3399', 'ff33cc', 'ff33ff', 'ff6600', 'ff6633', 'ff6666', 'ff6699', 'ff66cc', 'ff66ff', 'ff9900', 'ff9933', 'ff9966', 'ff9999', 'ff99cc', 'ff99ff', 'ffcc00', 'ffcc33', 'ffcc66', 'ffcc99', 'ffcccc', 'ffccff', 'ffff00', 'ffff33', 'ffff66', 'ffff99', 'ffffcc', 'ffffff']
2316
+
2317
+ X11_Colors =[
2318
+ "000000",
2319
+ "800000",
2320
+ "008000",
2321
+ "808000",
2322
+ "000080",
2323
+ "800080",
2324
+ "008080",
2325
+ "c0c0c0",
2326
+ "808080",
2327
+ "ff0000",
2328
+ "00ff00",
2329
+ "ffff00",
2330
+ "0000ff",
2331
+ "ff00ff",
2332
+ "00ffff",
2333
+ "ffffff",
2334
+ "000000",
2335
+ "00005f",
2336
+ "000087",
2337
+ "0000af",
2338
+ "0000d7",
2339
+ "0000ff",
2340
+ "005f00",
2341
+ "005f5f",
2342
+ "005f87",
2343
+ "005faf",
2344
+ "005fd7",
2345
+ "005fff",
2346
+ "008700",
2347
+ "00875f",
2348
+ "008787",
2349
+ "0087af",
2350
+ "0087d7",
2351
+ "0087ff",
2352
+ "00af00",
2353
+ "00af5f",
2354
+ "00af87",
2355
+ "00afaf",
2356
+ "00afd7",
2357
+ "00afff",
2358
+ "00d700",
2359
+ "00d75f",
2360
+ "00d787",
2361
+ "00d7af",
2362
+ "00d7d7",
2363
+ "00d7ff",
2364
+ "00ff00",
2365
+ "00ff5f",
2366
+ "00ff87",
2367
+ "00ffaf",
2368
+ "00ffd7",
2369
+ "00ffff",
2370
+ "5f0000",
2371
+ "5f005f",
2372
+ "5f0087",
2373
+ "5f00af",
2374
+ "5f00d7",
2375
+ "5f00ff",
2376
+ "5f5f00",
2377
+ "5f5f5f",
2378
+ "5f5f87",
2379
+ "5f5faf",
2380
+ "5f5fd7",
2381
+ "5f5fff",
2382
+ "5f8700",
2383
+ "5f875f",
2384
+ "5f8787",
2385
+ "5f87af",
2386
+ "5f87d7",
2387
+ "5f87ff",
2388
+ "5faf00",
2389
+ "5faf5f",
2390
+ "5faf87",
2391
+ "5fafaf",
2392
+ "5fafd7",
2393
+ "5fafff",
2394
+ "5fd700",
2395
+ "5fd75f",
2396
+ "5fd787",
2397
+ "5fd7af",
2398
+ "5fd7d7",
2399
+ "5fd7ff",
2400
+ "5fff00",
2401
+ "5fff5f",
2402
+ "5fff87",
2403
+ "5fffaf",
2404
+ "5fffd7",
2405
+ "5fffff",
2406
+ "870000",
2407
+ "87005f",
2408
+ "870087",
2409
+ "8700af",
2410
+ "8700d7",
2411
+ "8700ff",
2412
+ "875f00",
2413
+ "875f5f",
2414
+ "875f87",
2415
+ "875faf",
2416
+ "875fd7",
2417
+ "875fff",
2418
+ "878700",
2419
+ "87875f",
2420
+ "878787",
2421
+ "8787af",
2422
+ "8787d7",
2423
+ "8787ff",
2424
+ "87af00",
2425
+ "87af5f",
2426
+ "87af87",
2427
+ "87afaf",
2428
+ "87afd7",
2429
+ "87afff",
2430
+ "87d700",
2431
+ "87d75f",
2432
+ "87d787",
2433
+ "87d7af",
2434
+ "87d7d7",
2435
+ "87d7ff",
2436
+ "87ff00",
2437
+ "87ff5f",
2438
+ "87ff87",
2439
+ "87ffaf",
2440
+ "87ffd7",
2441
+ "87ffff",
2442
+ "af0000",
2443
+ "af005f",
2444
+ "af0087",
2445
+ "af00af",
2446
+ "af00d7",
2447
+ "af00ff",
2448
+ "af5f00",
2449
+ "af5f5f",
2450
+ "af5f87",
2451
+ "af5faf",
2452
+ "af5fd7",
2453
+ "af5fff",
2454
+ "af8700",
2455
+ "af875f",
2456
+ "af8787",
2457
+ "af87af",
2458
+ "af87d7",
2459
+ "af87ff",
2460
+ "afaf00",
2461
+ "afaf5f",
2462
+ "afaf87",
2463
+ "afafaf",
2464
+ "afafd7",
2465
+ "afafff",
2466
+ "afd700",
2467
+ "afd75f",
2468
+ "afd787",
2469
+ "afd7af",
2470
+ "afd7d7",
2471
+ "afd7ff",
2472
+ "afff00",
2473
+ "afff5f",
2474
+ "afff87",
2475
+ "afffaf",
2476
+ "afffd7",
2477
+ "afffff",
2478
+ "d70000",
2479
+ "d7005f",
2480
+ "d70087",
2481
+ "d700af",
2482
+ "d700d7",
2483
+ "d700ff",
2484
+ "d75f00",
2485
+ "d75f5f",
2486
+ "d75f87",
2487
+ "d75faf",
2488
+ "d75fd7",
2489
+ "d75fff",
2490
+ "d78700",
2491
+ "d7875f",
2492
+ "d78787",
2493
+ "d787af",
2494
+ "d787d7",
2495
+ "d787ff",
2496
+ "d7af00",
2497
+ "d7af5f",
2498
+ "d7af87",
2499
+ "d7afaf",
2500
+ "d7afd7",
2501
+ "d7afff",
2502
+ "d7d700",
2503
+ "d7d75f",
2504
+ "d7d787",
2505
+ "d7d7af",
2506
+ "d7d7d7",
2507
+ "d7d7ff",
2508
+ "d7ff00",
2509
+ "d7ff5f",
2510
+ "d7ff87",
2511
+ "d7ffaf",
2512
+ "d7ffd7",
2513
+ "d7ffff",
2514
+ "ff0000",
2515
+ "ff005f",
2516
+ "ff0087",
2517
+ "ff00af",
2518
+ "ff00d7",
2519
+ "ff00ff",
2520
+ "ff5f00",
2521
+ "ff5f5f",
2522
+ "ff5f87",
2523
+ "ff5faf",
2524
+ "ff5fd7",
2525
+ "ff5fff",
2526
+ "ff8700",
2527
+ "ff875f",
2528
+ "ff8787",
2529
+ "ff87af",
2530
+ "ff87d7",
2531
+ "ff87ff",
2532
+ "ffaf00",
2533
+ "ffaf5f",
2534
+ "ffaf87",
2535
+ "ffafaf",
2536
+ "ffafd7",
2537
+ "ffafff",
2538
+ "ffd700",
2539
+ "ffd75f",
2540
+ "ffd787",
2541
+ "ffd7af",
2542
+ "ffd7d7",
2543
+ "ffd7ff",
2544
+ "ffff00",
2545
+ "ffff5f",
2546
+ "ffff87",
2547
+ "ffffaf",
2548
+ "ffffd7",
2549
+ "ffffff",
2550
+ "080808",
2551
+ "121212",
2552
+ "1c1c1c",
2553
+ "262626",
2554
+ "303030",
2555
+ "3a3a3a",
2556
+ "444444",
2557
+ "4e4e4e",
2558
+ "585858",
2559
+ "606060",
2560
+ "666666",
2561
+ "767676",
2562
+ "808080",
2563
+ "8a8a8a",
2564
+ "949494",
2565
+ "9e9e9e",
2566
+ "a8a8a8",
2567
+ "b2b2b2",
2568
+ "bcbcbc",
2569
+ "c6c6c6",
2570
+ "d0d0d0",
2571
+ "dadada",
2572
+ "e4e4e4",
2573
+ "eeeeee"
2574
+ ]
2575
+
2576
+
2577
+ if __name__ == "__main__":
2578
+ main()