Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
same name ("Overwrite"). It frees its names and removes an output folder it made if that is left empty.
"Merge into one PDF" converts each file to PDF and merges with PDFsharp.
"Compress into one archive" packs the dropped files, unconverted, with the archive engine (`IFileCombiner`).
"Merge videos", "Merge audio" and "Video from images" join the files, in the order picked in the merge order
window, into one file with FFmpeg (`IMediaJoiner`); pictures become PNG through the image engines first. Like the
other one-file jobs, the output follows "subfolder only for several files", and a join that fails or is cancelled
is undone by the job's allocator, which deletes only paths that were the job's own.
6. **Report** – progress and results appear in the toast window and in Home → Recent conversions.

## Files dragged from a web browser
Expand Down
25 changes: 23 additions & 2 deletions docs/ENGINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Filee chooses engines automatically. Settings → *Engines* shows their status,
| Windows Imaging Component | part of Windows (Windows only) | **JPEG XR** (JXR, WDP, HDP; HDR screenshots of Windows) → the images ImageMagick writes, and PDF, ICNS, HEIC and SVG through PNG; HDR tone-mapped to SDR |
| Vector graphics | built in (Svg.Skia, SkiaSharp, ACadSharp) | **SVG/SVGZ → PDF (vector) and images**, SVG ↔ SVGZ, **SVG → DXF** (→ DWG with the CAD engine), **raster images → SVG (tracing)**, PDF-compatible AI → PDF |
| ICNS | built in | images → ICNS (16–1024 px), ICNS → images |
| PDFsharp | built in (library) | images → PDF, merge, split, page ranges, **compression** (smaller PDFs, see below) |
| PDFsharp | built in (library) | images → PDF, merge, split, page ranges, **compression** (smaller PDFs, see below), PDFs without their metadata |
| PDFium | built in (library) | PDF → images (multi-page TIFF/GIF supported) |
| Unhwp | built in (library) | HWP/HWPX → TXT, Markdown, HTML (pictures in a `<name>_files` folder next to the Markdown, embedded in the HTML) |
| Text & Markdown (Markdig) | built in (library) | **Markdown → HTML, TXT**; **TXT, LOG, PY, PAC, BAT, COMMAND → UTF-8 TXT**, preserving source text without running scripts (and → PDF / DOCX through the HWPX writer, rhwp or LibreOffice) |
Expand All @@ -32,7 +32,7 @@ Filee chooses engines automatically. Settings → *Engines* shows their status,
| LibreOffice + H2Orestart + Java | **optional download** (~420 MB, 1.3 GB on disk) | older and rare formats only: DOC, XLS, PPT, RTF and OpenDocument → PDF and to each other, output as DOCX/ODT/ODS/ODP; HWP/HWPX → DOCX/ODT; read-only formats (see below) → PDF and their kind's editable formats; FODT, OpenDocument templates (OTT, OTS, OTP) and XLT out; SVG → EMF/WMF/ODG, a PDF page → SVG |
| Pandoc | **optional download** (~42 MB, 240 MB on disk) | Markdown ↔ DOCX/ODT/RTF, DOCX/ODT/HTML/RTF → Markdown, HTML ↔ DOCX/ODT, markup languages (reStructuredText, LaTeX, Org, AsciiDoc, Typst, MediaWiki, DocBook, Jupyter, Textile, man, OPML) ↔ Markdown/HTML/DOCX/ODT and each other (and → RTF, EPUB, TXT), Markdown and markup → PPTX slides |
| Ghostscript | **optional download** (~20 MB, 31 MB on disk) | EPS/PS → PDF, PDF → EPS/PS, PostScript-based AI → PDF (images through PDF and PDFium); smaller PDFs when a preset asks for it |
| FFmpeg | **optional download** (~100 MB, 272 MB on disk) | **all video and audio**: video ↔ video (H.264, HEVC, AV1), video → animated GIF / APNG, a still frame or every frame, audio and subtitle extraction, audio ↔ audio (also APE, WavPack, TTA, DSD, DTS, ALAC, …), GIF, APNG and photos → MP4/WEBM/MOV, Live / Motion Photos → their video, a clip of a video → an iPhone Live Photo or Android Motion Photo (experimental), images → HEIC |
| FFmpeg | **optional download** (~100 MB, 272 MB on disk) | **all video and audio**: video ↔ video (H.264, HEVC, AV1), video → animated GIF / APNG, a still frame or every frame, audio and subtitle extraction, audio ↔ audio (also APE, WavPack, TTA, DSD, DTS, ALAC, …), GIF, APNG and photos → MP4/WEBM/MOV, Live / Motion Photos → their video, a clip of a video → an iPhone Live Photo or Android Motion Photo (experimental), images → HEIC, clips or audio files joined into one, pictures → a slideshow MP4, copies without metadata (see "Media tools") |
| Calibre | **optional download** (~216 MB, 660 MB on disk) | rare e-book formats: LIT, LRF, CHM, PDB, PML, RB, SNB, TCR, OEB → EPUB; EPUB → MOBI, AZW3, LIT, LRF, PDB, PML, RB, SNB, TCR; e-books → PDF (ranked above the HWPX writer, see below) |

