sticker-convert 2.7.6__tar.gz → 2.7.8__tar.gz

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 (110) hide show
  1. {sticker-convert-2.7.6/src/sticker_convert.egg-info → sticker-convert-2.7.8}/PKG-INFO +4 -4
  2. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/README.md +1 -1
  3. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/requirements.txt +2 -2
  4. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/converter.py +68 -33
  5. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui.py +5 -9
  6. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/progress_frame.py +67 -47
  7. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/job.py +3 -4
  8. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/compression.json +11 -11
  9. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/help.json +1 -1
  10. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/media/codec_info.py +8 -8
  11. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/version.py +1 -1
  12. {sticker-convert-2.7.6 → sticker-convert-2.7.8/src/sticker_convert.egg-info}/PKG-INFO +4 -4
  13. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert.egg-info/requires.txt +2 -2
  14. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/LICENSE +0 -0
  15. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/MANIFEST.in +0 -0
  16. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/pyproject.toml +0 -0
  17. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/setup.cfg +0 -0
  18. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/__init__.py +0 -0
  19. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/__main__.py +0 -0
  20. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/cli.py +0 -0
  21. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/definitions.py +0 -0
  22. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/__init__.py +0 -0
  23. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/download_base.py +0 -0
  24. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/download_kakao.py +0 -0
  25. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/download_line.py +0 -0
  26. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/download_signal.py +0 -0
  27. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/downloaders/download_telegram.py +0 -0
  28. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/__init__.py +0 -0
  29. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/__init__.py +0 -0
  30. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/comp_frame.py +0 -0
  31. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/config_frame.py +0 -0
  32. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/control_frame.py +0 -0
  33. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/cred_frame.py +0 -0
  34. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/input_frame.py +0 -0
  35. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/output_frame.py +0 -0
  36. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/frames/right_clicker.py +0 -0
  37. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/gui_utils.py +0 -0
  38. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/__init__.py +0 -0
  39. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/advanced_compression_window.py +0 -0
  40. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/base_window.py +0 -0
  41. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/kakao_get_auth_window.py +0 -0
  42. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/line_get_auth_window.py +0 -0
  43. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/gui_components/windows/signal_get_auth_window.py +0 -0
  44. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +0 -0
  45. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/.gitignore +0 -0
  46. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/README.md +0 -0
  47. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers/Info.plist +0 -0
  48. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +0 -0
  49. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +0 -0
  50. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +0 -0
  51. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +0 -0
  52. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
  53. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +0 -0
  54. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
  55. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +0 -0
  56. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
  57. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
  58. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +0 -0
  59. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
  60. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
  61. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
  62. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
  63. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
  64. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
  65. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
  66. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
  67. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
  68. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
  69. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
  70. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
  71. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +0 -0
  72. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  73. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  74. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  75. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  76. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/job_option.py +0 -0
  77. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  78. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/appicon.icns +0 -0
  79. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/appicon.ico +0 -0
  80. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/appicon.png +0 -0
  81. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/emoji.json +0 -0
  82. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/input.json +0 -0
  83. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/resources/output.json +0 -0
  84. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/__init__.py +0 -0
  85. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/compress_wastickers.py +0 -0
  86. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/upload_base.py +0 -0
  87. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/upload_signal.py +0 -0
  88. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/upload_telegram.py +0 -0
  89. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/uploaders/xcode_imessage.py +0 -0
  90. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/auth/get_kakao_auth.py +0 -0
  91. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/auth/get_line_auth.py +0 -0
  92. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/auth/get_signal_auth.py +0 -0
  93. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/callback.py +0 -0
  94. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/cache_store.py +0 -0
  95. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/json_manager.py +0 -0
  96. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/json_resources_loader.py +0 -0
  97. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/metadata_handler.py +0 -0
  98. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/run_bin.py +0 -0
  99. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/files/sanitize_filename.py +0 -0
  100. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/media/apple_png_normalize.py +0 -0
  101. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/media/decrypt_kakao.py +0 -0
  102. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/media/format_verify.py +0 -0
  103. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert/utils/url_detect.py +0 -0
  104. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert.egg-info/SOURCES.txt +0 -0
  105. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert.egg-info/dependency_links.txt +0 -0
  106. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert.egg-info/entry_points.txt +0 -0
  107. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/src/sticker_convert.egg-info/top_level.txt +0 -0
  108. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/tests/test_compression.py +0 -0
  109. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/tests/test_download.py +0 -0
  110. {sticker-convert-2.7.6 → sticker-convert-2.7.8}/tests/test_export.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.7.6
