sticker-convert 2.13.2.2__py3-none-any.whl → 2.14.0.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.
sticker_convert/cli.py CHANGED
@@ -15,8 +15,9 @@ from sticker_convert.definitions import CONFIG_DIR, DEFAULT_DIR
15
15
  from sticker_convert.job import Job
16
16
  from sticker_convert.job_option import CompOption, CredOption, InputOption, OutputOption
17
17
  from sticker_convert.utils.auth.get_discord_auth import GetDiscordAuth
18
- from sticker_convert.utils.auth.get_kakao_auth import GetKakaoAuth
19
- from sticker_convert.utils.auth.get_kakao_desktop_auth import GetKakaoDesktopAuth
18
+ from sticker_convert.utils.auth.get_kakao_auth_android_login import GetKakaoAuthAndroidLogin
19
+ from sticker_convert.utils.auth.get_kakao_auth_desktop_login import GetKakaoAuthDesktopLogin
20
+ from sticker_convert.utils.auth.get_kakao_auth_desktop_memdump import GetKakaoAuthDesktopMemdump
20
21
  from sticker_convert.utils.auth.get_line_auth import GetLineAuth
21
22
  from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
22
23
  from sticker_convert.utils.auth.get_viber_auth import GetViberAuth
@@ -141,7 +142,12 @@ class CLI:
141
142
  "quantize_method",
142
143
  "chromium_path",
143
144
  )
144
- flags_comp_bool = ("fake_vid",)
145
+ flags_comp_bool = (
146
+ "fake_vid",
147
+ "no_fake_vid",
148
+ "res_snap_pow2",
149
+ "no_res_snap_pow2",
150
+ )
145
151
  keyword_args: Dict[str, Any]
146
152
  for k, v in self.help["comp"].items():
147
153
  if k in flags_comp_int:
@@ -171,8 +177,9 @@ class CLI:
171
177
  flags_cred_bool = (
172
178
  "signal_get_auth",
173
179
  "telethon_setup",
174
- "kakao_get_auth",
175
- "kakao_get_auth_desktop",
180
+ "kakao_get_auth_desktop_memdump",
181
+ "kakao_get_auth_desktop_login",
182
+ "kakao_get_auth_android_login",
176
183
  "line_get_auth",
177
184
  "discord_get_auth",
178
185
  "save_cred",
@@ -394,6 +401,9 @@ class CLI:
394
401
  res_power=self.compression_presets[preset]["res"]["power"]
395
402
  if args.res_power is None
396
403
  else args.res_power,
404
+ res_snap_pow2=self.compression_presets[preset]["res"]["snap_pow2"]
405
+ if args.res_snap_pow2 is None and args.no_res_snap_pow2 is None
406
+ else args.res_snap_pow2,
397
407
  quality_min=self.compression_presets[preset]["quality"]["min"]
398
408
  if args.quality_min is None
399
409
  else args.quality_min,
@@ -428,7 +438,7 @@ class CLI:
428
438
  if args.steps is None
429
439
  else args.steps,
430
440
  fake_vid=self.compression_presets[preset]["fake_vid"]
431
- if args.fake_vid is None
441
+ if args.fake_vid is None and args.no_fake_vid is None
432
442
  else args.fake_vid,
433
443
  chromium_path=args.chromium_path,
434
444
  cache_dir=args.cache_dir,
@@ -503,28 +513,42 @@ class CLI:
503
513
  else creds.get("discord", {}).get("token"),
504
514
  )
505
515
 
