Post 从Mathematica向Imgur上传图像
这是对所有Post 从Mathematica向Imgur上传图像,post,wolfram-mathematica,imgur,Post,Wolfram Mathematica,Imgur,这是对所有mathematicatag追随者的挑战。让我们通过创建一个上传程序,使从Mathematica向SO post中插入图像更加方便 我们如何才能创建一个函数imgur[g_],将其参数光栅化(确保最终大小不超过StackOverflow帖子的宽度),将其转换为PNG,上传到imgur,并返回一个准备粘贴的行,如![数学图形](http://i.imgur.com/ZENa4.jpg) 有用的参考资料: 借 我无法适应后一种方法,即在不首先将图像导出到文件的情况下上载图像 警告
mathematica
tag追随者的挑战。让我们通过创建一个上传程序,使从Mathematica向SO post中插入图像更加方便
我们如何才能创建一个函数imgur[g_]
,将其参数光栅化(确保最终大小不超过StackOverflow帖子的宽度),将其转换为PNG,上传到imgur,并返回一个准备粘贴的行,如![数学图形](http://i.imgur.com/ZENa4.jpg)
有用的参考资料:
- 借
警告,小心使用StackOverflow使用可无限期保留图像的。如果您使用主图像。不幸的是,截至2011年11月,似乎还没有通过编程方式将图像上传到StackOverflow
更新:直接上传到StackOverflow的解决方案。注意:这是使用带有我的匿名密钥的匿名imgur上传程序。imgur网站将上传限制为每小时50次,正常情况下应该可以,但如果很多人同时尝试,这可能会导致问题。因此,请在此处获取您自己的匿名密钥: 然后用您自己的密钥替换下面代码中的密钥(谢谢!) 编码最棘手的部分是从Mathematica表达式到PNG图像再到Base64编码再到URL编码的转换。有大约1000种方法可以做错事,我想我都试过了 代码分为几部分:
- 构造POST url
- 建立HTTP连接
- 发送帖子url
- 读回结果,即XML
- 从XML中提取imgur url
- 将imgur url格式化为markdown(或Mathematica
函数)Hyperlink
imgur[expr_] :=
Module[{url, key, image, data, jUrl, jConn, jWriter, jInput, buffer,
byte, xml, imgurUrl},
Needs["JLink`"];
JLink`JavaBlock[
JLink`LoadJavaClass["java.net.URLEncoder"];
url = "http://api.imgur.com/2/upload";
key = "c07bc3fb59ef878d5e23a0c4972fbb29";
image = ExportString[ExportString[expr, "PNG"], "Base64"];
data =
URLEncoder`encode["key" , "UTF-8"] <> "=" <>
URLEncoder`encode[ key , "UTF-8"] <> "&" <>
URLEncoder`encode["image" , "UTF-8"] <> "=" <>
URLEncoder`encode[ image , "UTF-8"] ;
jUrl = JLink`JavaNew["java.net.URL", url];
jConn = jUrl@openConnection[];
jConn@setDoOutput[True];
jWriter =
JLink`JavaNew["java.io.OutputStreamWriter",
jConn@getOutputStream[]];
jWriter@write[data];
jWriter@flush[];
jInput = jConn@getInputStream[];
buffer = {};
While[(byte = jInput@read[]; byte >= 0), AppendTo[buffer, byte]];
];
xml = ImportString[FromCharacterCode[buffer], "XML"];
imgurUrl =
Cases[xml,
XMLElement["original", {}, {string_}] :>
string, \[Infinity]][[1]];
"![Mathematica graphic](" <> imgurUrl <> ")"
]
和实际图像:
注意:使用此功能准备一个现成的调色板
阿诺德的解决方案让我既兴奋又不耐烦,所以这里有一个改进。如果不研究他的代码,我不可能做到这一点。这个版本似乎更可靠,也不太容易出现超时错误,但老实说,我根本不懂Java,所以任何改进都是受欢迎的 最重要的是:这个版本直接上传到
stack.imgur.com
,因此在StackOverflow上使用它是安全的,而不必担心上传的图像会在一段时间后消失
我提供三个功能:
上载表达式,导出为PNG,并返回URLstackImage
返回标记,准备复制stackMarkdown
将标记复制到剪贴板stackCopyMarkdown
不幸的是,我无法将按钮放入调色板(
CreatePalette
),因为调色板尺寸将影响光栅化。这个问题的解决方案是受欢迎的
更新2:
根据对的回答,这里有一个仅适用于Windows的调色板按钮:
button = Button["Upload to SO",
Module[{sel},
FrontEndExecute[
FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial", "MGF"]];
sel = Cases[NotebookGet@ClipboardNotebook[],
RasterBox[data_, ___] :>
Image[data, "Byte", ColorSpace -> "RGB", Magnification -> 1],
Infinity];
If[sel =!= {},
With[{img = First[sel]},
MessageDialog[
Column[{"Upload image to StackExchange sites?",
img}], {"Upload and copy MarkDown" :> stackCopyMarkdown[img],
"Cancel" :> Null}, WindowTitle -> "Upload to StackExchange"]
]
]
]
]
CreatePalette[button]
警告:即使您在预览框中单击“取消”,它也会破坏剪贴板内容。一只小鸟刚刚通知我关于此问题的Mathematica解决方案(底层实现仍然使用JLink,但此答案隐藏了所有与java相关的代码):
imgur[expr\:=模块[
{url,key,image,data,xml,imgurUrl},
url=”http://api.imgur.com/2/upload";
key=“c07bc3fb59ef878d5e23a0c4972fbb29”;
image=Fold[ExportString,expr,{“PNG”,“Base64}];
xml=Import[url,
“XML”、“RequestMethod”->“POST”,
“RequestParameters”->{“key”->key,“image”->image}];
imgurUrl=Cases[xml,XMLElement[“original”,{},{string}]:>string,
无穷大][[1]];
“![Mathematica graphic](“imgurUrl”)”
]
这只是V8版本,导入选项
“RequestMethod”
和“RequestParameters”
是未记录的和实验性的(因此可能会更改)。请注意上传到http://i.stack.imgur.com/
更难(你必须“驱动”SO接口)@belisarius Oops,我不知道StackOverflow使用单独的imgur站点。。。在imgur主站点上,图像可能不会永远保存,因此使用它可能不是一个好主意(保存图像至少需要1次查看/6个月)。手动发布图形并不是那么难(在V8中)。在图形上单击鼠标右键,选择“将图像另存为…”。然后,文件对话框在上次打开的地方打开,通常是我的桌面,其中一个名为output.png的文件已经在等待被下一个版本覆盖。只需点击两下,再点击两下,就可以在我的答案框中找到答案。最多需要15秒。获取标记行和粘贴大约需要相同的时间。@Sjoerd在图像处理标签中发布时,我必须一次又一次地重复…@belisarius但对于建议的解决方案,您必须为每个要包含的图形键入imgur[g]
,并复制和粘贴标记文本。在努力方面似乎真的没有太大区别。有没有一种方法可以在Mathematica内部进行编码和上传,而不必求助于JLink
+1,顺便说一句。我得到了错误:Java::excptn:发生了Java异常:Java.io.IOException:服务器返回了URL的HTTP响应代码:400:http://api.imgur.com/2/upload 位于sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1290)。XML`Parser`XMLGetString::string:XML`Parser`XMLGetString[EndOfFile]中的位置1应为字符串
Needs["JLink`"]
stackImage::httperr = "Server returned respose code: `1`";
stackImage::err = "Server returner error: `1`";
stackImage[g_] :=
Module[
{getVal, url, client, method, data, partSource, part, entity, code,
response, error, result},
(* this function attempts to parse the response fro the SO server *)
getVal[res_, key_String] :=
With[{k = "var " <> key <> " = "},
StringTrim[
First@StringCases[First@Select[res, StringMatchQ[#, k ~~ ___] &],
k ~~ v___ ~~ ";" :> v],
"'"]
];
data = ExportString[g, "PNG"];
JavaBlock[
url = "https://stackoverflow.com/upload/image";
client = JavaNew["org.apache.commons.httpclient.HttpClient"];
method = JavaNew["org.apache.commons.httpclient.methods.PostMethod", url];
partSource = JavaNew["org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource", "mmagraphics.png", MakeJavaObject[data]@toCharArray[]];
part = JavaNew["org.apache.commons.httpclient.methods.multipart.FilePart", "name", partSource];
part@setContentType["image/png"];
entity = JavaNew["org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity", {part}, method@getParams[]];
method@setRequestEntity[entity];
code = client@executeMethod[method];
response = method@getResponseBodyAsString[];
]
If[code =!= 200, Message[stackImage::httperr, code]; Return[$Failed]];
response = StringTrim /@ StringSplit[response, "\n"];
error = getVal[response, "error"];
result = getVal[response, "result"];
If[StringMatchQ[result, "http*"],
result,
Message[stackImage::err, error]; $Failed]
]
stackMarkdown[g_] := "![Mathematica graphics](" <> stackImage[g] <> ")"
stackCopyMarkdown[g_] := Module[{nb, markdown},
markdown = Check[stackMarkdown[g], $Failed];
If[markdown =!= $Failed,
nb = NotebookCreate[Visible -> False];
NotebookWrite[nb, Cell[markdown, "Text"]];
SelectionMove[nb, All, Notebook];
FrontEndTokenExecute[nb, "Copy"];
NotebookClose[nb];
]
]
Button["Upload to SO",
Module[{cell = NotebookRead@InputNotebook[], img},
If[cell =!= {}, img = Rasterize[cell];
MessageDialog[
Column[{"Upload image to StackExchange sites?",
img}], {"Upload and copy MarkDown" :> stackCopyMarkdown[img],
"Cancel" :> Null}, WindowTitle -> "Upload to StackExchange"]]]]
button = Button["Upload to SO",
Module[{sel},
FrontEndExecute[
FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial", "MGF"]];
sel = Cases[NotebookGet@ClipboardNotebook[],
RasterBox[data_, ___] :>
Image[data, "Byte", ColorSpace -> "RGB", Magnification -> 1],
Infinity];
If[sel =!= {},
With[{img = First[sel]},
MessageDialog[
Column[{"Upload image to StackExchange sites?",
img}], {"Upload and copy MarkDown" :> stackCopyMarkdown[img],
"Cancel" :> Null}, WindowTitle -> "Upload to StackExchange"]
]
]
]
]
CreatePalette[button]
imgur[expr_] := Module[
{url, key, image, data, xml, imgurUrl},
url = "http://api.imgur.com/2/upload";
key = "c07bc3fb59ef878d5e23a0c4972fbb29";
image = Fold[ExportString, expr, {"PNG", "Base64"}];
xml = Import[url,
"XML", "RequestMethod" -> "POST",
"RequestParameters" -> {"key" -> key, "image" -> image}];
imgurUrl = Cases[xml, XMLElement["original", {}, {string_}] :> string,
Infinity][[1]];
"![Mathematica graphic](" <> imgurUrl <> ")"
]