mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Use eimp instead of ImageMagick calls for thumbnails creation
This commit is contained in:
parent
138cc25355
commit
3e987d3bae
@ -44,7 +44,7 @@
|
||||
{tag, "1.0.2"}}}},
|
||||
{if_var_true, riak, {riakc, ".*", {git, "https://github.com/processone/riak-erlang-client.git",
|
||||
{tag, "2.5.3"}}}},
|
||||
{if_var_true, graphics, {eimp, ".*", {git, "https://github.com/processone/eimp.git", "dc5bfe0"}}},
|
||||
{if_var_true, graphics, {eimp, ".*", {git, "https://github.com/processone/eimp.git", "685d2a2c9b"}}},
|
||||
%% Elixir support, needed to run tests
|
||||
{if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir",
|
||||
{tag, {if_version_above, "17", "v1.4.4", "v1.1.1"}}}}},
|
||||
|
@ -33,7 +33,7 @@
|
||||
atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1,
|
||||
l2i/1, i2l/1, i2l/2, expr_to_term/1, term_to_expr/1,
|
||||
now_to_usec/1, usec_to_now/1, encode_pid/1, decode_pid/2,
|
||||
compile_exprs/2, join_atoms/2, try_read_file/1]).
|
||||
compile_exprs/2, join_atoms/2, try_read_file/1, have_eimp/0]).
|
||||
|
||||
%% Deprecated functions
|
||||
-export([decode_base64/1, encode_base64/1]).
|
||||
@ -213,6 +213,12 @@ try_read_file(Path) ->
|
||||
erlang:error(badarg)
|
||||
end.
|
||||
|
||||
-ifdef(GRAPHICS).
|
||||
have_eimp() -> true.
|
||||
-else.
|
||||
have_eimp() -> false.
|
||||
-endif.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
|
@ -38,7 +38,7 @@
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
start(Host, _Opts) ->
|
||||
case have_eimp() of
|
||||
case misc:have_eimp() of
|
||||
true ->
|
||||
ejabberd_hooks:add(pubsub_publish_item, Host, ?MODULE,
|
||||
pubsub_publish_item, 50),
|
||||
@ -416,12 +416,6 @@ decode_mime_type(MimeType) ->
|
||||
encode_mime_type(Type) ->
|
||||
<<"image/", (atom_to_binary(Type, latin1))/binary>>.
|
||||
|
||||
-ifdef(GRAPHICS).
|
||||
have_eimp() -> true.
|
||||
-else.
|
||||
have_eimp() -> false.
|
||||
-endif.
|
||||
|
||||
mod_opt_type({convert, png}) ->
|
||||
fun(jpeg) -> jpeg;
|
||||
(webp) -> webp;
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
-module(mod_http_upload).
|
||||
-author('holger@zedat.fu-berlin.de').
|
||||
|
||||
-compile(export_all).
|
||||
-protocol({xep, 363, '0.1'}).
|
||||
|
||||
-define(SERVICE_REQUEST_TIMEOUT, 5000). % 5 seconds.
|
||||
@ -110,7 +110,7 @@
|
||||
slots = #{} :: map()}).
|
||||
|
||||
-record(media_info,
|
||||
{type :: binary(),
|
||||
{type :: atom(),
|
||||
height :: integer(),
|
||||
width :: integer()}).
|
||||
|
||||
@ -236,12 +236,14 @@ init([ServerHost, Opts]) ->
|
||||
end,
|
||||
case Thumbnail of
|
||||
true ->
|
||||
case string:str(os:cmd("identify"), "Magick") of
|
||||
0 ->
|
||||
?ERROR_MSG("Cannot find 'identify' command, please install "
|
||||
"ImageMagick or disable thumbnail creation", []);
|
||||
_ ->
|
||||
ok
|
||||
case misc:have_eimp() of
|
||||
false ->
|
||||
?ERROR_MSG("ejabberd is built without graphics support, "
|
||||
"please rebuild it with --enable-graphics or "
|
||||
"set 'thumbnail: false' for module '~s' in "
|
||||
"ejabberd.yml", [?MODULE]);
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
false ->
|
||||
ok
|
||||
@ -726,15 +728,15 @@ parse_http_request(#request{host = Host, path = Path}) ->
|
||||
store_file(Path, Data, FileMode, DirMode, GetPrefix, Slot, Thumbnail) ->
|
||||
case do_store_file(Path, Data, FileMode, DirMode) of
|
||||
ok when Thumbnail ->
|
||||
case identify(Path) of
|
||||
case identify(Path, Data) of
|
||||
{ok, MediaInfo} ->
|
||||
case convert(Path, MediaInfo) of
|
||||
{ok, OutPath} ->
|
||||
case convert(Path, Data, MediaInfo) of
|
||||
{ok, OutPath, OutMediaInfo} ->
|
||||
[UserDir, RandDir | _] = Slot,
|
||||
FileName = filename:basename(OutPath),
|
||||
URL = str:join([GetPrefix, UserDir,
|
||||
RandDir, FileName], <<$/>>),
|
||||
ThumbEl = thumb_el(OutPath, URL),
|
||||
ThumbEl = thumb_el(OutMediaInfo, URL),
|
||||
{ok,
|
||||
[{<<"Content-Type">>,
|
||||
<<"text/xml; charset=utf-8">>}],
|
||||
@ -830,59 +832,68 @@ code_to_message(_Code) -> <<"">>.
|
||||
%% Image manipulation stuff.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec identify(binary()) -> {ok, media_info()} | pass.
|
||||
-spec identify(binary(), binary()) -> {ok, media_info()} | pass.
|
||||
|
||||
identify(Path) ->
|
||||
Cmd = io_lib:format("identify -format 'ok %m %h %w' ~s", [Path]),
|
||||
Res = string:strip(os:cmd(Cmd), right, $\n),
|
||||
case string:tokens(Res, " ") of
|
||||
["ok", T, H, W] ->
|
||||
{ok, #media_info{type = list_to_binary(string:to_lower(T)),
|
||||
height = list_to_integer(H),
|
||||
width = list_to_integer(W)}};
|
||||
_ ->
|
||||
?DEBUG("Cannot identify type of ~s: ~s", [Path, Res]),
|
||||
identify(Path, Data) ->
|
||||
case misc:have_eimp() of
|
||||
true ->
|
||||
case eimp:identify(Data) of
|
||||
{ok, Info} ->
|
||||
{ok, #media_info{
|
||||
type = proplists:get_value(type, Info),
|
||||
width = proplists:get_value(width, Info),
|
||||
height = proplists:get_value(height, Info)}};
|
||||
{error, Why} ->
|
||||
?DEBUG("Cannot identify type of ~s: ~s",
|
||||
[Path, eimp:format_error(Why)]),
|
||||
pass
|
||||
end;
|
||||
false ->
|
||||
pass
|
||||
end.
|
||||
|
||||
-spec convert(binary(), media_info()) -> {ok, binary()} | pass.
|
||||
-spec convert(binary(), binary(), media_info()) -> {ok, binary(), media_info()} | pass.
|
||||
|
||||
convert(Path, #media_info{type = T, width = W, height = H}) ->
|
||||
convert(Path, Data, #media_info{type = T, width = W, height = H} = Info) ->
|
||||
if W * H >= 25000000 ->
|
||||
?DEBUG("The image ~s is more than 25 Mpix", [Path]),
|
||||
pass;
|
||||
W =< 300, H =< 300 ->
|
||||
{ok, Path};
|
||||
T == <<"gif">>; T == <<"jpeg">>; T == <<"png">>; T == <<"webp">> ->
|
||||
Dir = filename:dirname(Path),
|
||||
FileName = <<(randoms:get_string())/binary, $., T/binary>>,
|
||||
OutPath = filename:join(Dir, FileName),
|
||||
Cmd = io_lib:format("convert -resize 300 ~s ~s", [Path, OutPath]),
|
||||
case os:cmd(Cmd) of
|
||||
"" ->
|
||||
{ok, OutPath};
|
||||
Err ->
|
||||
?ERROR_MSG("Failed to convert ~s to ~s: ~s",
|
||||
[Path, OutPath, string:strip(Err, right, $\n)]),
|
||||
pass
|
||||
end;
|
||||
{ok, Path, Info};
|
||||
true ->
|
||||
?DEBUG("Won't call 'convert' for unknown type ~s", [T]),
|
||||
pass
|
||||
Dir = filename:dirname(Path),
|
||||
Ext = atom_to_binary(T, latin1),
|
||||
FileName = <<(randoms:get_string())/binary, $., Ext/binary>>,
|
||||
OutPath = filename:join(Dir, FileName),
|
||||
{W1, H1} = if W > H -> {300, round(H*300/W)};
|
||||
H > W -> {round(W*300/H), 300};
|
||||
true -> {300, 300}
|
||||
end,
|
||||
OutInfo = #media_info{type = T, width = W1, height = H1},
|
||||
case eimp:convert(Data, T, [{scale, {W1, H1}}]) of
|
||||
{ok, OutData} ->
|
||||
case file:write_file(OutPath, OutData) of
|
||||
ok ->
|
||||
{ok, OutPath, OutInfo};
|
||||
{error, Why} ->
|
||||
?ERROR_MSG("Failed to write to ~s: ~s",
|
||||
[OutPath, file:format_error(Why)]),
|
||||
pass
|
||||
end;
|
||||
{error, Why} ->
|
||||
?ERROR_MSG("Failed to convert ~s to ~s: ~s",
|
||||
[Path, OutPath, eimp:format_error(Why)]),
|
||||
pass
|
||||
end
|
||||
end.
|
||||
|
||||
-spec thumb_el(binary(), binary()) -> xmlel().
|
||||
-spec thumb_el(media_info(), binary()) -> xmlel().
|
||||
|
||||
thumb_el(Path, URI) ->
|
||||
ContentType = guess_content_type(Path),
|
||||
xmpp:encode(
|
||||
case identify(Path) of
|
||||
{ok, #media_info{height = H, width = W}} ->
|
||||
#thumbnail{'media-type' = ContentType, uri = URI,
|
||||
height = H, width = W};
|
||||
pass ->
|
||||
#thumbnail{uri = URI, 'media-type' = ContentType}
|
||||
end).
|
||||
thumb_el(#media_info{type = T, height = H, width = W}, URI) ->
|
||||
MimeType = <<"image/", (atom_to_binary(T, latin1))/binary>>,
|
||||
Thumb = #thumbnail{'media-type' = MimeType, uri = URI,
|
||||
height = H, width = W},
|
||||
xmpp:encode(Thumb).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Remove user.
|
||||
|
Loading…
Reference in New Issue
Block a user