Skip to content

Commit

Permalink
Merge pull request #11 from umyuu/feature/0.0.6
Browse files Browse the repository at this point in the history
Feature/0.0.6
  • Loading branch information
umyuu authored Jun 23, 2024
2 parents 4b70ccb + 57d60d3 commit f23669f
Show file tree
Hide file tree
Showing 17 changed files with 395 additions and 316 deletions.
2 changes: 0 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@
"args": [
"app.py",
"--icon=assets/icons/app_icon.ico",
"--onefile",
"--windowed",
"--name",
"MosaicTool",
"--noconfirm",
"--noconsole",
"--clean",
"--collect-data",
"tkinterdnd2",
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"columnspan",
"confirmoverwrite",
"exif",
"initialfile",
"ipadx",
"itxt",
"opsz",
Expand Down
14 changes: 10 additions & 4 deletions MosaicTool.spec
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,13 @@ pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
exclude_binaries=True,
name='MosaicTool',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
Expand All @@ -41,3 +38,12 @@ exe = EXE(
entitlements_file=None,
icon=['assets\\icons\\app_icon.ico'],
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='MosaicTool',
)
Binary file modified dist/MosaicTool.zip
Binary file not shown.
4 changes: 2 additions & 2 deletions dist/ReadMe.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
2024/06/16 ver 0.0.5
2024/06/23 ver 0.0.6
# 🌟 MosaicTool — モザイク編集のお供に
![Python version](https://img.shields.io/badge/python-3.9+-important)

Expand Down Expand Up @@ -47,7 +47,7 @@


## ハッシュ値
MosaicTool.exe Hash Value (SHA-256): 6527274CE267D508E34E030CA6071C75DA54B9BBC2B420948D71E1220040F203
MosaicTool.exe Hash Value (SHA-256): 331B940D7F8712B7C0AAA8DD1CC526522BC9EDD215ECB1771C5A9EE882F87434

## 補足説明
1. アプリがアンチウィルスソフトで検知された場合は、使用しているライブラリが影響している誤検知です。
Expand Down
6 changes: 2 additions & 4 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
- `./run.bat`: app.pyを実行するスクリプト。またはVSCodeの実行ボタンより。
- `./build.bat`: 実行ファイルを作成するスクリプト。PyInstallerライブラリを使用して生成します。
- `./release.bat`: 配布用zipファイルを作成するスクリプト。release.pyを使用します。
- 🎨`/dist`: 実行ファイル生成フォルダ。
視覚的な要素を提供します。
- 🎨`/dist`: 実行ファイル生成フォルダ。
視覚的な要素を提供します。
- 🎨`/assets`: アプリで使用するプログラムアイコン
- 📦`/dist`: 実行ファイル生成フォルダ。配布物のディレクトリ
- 🎨`/third_party`:サードパーティのリソースを含むディレクトリ。
- `/third_party/icons`:アプリで使用するアイコン。
- 📚`/docs`: ドキュメンテーション。
Expand Down
Binary file modified docs/initial_screen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 21 additions & 34 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from src import PROGRAM_NAME, get_package_version
from src.utils import Stopwatch

__version__ = get_package_version()

Expand Down Expand Up @@ -63,45 +64,31 @@ def create_readMe(file1_path: Path, file2_path: Path, hash_value: str, output_pa
output_path.write_text(readme_content, "utf-8")


def get_compressible_files(root_dir: Path, exclude_files: list[Path]) -> list[Path]:
def create_zip(folder_path: Path, output_zip: Path, additional_files_with_names: dict[Path, str]) -> int:
"""
圧縮対象のファイル一覧を取得します
引数で指定されたフォルダとファイルをZIPファイルに格納します
:param root_dir: 圧縮したいディレクトリのパス。
:param exclude_file: 除外するファイルのリスト。
:return: 圧縮対象のファイルパスのリスト。
"""
compressible_files: list[Path] = []

for file_path in glob.glob(str(root_dir) + "/*.*"):
file_path = Path(file_path) # 文字列からPathに変換
if not any(file_path.samefile(exclude_file) for exclude_file in exclude_files if exclude_file.exists()):
compressible_files.append(file_path)

return compressible_files


def create_zip(source_files: list[Path], output_zip: Path, additional_files_with_names: dict[Path, str]) -> int:
"""
引数で指定されたファイルをZIPファイルに格納します。
:param source_files: ZIPファイルに含めるファイル。
:param folder_path: ZIPファイルに含めるフォルダ。
:param output_zip: 出力するZIPファイルのパス。
:param additional_files_with_names: 追加ファイルとその保存名の辞書。
:return: ZIPファイルに追加されたファイルの数。
"""
count: int = 0

with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zip_file:
for file_path in source_files:
print(file_path)
zip_file.write(file_path, arcname=file_path.name)
count += 1
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = Path(root) / file
arcname = file_path.relative_to(folder_path)
zip_file.write(file_path, arcname)
print(arcname)
count += 1

for file_path, save_name in additional_files_with_names.items():
print(file_path)
zip_file.write(file_path, arcname=save_name)
count += 1

return count


Expand All @@ -112,37 +99,37 @@ class SetupConfigRation:
"""
source_dir: Path = Path("dist")
output_zip: Path = source_dir / f"{PROGRAM_NAME}.zip"
app_file: Path = source_dir / f"{PROGRAM_NAME}.exe"
app_file: Path = source_dir / f"{PROGRAM_NAME}/{PROGRAM_NAME}.exe"
handouts_file: Path = source_dir / "handouts.txt"
exclude_files: list[Path] = field(default_factory=list)


def main():
start: float = time.perf_counter()
sw = Stopwatch.start_new()
# Configuration
config = SetupConfigRation()
# 除外するファイル
config.exclude_files.extend([config.output_zip, config.source_dir / ".gitignore", config.handouts_file])
# zipファイルに追加するファイル

readme = config.source_dir / "ReadMe.txt"
additional_files_with_names = {
readme: readme.name,
Path("docs/initial_screen.png"): "initial_screen.png",
Path(f"{PROGRAM_NAME}.json"): f"sample/{PROGRAM_NAME}.json",
}

hash_value = hash_compute(config.app_file)
print(f"Compute hash, ({time.perf_counter() - start:.3f}s)")
print(f"Compute hash, ({sw.elapsed:.3f}s)")

create_readMe(Path("ReadMe.md"), config.handouts_file, hash_value, config.source_dir / "ReadMe.txt")
print(f"Created ReadMe.txt, ({time.perf_counter() - start:.3f}s)")
create_readMe(Path("ReadMe.md"), config.handouts_file, hash_value, readme)
print(f"Created ReadMe.txt, ({sw.elapsed:.3f}s)")

compressible_files = get_compressible_files(config.source_dir, config.exclude_files)
print(f"Get_compressible_files, ({time.perf_counter() - start:.3f}s)")
count: int = create_zip(compressible_files, config.output_zip, additional_files_with_names)
count: int = create_zip(config.source_dir / str(f"{PROGRAM_NAME}"), config.output_zip, additional_files_with_names)

current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"Release zip file created at: {config.output_zip} on {current_time}")
print(f" Store total:{count}, ({time.perf_counter() - start:.3f}s)")
print(f" Store total:{count}, ({sw.elapsed:.3f}s)")


if __name__ == '__main__':
Expand Down
20 changes: 14 additions & 6 deletions src/abstract_controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,21 @@ def get_view(self):
def get_config(self) -> AppConfig:
pass

@abstractmethod
def set_file_property_visible(self, visible: bool):
pass
@property
def file_property_visible(self):
"""
画像ファイルのプロパティウィンドウの表示・非表示状態
:return: true:表示, false: 非表示
"""
raise NotImplementedError()

@abstractmethod
def is_file_property_visible(self) -> bool:
pass
@file_property_visible.setter
def file_property_visible(self, visible: bool):
"""
ファイルプロパティウィンドウの表示・非表示状態を設定します。
:param visible: true:表示, false: 非表示
"""
raise NotImplementedError()

@property
def current_effect(self) -> MosaicEffect:
Expand Down
28 changes: 18 additions & 10 deletions src/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def add_file_path(self, file_path: Path) -> int:
files: list[Path] = []
for f in file_path.glob("*.*"): # ディレクトリの場合
files.append(f)
if len(files) != 0:
self.model.save_directory = True
return self.model.add_images(files)

def get_current_image(self) -> Optional[Path]:
Expand Down Expand Up @@ -99,7 +101,11 @@ def on_save_as(self, event=None):
ファイルを選択して保存ボタンをクリック時
:param event: イベント
"""
self.view.on_save_as(None)
current = self.model.get_current_image()
if current is None:
return
mosaic_filename = ImageFileService.mosaic_filename(current, self.model.save_directory)
self.view.on_save_as(None, mosaic_filename)

def handle_back_image(self, event=None):
"""
Expand Down Expand Up @@ -130,20 +136,22 @@ def on_show_file_property(self, event=None):
image_info = ImageFileService.get_image_info(status.file_path)
self.view.on_show_file_property(status, str(image_info))

def set_file_property_visible(self, visible: bool):
"""
ファイルプロパティウィンドウの表示・非表示状態を設定します。
:param visible: true:表示, false: 非表示
"""
self.model.file_property_visible = visible

def is_file_property_visible(self):
@property
def file_property_visible(self):
"""
画像ファイルのプロパティウィンドウの表示・非表示状態
:return: true:表示, false: 非表示
"""
return self.model.file_property_visible

@file_property_visible.setter
def file_property_visible(self, visible: bool):
"""
ファイルプロパティウィンドウの表示・非表示状態を設定します。
:param visible: true:表示, false: 非表示
"""
self.model.file_property_visible = visible

def handle_back_effect(self, event=None):
"""
前のエフェクトに切り替えます。
Expand Down Expand Up @@ -218,7 +226,7 @@ def get_mosaic_filename(self) -> Path:
"""
f = self.model.get_current_image()
if f is not None:
return ImageFileService.mosaic_filename(f)
return ImageFileService.mosaic_filename(f, self.model.save_directory)
raise ValueError("get_mosaic_filename")

def set_window_title(self, text: Path):
Expand Down
39 changes: 31 additions & 8 deletions src/image_file_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ def save(out_image: Image.Image, output_path: Path, filename: Path):
# Todo: PNGINFOの情報はテストパターンを増やす。
# ファイルの読み込み処理を改善する。
# DataModel側に保持する。
if not output_path.parent.exists():
output_path.parent.mkdir(parents=True)

if ImageFileService.is_png(filename):
with Image.open(filename) as src_img:
ImageFileService.save_png_metadata(src_img, out_image, output_path)
Expand Down Expand Up @@ -174,11 +177,12 @@ def save_jpeg_metadata(src_image: Image.Image, out_image: Image.Image, output_pa
out_image.save(output_path)

@staticmethod
def mosaic_filename(file_path: Path) -> Path:
def mosaic_filename(file_path: Path, is_dir: bool = False) -> Path:
"""
モザイク適用済みのファイルパスを生成します。
同名ファイルが存在する場合は、画像の大きさを比較します。
:param file_path: 元画像のファイルのパス
:param is_dir: ディレクトリの場合はTrue
:return: モザイク適用済みのファイルパス
"""
size = (0, 0)
Expand All @@ -188,21 +192,40 @@ def mosaic_filename(file_path: Path) -> Path:
except Exception as e:
print(e)

new_file = file_path
if is_dir: # 新しいディレクトリパスを作成
# パスの親ディレクトリとファイル名を取得
parent_dir = file_path.parent
file_name = file_path.name

# ディレクトリ名の末尾に_mosaicを付ける
new_parent_dir = parent_dir.with_name(parent_dir.name + '_mosaic')
new_file = new_parent_dir / file_name
return ImageFileService.generate_new_filename(new_file, size)

@staticmethod
def generate_new_filename(base_path: Path, size: tuple[int, int]) -> Path:
"""
新しいファイル名を生成します。同名ファイルが存在する場合は、画像の大きさを比較します。
:param base_path: 元となるファイルパス
:param size: 元画像のサイズ
:return: 新しいファイルパス
"""
# 元のファイル名から新しいファイル名を作成
for i in range(0, 1000): # rangeは1から1000まで動作します
newFileName = file_path.with_stem(file_path.stem + f"_mosaic_{i}")
if not newFileName.exists():
return newFileName # ファイルが存在しなければ新しいファイル名を返す
new_filename = base_path.with_stem(base_path.stem + f"_mosaic_{i}")
if not new_filename.exists():
return new_filename # ファイルが存在しなければ新しいファイル名を返します。
try:
new_size = ImageFileService.get_image_size(newFileName)
new_size = ImageFileService.get_image_size(new_filename)
if size == new_size:
return newFileName # 画像の大きさが同じなら新しいファイル名を返す
return new_filename # 画像の大きさが同じなら新しいファイル名を返します。
if size == (0, 0):
return newFileName # 元ファイルが削除されている場合は新しいファイル名を返す
return new_filename # 元ファイルが削除されている場合、新しいファイル名を返します。
except Exception as e:
print(e)
time.sleep(3)

if i == 1000:
raise ValueError("Failed to generate a new file name after 1000 attempts.")
return newFileName
return new_filename
11 changes: 11 additions & 0 deletions src/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def __init__(self, settings: AppConfig):
# プリセット
self._current_preset_name = settings.effect_presets.default_preset
self._current_effect = settings.effect_presets.get_preset(self._current_preset_name)
# ディレクトリをドロップ時
self._is_save_directory: bool = False

def add_images(self, image_list: list[Path]) -> int:
"""
Expand All @@ -111,6 +113,14 @@ def get(self, key: str, default=None) -> Any:
"""
return self.settings.get(key, default)

@property
def save_directory(self):
return self._is_save_directory

@save_directory.setter
def save_directory(self, value: bool):
self._is_save_directory = value

@property
def settings(self) -> AppConfig:
"""
Expand Down Expand Up @@ -153,6 +163,7 @@ def clear(self):
"""
self.image_list = []
self.current = 0
self._is_save_directory = False

def back_image(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def get_package_version() -> str:
"""
バージョン情報を取得します。
"""
return '0.0.5'
return '0.0.6'


def round_up_decimal(value: Decimal, places: int) -> Decimal:
Expand Down
Loading

0 comments on commit f23669f

Please sign in to comment.