sticker-convert 2.8.2__tar.gz → 2.8.3__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. {sticker-convert-2.8.2/src/sticker_convert.egg-info → sticker-convert-2.8.3}/PKG-INFO +1 -1
  2. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/converter.py +91 -43
  3. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/compress_wastickers.py +3 -3
  4. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/metadata_handler.py +5 -0
  5. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/version.py +1 -1
  6. {sticker-convert-2.8.2 → sticker-convert-2.8.3/src/sticker_convert.egg-info}/PKG-INFO +1 -1
  7. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/LICENSE +0 -0
  8. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/MANIFEST.in +0 -0
  9. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/README.md +0 -0
  10. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/pyproject.toml +0 -0
  11. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/requirements.txt +0 -0
  12. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/setup.cfg +0 -0
  13. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/__init__.py +0 -0
  14. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/__main__.py +0 -0
  15. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/cli.py +0 -0
  16. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/definitions.py +0 -0
  17. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/__init__.py +0 -0
  18. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/download_base.py +0 -0
  19. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/download_kakao.py +0 -0
  20. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/download_line.py +0 -0
  21. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/download_signal.py +0 -0
  22. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/downloaders/download_telegram.py +0 -0
  23. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui.py +0 -0
  24. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/__init__.py +0 -0
  25. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/__init__.py +0 -0
  26. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/comp_frame.py +0 -0
  27. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/config_frame.py +0 -0
  28. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/control_frame.py +0 -0
  29. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/cred_frame.py +0 -0
  30. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/input_frame.py +0 -0
  31. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/output_frame.py +0 -0
  32. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/progress_frame.py +0 -0
  33. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/frames/right_clicker.py +0 -0
  34. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/gui_utils.py +0 -0
  35. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/__init__.py +0 -0
  36. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/advanced_compression_window.py +0 -0
  37. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/base_window.py +0 -0
  38. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/kakao_get_auth_window.py +0 -0
  39. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/line_get_auth_window.py +0 -0
  40. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/gui_components/windows/signal_get_auth_window.py +0 -0
  41. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +0 -0
  42. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/.gitignore +0 -0
  43. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/README.md +0 -0
  44. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers/Info.plist +0 -0
  45. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +0 -0
  46. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +0 -0
  47. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +0 -0
  48. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +0 -0
  49. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
  50. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +0 -0
  51. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
  52. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +0 -0
  53. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
  54. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
  55. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +0 -0
  56. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
  57. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
  58. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
  59. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
  60. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
  61. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
  62. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
  63. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
  64. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
  65. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
  66. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
  67. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
  68. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +0 -0
  69. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  70. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  71. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  72. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  73. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/job.py +0 -0
  74. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/job_option.py +0 -0
  75. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  76. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/appicon.icns +0 -0
  77. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/appicon.ico +0 -0
  78. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/appicon.png +0 -0
  79. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/compression.json +0 -0
  80. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/emoji.json +0 -0
  81. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/help.json +0 -0
  82. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/input.json +0 -0
  83. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/resources/output.json +0 -0
  84. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/__init__.py +0 -0
  85. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/upload_base.py +0 -0
  86. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/upload_signal.py +0 -0
  87. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/upload_telegram.py +0 -0
  88. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/uploaders/xcode_imessage.py +0 -0
  89. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/auth/get_kakao_auth.py +0 -0
  90. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/auth/get_line_auth.py +0 -0
  91. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/auth/get_signal_auth.py +0 -0
  92. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/callback.py +0 -0
  93. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/cache_store.py +0 -0
  94. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/json_manager.py +0 -0
  95. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/json_resources_loader.py +0 -0
  96. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/run_bin.py +0 -0
  97. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/files/sanitize_filename.py +0 -0
  98. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/media/apple_png_normalize.py +0 -0
  99. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/media/codec_info.py +0 -0
  100. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/media/decrypt_kakao.py +0 -0
  101. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/media/format_verify.py +0 -0
  102. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert/utils/url_detect.py +0 -0
  103. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert.egg-info/SOURCES.txt +0 -0
  104. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert.egg-info/dependency_links.txt +0 -0
  105. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert.egg-info/entry_points.txt +0 -0
  106. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert.egg-info/requires.txt +0 -0
  107. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/src/sticker_convert.egg-info/top_level.txt +0 -0
  108. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/tests/test_compression.py +0 -0
  109. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/tests/test_download.py +0 -0
  110. {sticker-convert-2.8.2 → sticker-convert-2.8.3}/tests/test_export.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.2
