From 77afd27bd4bebd739120065ff372e498435fa032 Mon Sep 17 00:00:00 2001 From: divyansharma001 Date: Sat, 7 Mar 2026 23:44:58 +0530 Subject: [PATCH 1/2] 203_26: fix LaTeX export images in inaccessible formats - Add magic header detection for images with unknown suffixes - Add jpeg to fast-path suffix list in tmtex-as-eps - Copy files with correct extension when format is LaTeX-compatible - Add fallback to print-snippet when convert-to-file fails - Register postscript-file converters for jpeg, gif, tif via ImageMagick --- TeXmacs/plugins/image/progs/image/gif.scm | 7 ++- TeXmacs/plugins/image/progs/image/jpeg.scm | 7 ++- TeXmacs/plugins/image/progs/image/tif.scm | 7 ++- .../latex/progs/convert/latex/tmtex.scm | 60 ++++++++++++++++--- TeXmacs/progs/convert/latex/tmtex.scm | 60 ++++++++++++++++--- devel/203_26.md | 22 +++++++ 6 files changed, 142 insertions(+), 21 deletions(-) create mode 100644 devel/203_26.md diff --git a/TeXmacs/plugins/image/progs/image/gif.scm b/TeXmacs/plugins/image/progs/image/gif.scm index 97be9e6d24..1e6ec85dc0 100644 --- a/TeXmacs/plugins/image/progs/image/gif.scm +++ b/TeXmacs/plugins/image/progs/image/gif.scm @@ -12,7 +12,12 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(texmacs-module (image gif)) +(texmacs-module (image gif) + (:use (binary convert))) (converter gif-file postscript-document (:function image->psdoc)) + +(converter gif-file postscript-file + (:require (has-binary-convert?)) + (:shell ,(url->system (find-binary-convert)) from to)) diff --git a/TeXmacs/plugins/image/progs/image/jpeg.scm b/TeXmacs/plugins/image/progs/image/jpeg.scm index fbde4232b3..44cded9d91 100644 --- a/TeXmacs/plugins/image/progs/image/jpeg.scm +++ b/TeXmacs/plugins/image/progs/image/jpeg.scm @@ -12,7 +12,12 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(texmacs-module (image jpeg)) +(texmacs-module (image jpeg) + (:use (binary convert))) (converter jpeg-file postscript-document (:function image->psdoc)) + +(converter jpeg-file postscript-file + (:require (has-binary-convert?)) + (:shell ,(url->system (find-binary-convert)) from to)) diff --git a/TeXmacs/plugins/image/progs/image/tif.scm b/TeXmacs/plugins/image/progs/image/tif.scm index dad9f933a5..d9bb682f3a 100644 --- a/TeXmacs/plugins/image/progs/image/tif.scm +++ b/TeXmacs/plugins/image/progs/image/tif.scm @@ -12,7 +12,12 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(texmacs-module (image tif)) +(texmacs-module (image tif) + (:use (binary convert))) (converter tif-file postscript-document (:function image->psdoc)) + +(converter tif-file postscript-file + (:require (has-binary-convert?)) + (:shell ,(url->system (find-binary-convert)) from to)) diff --git a/TeXmacs/plugins/latex/progs/convert/latex/tmtex.scm b/TeXmacs/plugins/latex/progs/convert/latex/tmtex.scm index f96afe4b9c..e2cf1ec646 100644 --- a/TeXmacs/plugins/latex/progs/convert/latex/tmtex.scm +++ b/TeXmacs/plugins/latex/progs/convert/latex/tmtex.scm @@ -1827,22 +1827,64 @@ (define (tmtex-graphics l) (tmtex-eps (cons 'graphics l))) +(define (tmtex-guess-format u suffix) + "Detect image format via magic header when suffix is unknown." + (if (and (url-exists? u) (== (format-from-suffix suffix) "generic")) + (with data (string-load u) + (cond ((and (> (string-length data) 8) + (== (char->integer (string-ref data 0)) #xff) + (== (char->integer (string-ref data 1)) #xd8)) + "jpeg") + ((and (> (string-length data) 8) + (string-starts? data "\x89PNG")) + "png") + ((and (> (string-length data) 5) + (string-starts? data "%PDF-")) + "pdf") + (else #f))) + #f)) + (define (tmtex-as-eps name) (let* ((u (url-relative current-save-target (unix->url name))) (suffix (url-suffix u)) - (fm (string-append (format-from-suffix suffix) "-file"))) - (if (and (url-exists? u) (in? suffix (list "eps" "pdf" "png" "jpg"))) + (detected (tmtex-guess-format u suffix)) + (fm (if detected + (string-append detected "-file") + (string-append (format-from-suffix suffix) "-file")))) + (if (and (url-exists? u) + (in? suffix (list "eps" "pdf" "png" "jpg" "jpeg"))) + ;; Fast path: image already in LaTeX-compatible format (with p (url->string "$TEXMACS_PATH") (set! name (string-replace name "$TEXMACS_PATH" p)) (set! name (string-replace name "file://" "")) (list 'includegraphics name)) - (receive (name-url name-string) (tmtex-eps-names) - (when (string-starts? name "..") - (set! u (url-relative current-save-source (unix->url name)))) - (with nfm (if (== (url-suffix name-url) "pdf") "pdf-file" - "postscript-file") - (convert-to-file u fm nfm name-url)) - (list 'includegraphics name-string))))) + (if (and (url-exists? u) detected + (in? detected (list "pdf" "png" "jpeg"))) + ;; Image has wrong suffix but is actually LaTeX-compatible; + ;; copy with correct extension + (receive (name-url name-string) (tmtex-eps-names) + (let* ((ext (if (== detected "jpeg") "jpg" detected)) + (dest-url (url-glue (url-unglue name-url 4) + (string-append "." ext))) + (dest-string (string-append + (string-drop-right name-string 4) + "." ext))) + (system-copy u dest-url) + (list 'includegraphics dest-string))) + ;; Need format conversion + (receive (name-url name-string) (tmtex-eps-names) + (when (string-starts? name "..") + (set! u (url-relative current-save-source (unix->url name)))) + (let* ((nfm (if (== (url-suffix name-url) "pdf") "pdf-file" + "postscript-file")) + (result (convert-to-file u fm nfm name-url))) + (if result + (list 'includegraphics name-string) + ;; Conversion failed: fall back to rendering via TeXmacs + (begin + (print-snippet name-url + `(image ,name "0.618par" "" "" "") #t) + (list 'includegraphics name-string))))))))) (define (tmtex-image-length len) (let* ((s (force-string len)) diff --git a/TeXmacs/progs/convert/latex/tmtex.scm b/TeXmacs/progs/convert/latex/tmtex.scm index 710626990e..098930902a 100644 --- a/TeXmacs/progs/convert/latex/tmtex.scm +++ b/TeXmacs/progs/convert/latex/tmtex.scm @@ -1825,22 +1825,64 @@ (define (tmtex-graphics l) (tmtex-eps (cons 'graphics l))) +(define (tmtex-guess-format u suffix) + "Detect image format via magic header when suffix is unknown." + (if (and (url-exists? u) (== (format-from-suffix suffix) "generic")) + (with data (string-load u) + (cond ((and (> (string-length data) 8) + (== (char->integer (string-ref data 0)) #xff) + (== (char->integer (string-ref data 1)) #xd8)) + "jpeg") + ((and (> (string-length data) 8) + (string-starts? data "\x89PNG")) + "png") + ((and (> (string-length data) 5) + (string-starts? data "%PDF-")) + "pdf") + (else #f))) + #f)) + (define (tmtex-as-eps name) (let* ((u (url-relative current-save-target (unix->url name))) (suffix (url-suffix u)) - (fm (string-append (format-from-suffix suffix) "-file"))) - (if (and (url-exists? u) (in? suffix (list "eps" "pdf" "png" "jpg"))) + (detected (tmtex-guess-format u suffix)) + (fm (if detected + (string-append detected "-file") + (string-append (format-from-suffix suffix) "-file")))) + (if (and (url-exists? u) + (in? suffix (list "eps" "pdf" "png" "jpg" "jpeg"))) + ;; Fast path: image already in LaTeX-compatible format (with p (url->string "$TEXMACS_PATH") (set! name (string-replace name "$TEXMACS_PATH" p)) (set! name (string-replace name "file://" "")) (list 'includegraphics name)) - (receive (name-url name-string) (tmtex-eps-names) - (when (string-starts? name "..") - (set! u (url-relative current-save-source (unix->url name)))) - (with nfm (if (== (url-suffix name-url) "pdf") "pdf-file" - "postscript-file") - (convert-to-file u fm nfm name-url)) - (list 'includegraphics name-string))))) + (if (and (url-exists? u) detected + (in? detected (list "pdf" "png" "jpeg"))) + ;; Image has wrong suffix but is actually LaTeX-compatible; + ;; copy with correct extension + (receive (name-url name-string) (tmtex-eps-names) + (let* ((ext (if (== detected "jpeg") "jpg" detected)) + (dest-url (url-glue (url-unglue name-url 4) + (string-append "." ext))) + (dest-string (string-append + (string-drop-right name-string 4) + "." ext))) + (system-copy u dest-url) + (list 'includegraphics dest-string))) + ;; Need format conversion + (receive (name-url name-string) (tmtex-eps-names) + (when (string-starts? name "..") + (set! u (url-relative current-save-source (unix->url name)))) + (let* ((nfm (if (== (url-suffix name-url) "pdf") "pdf-file" + "postscript-file")) + (result (convert-to-file u fm nfm name-url))) + (if result + (list 'includegraphics name-string) + ;; Conversion failed: fall back to rendering via TeXmacs + (begin + (print-snippet name-url + `(image ,name "0.618par" "" "" "") #t) + (list 'includegraphics name-string))))))))) (define (tmtex-image-length len) (let* ((s (force-string len)) diff --git a/devel/203_26.md b/devel/203_26.md new file mode 100644 index 0000000000..eb40cb2537 --- /dev/null +++ b/devel/203_26.md @@ -0,0 +1,22 @@ +# 203_26 Export to LaTeX: fix images in inaccessible formats + +## 如何测试 +1. 打开墨干,插入一张图片(尝试GIF、WebP、SVG等非LaTeX原生格式,或者将一张JPG重命名为.dat) +2. 导出为LaTeX(File → Export → LaTeX...) +3. 用pdflatex编译导出的.tex文件,确认图片能正常显示 + +## 2026/03/07 修复LaTeX导出时图片格式不可用的问题 +### What +1. `tmtex-as-eps`增加了`jpeg`后缀到快速路径 +2. 新增`tmtex-guess-format`函数,通过Magic Header检测未知后缀的图片格式(PDF/PNG/JPEG) +3. 当图片后缀未知但实际格式可被LaTeX直接使用时,复制文件并使用正确的扩展名 +4. `convert-to-file`失败时,回退到`print-snippet`通过TeXmacs内部渲染引擎生成PDF +5. 为JPEG、GIF、TIF添加`postscript-file`转换器(通过ImageMagick),补全到PDF的转换链 + +### Why +导出LaTeX时,图片格式可能不被LaTeX识别(如GIF、WebP、SVG),或者图片后缀与实际格式不符。 +原有代码中`tmtex-as-eps`不检查`convert-to-file`的返回值,转换失败时仍然生成指向不存在文件的`\includegraphics`,导致pdflatex编译失败。 + +### How +- 修改`TeXmacs/progs/convert/latex/tmtex.scm`和`TeXmacs/plugins/latex/progs/convert/latex/tmtex.scm` +- 修改`TeXmacs/plugins/image/progs/image/jpeg.scm`、`gif.scm`、`tif.scm` From 77945d57de6744b6ac56e9e30c26c182a33cc873 Mon Sep 17 00:00:00 2001 From: divyansharma001 Date: Sun, 15 Mar 2026 14:38:50 +0530 Subject: [PATCH 2/2] 203_26: fix double base64 encoding for embedded images in LaTeX export - object_l1.cpp: decode base64 in tmscm_to_content for RAW_DATA nodes so Scheme->C++ path always stores binary in RAW_DATA tree - embedded-edit.scm: encode binary image data as base64 before storing in (raw-data ...) to match the decode in object_l1.cpp Invariant: Scheme layer always has base64, C++ layer always has binary --- TeXmacs/progs/generic/embedded-edit.scm | 2 +- devel/203_26.md | 3 ++- moebius/Scheme/L1/object_l1.cpp | 14 +++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/TeXmacs/progs/generic/embedded-edit.scm b/TeXmacs/progs/generic/embedded-edit.scm index 6d11e03ac1..c4834c26d8 100644 --- a/TeXmacs/progs/generic/embedded-edit.scm +++ b/TeXmacs/progs/generic/embedded-edit.scm @@ -143,7 +143,7 @@ (u (url-relative (current-buffer) f)) (s (url-suffix f))) (when (url-exists? u) - (let* ((data (string-load u)) + (let* ((data (encode-base64 (string-load u))) (raw `(tuple (raw-data ,data) ,(utf8->cork (url->string (url-tail f)))))) (tree-set t 0 raw)))))) diff --git a/devel/203_26.md b/devel/203_26.md index eb40cb2537..967bc3e7d6 100644 --- a/devel/203_26.md +++ b/devel/203_26.md @@ -1,9 +1,10 @@ # 203_26 Export to LaTeX: fix images in inaccessible formats ## 如何测试 -1. 打开墨干,插入一张图片(尝试GIF、WebP、SVG等非LaTeX原生格式,或者将一张JPG重命名为.dat) +1. 打开墨干,插入一张PNG或JPG图片并将其嵌入文档(使用 Edit → Embed image) 2. 导出为LaTeX(File → Export → LaTeX...) 3. 用pdflatex编译导出的.tex文件,确认图片能正常显示 +4. 也可测试GIF、WebP、SVG等非LaTeX原生格式,或将一张JPG重命名为.dat后插入 ## 2026/03/07 修复LaTeX导出时图片格式不可用的问题 ### What diff --git a/moebius/Scheme/L1/object_l1.cpp b/moebius/Scheme/L1/object_l1.cpp index 5ea339eb69..aeace004f1 100644 --- a/moebius/Scheme/L1/object_l1.cpp +++ b/moebius/Scheme/L1/object_l1.cpp @@ -17,7 +17,10 @@ #include "moebius/data/scheme.hpp" #include "moebius/tree_label.hpp" +#include + using moebius::make_tree_label; +using moebius::RAW_DATA; using moebius::data::scm_quote; using moebius::data::scm_unquote; using moebius::data::tree_to_scheme_tree; @@ -122,7 +125,16 @@ tmscm_to_content (tmscm p) { if (tmscm_is_tree (p)) return tmscm_to_tree (p); if (tmscm_is_pair (p)) { if (!tmscm_is_symbol (tmscm_car (p))) return "?"; - tree t (make_tree_label (tmscm_to_symbol (tmscm_car (p)))); + tree_label tl= make_tree_label (tmscm_to_symbol (tmscm_car (p))); + if (tl == RAW_DATA) { + // RAW_DATA in Scheme S-expression contains base64-encoded data; + // decode back to binary for the C++ tree representation + tree t (RAW_DATA, 1); + t[0]->label= + lolly::data::decode_base64 (tmscm_to_string (tmscm_cadr (p))); + return t; + } + tree t (tl); p= tmscm_cdr (p); while (!tmscm_is_null (p)) { t << tmscm_to_content (tmscm_car (p));