This should be a floating object. The only problem is to set up a convenient way of coding it.
Here's a possibility: framedfigure has a standard positioning optional argument (default [!htp]) and first argument consisting of key-value pairs:
ratio for setting the amount of the available width for the width of the text;
sep for the inner margins between the object and the frame (default \fboxsep);
gutter for the separation between the two parts (default \columnsep);
align for the reciprocal alignment, can be c (default), t or b;
file for the name of the graphic file
options for additional options to \includegraphics, perhaps overriding the default width=\linewidth;
shortcaption for the possible table of contents short caption;
caption for the caption text.
\documentclass{article}
\usepackage{graphicx}
\usepackage{lipsum}% filler text
\ExplSyntaxOn
\NewDocumentEnvironment{framedfigure}{O{!htp} m +b}
{% #1 = pos options, #2 = data, #3 = text
\jacopo_framefigure:nnn {#1} {#2} {#3}
}
{}
\keys_define:nn { jacopo/framefigure }
{
ratio .fp_set:N = \l__jacopo_framefigure_ratio_fp,
ratio .initial:n = 0.5,
sep .dim_set:N = \l__jacopo_framefigure_sep_dim,
sep .initial:n = \fboxsep,
gutter .dim_set:N = \l__jacopo_framefigure_gutter_dim,
gutter .initial:n = \columnsep,
align .tl_set:N = \l__jacopo_framefigure_align_tl,
align .initial:n = c,
file .tl_set:N = \l__jacopo_framefigure_file_tl,
options .tl_set:N = \l__jacopo_framefigure_options_tl,
shortcaption .tl_set:N = \l__jacopo_framefigure_shortcaption_tl,
caption .tl_set:N = \l__jacopo_framefigure_caption_tl,
}
\dim_new:N \l__jacopo_framefigure_wd_dim
\cs_new_protected:Nn \jacopo_framefigure:nnn
{
\keys_set:nn { jacopo/framefigure } {#2}
\dim_set:Nn \fboxsep { \l__jacopo_framefigure_sep_dim }
\dim_set:Nn \l__jacopo_framefigure_wd_dim
{
\columnwidth - 2\fboxrule - 2\fboxsep - \l__jacopo_framefigure_gutter_dim
}
\begin{figure}[#1]
\framebox[\columnwidth][s]
{
\begin{minipage}
[\l__jacopo_framefigure_align_tl] % alignment
{\fp_eval:n {\l__jacopo_framefigure_ratio_fp}\l__jacopo_framefigure_wd_dim} % width
\vspace{0pt}
#3 % the text
\par\vspace{0pt}
\end{minipage}
\hfill % the gutter
\begin{minipage}
[\l__jacopo_framefigure_align_tl] % alignment
{\fp_eval:n {1-\l__jacopo_framefigure_ratio_fp}\l__jacopo_framefigure_wd_dim} % width
\centering
\vspace{0pt}
% the image
\use:e
{
\exp_not:N \includegraphics[width=\linewidth,\l__jacopo_framefigure_options_tl]
{\l__jacopo_framefigure_file_tl}
}
% the caption
\tl_if_blank:VTF \l__jacopo_framefigure_shortcaption_tl
{
\caption{\l__jacopo_framefigure_caption_tl}
}
{
\caption[\l__jacopo_framefigure_shortcaption_tl]{\l__jacopo_framefigure_caption_tl}
}
\par\vspace{0pt}
\end{minipage}
}% end of \framebox
\end{figure}
}{}
\ExplSyntaxOff
\begin{document}
\begin{framedfigure}{
ratio=0.5,
file=example-image,
caption={This is a caption},
}
\lipsum[1][1-8]
\end{framedfigure}
\begin{framedfigure}{
ratio=0.5,
gutter=0.5em,
sep=1em,
options={width=0.8\linewidth},
file=example-image,
caption={This is a caption},
}
\lipsum[1][1-8]
\end{framedfigure}
\begin{framedfigure}[!b]{
sep=1em,
ratio=0.6,
align=t,
file=example-image,
caption={This is a caption},
}
\lipsum[1][1-8]
\end{framedfigure}
\end{document}
Getting a pleasant result requires experiments with the various parameters.