3
+ Version: 2.8.3
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>
@@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Uni
9
9
  import numpy as np
10
10
  from PIL import Image
11
11
  from PIL import __version__ as PillowVersion
12
+ from PIL import features
12
13
 
13
14
  from sticker_convert.job_option import CompOption
14
15
  from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
@@ -32,6 +33,17 @@ MSG_FAIL_COMP = (
32
33
  "[F] Failed Compression {} -> {}, "
33
34
  "cannot get below limit {} with lowest quality under current settings (Best size: {})"
34
35
  )
36
+ MSG_PYWEBP_DUPFRAME = (
37
+ "[W] {} contains duplicated frame.\n"
38
+ " System WebP>=0.5.0 was not found, hence Pillow cannot be used\n"
39
+ " for creating animated webp. Using pywebp instead, which is known to\n"
40
+ " collapse same frames into single frame, causing problem with animation timing."
41
+ )
42
+ MSG_WEBP_PIL_DUPFRAME = (
43
+ "[W] {} contains duplicated frame.\n"
44
+ " Using Pillow to create animated webp to avoid same frames collapse\n"
45
+ " into single frame, but this is slower."
46
+ )
35
47
 
36
48
  YUV_RGB_MATRIX = np.array(
37
49
  [
@@ -41,6 +53,10 @@ YUV_RGB_MATRIX = np.array(
41
53
  ]
42
54
  )
43
55
 
56
+ # Whether animated WebP is supported
57
+ # See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#saving-sequences
58
+ PIL_WEBP_ANIM = cast(bool, features.check("webp_anim")) # type: ignore
59
+
44
60
 
45
61
  def get_step_value(
46
62
  max_step: Optional[int],
@@ -179,6 +195,8 @@ class StickerConvert:
179
195
  self.result_step: Optional[int] = None
180
196
 
181
197
  self.apngasm = None
198
+ self.msg_pywebp_dupframe_displayed = False
199
+ self.msg_webp_pil_dupframe_displayed = False
182
200
 
183
201
  @staticmethod
184
202
  def convert(
@@ -394,7 +412,7 @@ class StickerConvert:
394
412
  with open(self.out_f, "wb+") as f:
395
413
  f.write(data)
396
414
 
397
- if result_step:
415
+ if result_step is not None:
398
416
  msg = MSG_DONE_COMP.format(
399
417
  self.in_f_name, self.out_f_name, self.result_size, result_step
400
418
  )
@@ -678,14 +696,51 @@ class StickerConvert:
678
696
  self._frames_export_apng()
679
697
  else:
680
698
  self._frames_export_png()
681
- elif self.out_f.suffix == ".webp" and is_animated:
699
+ elif self.out_f.suffix == ".webp":
682
700
  self._frames_export_webp()
683
701
  elif self.out_f.suffix == ".gif":
684
- self._frames_export_gif()
702
+ self._frames_export_pil_anim()
685
703
  elif self.out_f.suffix in (".webm", ".mp4", ".mkv") or is_animated:
686
704
  self._frames_export_pyav()
687
705
  else:
688
706
  self._frames_export_pil()
707
+
708
+ def _check_dup(self) -> bool:
709
+ if len(self.frames_processed) == 1:
710
+ return False
711
+
712
+ prev_frame = self.frames_processed[0]
713
+ for frame in self.frames_processed[1:]:
714
+ if np.array_equal(frame, prev_frame):
715
+ return True
716
+ prev_frame = frame
717
+
718
+ return False
719
+
720
+ def _frames_export_webp(self) -> None:
721
+ has_dup_frames = self._check_dup()
722
+ if self.fps:
723
+ # It was noted that pywebp would collapse all frames.
724
+ # aed005b attempted to fix this by creating webp with
725
+ # variable frame duration. However, the webp created would
726
+ # not be accepted by WhatsApp.
727
+ # Therefore, we are preferring Pillow over pywebp.
728
+ if has_dup_frames:
729
+ if PIL_WEBP_ANIM:
730
+ # Warn that using Pillow is slower
731
+ if not self.msg_webp_pil_dupframe_displayed:
732
+ self.cb.put(MSG_WEBP_PIL_DUPFRAME.format(self.in_f_name))
733
+ self.msg_webp_pil_dupframe_displayed = True
734
+ self._frames_export_pil_anim()
735
+ else:
736
+ if not self.msg_pywebp_dupframe_displayed:
737
+ self.cb.put(MSG_PYWEBP_DUPFRAME.format(self.in_f_name))
738
+ self.msg_pywebp_dupframe_displayed = True
739
+ self._frames_export_pywebp()
740
+ else:
741
+ self._frames_export_pywebp()
742
+ else:
743
+ self._frames_export_pil()
689
744
 
690
745
  def _frames_export_pil(self) -> None:
691
746
  with Image.fromarray(self.frames_processed[0]) as im: # type: ignore
@@ -710,7 +765,7 @@ class StickerConvert:
710
765
  codec = "apng"
711
766
  pixel_format = "rgba"
712
767
  options["plays"] = "0"
713
- elif self.out_f.suffix in (".webp", ".webm", ".mkv"):
768
+ elif self.out_f.suffix in (".webm", ".mkv"):
714
769
  codec = "libvpx-vp9"
715
770
  pixel_format = "yuva420p"
716
771
  options["loop"] = "0"
@@ -734,7 +789,7 @@ class StickerConvert:
734
789
  output.mux(out_stream.encode(av_frame))
735
790
  output.mux(out_stream.encode())
736
791
 
737
- def _frames_export_gif(self) -> None:
792
+ def _frames_export_pil_anim(self) -> None:
738
793
  extra_kwargs: Dict[str, Any] = {}
739
794
 
740
795
  # disposal=2 on gif cause flicker in image with transparency
@@ -745,25 +800,34 @@ class StickerConvert:
745
800
  else:
746
801
  extra_kwargs["optimize"] = True
747
802
 
748
- # GIF can only have one alpha color
749
- # Change lowest alpha to alpha=0
750
- # Only keep alpha=0 and alpha=255, nothing in between
751
- frames_processed = np.array(self.frames_processed)
752
- alpha = frames_processed[:, :, :, 3]
753
- alpha_min = np.min(alpha) # type: ignore
754
- if alpha_min < 255:
755
- alpha[alpha > alpha_min] = 255
756
- alpha[alpha == alpha_min] = 0
757
-
758
- if 0 in alpha:
759
- extra_kwargs["transparency"] = 0
760
- extra_kwargs["disposal"] = 2
761
- im_out = [self.quantize(Image.fromarray(i)) for i in frames_processed] # type: ignore
803
+ if self.out_f.suffix == ".gif":
804
+ # GIF can only have one alpha color
805
+ # Change lowest alpha to alpha=0
806
+ # Only keep alpha=0 and alpha=255, nothing in between
807
+ frames_processed = np.array(self.frames_processed)
808
+ alpha = frames_processed[:, :, :, 3]
809
+ alpha_min = np.min(alpha) # type: ignore
810
+ if alpha_min < 255:
811
+ alpha[alpha > alpha_min] = 255
812
+ alpha[alpha == alpha_min] = 0
813
+
814
+ if 0 in alpha:
815
+ extra_kwargs["transparency"] = 0
816
+ extra_kwargs["disposal"] = 2
817
+ im_out = [self.quantize(Image.fromarray(i)) for i in frames_processed] # type: ignore
818
+ else:
819
+ im_out = [
820
+ self.quantize(Image.fromarray(i).convert("RGB")).convert("RGB") # type: ignore
821
+ for i in frames_processed
822
+ ]
823
+ extra_kwargs["format"] = "GIF"
824
+ elif self.out_f.suffix == ".webp":
825
+ im_out = [Image.fromarray(i) for i in self.frames_processed] # type: ignore
826
+ extra_kwargs["format"] = "WebP"
827
+ extra_kwargs["minimize_size"] = True
828
+ extra_kwargs["method"] = 6
762
829
  else:
763
- im_out = [
764
- self.quantize(Image.fromarray(i).convert("RGB")).convert("RGB") # type: ignore
765
- for i in frames_processed
766
- ]
830
+ raise RuntimeError(f"Invalid format {self.out_f.suffix}")
767
831
 
768
832
  if self.fps:
769
833
  extra_kwargs["save_all"] = True
@@ -773,12 +837,11 @@ class StickerConvert:
773
837
 
774
838
  im_out[0].save(
775
839
  self.tmp_f,
776
- format="GIF",
777
840
  quality=self.quality,
778
841
  **extra_kwargs,
779
842
  )
780
843
 
781
- def _frames_export_webp(self) -> None:
844
+ def _frames_export_pywebp(self) -> None:
782
845
  import webp # type: ignore
783
846
 
784
847
  assert self.fps
@@ -786,25 +849,10 @@ class StickerConvert:
786
849
  config = webp.WebPConfig.new(quality=self.quality) # type: ignore
787
850
  enc = webp.WebPAnimEncoder.new(self.res_w, self.res_h) # type: ignore
788
851
  timestamp_ms = 0
789
- timestamp_inc = int(1000 / self.fps)
790
-
791
- pic = webp.WebPPicture.from_numpy(self.frames_processed[0]) # type: ignore
792
- enc.encode_frame(pic, 0, config=config) # type: ignore
793
-
794
- frame_num = 1
795
- frame_num_prev = 1
796
- frame_total = len(self.frames_processed)
797
- while frame_num < frame_total - 1:
798
- while frame_num < frame_total - 1 and np.array_equal(
799
- self.frames_processed[frame_num_prev],
800
- self.frames_processed[frame_num],
801
- ):
802
- timestamp_ms += timestamp_inc
803
- frame_num += 1
804
- pic = webp.WebPPicture.from_numpy(self.frames_processed[frame_num]) # type: ignore
852
+ for frame in self.frames_processed:
853
+ pic = webp.WebPPicture.from_numpy(frame) # type: ignore
805
854
  enc.encode_frame(pic, timestamp_ms, config=config) # type: ignore
806
- frame_num_prev = frame_num
807
-
855
+ timestamp_ms += int(1000 / self.fps)
808
856
  anim_data = enc.assemble(timestamp_ms) # type: ignore
809
857
  self.tmp_f.write(anim_data.buffer()) # type: ignore
810
858
 
@@ -79,7 +79,7 @@ class CompressWastickers(UploadBase):
79
79
  else:
80
80
  ext = ".png"
81
81
 
82
- dst = Path(tempdir, str(num) + ext)
82
+ dst = Path(tempdir, f"sticker_{num+1}{ext}")
83
83
 
84
84
  if FormatVerify.check_file(
85
85
  src, spec=self.webp_spec
@@ -114,7 +114,7 @@ class CompressWastickers(UploadBase):
114
114
  opt_comp_merged.merge(self.spec_cover)
115
115
 
116
116
  cover_path_old = MetadataHandler.get_cover(self.opt_output.dir)
117
- cover_path_new = Path(pack_dir, "100.png")
117
+ cover_path_new = Path(pack_dir, "tray.png")
118
118
  if cover_path_old:
119
119
  if FormatVerify.check_file(cover_path_old, spec=self.spec_cover):
120
120
  shutil.copy(cover_path_old, cover_path_new)
@@ -142,7 +142,7 @@ class CompressWastickers(UploadBase):
142
142
  self.cb_return,
143
143
  )
144
144
 
145
- MetadataHandler.set_metadata(pack_dir, author=author, title=title)
145
+ MetadataHandler.set_metadata(pack_dir, author=author, title=title, newline=True)
146
146
 
147
147
  @staticmethod
148
148
  def start(
@@ -133,16 +133,21 @@ class MetadataHandler:
133
133
  title: Optional[str] = None,
134
134
  author: Optional[str] = None,
135
135
  emoji_dict: Optional[Dict[str, str]] = None,
136
+ newline: bool = False,
136
137
  ) -> None:
137
138
  title_path = Path(directory, "title.txt")
138
139
  if title is not None:
139
140
  with open(title_path, "w+", encoding="utf-8") as f:
140
141
  f.write(title)
142
+ if newline:
143
+ f.write("\n")
141
144
 
142
145
  author_path = Path(directory, "author.txt")
143
146
  if author is not None:
144
147
  with open(author_path, "w+", encoding="utf-8") as f:
145
148
  f.write(author)
149
+ if newline:
150
+ f.write("\n")
146
151
 
147
152
  emoji_path = Path(directory, "emoji.txt")
148
153
  if emoji_dict is not None:
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.2"
3
+ __version__ = "2.8.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.2
3
+ Version: 2.8.3
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>
File without changes