3
+ Version: 2.7.8
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -367,13 +367,13 @@ License-File: LICENSE
367
367
  Requires-Dist: aiolimiter~=1.1.0
368
368
  Requires-Dist: anyio~=3.7.1
369
369
  Requires-Dist: apngasm_python~=1.2.3
370
- Requires-Dist: av~=11.0.0
370
+ Requires-Dist: av~=12.0.0
371
371
  Requires-Dist: beautifulsoup4~=4.12.3
372
372
  Requires-Dist: rookiepy~=0.3.6
373
373
  Requires-Dist: imagequant~=1.1.1
374
374
  Requires-Dist: memory-tempfile~=2.2.3
375
375
  Requires-Dist: numpy>=1.22.4
376
- Requires-Dist: Pillow~=10.2.0
376
+ Requires-Dist: Pillow==10.1.0
377
377
  Requires-Dist: pyoxipng~=9.0.0
378
378
  Requires-Dist: python-telegram-bot~=20.5
379
379
  Requires-Dist: requests~=2.31.0
@@ -592,7 +592,7 @@ Compression options:
592
592
  (1) Size limit for video is larger than image;
593
593
  (2) Mix image and video into same pack.
594
594
  --scale-filter SCALE_FILTER
595
- Set scale filter. Default as lanczos. Valid options are:
595
+ Set scale filter. Default as bicubic. Valid options are:
596
596
  - nearest = Use nearest neighbour (Suitable for pixel art)
597
597
  -box = Similar to nearest, but better downscaling
598
598
  - bilinear = Linear interpolation
@@ -206,7 +206,7 @@ Compression options:
206
206
  (1) Size limit for video is larger than image;
207
207
  (2) Mix image and video into same pack.
208
208
  --scale-filter SCALE_FILTER
209
- Set scale filter. Default as lanczos. Valid options are:
209
+ Set scale filter. Default as bicubic. Valid options are:
210
210
  - nearest = Use nearest neighbour (Suitable for pixel art)
211
211
  -box = Similar to nearest, but better downscaling
212
212
  - bilinear = Linear interpolation
@@ -1,13 +1,13 @@
1
1
  aiolimiter~=1.1.0
2
2
  anyio~=3.7.1
3
3
  apngasm_python~=1.2.3
4
- av~=11.0.0
4
+ av~=12.0.0
5
5
  beautifulsoup4~=4.12.3
6
6
  rookiepy~=0.3.6
7
7
  imagequant~=1.1.1
8
8
  memory-tempfile~=2.2.3
9
9
  numpy>=1.22.4
10
- Pillow~=10.2.0
10
+ Pillow==10.1.0
11
11
  pyoxipng~=9.0.0
12
12
  python-telegram-bot~=20.5
13
13
  requests~=2.31.0
@@ -6,10 +6,11 @@ from io import BytesIO
6
6
  from math import ceil, floor
7
7
  from pathlib import Path
8
8
  from queue import Queue
9
- from typing import TYPE_CHECKING, Any, List, Literal, Optional, Tuple, Union, cast
9
+ from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union, cast
10
10
 
11
11
  import numpy as np
12
12
  from PIL import Image
13
+ from PIL import __version__ as PillowVersion
13
14
 
14
15
  from sticker_convert.job_option import CompOption
15
16
  from sticker_convert.utils.callback import Callback, CallbackReturn, CbQueueItemType
@@ -378,10 +379,10 @@ class StickerConvert:
378
379
  self.frames_raw.append(np.asarray(im.convert("RGBA")))
379
380
 
380
381
  def _frames_import_pyav(self) -> None:
381
- import av # type: ignore
382
- from av.codec.context import CodecContext # type: ignore
383
- from av.container.input import InputContainer # type: ignore
384
- from av.video.codeccontext import VideoCodecContext # type: ignore
382
+ import av
383
+ from av.codec.context import CodecContext
384
+ from av.container.input import InputContainer
385
+ from av.video.codeccontext import VideoCodecContext
385
386
 
386
387
  # Crashes when handling some webm in yuv420p and convert to rgba
387
388
  # https://github.com/PyAV-Org/PyAV/issues/1166
@@ -390,16 +391,17 @@ class StickerConvert:
390
391
  file = self.in_f.as_posix()
391
392
  else:
392
393
  file = BytesIO(self.in_f)
393
- with av.open(file) as container: # type: ignore
394
+ with av.open(file) as container:
394
395
  container = cast(InputContainer, container)