DOCX, XLSX, XLS, ODS and PPTX → PDF need neither Microsoft Office nor LibreOffice: they are read in-process, written as HWPX
Expand Down Expand Up @@ -686,6 +686,27 @@ PDFsharp and Magick.NET; nothing has to be installed.
- **Not done**: object streams (PDFsharp writes none), font subsetting or removal of unused glyphs, converting
colour to gray, flattening transparency or form fields, recompressing JBIG2/CCITT scans.

## Media tools

The everyday presets on the back faces of the images, PDF, video and audio donuts. Video and audio need FFmpeg.

- **Compress image / video / audio** re-encode smaller (quality 75, never above a JPEG's own and PNG at zlib level 9;
H.264 at the Small quality, at most 1080p; AAC at the Small quality). A copy in the same format that isn't smaller is
replaced by the source, with the same notice as Compress PDF (`OutputRule.OnlyIfSmaller`).
- **Extract audio** copies AAC or ALAC into M4A without an encode (`MediaOptions.CopyAudioWhenPossible`); other sound
is encoded to AAC.
- **Merge videos** copies the clips with the concat demuxer only when all share the codec setup (ffprobe's extradata
hash), size, pixel format, frame rate, turn and kind of sound; otherwise every clip is fitted into the first clip's
frame and encoded, a clip without sound silent for its length. **Merge audio** always decodes and joins the sound
into one M4A, so no encoder padding or gap is left between files. Both are in `Media/MediaJoining.cs`.
- **Video from images**: each picture is fitted into 1920 × 1080 as a JPEG, then shown for the preset's seconds with
1 s crossfades (`xfade`) or cuts. At most `MediaOptions.MaxSlides` (300) pictures; the queue refuses more before any
is converted. A filter graph too long for a command line goes into a `-/filter_complex` file.
- **Remove metadata** keeps the format. Images lose EXIF, XMP, IPTC, comments and the ICC profile, and a JPEG keeps
its own quality. Video and audio are copied without global and per-stream tags, chapters and data tracks; an MKV's
attachments (subtitle fonts) stay, with their file name and type. PDFs lose their document information and every
XMP packet (`PdfSharpConverter.StripMetadata`); pages, links, bookmarks and form fields stay.

## Office Open XML variants