506
- if args.kakao_get_auth:
507
- get_kakao_auth = GetKakaoAuth(
516
+ if args.kakao_get_auth_android_login:
517
+ get_kakao_auth_android_login = GetKakaoAuthAndroidLogin(
508
518
  opt_cred=opt_cred,
509
519
  cb_msg=self.cb.msg,
510
520
  cb_msg_block=self.cb.msg_block,
511
521
  cb_ask_str=self.cb.ask_str,
512
522
  )
513
- auth_token = get_kakao_auth.get_cred()
523
+ auth_token = get_kakao_auth_android_login.get_cred()
514
524
 
515
525
  if auth_token:
516
526
  opt_cred.kakao_auth_token = auth_token
517
527
 
518
528
  self.cb.msg(f"Got auth_token successfully: {auth_token}")
519
529
 
520
- if args.kakao_get_auth_desktop:
521
- get_kakao_desktop_auth = GetKakaoDesktopAuth(
530
+ if args.kakao_get_auth_desktop_memdump:
531
+ get_kakao_auth_desktop_memdump = GetKakaoAuthDesktopMemdump(
522
532
  cb_ask_str=self.cb.ask_str,
523
533
  )
524
534
  kakao_bin_path = None
525
535
  if args.kakao_bin_path:
526
536
  kakao_bin_path = args.kakao_bin_path
527
- auth_token, msg = get_kakao_desktop_auth.get_cred(kakao_bin_path)
537
+ auth_token, msg = get_kakao_auth_desktop_memdump.get_cred(kakao_bin_path)
538
+
539
+ if auth_token:
540
+ opt_cred.kakao_auth_token = auth_token
541
+
542
+ self.cb.msg(msg)
543
+
544
+ if args.kakao_get_auth_desktop_login:
545
+ get_kakao_auth_desktop_login = GetKakaoAuthDesktopLogin(
546
+ opt_cred=opt_cred,
547
+ cb_msg=self.cb.msg,
548
+ cb_msg_block=self.cb.msg_block,
549
+ cb_ask_str=self.cb.ask_str,
550
+ )
551
+ auth_token, msg = get_kakao_auth_desktop_login.get_cred()
528
552
 
529
553
  if auth_token:
530
554
  opt_cred.kakao_auth_token = auth_token
@@ -3,7 +3,7 @@ import json
3
3
  import os
4
4
  from fractions import Fraction
5
5
  from io import BytesIO
6
- from math import ceil, floor
6
+ from math import ceil, floor, log2
7
7
  from pathlib import Path
8
8
  from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union, cast
9
9
 
@@ -57,6 +57,7 @@ def get_step_value(
57
57
  steps: int,
58
58
  power: float = 1.0,
59
59
  even: bool = False,
60
+ snap_pow2: bool = False,
60
61
  ) -> Optional[int]:
61
62
  # Power should be between -1 and positive infinity
62
63
  # Smaller power = More 'importance' of the parameter
@@ -70,6 +71,15 @@ def get_step_value(
70
71
 
71
72
  if max_step is not None and min_step is not None:
72
73
  v = round((max_step - min_step) * step / steps * factor + min_step)
74
+ if snap_pow2 is True and floor(log2(max_step)) >= ceil(log2(min_step)):
75
+ lower_exp = max(floor(log2(v)), ceil(log2(min_step)))
76
+ lower_pow2 = 2**lower_exp
77
+ upper_exp = min(ceil(log2(v)), floor(log2(max_step)))
78
+ upper_pow2 = 2**upper_exp
79
+ if abs(v - lower_pow2) <= abs(v - upper_pow2):
80
+ return lower_pow2
81
+ else:
82
+ return upper_pow2
73
83
  if even is True and v % 2 == 1:
74
84
  return v + 1
75
85
  return v
@@ -101,10 +111,10 @@ def yuva_to_rgba(frame: "VideoFrame") -> "np.ndarray[Any, Any]":
101
111
  u = u.repeat(2, axis=0).repeat(2, axis=1)
102
112
  v = v.repeat(2, axis=0).repeat(2, axis=1)
103
113
 
104
- y = y.reshape((y.shape[0], y.shape[1], 1))
105
- u = u.reshape((u.shape[0], u.shape[1], 1))
106
- v = v.reshape((v.shape[0], v.shape[1], 1))
107
- a = a.reshape((a.shape[0], a.shape[1], 1))
114
+ y = y.reshape((y.shape[0], y.shape[1], 1)) # type: ignore
115
+ u = u.reshape((u.shape[0], u.shape[1], 1)) # type: ignore
116
+ v = v.reshape((v.shape[0], v.shape[1], 1)) # type: ignore
117
+ a = a.reshape((a.shape[0], a.shape[1], 1)) # type: ignore
108
118
 
109
119
  yuv_array = np.concatenate((y, u, v), axis=2)
110
120
 
@@ -342,6 +352,7 @@ class StickerConvert:
342
352
  self.opt_comp.steps,
343
353
  self.opt_comp.res_power,
344
354
  need_even,
355
+ self.opt_comp.res_snap_pow2,
345
356
  ),
346
357
  get_step_value(
347
358
  self.opt_comp.res_h_max,
@@ -350,6 +361,7 @@ class StickerConvert:
350
361
  self.opt_comp.steps,
351
362
  self.opt_comp.res_power,
352
363
  need_even,
364
+ self.opt_comp.res_snap_pow2,
353
365
  ),
354
366
  get_step_value(
355
367
  self.opt_comp.quality_max,
@@ -932,13 +944,19 @@ class StickerConvert:
932
944
  self.tmp_f.write(frame_optimized)
933
945
 
934
946
  def _frames_export_apng(self) -> None:
935
- from apngasm_python._apngasm_python import APNGAsm, create_frame_from_rgba # type: ignore
947
+ from apngasm_python._apngasm_python import APNGAsm, create_frame_from_rgb, create_frame_from_rgba # type: ignore
936
948
 
937
949
  assert self.fps
938
950
  assert self.res_h
939
951
 
940
952
  frames_concat = np.concatenate(self.frames_processed)
941
953
  with Image.fromarray(frames_concat, "RGBA") as image_concat: # type: ignore
954
+ if image_concat.getextrema()[3][0] < 255: # type: ignore
955
+ mode = "RGBA"
956
+ create_frame_method = create_frame_from_rgba
957
+ else:
958
+ mode = "RGB"
959
+ create_frame_method = create_frame_from_rgb
942
960
  image_quant = self.quantize(image_concat)
943
961
 
944
962
  if self.apngasm is None:
@@ -947,15 +965,10 @@ class StickerConvert:
947
965
 
948
966
  delay_num = int(1000 / self.fps)
949
967
  for i in range(0, image_quant.height, self.res_h):
950
- with BytesIO() as f:
951
- crop_dimension = (0, i, image_quant.width, i + self.res_h)
952
- image_cropped = image_quant.crop(crop_dimension)
953
- image_cropped.save(f, format="png")
954
- f.seek(0)
955
- frame_optimized = self.optimize_png(f.read())
956
- with Image.open(BytesIO(frame_optimized)) as im:
957
- image_final = im.convert("RGBA")
958
- frame_final = create_frame_from_rgba(
968
+ crop_dimension = (0, i, image_quant.width, i + self.res_h)
969
+ image_cropped = image_quant.crop(crop_dimension)
970
+ image_final = image_cropped.convert(mode)
971
+ frame_final = create_frame_method(
959
972
  np.array(image_final),
960
973
  width=image_final.width,
961
974
  height=image_final.height,
@@ -969,7 +982,8 @@ class StickerConvert:
969
982
  self.apngasm.assemble(tmp_apng.as_posix())
970
983
 
971
984
  with open(tmp_apng, "rb") as f:
972
- self.tmp_f.write(f.read())
985
+ apng_optimized = self.optimize_png(f.read())
986
+ self.tmp_f.write(apng_optimized)
973
987
 
974
988
  self.apngasm.reset()
975
989
 
@@ -978,7 +992,7 @@ class StickerConvert:
978
992
 
979
993
  return oxipng.optimize_from_memory(
980
994
  image_bytes,
981
- level=4,
995
+ level=6,
982
996
  fix_errors=True,
983
997
  filter=[oxipng.RowFilter.Brute],
984
998
  optimize_alpha=True,
@@ -990,8 +1004,8 @@ class StickerConvert:
990
1004
  return image.copy()
991
1005
  if self.opt_comp.quantize_method == "imagequant":
992
1006
  return self._quantize_by_imagequant(image)
993
- if self.opt_comp.quantize_method == "fastoctree":
994
- return self._quantize_by_fastoctree(image)
1007
+ if self.opt_comp.quantize_method in ("mediancut", "maxcoverage", "fastoctree"):
1008
+ return self._quantize_by_pillow(image)
995
1009
 
996
1010
  return image
997
1011
 
@@ -1022,10 +1036,24 @@ class StickerConvert:
1022
1036
 
1023
1037
  return image
1024
1038
 
1025
- def _quantize_by_fastoctree(self, image: Image.Image) -> Image.Image:
1039
+ def _quantize_by_pillow(self, image: Image.Image) -> Image.Image:
1026
1040
  assert self.color
1027
1041
 
1028
- return image.quantize(colors=self.color, method=2)
1042
+ if image.mode == "RGBA" and self.opt_comp.quantize_method in (
1043
+ "mediancut",
1044
+ "maxcoverage",
1045
+ ):
1046
+ self.cb.put(
1047
+ f"[W] {self.opt_comp.quantize_method} does not support RGBA, defaulted to fastoctree quantization"
1048
+ )
1049
+ method = Image.Quantize.FASTOCTREE
1050
+ elif self.opt_comp.quantize_method == "mediancut":
1051
+ method = Image.Quantize.MEDIANCUT
1052
+ elif self.opt_comp.quantize_method == "maxcoverage":
1053
+ method = Image.Quantize.MAXCOVERAGE
1054
+ else:
1055
+ method = Image.Quantize.FASTOCTREE
1056
+ return image.quantize(colors=self.color, method=method)
1029
1057
 
1030
1058
  def fix_fps(self, fps: float) -> Fraction:
1031
1059
  # After rounding fps/duration during export,
sticker_convert/gui.py CHANGED
@@ -116,6 +116,7 @@ class GUI(Window):
116
116
  self.res_h_max_var = IntVar(self)
117
117
  self.res_h_disable_var = BooleanVar()
118
118
  self.res_power_var = DoubleVar()
119
+ self.res_snap_pow2_var = BooleanVar()
119
120
  self.quality_min_var = IntVar(self)
120
121
  self.quality_max_var = IntVar(self)
121
122
  self.quality_disable_var = BooleanVar()
@@ -162,6 +163,7 @@ class GUI(Window):
162
163
  self.kakao_password_var = StringVar(self)
163
164
  self.kakao_country_code_var = StringVar(self)
164
165
  self.kakao_phone_number_var = StringVar(self)
166
+ self.kakao_device_uuid_var = StringVar(self)
165
167
  self.kakao_bin_path_var = StringVar(self)
166
168
  self.line_cookies_var = StringVar(self)
167
169
  self.viber_auth_var = StringVar(self)
@@ -426,6 +428,9 @@ class GUI(Window):
426
428
  self.kakao_phone_number_var.set(
427
429
  self.creds.get("kakao", {}).get("phone_number", "")
428
430
  )
431
+ self.kakao_device_uuid_var.set(
432
+ self.creds.get("kakao", {}).get("device_uuid", "")
433
+ )
429
434
  self.line_cookies_var.set(self.creds.get("line", {}).get("cookies", ""))
430
435
  self.viber_auth_var.set(self.creds.get("viber", {}).get("auth", ""))
431
436
  self.discord_token_var.set(self.creds.get("discord", {}).get("token", ""))
@@ -547,6 +552,7 @@ class GUI(Window):
547
552
  if not self.res_h_disable_var.get()
548
553
  else None,
549
554
  res_power=self.res_power_var.get(),
555
+ res_snap_pow2=self.res_snap_pow2_var.get(),
550
556
  quality_min=self.quality_min_var.get()
551
557
  if not self.quality_disable_var.get()
552
558
  else None,
@@ -597,6 +603,7 @@ class GUI(Window):
597
603
  kakao_password=self.kakao_password_var.get(),
598
604
  kakao_country_code=self.kakao_country_code_var.get(),
599
605
  kakao_phone_number=self.kakao_phone_number_var.get(),
606
+ kakao_device_uuid=self.kakao_device_uuid_var.get(),
600
607
  line_cookies=self.line_cookies_var.get(),
601
608
  viber_auth=self.viber_auth_var.get(),
602
609
  discord_token=self.discord_token_var.get(),
@@ -119,6 +119,7 @@ class CompFrame(LabelFrame):
119
119
  self.gui.res_h_min_var.set(preset.get("res", {}).get("h", {}).get("min"))
120
120
  self.gui.res_h_max_var.set(preset.get("res", {}).get("h", {}).get("max"))
121
121
  self.gui.res_power_var.set(preset.get("res", {}).get("power"))
122
+ self.gui.res_snap_pow2_var.set(preset.get("res", {}).get("snap_pow2"))
122
123
  self.gui.quality_min_var.set(preset.get("quality", {}).get("min"))
123
124
  self.gui.quality_max_var.set(preset.get("quality", {}).get("max"))
124
125
  self.gui.quality_power_var.set(preset.get("quality", {}).get("power"))
@@ -15,7 +15,6 @@ from sticker_convert.gui_components.windows.base_window import BaseWindow
15
15
 
16
16
 
17
17
  class AdvancedCompressionWindow(BaseWindow):
18
- emoji_column_per_row = 8
19
18
  emoji_visible_rows = 5
20
19
  emoji_btns: List[Tuple[Button, ImageTk.PhotoImage]] = []
21
20
 
@@ -101,6 +100,20 @@ class AdvancedCompressionWindow(BaseWindow):
101
100
  bootstyle="danger-round-toggle", # type: ignore
102
101
  )
103
102
 
103
+ self.res_snap_pow2_help_btn = self.add_help_btn(
104
+ self.gui.help["comp"]["res_snap_pow2"]
105
+ )
106
+ self.res_snap_pow2_lbl = Label(
107
+ self.frame_advcomp, text="Snap resolution to power of 2"
108
+ )
109
+ self.res_snap_pow2_cbox = Checkbutton(
110
+ self.frame_advcomp,
111
+ variable=self.gui.res_snap_pow2_var,
112
+ onvalue=True,
113
+ offvalue=False,
114
+ bootstyle="success-round-toggle", # type: ignore
115
+ )
116
+
104
117
  self.quality_help_btn = self.add_help_btn(self.gui.help["comp"]["quality"])
105
118
  self.quality_lbl = Label(self.frame_advcomp, text="Output quality (0-100)")
106
119
  self.quality_min_lbl = Label(self.frame_advcomp, text="Min:")
@@ -289,6 +302,8 @@ class AdvancedCompressionWindow(BaseWindow):
289
302
  self.gui.quantize_method_var.get(),
290
303
  "imagequant",
291
304
  "fastoctree",
305
+ "maxcoverage",
306
+ "mediancut",
292
307
  "none",
293
308
  bootstyle="secondary", # type: ignore
294
309
  )
@@ -326,7 +341,7 @@ class AdvancedCompressionWindow(BaseWindow):
326
341
  self.fps_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
327
342
  self.fps_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
328
343
  self.fps_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
329
- self.fps_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
344
+ self.fps_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
330
345
  r += 1
331
346
  self.res_w_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
332
347
  self.res_w_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -334,7 +349,7 @@ class AdvancedCompressionWindow(BaseWindow):
334
349
  self.res_w_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
335
350
  self.res_w_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
336
351
  self.res_w_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
337
- self.res_w_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
352
+ self.res_w_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
338
353
  r += 1
339
354
  self.res_h_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
340
355
  self.res_h_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -342,7 +357,11 @@ class AdvancedCompressionWindow(BaseWindow):
342
357
  self.res_h_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
343
358
  self.res_h_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
344
359
  self.res_h_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
345
- self.res_h_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
360
+ self.res_h_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
361
+ r += 1
362
+ self.res_snap_pow2_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
363
+ self.res_snap_pow2_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
364
+ self.res_snap_pow2_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
346
365
  r += 1
347
366
  self.quality_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
348
367
  self.quality_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -350,7 +369,7 @@ class AdvancedCompressionWindow(BaseWindow):
350
369
  self.quality_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
351
370
  self.quality_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
352
371
  self.quality_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
353
- self.quality_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
372
+ self.quality_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
354
373
  r += 1
355
374
  self.color_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
356
375
  self.color_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -358,7 +377,7 @@ class AdvancedCompressionWindow(BaseWindow):
358
377
  self.color_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
359
378
  self.color_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
360
379
  self.color_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
361
- self.color_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
380
+ self.color_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
362
381
  r += 1
363
382
  self.duration_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
364
383
  self.duration_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -366,7 +385,7 @@ class AdvancedCompressionWindow(BaseWindow):
366
385
  self.duration_min_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
367
386
  self.duration_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
368
387
  self.duration_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
369
- self.duration_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
388
+ self.duration_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
370
389
  r += 1
371
390
  self.size_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
372
391
  self.size_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -374,14 +393,14 @@ class AdvancedCompressionWindow(BaseWindow):
374
393
  self.img_size_max_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
375
394
  self.vid_size_max_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
376
395
  self.vid_size_max_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
377
- self.size_disable_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
396
+ self.size_disable_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
378
397
  r += 1
379
398
  self.format_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
380
399
  self.format_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
381
400
  self.img_format_lbl.grid(column=2, row=r, sticky="w", padx=3, pady=3)
382
401
  self.img_format_entry.grid(column=3, row=r, sticky="nes", padx=3, pady=3)
383
402
  self.vid_format_lbl.grid(column=4, row=r, sticky="w", padx=3, pady=3)
384
- self.vid_format_entry.grid(column=5, row=r, sticky="nes", padx=3, pady=3)
403
+ self.vid_format_entry.grid(column=5, row=r, sticky="w", padx=3, pady=3)
385
404
  r += 1
386
405
  self.power_help_btn1.grid(column=0, row=r, sticky="w", padx=3, pady=3)
387
406
  self.power_lbl1.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -404,12 +423,12 @@ class AdvancedCompressionWindow(BaseWindow):
404
423
  r += 1
405
424
  self.fake_vid_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
406
425
  self.fake_vid_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
407
- self.fake_vid_cbox.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
426
+ self.fake_vid_cbox.grid(column=6, row=r, sticky="w", padx=3, pady=3)
408
427
  r += 1
409
428
  self.bg_color_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
410
429
  self.bg_color_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
411
430
  self.bg_color_entry.grid(column=5, row=r, sticky="w", padx=3, pady=3)
412
- self.bg_color_btn.grid(column=6, row=r, sticky="nes", padx=3, pady=3)
431
+ self.bg_color_btn.grid(column=6, row=r, sticky="w", padx=3, pady=3)
413
432
  r += 1
414
433
  self.scale_filter_help_btn.grid(column=0, row=r, sticky="w", padx=3, pady=3)
415
434
  self.scale_filter_lbl.grid(column=1, row=r, sticky="w", padx=3, pady=3)
@@ -662,6 +681,7 @@ class AdvancedCompressionWindow(BaseWindow):
662
681
 
663
682
  column = 0
664
683
  row = 0
684
+ emoji_column_per_row = 0
665
685
 
666
686
  self.emoji_btns = []
667
687
  for entry in self.gui.emoji_list:
@@ -702,7 +722,12 @@ class AdvancedCompressionWindow(BaseWindow):
702
722
 
703
723
  column += 1
704
724
 
705
- if column == self.emoji_column_per_row:
725
+ if emoji_column_per_row == 0:
726
+ self.emoji_canvas.update_idletasks()
727
+ emoji_column_per_row = int(
728
+ self.emoji_canvas.winfo_width() / button.winfo_width()
729
+ )
730
+ if column == emoji_column_per_row:
706
731
  column = 0
707
732
  row += 1
708
733
 
@@ -714,7 +739,7 @@ class AdvancedCompressionWindow(BaseWindow):
714
739
  # Resize the canvas frame to show specified number of buttons and the scrollbar
715
740
  if len(self.emoji_btns) > 0:
716
741
  in_view_columns_width = (
717
- self.emoji_btns[0][0].winfo_width() * self.emoji_column_per_row
742
+ self.emoji_btns[0][0].winfo_width() * emoji_column_per_row
718
743
  )
719
744
  in_view_rows_height = (
720
745
  self.emoji_btns[0][0].winfo_height() * self.emoji_visible_rows