395
396
  context = container.streams.video[0].codec_context
396
397
  if context.name == "vp8":
397
- context = CodecContext.create("libvpx", "r") # type: ignore
398
+ context = cast(VideoCodecContext, CodecContext.create("libvpx", "r"))
398
399
  elif context.name == "vp9":
399
- context = CodecContext.create("libvpx-vp9", "r") # type: ignore
400
- context = cast(VideoCodecContext, context)
400
+ context = cast(
401
+ VideoCodecContext, CodecContext.create("libvpx-vp9", "r")
402
+ )
401
403
 
402
- for packet in container.demux(container.streams.video): # type: ignore
404
+ for packet in container.demux(container.streams.video):
403
405
  for frame in context.decode(packet):
404
406
  if frame.width % 2 != 0:
405
407
  width = frame.width - 1
@@ -410,22 +412,22 @@ class StickerConvert:
410
412
  else:
411
413
  height = frame.height
412
414
  if frame.format.name == "yuv420p":
413
- rgb_array = frame.to_ndarray(format="rgb24") # type: ignore
415
+ rgb_array = frame.to_ndarray(format="rgb24")
414
416
  cast("np.ndarray[Any, Any]", rgb_array)
415
417
  rgba_array = np.dstack(
416
418
  (
417
419
  rgb_array,
418
420
  np.zeros(rgb_array.shape[:2], dtype=np.uint8) + 255,
419
- ) # type: ignore
421
+ )
420
422
  )
421
423
  else:
422
424
  # yuva420p may cause crash
423
425
  # https://github.com/laggykiller/sticker-convert/issues/114
424
- frame = frame.reformat( # type: ignore
426
+ frame = frame.reformat(
425
427
  width=width,
426
428
  height=height,
427
429
  format="yuva420p",
428
- dst_colorspace=1, # type: ignore
430
+ dst_colorspace=1,
429
431
  )
430
432
 
431
433
  # https://stackoverflow.com/questions/72308308/converting-yuv-to-rgb-in-python-coefficients-work-with-array-dont-work-with-n
@@ -522,7 +524,7 @@ class StickerConvert:
522
524
  elif self.opt_comp.scale_filter == "lanczos":
523
525
  resample = Image.LANCZOS
524
526
  else:
525
- resample = Image.LANCZOS
527
+ resample = Image.BICUBIC
526
528
 
527
529
  for frame in frames_in:
528
530
  with Image.fromarray(frame, "RGBA") as im: # type: ignore
@@ -615,6 +617,8 @@ class StickerConvert:
615
617
  self._frames_export_png()
616
618
  elif self.out_f.suffix == ".webp" and is_animated:
617
619
  self._frames_export_webp()
620
+ elif self.out_f.suffix == ".gif":
621
+ self._frames_export_gif()
618
622
  elif self.out_f.suffix in (".webm", ".mp4", ".mkv") or is_animated:
619
623
  self._frames_export_pyav()
620
624
  else:
@@ -629,22 +633,17 @@ class StickerConvert:
629
633
  )
630
634
 
631
635
  def _frames_export_pyav(self) -> None:
632
- import av # type: ignore
633
- from av.container import OutputContainer # type: ignore
634
- from av.video.stream import VideoStream # type: ignore
636
+ import av
637
+ from av.video.stream import VideoStream
635
638
 
636
- options = {}
639
+ options: Dict[str, str] = {}
637
640
 
638
641
  if isinstance(self.quality, int):
639
642
  # Seems not actually working
640
643
  options["quality"] = str(self.quality)
641
644
  options["lossless"] = "0"
642
645
 
643
- if self.out_f.suffix == ".gif":
644
- codec = "gif"
645
- pixel_format = "rgb8"
646
- options["loop"] = "0"
647
- elif self.out_f.suffix in (".apng", ".png"):
646
+ if self.out_f.suffix in (".apng", ".png"):
648
647
  codec = "apng"
649
648
  pixel_format = "rgba"
650
649
  options["plays"] = "0"
@@ -657,11 +656,10 @@ class StickerConvert:
657
656
  pixel_format = "yuv420p"
658
657
  options["loop"] = "0"
659
658
 