`Office/OoxmlConverter.cs` converts between the variants of a family (Word, Excel, PowerPoint) by copying the
Expand Down
12 changes: 12 additions & 0 deletions src/Filee.App/Assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"error.no_route": "لا يوجد محرك يستطيع إجراء هذا التحويل",
"error.cannot_turn": "التدوير والانعكاس متاحان للصور فقط",
"error.too_many_frames": "عدد الإطارات كبير جدًا لحفظها كصور. زِد قيمة «كل إطار رقم N»",
"error.too_many_pictures": "عدد الصور كبير جدًا لفيديو واحد، قسّمها على عدة فيديوهات",
"error.not_enough_space": "لا توجد مساحة كافية على القرص لحفظ الصور",
"error.no_motion_photo": "لا تحتوي هذه الصورة على فيديو يستطيع Filee قراءته (صورة Motion Photo من Android، أو Live Photo من iPhone مع ملف MOV بجانبها)",
"error.live_photo_start": "يبدأ المقطع بعد نهاية هذا الفيديو. اختر «بداية المقطع» أبكر",
Expand Down Expand Up @@ -212,6 +213,14 @@
"preset.extract_motion": "استخراج فيديو Live Photo",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "ضغط الصورة",
"preset.compress_video": "ضغط الفيديو",
"preset.video_from_images": "فيديو من الصور",
"preset.extract_audio": "استخراج الصوت",
"preset.merge_videos": "دمج الفيديوهات",
"preset.compress_audio": "ضغط الصوت",
"preset.merge_audio": "دمج الصوت",
"preset.remove_metadata": "إزالة البيانات الوصفية",
"format.folder": "مجلد",
"format.category.Image": "صورة",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -476,6 +485,9 @@
"presets.frame_estimate": "تنتج دقيقة من فيديو بمعدل 30 إطارًا/ث {0} صورة، بحد أقصى {1} لكل فيديو.",
"presets.extract_motion_photo": "استخراج فيديو Live/Motion Photo",
"presets.extract_motion_photo_hint": "تتحول الصورة إلى الفيديو المحفوظ معها: المضمّن في Motion Photo من Android، أو ملف MOV بجانب Live Photo من iPhone.\nتتحول الصور الأخرى إلى فيديو للصورة الثابتة.",
"presets.slide_seconds": "ثوانٍ لكل صورة",
"presets.crossfade": "تلاشٍ متداخل بين الصور",
"presets.crossfade_hint": "تتلاشى كل صورة في التالية خلال ثانية بدلًا من الانتقال المفاجئ.",
"presets.group.live_photo": "Live / Motion Photo",
"presets.live_photo": "يصبح الفيديو",
"presets.live_photo.None": "إطارًا ثابتًا واحدًا",
Expand Down
12 changes: 12 additions & 0 deletions src/Filee.App/Assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"error.no_route": "No engine can do this conversion",
"error.cannot_turn": "Rotate and flip work on images only",
"error.too_many_frames": "Too many frames to save as pictures, raise \"Every Nth frame\"",
"error.too_many_pictures": "Too many pictures for one video, split them into several",
"error.not_enough_space": "Not enough free disk space for the pictures",
"error.no_motion_photo": "This photo has no video Filee can read (an Android Motion Photo, or an iPhone Live Photo with its MOV next to it)",
"error.live_photo_start": "The clip starts after the end of this video. Choose an earlier \"Clip start\"",
Expand Down Expand Up @@ -222,6 +223,14 @@
"preset.extract_motion": "Extract Live Photo video",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "Compress image",
"preset.compress_video": "Compress video",
"preset.video_from_images": "Video from images",
"preset.extract_audio": "Extract audio",
"preset.merge_videos": "Merge videos",
"preset.compress_audio": "Compress audio",
"preset.merge_audio": "Merge audio",
"preset.remove_metadata": "Remove metadata",

