diff --git a/assets/l10n/en.json b/assets/l10n/en.json index b62a165..b9237ec 100644 --- a/assets/l10n/en.json +++ b/assets/l10n/en.json @@ -39,6 +39,7 @@ "\"백그라운드로 실행\" 이 꺼져 있어 앱을 끝내면 작업이 멈춥니다.": "\"Run in background\" is off, so closing the app stops these tasks.", "\"외부 브라우저로 열기\" 에 쓸 브라우저 (이 PC 에 설치된 것)": "Browser for \"Open in external browser\" (installed on this PC)", "# Netscape HTTP Cookie File\n# JJ_MKVMaker 앱 안 브라우저에서 내보냄\n\n": "# Netscape HTTP Cookie File\n# Exported from the JJ_MKVMaker in-app browser\n\n", + "'사진' 모델로 바꿔 다시": "Switch to 'Photos' and redo", "(AI 번역을 쓸 수 없는 기기라 언어를 더할 수 없습니다)": "(Languages cannot be added because AI translation is unavailable on this device)", "({0}개 지움)": "(delete {0})", "(동영상을 세 번 누르면 옮깁니다)": "(Tapping a video three times moves it)", @@ -880,6 +881,7 @@ "사용자가 취소했습니다.": "Cancelled by the user.", "사용할 수 있는 자막 사이트가 없습니다.": "No subtitle site is available.", "사진": "Photos", + "사진에는 '사진' 모델이 더 낫지만, 이 기기 (그래픽카드 없음) 에서는 한 장에 약 20분 걸립니다.": "The 'Photos' model is better for photos, but on this device (no graphics card) it takes about 20 minutes per image.", "삭제": "Delete", "삭제 (목록에서 제거)": "Delete (remove from list)", "삭제 (중지하고 받던 파일 삭제)": "Delete (stop and delete the partial file)", diff --git a/assets/l10n/ja.json b/assets/l10n/ja.json index 723cd6e..705990c 100644 --- a/assets/l10n/ja.json +++ b/assets/l10n/ja.json @@ -39,6 +39,7 @@ "\"백그라운드로 실행\" 이 꺼져 있어 앱을 끝내면 작업이 멈춥니다.": "「バックグラウンドで実行」がオフなので、アプリを終了すると作業が止まります。", "\"외부 브라우저로 열기\" 에 쓸 브라우저 (이 PC 에 설치된 것)": "「外部ブラウザーで開く」に使うブラウザー(この PC にインストール済み)", "# Netscape HTTP Cookie File\n# JJ_MKVMaker 앱 안 브라우저에서 내보냄\n\n": "# Netscape HTTP Cookie File\n# JJ_MKVMaker アプリ内ブラウザーから書き出し\n\n", + "'사진' 모델로 바꿔 다시": "「写真」モデルに変えてやり直す", "(AI 번역을 쓸 수 없는 기기라 언어를 더할 수 없습니다)": "(この端末では AI 翻訳が使えないため言語を追加できません)", "({0}개 지움)": "({0} 個を削除)", "(동영상을 세 번 누르면 옮깁니다)": "(動画を 3 回タップすると移動します)", @@ -880,6 +881,7 @@ "사용자가 취소했습니다.": "ユーザーがキャンセルしました。", "사용할 수 있는 자막 사이트가 없습니다.": "使用できる字幕サイトがありません。", "사진": "写真", + "사진에는 '사진' 모델이 더 낫지만, 이 기기 (그래픽카드 없음) 에서는 한 장에 약 20분 걸립니다.": "写真には「写真」モデルが適していますが、この端末 (グラフィックカードなし) では 1 枚に約 20 分かかります。", "삭제": "削除", "삭제 (목록에서 제거)": "削除(リストから外す)", "삭제 (중지하고 받던 파일 삭제)": "削除(中止してダウンロード中のファイルを削除)", diff --git a/assets/l10n/zh-Hans.json b/assets/l10n/zh-Hans.json index a5beeb2..5aeccde 100644 --- a/assets/l10n/zh-Hans.json +++ b/assets/l10n/zh-Hans.json @@ -39,6 +39,7 @@ "\"백그라운드로 실행\" 이 꺼져 있어 앱을 끝내면 작업이 멈춥니다.": "“后台运行”已关闭,退出应用会停止这些任务。", "\"외부 브라우저로 열기\" 에 쓸 브라우저 (이 PC 에 설치된 것)": "“在外部浏览器中打开”使用的浏览器(本机已安装)", "# Netscape HTTP Cookie File\n# JJ_MKVMaker 앱 안 브라우저에서 내보냄\n\n": "# Netscape HTTP Cookie File\n# 从 JJ_MKVMaker 内置浏览器导出\n\n", + "'사진' 모델로 바꿔 다시": "改用“照片”模型重新处理", "(AI 번역을 쓸 수 없는 기기라 언어를 더할 수 없습니다)": "(此设备无法使用 AI 翻译,因此无法添加语言)", "({0}개 지움)": "(删除 {0} 个)", "(동영상을 세 번 누르면 옮깁니다)": "(连按视频三次会移动它)", @@ -880,6 +881,7 @@ "사용자가 취소했습니다.": "用户已取消。", "사용할 수 있는 자막 사이트가 없습니다.": "没有可用的字幕网站。", "사진": "照片", + "사진에는 '사진' 모델이 더 낫지만, 이 기기 (그래픽카드 없음) 에서는 한 장에 약 20분 걸립니다.": "照片更适合使用“照片”模型,但在本设备 (无显卡) 上每张约需 20 分钟。", "삭제": "删除", "삭제 (목록에서 제거)": "删除(从列表中移除)", "삭제 (중지하고 받던 파일 삭제)": "删除(停止并删除正在下载的文件)", diff --git a/lib/app/ai_upscale.dart b/lib/app/ai_upscale.dart index dc8e309..9072c2f 100644 --- a/lib/app/ai_upscale.dart +++ b/lib/app/ai_upscale.dart @@ -69,9 +69,12 @@ Uint8List _finish((Uint8List, int, int, int, String, int) a) { /// 그림 한 장 올리기. [input] 은 이 기기의 파일 (ZIP · WebDAV 의 그림은 부르는 쪽이 임시 파일로). /// 결과를 [save] 가 true 면 저장하고 그 경로를, 아니면 임시 파일 경로를 돌려준다 (비교해 보고 저장할 때). class AiUpscaler { - AiUpscaler({required this.device, required this.modelPath}); + AiUpscaler({required this.device, required this.modelPath, this.modelId = ''}); final SdDevice device; final String modelPath; + + /// 카탈로그 id (자동이 CPU 에서 만화용을 골랐는지 알리려고) + final String modelId; Process? _proc; bool _cancelled = false; @@ -139,5 +142,5 @@ Future prepareUpscaler(AiStore store, {required String modelSetting final gpu = dev.backend != 'cpu'; final id = pickUpscaleModel(modelSetting, gpu: gpu); if (!store.isInstalled(id)) return null; - return AiUpscaler(device: dev, modelPath: store.pathOf(aiFile(id))); + return AiUpscaler(device: dev, modelPath: store.pathOf(aiFile(id)), modelId: id); } diff --git a/lib/ui/ai_upscale_ui.dart b/lib/ui/ai_upscale_ui.dart index 9e010ba..6ecfaab 100644 --- a/lib/ui/ai_upscale_ui.dart +++ b/lib/ui/ai_upscale_ui.dart @@ -68,6 +68,9 @@ Future upscaleOne(BuildContext context, AppController c, {required Stri if (up == null || !context.mounted) return null; final progress = ValueNotifier(null); var cancelled = false; + var toPhoto = false; + // 관리자: CPU 뿐이라 자동이 만화용을 고르면 사진은 질감이 뭉개질 수 있다 - 알리고 바로 바꿀 수 있게 + final cpuAnime = c.settings.aiUpModel == 'auto' && up.device.backend == 'cpu' && up.modelId == 'esrgan-anime6b'; final nav = Navigator.of(context); unawaited(showDialog( context: context, @@ -84,6 +87,19 @@ Future upscaleOne(BuildContext context, AppController c, {required Stri LinearProgressIndicator(value: v), const SizedBox(height: 4), Text(v == null ? tr('준비하는 중') : '${(v * 100).round()}%', style: const TextStyle(fontSize: 12)), + if (cpuAnime) ...[ + const SizedBox(height: 10), + Text(tr("사진에는 '사진' 모델이 더 낫지만, 이 기기 (그래픽카드 없음) 에서는 한 장에 약 20분 걸립니다."), + style: const TextStyle(fontSize: 12, color: JjColors.textDim)), + TextButton( + onPressed: () { + toPhoto = true; + cancelled = true; + up.cancel(); + }, + child: Text(tr("'사진' 모델로 바꿔 다시")), + ), + ], ]), ), ), @@ -107,6 +123,11 @@ Future upscaleOne(BuildContext context, AppController c, {required Stri } nav.pop(); // 진행 창 if (!context.mounted) return null; + if (toPhoto) { + await c.updateSettings((x) => x.aiUpModel = 'photo'); + if (!context.mounted) return null; + return upscaleOne(context, c, input: input, nameFrom: nameFrom, outDir: outDir); + } if (four == null) { if (!cancelled) ScaffoldMessenger.maybeOf(context)?.showSnackBar(SnackBar(content: Text('$error'))); return null;