660
- with av.open( # type: ignore
659
+ with av.open(
661
660
  self.tmp_f, "w", format=self.out_f.suffix.replace(".", "")
662
661
  ) as output:
663
- output = cast(OutputContainer, output) # type: ignore
664
- out_stream = output.add_stream(codec, rate=self.fps, options=options) # type: ignore
662
+ out_stream = output.add_stream(codec, rate=self.fps, options=options)
665
663
  out_stream = cast(VideoStream, out_stream)
666
664
  assert isinstance(self.res_w, int) and isinstance(self.res_h, int)
667
665
  out_stream.width = self.res_w
@@ -669,12 +667,49 @@ class StickerConvert:
669
667
  out_stream.pix_fmt = pixel_format
670
668
 
671
669
  for frame in self.frames_processed:
672
- av_frame = av.VideoFrame.from_ndarray(frame, format="rgba") # type: ignore
673
- for packet in out_stream.encode(av_frame): # type: ignore
674
- output.mux(packet) # type: ignore
675
-
676
- for packet in out_stream.encode(): # type: ignore
677
- output.mux(packet) # type: ignore
670
+ av_frame = av.VideoFrame.from_ndarray(frame, format="rgba")
671
+ output.mux(out_stream.encode(av_frame))
672
+ output.mux(out_stream.encode())
673
+
674
+ def _frames_export_gif(self) -> None:
675
+ extra_kwargs: Dict[str, Any] = {}
676
+
677
+ # disposal=2 on gif cause flicker in image with transparency
678
+ # Occurs in Pillow == 10.2.0
679
+ # https://github.com/python-pillow/Pillow/issues/7787
680
+ if PillowVersion == "10.2.0":
681
+ extra_kwargs["optimize"] = False
682
+ else:
683
+ extra_kwargs["optimize"] = True
684
+
685
+ # Only enable transparency if all pixels have alpha channel
686
+ # with value of 0 or 255
687
+ alpha_channel_values = np.unique(np.array(self.frames_raw)[:, :, :, 3])
688
+ illegals = np.setxor1d(
689
+ alpha_channel_values, [0, 255]
690
+ ) # Find all values not 0 or 255
691
+ if illegals.size == 0:
692
+ extra_kwargs["transparency"] = 0
693
+ extra_kwargs["disposal"] = 2
694
+ im_out = [self.quantize(Image.fromarray(i)) for i in self.frames_processed]
695
+ else:
696
+ im_out = [
697
+ self.quantize(Image.fromarray(i).convert("RGB")).convert("RGB")
698
+ for i in self.frames_processed
699
+ ]
700
+
701
+ if self.fps:
702
+ extra_kwargs["save_all"] = True
703
+ extra_kwargs["append_images"] = im_out[1:]
704
+ extra_kwargs["duration"] = int(1000 / self.fps)
705
+ extra_kwargs["loop"] = 0
706
+
707
+ im_out[0].save(
708
+ self.tmp_f,
709
+ format="GIF",
710
+ quality=self.quality,
711
+ **extra_kwargs,
712
+ )
678
713
 
679
714
  def _frames_export_webp(self) -> None:
680
715
  import webp # type: ignore
@@ -8,7 +8,7 @@ from json.decoder import JSONDecodeError
8
8
  from math import ceil
9
9
  from multiprocessing import Event, cpu_count
10
10
  from pathlib import Path
11
- from threading import Lock, Thread
11
+ from threading import Thread
12
12
  from typing import Any, Callable, Dict, Optional, Union
13
13
  from urllib.parse import urlparse
14
14
 
@@ -161,8 +161,6 @@ class GUI(Window):
161
161
  self.settings_save_cred_var = BooleanVar()
162
162
 
163
163
  # Other
164
- self.msg_lock = Lock()
165
- self.bar_lock = Lock()
166
164
  self.response_event = Event()
167
165
  self.response = None
168
166
  self.action: Optional[Callable[..., Any]] = None
@@ -609,8 +607,7 @@ class GUI(Window):
609
607
  return False
610
608
 
611
609
  def cb_msg(self, *args: Any, **kwargs: Any) -> None:
612
- with self.msg_lock:
613
- self.progress_frame.update_message_box(*args, **kwargs)
610
+ self.progress_frame.update_message_box(*args, **kwargs)
614
611
 
615
612
  def cb_msg_block(
616
613
  self,
@@ -641,10 +638,9 @@ class GUI(Window):
641
638
  update_bar: int = 0,
642
639
  **kwargs: Any,
643
640
  ) -> None:
644
- with self.bar_lock:
645
- self.progress_frame.update_progress_bar(
646
- set_progress_mode, steps, update_bar, *args, **kwargs
647
- )
641
+ self.progress_frame.update_progress_bar(
642
+ set_progress_mode, steps, update_bar, *args, **kwargs
643
+ )
648
644
 
649
645
  def highlight_fields(self) -> bool:
650
646
  if not self.init_done:
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python3
2
- from typing import TYPE_CHECKING, Any, Optional
2
+ from threading import Lock
3
+ from typing import TYPE_CHECKING, Any, List, Optional
3
4
 
4
5
  from tqdm import tqdm
5
6
  from ttkbootstrap import LabelFrame, Progressbar # type: ignore
@@ -15,13 +16,18 @@ class ProgressFrame(LabelFrame):
15
16
  progress_bar_cli = None
16
17
  progress_bar_steps = 0
17
18
  auto_scroll = True
19
+
18
20
  msg_cls = False
19
- msg_buffer = ""
21
+ msg_buffer: List[str] = []
22
+
20
23
  bar_mode_changed = False
21
24
  bar_mode = "clear"
22
25
  bar_updates = 0
23
26
  bar_steps = 0
24
27
 
28
+ msg_lock = Lock()
29
+ bar_lock = Lock()
30
+
25
31
  def __init__(self, gui: "GUI", *args: Any, **kwargs: Any) -> None:
26
32
  self.gui = gui
27
33
  super().__init__(*args, **kwargs) # type: ignore
@@ -46,12 +52,15 @@ class ProgressFrame(LabelFrame):
46
52
  update_bar: int = 0,
47
53
  ) -> None:
48
54
  if update_bar:
49
- self.bar_updates += update_bar
55
+ with self.bar_lock:
56
+ self.bar_updates += update_bar
57
+
50
58
  elif set_progress_mode:
51
- self.bar_mode = set_progress_mode
52
- self.bar_steps = steps
53
- self.bar_updates = 0
54
- self.bar_mode_changed = True
59
+ with self.bar_lock:
60
+ self.bar_mode = set_progress_mode
61
+ self.bar_steps = steps
62
+ self.bar_updates = 0
63
+ self.bar_mode_changed = True
55
64
 
56
65
  def update_message_box(self, *args: Any, **kwargs: Any) -> None:
57
66
  msg = kwargs.get("msg")
@@ -60,22 +69,30 @@ class ProgressFrame(LabelFrame):
60
69
  if not msg and len(args) == 1:
61
70
  msg = str(args[0])
62
71
 
63
- if cls:
64
- self.msg_cls = True
65
- self.msg_buffer = ""
66
-
67
72
  if msg:
68
- self.msg_buffer += msg + "\n"
73
+ with self.msg_lock:
74
+ self.msg_buffer.append(msg)
75
+
76
+ elif cls:
77
+ with self.msg_lock:
78
+ self.msg_cls = True
79
+ self.msg_buffer.clear()
69
80
 
70
81
  def update_ui(self) -> None:
71
- if self.msg_cls or self.msg_buffer:
82
+ if self.msg_buffer or self.msg_cls:
83
+ with self.msg_lock:
84
+ msg_cls = self.msg_cls
85
+ msg = "\n".join(self.msg_buffer)
86
+
87
+ self.msg_cls = False
88
+ self.msg_buffer.clear()
89
+
72
90
  self.message_box._text.config(state="normal") # type: ignore
73
91
 
74
- if self.msg_cls:
92
+ if msg_cls:
75
93
  self.message_box.delete(1.0, "end") # type: ignore
76
94
 
77
- if self.msg_buffer:
78
- msg = self.msg_buffer.strip()
95
+ if msg:
79
96
  if self.progress_bar_cli:
80
97
  self.progress_bar_cli.write(msg)
81
98
  else:
@@ -86,39 +103,42 @@ class ProgressFrame(LabelFrame):
86
103
  if self.auto_scroll:
87
104
  self.message_box._text.yview_moveto(1.0) # type: ignore
88
105
 
89
- self.msg_cls = False
90
- self.msg_buffer = ""
91
-
92
106
  self.message_box._text.config(state="disabled") # type: ignore
93
107
 