"format.folder": "Folder",
"format.category.Image": "Image",
Expand Down Expand Up @@ -491,6 +500,9 @@
"presets.frame_estimate": "One minute of 30 fps video gives {0} pictures, at most {1} per video.",
"presets.extract_motion_photo": "Extract Live/Motion Photo video",
"presets.extract_motion_photo_hint": "A photo becomes the video saved with it: the one inside an Android Motion Photo, or the MOV next to an iPhone Live Photo.\nOther pictures become a video of the still picture.",
"presets.slide_seconds": "Seconds per picture",
"presets.crossfade": "Crossfade between pictures",
"presets.crossfade_hint": "Each picture fades into the next over a second instead of cutting to it.",
"presets.group.live_photo": "Live / Motion Photo",
"presets.live_photo": "A video becomes",
"presets.live_photo.None": "One still frame",
Expand Down
12 changes: 12 additions & 0 deletions src/Filee.App/Assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"error.no_route": "Ningún motor puede hacer esta conversión",
"error.cannot_turn": "Rotar y voltear solo funcionan con imágenes",
"error.too_many_frames": "Demasiados fotogramas para guardar como imágenes; aumenta «Cada N fotogramas»",
"error.too_many_pictures": "Demasiadas imágenes para un vídeo; divídelas en varios",
"error.not_enough_space": "Espacio libre en disco insuficiente para las imágenes",
"error.no_motion_photo": "Esta foto no tiene un vídeo que Filee pueda leer (una Motion Photo de Android o una Live Photo de iPhone con su MOV al lado)",
"error.live_photo_start": "El clip empieza después del final de este vídeo. Elige un «Inicio del clip» anterior",
Expand Down Expand Up @@ -212,6 +213,14 @@
"preset.extract_motion": "Extraer vídeo de Live Photo",
"preset.live_photo_iphone": "Live Photo (iPhone)",
"preset.motion_photo_android": "Motion Photo (Android)",
"preset.compress_image": "Comprimir imagen",
"preset.compress_video": "Comprimir vídeo",
"preset.video_from_images": "Vídeo de imágenes",
"preset.extract_audio": "Extraer audio",
"preset.merge_videos": "Unir vídeos",
"preset.compress_audio": "Comprimir audio",
"preset.merge_audio": "Unir audio",
"preset.remove_metadata": "Quitar metadatos",
"format.folder": "Carpeta",
"format.category.Image": "Imagen",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -476,6 +485,9 @@
"presets.frame_estimate": "Un minuto de vídeo a 30 fps genera {0} imágenes, como máximo {1} por vídeo.",
"presets.extract_motion_photo": "Extraer vídeo de Live/Motion Photo",
"presets.extract_motion_photo_hint": "La foto se convierte en el vídeo guardado con ella: el que lleva dentro una Motion Photo de Android o el MOV junto a una Live Photo de iPhone.\nLas demás imágenes se convierten en un vídeo de la imagen fija.",
"presets.slide_seconds": "Segundos por imagen",
"presets.crossfade": "Fundido entre imágenes",
"presets.crossfade_hint": "Cada imagen se funde con la siguiente durante un segundo en lugar de cortar.",
"presets.group.live_photo": "Live Photo / Motion Photo",
"presets.live_photo": "Un vídeo se convierte en",
"presets.live_photo.None": "Un fotograma fijo",
Expand Down
12 changes: 12 additions & 0 deletions src/Filee.App/Assets/i18n/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"error.no_route": "कोई भी इंजन यह कन्वर्ज़न नहीं कर सकता",
"error.cannot_turn": "घुमाना और पलटना केवल इमेज पर काम करता है",
"error.too_many_frames": "तस्वीरों के रूप में सहेजने के लिए बहुत ज़्यादा फ़्रेम हैं, \"हर Nवाँ फ़्रेम\" बढ़ाएँ",
"error.too_many_pictures": "एक वीडियो के लिए तस्वीरें बहुत ज़्यादा हैं, इन्हें कई हिस्सों में बाँटें",
"error.not_enough_space": "तस्वीरों के लिए डिस्क पर पर्याप्त खाली जगह नहीं है",
"error.no_motion_photo": "इस फ़ोटो में ऐसा कोई वीडियो नहीं है जिसे Filee पढ़ सके (Android मोशन फ़ोटो, या पास में अपनी MOV फ़ाइल वाली iPhone लाइव फ़ोटो)",
"error.live_photo_start": "क्लिप इस वीडियो के ख़त्म होने के बाद शुरू होती है। \"क्लिप की शुरुआत\" पहले चुनें",
Expand Down Expand Up @@ -212,6 +213,14 @@
"preset.extract_motion": "लाइव फ़ोटो वीडियो निकालें",
"preset.live_photo_iphone": "लाइव फ़ोटो (iPhone)",
"preset.motion_photo_android": "मोशन फ़ोटो (Android)",
"preset.compress_image": "इमेज कंप्रेस करें",
"preset.compress_video": "वीडियो कंप्रेस करें",
"preset.video_from_images": "तस्वीरों से वीडियो",
"preset.extract_audio": "ऑडियो निकालें",
"preset.merge_videos": "वीडियो जोड़ें",
"preset.compress_audio": "ऑडियो कंप्रेस करें",
"preset.merge_audio": "ऑडियो जोड़ें",
"preset.remove_metadata": "मेटाडेटा हटाएँ",
"format.folder": "फ़ोल्डर",
"format.category.Image": "इमेज",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -476,6 +485,9 @@
"presets.frame_estimate": "30 fps के एक मिनट के वीडियो से {0} तस्वीरें बनती हैं, प्रति वीडियो अधिकतम {1}।",
"presets.extract_motion_photo": "लाइव/मोशन फ़ोटो का वीडियो निकालें",
"presets.extract_motion_photo_hint": "फ़ोटो उसके साथ सहेजा गया वीडियो बन जाती है: Android मोशन फ़ोटो के अंदर वाला वीडियो, या iPhone लाइव फ़ोटो के पास रखी उसी नाम की MOV फ़ाइल।\nबाकी तस्वीरें स्थिर तस्वीर का वीडियो बनती हैं।",
"presets.slide_seconds": "हर तस्वीर के सेकंड",
"presets.crossfade": "तस्वीरों के बीच क्रॉसफ़ेड",
"presets.crossfade_hint": "हर तस्वीर सीधे बदलने के बजाय एक सेकंड में अगली तस्वीर में घुल जाती है।",
"presets.group.live_photo": "लाइव / मोशन फ़ोटो",
"presets.live_photo": "वीडियो बनता है",
"presets.live_photo.None": "एक स्थिर फ़्रेम",
Expand Down
12 changes: 12 additions & 0 deletions src/Filee.App/Assets/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"error.no_route": "この変換に対応するエンジンがありません",
"error.cannot_turn": "回転と反転は画像でのみ使えます",
"error.too_many_frames": "画像として保存するフレーム数が多すぎます。「Nフレームごと」の値を大きくしてください",
"error.too_many_pictures": "1本の動画にするには画像が多すぎます。いくつかに分けてください",
"error.not_enough_space": "画像を保存するための空き容量が不足しています",
"error.no_motion_photo": "この写真には、Fileeが読み取れる動画がありません(Androidのモーションフォト、または隣にMOVがあるiPhoneのLive Photo)",
"error.live_photo_start": "クリップの開始位置が動画の終わりより後です。「クリップの開始」をもっと前にしてください",
Expand Down Expand Up @@ -212,6 +213,14 @@
"preset.extract_motion": "Live Photoの動画を抽出",
"preset.live_photo_iphone": "Live Photo(iPhone)",
"preset.motion_photo_android": "モーションフォト(Android)",
"preset.compress_image": "画像を圧縮",
"preset.compress_video": "動画を圧縮",
"preset.video_from_images": "写真から動画",
"preset.extract_audio": "音声を抽出",
"preset.merge_videos": "動画を結合",
"preset.compress_audio": "音声を圧縮",
"preset.merge_audio": "音声を結合",
"preset.remove_metadata": "メタデータを削除",
"format.folder": "フォルダー",
"format.category.Image": "画像",
"format.category.Pdf": "PDF",
Expand Down Expand Up @@ -476,6 +485,9 @@
"presets.frame_estimate": "30 fpsの動画は、1分あたり{0}枚の画像になります(動画1本につき最大{1}枚)。",
"presets.extract_motion_photo": "Live Photo・モーションフォトの動画を抽出",
"presets.extract_motion_photo_hint": "写真と一緒に保存された動画を取り出します。Androidのモーションフォトは写真の中の動画、iPhoneのLive Photoは隣にある同じ名前のMOVを使います。\nほかの画像は静止画の動画になります。",
"presets.slide_seconds": "1枚あたりの秒数",
"presets.crossfade": "写真の間をクロスフェード",
"presets.crossfade_hint": "次の写真へ切り替えず、1秒かけて徐々に移り変わります。",
"presets.group.live_photo": "Live Photo/モーションフォト",
"presets.live_photo": "動画の保存方法",
"presets.live_photo.None": "静止画1枚",
Expand Down
Loading
Loading