94
- if self.bar_mode_changed:
95
- if self.bar_mode == "determinate":
96
- self.progress_bar_cli = tqdm(total=self.bar_steps)
97
- self.progress_bar.config(mode="determinate")
98
- self.progress_bar_steps = self.bar_steps
99
- self.progress_bar.stop()
100
- elif self.progress_bar_cli:
101
- self.progress_bar_cli.close()
102
- self.progress_bar_cli = None
103
-
104
- if self.bar_mode == "indeterminate":
105
- self.progress_bar.config(mode="indeterminate")
106
- self.progress_bar.start(50)
107
- elif self.bar_mode == "clear":
108
- self.progress_bar.config(mode="determinate")
109
- self.progress_bar.stop()
110
-
111
- self.progress_bar["value"] = 0
112
-
113
- if self.bar_updates and self.progress_bar_cli:
114
- self.progress_bar_cli.update(self.bar_updates)
115
- self.progress_bar["value"] += (
116
- 100 / self.progress_bar_steps * self.bar_updates
117
- )
118
- self.update_progress_bar(update_bar=self.bar_updates)
119
-
120
- self.bar_mode_changed = False
121
- self.bar_updates = 0
108
+ if self.bar_mode_changed or self.bar_updates:
109
+ with self.bar_lock:
110
+ bar_mode_changed = self.bar_mode_changed
111
+ bar_mode = self.bar_mode
112
+ bar_updates = self.bar_updates
113
+ bar_steps = self.bar_steps
114
+
115
+ self.bar_mode_changed = False
116
+ self.bar_updates = 0
117
+
118
+ if bar_mode_changed:
119
+ if bar_mode == "determinate":
120
+ self.progress_bar_cli = tqdm(total=bar_steps)
121
+ self.progress_bar.config(mode="determinate")
122
+ self.progress_bar_steps = bar_steps
123
+ self.progress_bar.stop()
124
+ elif self.progress_bar_cli:
125
+ self.progress_bar_cli.close()
126
+ self.progress_bar_cli = None
127
+
128
+ if bar_mode == "indeterminate":
129
+ self.progress_bar.config(mode="indeterminate")
130
+ self.progress_bar.start(50)
131
+ elif bar_mode == "clear":
132
+ self.progress_bar.config(mode="determinate")
133
+ self.progress_bar.stop()
134
+
135
+ self.progress_bar["value"] = 0
136
+
137
+ if bar_updates and self.progress_bar_cli:
138
+ self.progress_bar_cli.update(bar_updates)
139
+ self.progress_bar["value"] += (
140
+ 100 / self.progress_bar_steps * bar_updates
141
+ )
122
142
 
123
143
  self.after(40, self.update_ui)
124
144
 
@@ -29,7 +29,6 @@ from sticker_convert.utils.files.json_resources_loader import OUTPUT_JSON
29
29
  from sticker_convert.utils.files.metadata_handler import MetadataHandler
30
30
  from sticker_convert.utils.media.codec_info import CodecInfo
31
31
 
32
- CbQueueType = Queue[CbQueueItemType]
33
32
  WorkListItemType = Optional[Tuple[Callable[..., Any], Tuple[Any, ...]]]
34
33
  if TYPE_CHECKING:
35
34
  # mypy complains about this
@@ -59,7 +58,7 @@ class Executor:
59
58
  # Especially when using scale_filter=nearest
60
59
  self.work_list: WorkListType = self.manager.list()
61
60
  self.results_queue: Queue[Any] = self.manager.Queue()
62
- self.cb_queue: CbQueueType = self.manager.Queue()
61
+ self.cb_queue: Queue[CbQueueItemType] = self.manager.Queue()
63
62
  self.cb_return = CallbackReturn()
64
63
  self.processes: List[Process] = []
65
64
 
@@ -76,7 +75,7 @@ class Executor:
76
75
 
77
76
  def cb_thread(
78
77
  self,
79
- cb_queue: CbQueueType,
78
+ cb_queue: Queue[CbQueueItemType],
80
79
  cb_return: CallbackReturn,
81
80
  ) -> None:
82
81
  for i in iter(cb_queue.get, None):
@@ -113,7 +112,7 @@ class Executor:
113
112
  def worker(
114
113
  work_list: WorkListType,
115
114
  results_queue: Queue[Any],
116
- cb_queue: CbQueueType,
115
+ cb_queue: Queue[CbQueueItemType],
117
116
  cb_return: CallbackReturn,
118
117
  ) -> None:
119
118
  while True:
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "steps": 16,
42
42
  "fake_vid": false,
43
- "scale_filter": "lanczos",
43
+ "scale_filter": "bicubic",
44
44
  "quantize_method": "imagequant",
45
45
  "default_emoji": "😀"
46
46
  },
@@ -85,7 +85,7 @@
85
85
  },
86
86
  "steps": 16,
87
87
  "fake_vid": false,
88
- "scale_filter": "lanczos",
88
+ "scale_filter": "bicubic",
89
89
  "quantize_method": "imagequant",
90
90
  "default_emoji": "😀"
91
91
  },
@@ -130,7 +130,7 @@
130
130
  },
131
131
  "steps": 16,
132
132
  "fake_vid": false,
133
- "scale_filter": "lanczos",
133
+ "scale_filter": "bicubic",
134
134
  "quantize_method": "imagequant",
135
135
  "default_emoji": "😀"
136
136
  },
@@ -175,7 +175,7 @@
175
175
  },
176
176
  "steps": 16,
177
177
  "fake_vid": false,
178
- "scale_filter": "lanczos",
178
+ "scale_filter": "bicubic",
179
179
  "quantize_method": "imagequant",
180
180
  "default_emoji": "😀"
181
181
  },
@@ -220,7 +220,7 @@
220
220
  },
221
221
  "steps": 16,
222
222
  "fake_vid": true,
223
- "scale_filter": "lanczos",
223
+ "scale_filter": "bicubic",
224
224
  "quantize_method": "imagequant",
225
225
  "default_emoji": "😀"
226
226
  },
@@ -265,7 +265,7 @@
265
265
  },
266
266
  "steps": 16,
267
267
  "fake_vid": false,
268
- "scale_filter": "lanczos",
268
+ "scale_filter": "bicubic",
269
269
  "quantize_method": "imagequant",
270
270
  "default_emoji": "😀"
271
271
  },
@@ -310,7 +310,7 @@
310
310
  },
311
311
  "steps": 16,
312
312
  "fake_vid": false,
313
- "scale_filter": "lanczos",
313
+ "scale_filter": "bicubic",
314
314
  "quantize_method": "imagequant",
315
315
  "default_emoji": "😀"
316
316
  },
@@ -355,7 +355,7 @@
355
355
  },
356
356
  "steps": 16,
357
357
  "fake_vid": false,
358
- "scale_filter": "lanczos",
358
+ "scale_filter": "bicubic",
359
359
  "quantize_method": "imagequant",
360
360
  "default_emoji": "😀"
361
361
  },
@@ -400,7 +400,7 @@
400
400
  },
401
401
  "steps": 16,
402
402
  "fake_vid": false,
403
- "scale_filter": "lanczos",
403
+ "scale_filter": "bicubic",
404
404
  "quantize_method": "imagequant",
405
405
  "default_emoji": "😀"
406
406
  },
@@ -445,7 +445,7 @@
445
445
  },
446
446
  "steps": 16,
447
447
  "fake_vid": false,
448
- "scale_filter": "lanczos",
448
+ "scale_filter": "bicubic",
449
449
  "quantize_method": "imagequant",
450
450
  "default_emoji": "😀"
451
451
  },
@@ -490,7 +490,7 @@
490
490
  },
491
491
  "steps": 16,
492
492
  "fake_vid": false,
493
- "scale_filter": "lanczos",
493
+ "scale_filter": "bicubic",
494
494
  "quantize_method": "imagequant",
495
495
  "default_emoji": "😀"
496
496
  }
@@ -45,7 +45,7 @@
45
45
  "vid_format": "Set file format if input is animated.",
46
46
  "img_format": "Set file format if input is static.",
47
47
  "fake_vid": "Convert (faking) image to video.\nUseful if:\n(1) Size limit for video is larger than image;\n(2) Mix image and video into same pack.",
48
- "scale_filter": "Set scale filter. Default as lanczos. Valid options are:\n- nearest = Use nearest neighbour (Suitable for pixel art)\n-box = Similar to nearest, but better downscaling\n- bilinear = Linear interpolation\n- hamming = Similar to bilinear, but better downscaling\n- bicubic = Cubic spline interpolation\n- lanczos = A high-quality downsampling filter",
48
+ "scale_filter": "Set scale filter. Default as bicubic. Valid options are:\n- nearest = Use nearest neighbour (Suitable for pixel art)\n-box = Similar to nearest, but better downscaling\n- bilinear = Linear interpolation\n- hamming = Similar to bilinear, but better downscaling\n- bicubic = Cubic spline interpolation\n- lanczos = A high-quality downsampling filter",
49
49
  "quantize_method": "Set method for quantizing image. Default as imagequant. Valid options are:\n- imagequant = Best quality but slow\n- fastoctree = Fast but image looks chunky\n- none = No image quantizing, large image size as result",
50
50
  "cache_dir": "Set custom cache directory.\nUseful for debugging, or speed up conversion if cache_dir is on RAM disk.",
51
51
  "default_emoji": "Set the default emoji for uploading Signal and Telegram sticker packs."
@@ -230,8 +230,8 @@ class CodecInfo:
230
230
  frames_to_iterate: Optional[int] = None,
231
231
  frames_only: bool = False,
232
232
  ) -> Tuple[int, int]:
233
- import av # type: ignore
234
- from av.container.input import InputContainer # type: ignore
233
+ import av
234
+ from av.container.input import InputContainer
235
235
 
236
236
  # Getting fps and frame count from metadata is not reliable
237
237
  # Example: https://github.com/laggykiller/sticker-convert/issues/114
@@ -242,7 +242,7 @@ class CodecInfo:
242
242
  else:
243
243
  file_ref = BytesIO(file)
244
244
 
245
- with av.open(file_ref) as container: # type: ignore
245
+ with av.open(file_ref) as container:
246
246
  container = cast(InputContainer, container)
247
247
  stream = container.streams.video[0]
248
248
  if container.duration:
@@ -257,7 +257,7 @@ class CodecInfo:
257
257
 
258
258
  frame_count = 0
259
259
  last_frame = None
260
- for frame_count, frame in enumerate(container.decode(stream)): # type: ignore
260
+ for frame_count, frame in enumerate(container.decode(stream)):
261
261
  if frames_to_iterate is not None and frame_count == frames_to_iterate:
262
262
  break
263
263
  last_frame = frame
@@ -310,11 +310,11 @@ class CodecInfo:
310
310
  if codec is not None:
311
311
  return codec.lower()
312
312
 
313
- import av # type: ignore
314
- from av.error import InvalidDataError # type: ignore
313
+ import av
314
+ from av.error import InvalidDataError
315
315
 
316
316
  try:
317
- with av.open(file_ref) as container: # type: ignore
317
+ with av.open(file_ref) as container:
318
318
  return container.streams.video[0].codec_context.name.lower()
319
319
  except InvalidDataError:
320
320
  pass
@@ -354,7 +354,7 @@ class CodecInfo:
354
354
  else:
355
355
  file_ref = BytesIO(file)
356
356
 
357
- with av.open(file_ref) as container: # type: ignore
357
+ with av.open(file_ref) as container:
358
358
  stream = container.streams.video[0]
359
359
  width = stream.width
360
360
  height = stream.height
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.7.6"
3
+ __version__ = "2.7.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.7.6
3
+ Version: 2.7.8
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -367,13 +367,13 @@ License-File: LICENSE
367
367
  Requires-Dist: aiolimiter~=1.1.0
368
368
  Requires-Dist: anyio~=3.7.1
369
369
  Requires-Dist: apngasm_python~=1.2.3
370
- Requires-Dist: av~=11.0.0
370
+ Requires-Dist: av~=12.0.0
371
371
  Requires-Dist: beautifulsoup4~=4.12.3
372
372
  Requires-Dist: rookiepy~=0.3.6
373
373
  Requires-Dist: imagequant~=1.1.1
374
374
  Requires-Dist: memory-tempfile~=2.2.3
375
375
  Requires-Dist: numpy>=1.22.4
376
- Requires-Dist: Pillow~=10.2.0
376
+ Requires-Dist: Pillow==10.1.0
377
377
  Requires-Dist: pyoxipng~=9.0.0
378
378
  Requires-Dist: python-telegram-bot~=20.5
379
379
  Requires-Dist: requests~=2.31.0
@@ -592,7 +592,7 @@ Compression options:
592
592
  (1) Size limit for video is larger than image;
593
593
  (2) Mix image and video into same pack.
594
594
  --scale-filter SCALE_FILTER
595
- Set scale filter. Default as lanczos. Valid options are:
595
+ Set scale filter. Default as bicubic. Valid options are:
596
596
  - nearest = Use nearest neighbour (Suitable for pixel art)
597
597
  -box = Similar to nearest, but better downscaling
598
598
  - bilinear = Linear interpolation
@@ -1,13 +1,13 @@
1
1
  aiolimiter~=1.1.0
2
2
  anyio~=3.7.1
3
3
  apngasm_python~=1.2.3
4
- av~=11.0.0
4
+ av~=12.0.0
5
5
  beautifulsoup4~=4.12.3
6
6
  rookiepy~=0.3.6
7
7
  imagequant~=1.1.1
8
8
  memory-tempfile~=2.2.3
9
9
  numpy>=1.22.4
10
- Pillow~=10.2.0
10
+ Pillow==10.1.0
11
11
  pyoxipng~=9.0.0
12
12
  python-telegram-bot~=20.5
13
13
  requests~=2.31.0
File without changes